001/* 002 * (C) Copyright 2012 Nuxeo SA (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 <ataillefer@nuxeo.com> 018 */ 019package org.nuxeo.drive.hierarchy.permission.factory; 020 021import java.security.Principal; 022import java.util.Map; 023 024import org.apache.commons.lang.StringUtils; 025import org.apache.commons.logging.Log; 026import org.apache.commons.logging.LogFactory; 027import org.nuxeo.drive.adapter.FileSystemItem; 028import org.nuxeo.drive.adapter.FolderItem; 029import org.nuxeo.drive.adapter.impl.DefaultSyncRootFolderItem; 030import org.nuxeo.drive.service.FileSystemItemAdapterService; 031import org.nuxeo.drive.service.FileSystemItemFactory; 032import org.nuxeo.drive.service.impl.AbstractSyncRootFolderItemFactory; 033import org.nuxeo.ecm.core.api.CoreSession; 034import org.nuxeo.ecm.core.api.DocumentModel; 035import org.nuxeo.ecm.core.api.NuxeoException; 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 Log log = LogFactory.getLog(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( 073 String.format( 074 "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.", 075 getName(), USER_SYNC_ROOT_PARENT_FACTORY_PARAM)); 076 } 077 userSyncRootParentFactoryName = userSyncRootParentFactoryParam; 078 079 String sharedSyncRootParentFactoryParam = parameters.get(SHARED_SYNC_ROOT_PARENT_FACTORY_PARAM); 080 if (StringUtils.isEmpty(sharedSyncRootParentFactoryParam)) { 081 throw new NuxeoException( 082 String.format( 083 "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.", 084 getName(), SHARED_SYNC_ROOT_PARENT_FACTORY_PARAM)); 085 } 086 sharedSyncRootParentFactoryName = sharedSyncRootParentFactoryParam; 087 } 088 089 /** 090 * Checks if the given {@link DocumentModel} is adaptable as a {@link FileSystemItem}. The permission 091 * synchronization root factory considers that a {@link DocumentModel} is adaptable as a {@link FileSystemItem} if: 092 * <ul> 093 * <li>It is Folderish</li> 094 * <li>AND it is not a version nor a proxy</li> 095 * <li>AND it is not HiddenInNavigation</li> 096 * <li>AND it is not in the "deleted" life cycle state, unless {@code includeDeleted} is true</li> 097 * <li>AND it is a synchronization root registered for the current user, unless {@code relaxSyncRootConstraint} is 098 * true</li> 099 * <li>AND the current user has the {@link #getRequiredPermission()} permission on the document</li> 100 * </ul> 101 */ 102 @Override 103 public boolean isFileSystemItem(DocumentModel doc, boolean includeDeleted, boolean relaxSyncRootConstraint) { 104 // Check required permission 105 CoreSession session = doc.getCoreSession(); 106 boolean hasRequiredPermission = session.hasPermission(doc.getRef(), requiredPermission); 107 if (!hasRequiredPermission) { 108 if (log.isDebugEnabled()) { 109 log.debug(String.format( 110 "Required permission %s is not granted on document %s to user %s, it cannot be adapted as a FileSystemItem.", 111 requiredPermission, doc.getId(), session.getPrincipal().getName())); 112 } 113 return false; 114 } 115 return super.isFileSystemItem(doc, includeDeleted, relaxSyncRootConstraint) && hasRequiredPermission; 116 } 117 118 @Override 119 protected FileSystemItem adaptDocument(DocumentModel doc, boolean forceParentId, FolderItem parentItem, 120 boolean relaxSyncRootConstraint, boolean getLockInfo) { 121 return new DefaultSyncRootFolderItem(name, parentItem, doc, relaxSyncRootConstraint, getLockInfo); 122 } 123 124 /*------------------ AbstractSyncRootFolderItemFactory ------------------*/ 125 @Override 126 protected FolderItem getParentItem(DocumentModel doc) { 127 Principal principal = doc.getCoreSession().getPrincipal(); 128 String docCreator = (String) doc.getPropertyValue("dc:creator"); 129 if (principal.getName().equals(docCreator)) { 130 FolderItem parent = getFileSystemAdapterService().getVirtualFolderItemFactory(userSyncRootParentFactoryName) 131 .getVirtualFolderItem(principal); 132 if (parent == null) { 133 throw new NuxeoException(String.format( 134 "Cannot find the parent of document %s: virtual folder from factory %s.", doc.getId(), 135 userSyncRootParentFactoryName)); 136 } 137 return parent; 138 } else { 139 FolderItem parent = getFileSystemAdapterService().getVirtualFolderItemFactory( 140 sharedSyncRootParentFactoryName).getVirtualFolderItem(principal); 141 if (parent == null) { 142 throw new NuxeoException(String.format( 143 "Cannot find the parent of document %s: virtual folder from factory %s.", doc.getId(), 144 sharedSyncRootParentFactoryName)); 145 } 146 return parent; 147 } 148 } 149 150 protected FileSystemItemAdapterService getFileSystemAdapterService() { 151 return Framework.getService(FileSystemItemAdapterService.class); 152 } 153 154}