001/* 002 * (C) Copyright 2012 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Antoine Taillefer <ataillefer@nuxeo.com> 016 */ 017package org.nuxeo.drive.hierarchy.permission.factory; 018 019import java.security.Principal; 020import java.util.Map; 021 022import org.apache.commons.lang.StringUtils; 023import org.apache.commons.logging.Log; 024import org.apache.commons.logging.LogFactory; 025import org.nuxeo.drive.adapter.FileSystemItem; 026import org.nuxeo.drive.adapter.FolderItem; 027import org.nuxeo.drive.adapter.impl.DefaultSyncRootFolderItem; 028import org.nuxeo.drive.service.FileSystemItemAdapterService; 029import org.nuxeo.drive.service.FileSystemItemFactory; 030import org.nuxeo.drive.service.impl.AbstractSyncRootFolderItemFactory; 031import org.nuxeo.ecm.core.api.CoreSession; 032import org.nuxeo.ecm.core.api.DocumentModel; 033import org.nuxeo.ecm.core.api.NuxeoException; 034import org.nuxeo.ecm.core.api.security.SecurityConstants; 035import org.nuxeo.runtime.api.Framework; 036 037/** 038 * Permission based implementation of {@link FileSystemItemFactory} for a synchronization root {@link FolderItem}. 039 * 040 * @author Antoine Taillefer 041 */ 042public class PermissionSyncRootFactory extends AbstractSyncRootFolderItemFactory { 043 044 private static final Log log = LogFactory.getLog(PermissionSyncRootFactory.class); 045 046 protected static final String REQUIRED_PERMISSION_PARAM = "requiredPermission"; 047 048 protected static final String USER_SYNC_ROOT_PARENT_FACTORY_PARAM = "userSyncRootParentFactory"; 049 050 protected static final String SHARED_SYNC_ROOT_PARENT_FACTORY_PARAM = "sharedSyncRootParentFactory"; 051 052 // Required permission to include a folder as a synchronization root, 053 // default is ReadWrite 054 protected String requiredPermission = SecurityConstants.READ_WRITE; 055 056 protected String userSyncRootParentFactoryName; 057 058 protected String sharedSyncRootParentFactoryName; 059 060 /*------------------- AbstractFileSystemItemFactory ---------------------*/ 061 @Override 062 public void handleParameters(Map<String, String> parameters) { 063 String requiredPermissionParam = parameters.get(REQUIRED_PERMISSION_PARAM); 064 if (!StringUtils.isEmpty(requiredPermissionParam)) { 065 requiredPermission = requiredPermissionParam; 066 } 067 068 String userSyncRootParentFactoryParam = parameters.get(USER_SYNC_ROOT_PARENT_FACTORY_PARAM); 069 if (StringUtils.isEmpty(userSyncRootParentFactoryParam)) { 070 throw new NuxeoException( 071 String.format( 072 "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.", 073 getName(), USER_SYNC_ROOT_PARENT_FACTORY_PARAM)); 074 } 075 userSyncRootParentFactoryName = userSyncRootParentFactoryParam; 076 077 String sharedSyncRootParentFactoryParam = parameters.get(SHARED_SYNC_ROOT_PARENT_FACTORY_PARAM); 078 if (StringUtils.isEmpty(sharedSyncRootParentFactoryParam)) { 079 throw new NuxeoException( 080 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 "deleted" life cycle state, 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 if (log.isDebugEnabled()) { 107 log.debug(String.format( 108 "Required permission %s is not granted on document %s to user %s, it cannot be adapted as a FileSystemItem.", 109 requiredPermission, doc.getId(), session.getPrincipal().getName())); 110 } 111 return false; 112 } 113 return super.isFileSystemItem(doc, includeDeleted, relaxSyncRootConstraint) && hasRequiredPermission; 114 } 115 116 @Override 117 protected FileSystemItem adaptDocument(DocumentModel doc, boolean forceParentId, FolderItem parentItem, 118 boolean relaxSyncRootConstraint) { 119 return new DefaultSyncRootFolderItem(name, parentItem, doc, relaxSyncRootConstraint); 120 } 121 122 /*------------------ AbstractSyncRootFolderItemFactory ------------------*/ 123 @Override 124 protected FolderItem getParentItem(DocumentModel doc) { 125 Principal principal = doc.getCoreSession().getPrincipal(); 126 String docCreator = (String) doc.getPropertyValue("dc:creator"); 127 if (principal.getName().equals(docCreator)) { 128 FolderItem parent = getFileSystemAdapterService().getVirtualFolderItemFactory(userSyncRootParentFactoryName).getVirtualFolderItem( 129 principal); 130 if (parent == null) { 131 throw new NuxeoException(String.format( 132 "Cannot find the parent of document %s: virtual folder from factory %s.", doc.getId(), 133 userSyncRootParentFactoryName)); 134 } 135 return parent; 136 } else { 137 FolderItem parent = getFileSystemAdapterService().getVirtualFolderItemFactory( 138 sharedSyncRootParentFactoryName).getVirtualFolderItem(principal); 139 if (parent == null) { 140 throw new NuxeoException(String.format( 141 "Cannot find the parent of document %s: virtual folder from factory %s.", doc.getId(), 142 sharedSyncRootParentFactoryName)); 143 } 144 return parent; 145 } 146 } 147 148 protected FileSystemItemAdapterService getFileSystemAdapterService() { 149 return Framework.getLocalService(FileSystemItemAdapterService.class); 150 } 151 152}