001/* 002 * (C) Copyright 2012-2018 Nuxeo (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Antoine Taillefer <[email protected]> 018 */ 019package org.nuxeo.drive.hierarchy.permission.factory; 020 021import java.util.Map; 022 023import org.apache.commons.lang3.StringUtils; 024import org.apache.logging.log4j.LogManager; 025import org.apache.logging.log4j.Logger; 026import org.nuxeo.drive.adapter.FileSystemItem; 027import org.nuxeo.drive.adapter.FolderItem; 028import org.nuxeo.drive.adapter.impl.DefaultSyncRootFolderItem; 029import org.nuxeo.drive.service.FileSystemItemAdapterService; 030import org.nuxeo.drive.service.FileSystemItemFactory; 031import org.nuxeo.drive.service.impl.AbstractSyncRootFolderItemFactory; 032import org.nuxeo.ecm.core.api.CoreSession; 033import org.nuxeo.ecm.core.api.DocumentModel; 034import org.nuxeo.ecm.core.api.NuxeoException; 035import org.nuxeo.ecm.core.api.NuxeoPrincipal; 036import org.nuxeo.ecm.core.api.security.SecurityConstants; 037import org.nuxeo.runtime.api.Framework; 038 039/** 040 * Permission based implementation of {@link FileSystemItemFactory} for a synchronization root {@link FolderItem}. 041 * 042 * @author Antoine Taillefer 043 */ 044public class PermissionSyncRootFactory extends AbstractSyncRootFolderItemFactory { 045 046 private static final Logger log = LogManager.getLogger(PermissionSyncRootFactory.class); 047 048 protected static final String REQUIRED_PERMISSION_PARAM = "requiredPermission"; 049 050 protected static final String USER_SYNC_ROOT_PARENT_FACTORY_PARAM = "userSyncRootParentFactory"; 051 052 protected static final String SHARED_SYNC_ROOT_PARENT_FACTORY_PARAM = "sharedSyncRootParentFactory"; 053 054 // Required permission to include a folder as a synchronization root, 055 // default is ReadWrite 056 protected String requiredPermission = SecurityConstants.READ; 057 058 protected String userSyncRootParentFactoryName; 059 060 protected String sharedSyncRootParentFactoryName; 061 062 /*------------------- AbstractFileSystemItemFactory ---------------------*/ 063 @Override 064 public void handleParameters(Map<String, String> parameters) { 065 String requiredPermissionParam = parameters.get(REQUIRED_PERMISSION_PARAM); 066 if (!StringUtils.isEmpty(requiredPermissionParam)) { 067 requiredPermission = requiredPermissionParam; 068 } 069 070 String userSyncRootParentFactoryParam = parameters.get(USER_SYNC_ROOT_PARENT_FACTORY_PARAM); 071 if (StringUtils.isEmpty(userSyncRootParentFactoryParam)) { 072 throw new NuxeoException(String.format( 073 "Factory %s has no %s parameter, please provide it in the factory contribution to set the name of the factory for the parent folder of the user's synchronization roots.", 074 getName(), USER_SYNC_ROOT_PARENT_FACTORY_PARAM)); 075 } 076 userSyncRootParentFactoryName = userSyncRootParentFactoryParam; 077 078 String sharedSyncRootParentFactoryParam = parameters.get(SHARED_SYNC_ROOT_PARENT_FACTORY_PARAM); 079 if (StringUtils.isEmpty(sharedSyncRootParentFactoryParam)) { 080 throw new NuxeoException(String.format( 081 "Factory %s has no %s parameter, please provide it in the factory contribution to set the name of the factory for the parent folder of the user's shared synchronization roots.", 082 getName(), SHARED_SYNC_ROOT_PARENT_FACTORY_PARAM)); 083 } 084 sharedSyncRootParentFactoryName = sharedSyncRootParentFactoryParam; 085 } 086 087 /** 088 * Checks if the given {@link DocumentModel} is adaptable as a {@link FileSystemItem}. The permission 089 * synchronization root factory considers that a {@link DocumentModel} is adaptable as a {@link FileSystemItem} if: 090 * <ul> 091 * <li>It is Folderish</li> 092 * <li>AND it is not a version nor a proxy</li> 093 * <li>AND it is not HiddenInNavigation</li> 094 * <li>AND it is not in the trash, unless {@code includeDeleted} is true</li> 095 * <li>AND it is a synchronization root registered for the current user, unless {@code relaxSyncRootConstraint} is 096 * true</li> 097 * <li>AND the current user has the {@link #getRequiredPermission()} permission on the document</li> 098 * </ul> 099 */ 100 @Override 101 public boolean isFileSystemItem(DocumentModel doc, boolean includeDeleted, boolean relaxSyncRootConstraint) { 102 // Check required permission 103 CoreSession session = doc.getCoreSession(); 104 boolean hasRequiredPermission = session.hasPermission(doc.getRef(), requiredPermission); 105 if (!hasRequiredPermission) { 106 log.debug( 107 "Required permission {} is not granted on document {} to user {}, it cannot be adapted as a FileSystemItem.", 108 () -> requiredPermission, doc::getId, session::getPrincipal); 109 return false; 110 } 111 return super.isFileSystemItem(doc, includeDeleted, relaxSyncRootConstraint) && hasRequiredPermission; 112 } 113 114 @Override 115 protected FileSystemItem adaptDocument(DocumentModel doc, boolean forceParentId, FolderItem parentItem, 116 boolean relaxSyncRootConstraint, boolean getLockInfo) { 117 return new DefaultSyncRootFolderItem(name, parentItem, doc, relaxSyncRootConstraint, getLockInfo); 118 } 119 120 /*------------------ AbstractSyncRootFolderItemFactory ------------------*/ 121 @Override 122 protected FolderItem getParentItem(DocumentModel doc) { 123 NuxeoPrincipal principal = doc.getCoreSession().getPrincipal(); 124 String docCreator = (String) doc.getPropertyValue("dc:creator"); 125 if (principal.getName().equals(docCreator)) { 126 FolderItem parent = getFileSystemAdapterService().getVirtualFolderItemFactory(userSyncRootParentFactoryName) 127 .getVirtualFolderItem(principal); 128 if (parent == null) { 129 throw new NuxeoException( 130 String.format("Cannot find the parent of document %s: virtual folder from factory %s.", 131 doc.getId(), userSyncRootParentFactoryName)); 132 } 133 return parent; 134 } else { 135 FolderItem parent = getFileSystemAdapterService().getVirtualFolderItemFactory( 136 sharedSyncRootParentFactoryName).getVirtualFolderItem(principal); 137 if (parent == null) { 138 throw new NuxeoException( 139 String.format("Cannot find the parent of document %s: virtual folder from factory %s.", 140 doc.getId(), sharedSyncRootParentFactoryName)); 141 } 142 return parent; 143 } 144 } 145 146 protected FileSystemItemAdapterService getFileSystemAdapterService() { 147 return Framework.getService(FileSystemItemAdapterService.class); 148 } 149 150}