mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-06-30 18:15:39 +00:00
26373: WIP: ALF-7339: RSOLR 009: Index track and build from SOLR - track content, track dates, basic sorting 26388: WIP: ALF-7339: RSOLR 009: Index track and build from SOLR - basic tracking of d:text and d:mltext (not dual tokenisation and identifier support) 26527: WIP ALF-7339: RSOLR 009: Index track and build from SOLR - track d:content, d:mltext, d:text - start of cross locale search and ordering support int the index (not at query time yet) - no dual tokenisation support yet - currently adding all fields for tokenized BOTH - .sort needs additional tokenisation support to use a different separator (\u0000 used to indicate locale and split stuff - better toe use {en}woof style with \u0000 split 26822: ALF-8166: RINF 10: treenode.get.js - tweak to use "childFileFolders" 26825: ALF-8133: RINF 10: ScriptNode - update "childByNamePath" to use optimised NodeService.getChildByName 26850: ALF-8133: RINF 10: ScriptNode - update "childByNamePath" to use optimised NodeService.getChildByName - follow-on to r26825 26862: ALF-8110: RINF 10: doclist.get.js - update "path" filter to use DB-based queries (by default) - milestone check-in for review and comparison (note: sorting will be pushed down as part of paging support in lower layers) 26872: Updated SOLR dev env 26915: ALF-8224: part 1: encapsulate cmis dictionary for SOLR usage 27017: Javadoc: removed uncommented param 27018: Added 'namePattern' property to NamedObjectRegistry to enforce naming conventions where required 27019: CannedQuery interface and related infrastructure - Provides basic support for query, sort, filter and page - CannedQueryFactory allows more complex implementations where required - Should be enough of a starter for tasks requiring miscellaneous queries - ALF-7167: Canned queries 27037: WCM QS Needs the Web-Client, so define the dependency to Eclipse 27041: Move WCM-QS test setup to a common base class 27044: Start to conver the WCM QS behaviour from JS to Java 27080: Added comment section for NodeLocator script declarations 27081: General cleanup: Removed non-javadocs, empty javadocs, unused code, etc 27104: Fixed ALF-7476: Typo in output from MMT 27114: ALF-7479: RSOLR 016: Query Handler ALF-7480: RSOLR 017: SOLR result set ALF-7481: RSOLR 018: Execute query against SOLR - First working stack git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@28286 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
508 lines
18 KiB
Java
508 lines
18 KiB
Java
/*
|
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
|
*
|
|
* This file is part of Alfresco
|
|
*
|
|
* Alfresco is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Alfresco is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
package org.alfresco.cmis.acl;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.Comparator;
|
|
import java.util.EnumSet;
|
|
import java.util.HashSet;
|
|
import java.util.LinkedHashSet;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import org.alfresco.cmis.CMISAccessControlEntry;
|
|
import org.alfresco.cmis.CMISAccessControlReport;
|
|
import org.alfresco.cmis.CMISAccessControlService;
|
|
import org.alfresco.cmis.CMISAclCapabilityEnum;
|
|
import org.alfresco.cmis.CMISAclPropagationEnum;
|
|
import org.alfresco.cmis.CMISAclSupportedPermissionEnum;
|
|
import org.alfresco.cmis.CMISAllowedActionEnum;
|
|
import org.alfresco.cmis.CMISConstraintException;
|
|
import org.alfresco.cmis.CMISDictionaryService;
|
|
import org.alfresco.cmis.CMISPermissionDefinition;
|
|
import org.alfresco.cmis.CMISPermissionMapping;
|
|
import org.alfresco.cmis.CMISTypeDefinition;
|
|
import org.alfresco.cmis.mapping.CMISMapping;
|
|
import org.alfresco.opencmis.CMISAccessControlFormatEnum;
|
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
|
import org.alfresco.repo.security.permissions.PermissionReference;
|
|
import org.alfresco.repo.security.permissions.impl.AccessPermissionImpl;
|
|
import org.alfresco.repo.security.permissions.impl.ModelDAO;
|
|
import org.alfresco.service.cmr.repository.NodeRef;
|
|
import org.alfresco.service.cmr.repository.NodeService;
|
|
import org.alfresco.service.cmr.security.AccessPermission;
|
|
import org.alfresco.service.cmr.security.AccessStatus;
|
|
import org.alfresco.service.cmr.security.PermissionService;
|
|
import org.alfresco.service.namespace.QName;
|
|
import org.alfresco.util.Pair;
|
|
|
|
/**
|
|
* @author andyh
|
|
*/
|
|
public class CMISAccessControlServiceImpl implements CMISAccessControlService
|
|
{
|
|
private CMISAclCapabilityEnum aclCapabilityEnum;
|
|
|
|
private CMISAclSupportedPermissionEnum aclSupportedPermissionEnum;
|
|
|
|
private CMISAclPropagationEnum aclPropagationEnum;
|
|
|
|
private ModelDAO permissionModelDao;
|
|
|
|
private PermissionService permissionService;
|
|
|
|
private CMISMapping cmisMapping;
|
|
|
|
private NodeService nodeService;
|
|
|
|
private CMISDictionaryService cmisDictionaryService;
|
|
|
|
/**
|
|
* @param aclCapabilityEnum
|
|
* the aclCapabilityEnum to set
|
|
*/
|
|
public void setAclCapabilityEnum(CMISAclCapabilityEnum aclCapabilityEnum)
|
|
{
|
|
this.aclCapabilityEnum = aclCapabilityEnum;
|
|
}
|
|
|
|
/**
|
|
* Sets the acl supported permission enum.
|
|
*
|
|
* @param aclSupportedPermissionEnum
|
|
* the aclSupportedPermissionEnum to set
|
|
*/
|
|
public void setAclSupportedPermissionEnum(CMISAclSupportedPermissionEnum aclSupportedPermissionEnum)
|
|
{
|
|
this.aclSupportedPermissionEnum = aclSupportedPermissionEnum;
|
|
}
|
|
|
|
/**
|
|
* @param aclPropagationEnum
|
|
* the aclPropagationEnum to set
|
|
*/
|
|
public void setAclPropagationEnum(CMISAclPropagationEnum aclPropagationEnum)
|
|
{
|
|
this.aclPropagationEnum = aclPropagationEnum;
|
|
}
|
|
|
|
/**
|
|
* @param permissionModelDao
|
|
* the permissionModelDao to set
|
|
*/
|
|
public void setPermissionModelDao(ModelDAO permissionModelDao)
|
|
{
|
|
this.permissionModelDao = permissionModelDao;
|
|
}
|
|
|
|
/**
|
|
* @param permissionService
|
|
* the permissionService to set
|
|
*/
|
|
public void setPermissionService(PermissionService permissionService)
|
|
{
|
|
this.permissionService = permissionService;
|
|
}
|
|
|
|
/**
|
|
* Sets the cmis mapping.
|
|
*
|
|
* @param cmisMapping
|
|
* the cmis mapping
|
|
*/
|
|
public void setCMISMapping(CMISMapping cmisMapping)
|
|
{
|
|
this.cmisMapping = cmisMapping;
|
|
}
|
|
|
|
/**
|
|
* @param nodeService
|
|
* the nodeService to set
|
|
*/
|
|
public void setNodeService(NodeService nodeService)
|
|
{
|
|
this.nodeService = nodeService;
|
|
}
|
|
|
|
/**
|
|
* @param cmisDictionaryService
|
|
* the cmisDictionaryService to set
|
|
*/
|
|
public void setCMISDictionaryService(CMISDictionaryService cmisDictionaryService)
|
|
{
|
|
this.cmisDictionaryService = cmisDictionaryService;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see org.alfresco.cmis.CMISAccessControlService#applyAcl(org.alfresco.service.cmr.repository.NodeRef,
|
|
* java.util.List)
|
|
*/
|
|
public CMISAccessControlReport applyAcl(NodeRef nodeRef, List<CMISAccessControlEntry> acesToApply) throws CMISConstraintException
|
|
{
|
|
Set<CMISAccessControlEntry> acesToAdd = new LinkedHashSet<CMISAccessControlEntry>(acesToApply);
|
|
List<? extends CMISAccessControlEntry> acesExisting = getAcl(nodeRef,
|
|
CMISAccessControlFormatEnum.REPOSITORY_SPECIFIC_PERMISSIONS).getAccessControlEntries();
|
|
List<CMISAccessControlEntry> acesToRemove = new ArrayList<CMISAccessControlEntry>(acesExisting.size());
|
|
for (CMISAccessControlEntry accessControlEntry : acesExisting)
|
|
{
|
|
// Only pay attention to existing direct entries
|
|
if (accessControlEntry.getDirect() && !acesToAdd.remove(accessControlEntry))
|
|
{
|
|
acesToRemove.add(accessControlEntry);
|
|
}
|
|
}
|
|
return applyAcl(nodeRef, acesToRemove, new ArrayList<CMISAccessControlEntry>(acesToAdd),
|
|
CMISAclPropagationEnum.PROPAGATE,
|
|
CMISAccessControlFormatEnum.REPOSITORY_SPECIFIC_PERMISSIONS);
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see org.alfresco.cmis.CMISAccessControlService#applyAcl(org.alfresco.service.cmr.repository.NodeRef,
|
|
* java.util.List, java.util.List, org.alfresco.cmis.CMISAclPropagationEnum)
|
|
*/
|
|
public CMISAccessControlReport applyAcl(NodeRef nodeRef, List<CMISAccessControlEntry> acesToRemove, List<CMISAccessControlEntry> acesToAdd, CMISAclPropagationEnum propagation,
|
|
CMISAccessControlFormatEnum format) throws CMISConstraintException
|
|
{
|
|
if (propagation == CMISAclPropagationEnum.OBJECT_ONLY)
|
|
{
|
|
throw new CMISConstraintException("Unsupported ACL propagation mode: " + propagation);
|
|
}
|
|
// Check controllable ACL
|
|
QName type = nodeService.getType(nodeRef);
|
|
CMISTypeDefinition cmisType = cmisDictionaryService.findTypeForClass(type);
|
|
if (false == cmisType.isControllableACL())
|
|
{
|
|
throw new CMISConstraintException("ACLs are not supported for type: " + cmisType.getDisplayName());
|
|
}
|
|
// TODO: Check valid permissions. We do not check this internally. Ignore for now ...
|
|
|
|
if (acesToRemove != null)
|
|
{
|
|
Set<AccessPermission> permissions = permissionService.getAllSetPermissions(nodeRef);
|
|
for (CMISAccessControlEntry entry : acesToRemove)
|
|
{
|
|
String alfrescoPermission = cmisMapping.getSetPermission(compressPermission(entry.getPermission()));
|
|
AccessPermission toCheck = new AccessPermissionImpl(alfrescoPermission, AccessStatus.ALLOWED, entry.getPrincipalId(), 0);
|
|
if (false == permissions.contains(toCheck))
|
|
{
|
|
throw new CMISConstraintException("No matching ACE found to delete");
|
|
}
|
|
permissionService.deletePermission(nodeRef, entry.getPrincipalId(), alfrescoPermission);
|
|
}
|
|
}
|
|
if (acesToAdd != null)
|
|
{
|
|
for (CMISAccessControlEntry entry : acesToAdd)
|
|
{
|
|
String alfrescoPermission = cmisMapping.getSetPermission(compressPermission(entry.getPermission()));
|
|
permissionService.setPermission(nodeRef, entry.getPrincipalId(), alfrescoPermission, true);
|
|
}
|
|
}
|
|
return getAcl(nodeRef, format);
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see org.alfresco.cmis.CMISAccessControlService#getAcl(org.alfresco.service.cmr.repository.NodeRef,
|
|
* org.alfresco.cmis.CMISAccessControlFormatEnum)
|
|
*/
|
|
public CMISAccessControlReport getAcl(NodeRef nodeRef, CMISAccessControlFormatEnum format)
|
|
{
|
|
CMISAccessControlReportImpl merge = new CMISAccessControlReportImpl();
|
|
// Need to compact deny to mask correctly
|
|
Set<AccessPermission> permissions = permissionService.getAllSetPermissions(nodeRef);
|
|
ArrayList<AccessPermission> ordered = new ArrayList<AccessPermission>();
|
|
AccessPermissionComparator comparator = new AccessPermissionComparator();
|
|
for (AccessPermission current : permissions)
|
|
{
|
|
int index = Collections.binarySearch(ordered, current, comparator);
|
|
if (index < 0)
|
|
{
|
|
ordered.add(-index - 1, current);
|
|
}
|
|
}
|
|
|
|
for (AccessPermission entry : ordered)
|
|
{
|
|
if (entry.getAccessStatus() == AccessStatus.ALLOWED)
|
|
{
|
|
//answer.addEntry(new CMISAccessControlEntryImpl(entry.getAuthority(), expandPermission(cmisMapping.getReportedPermission(getPermission(entry.getPermission()),
|
|
// format)), entry.getPosition()));
|
|
merge.addEntry(new CMISAccessControlEntryImpl(entry.getAuthority(), entry.getPermission(), entry.getPosition()));
|
|
}
|
|
else if (entry.getAccessStatus() == AccessStatus.DENIED)
|
|
{
|
|
//answer.removeEntry(new CMISAccessControlEntryImpl(entry.getAuthority(), expandPermission(cmisMapping.getReportedPermission(getPermission(entry.getPermission()),
|
|
// format)), entry.getPosition()));
|
|
merge.removeEntry(new CMISAccessControlEntryImpl(entry.getAuthority(), entry.getPermission(), entry.getPosition()));
|
|
}
|
|
}
|
|
|
|
CMISAccessControlReportImpl answer = new CMISAccessControlReportImpl();
|
|
for(CMISAccessControlEntry entry : merge.getAccessControlEntries())
|
|
{
|
|
CMISAccessControlEntryImpl impl = (CMISAccessControlEntryImpl)entry;
|
|
PermissionReference permissionReference = permissionModelDao.getPermissionReference(null, impl.getPermission());
|
|
Set<PermissionReference> longForms = permissionModelDao.getGranteePermissions(permissionReference);
|
|
HashSet<String> shortForms = new HashSet<String>();
|
|
for(PermissionReference longForm : longForms)
|
|
{
|
|
shortForms.add(getPermission(longForm));
|
|
}
|
|
for(Pair<String, Boolean> toAdd : cmisMapping.getReportedPermissions(impl.getPermission(), shortForms, permissionModelDao.hasFull(permissionReference), impl.getDirect(), format))
|
|
{
|
|
answer.addEntry(new CMISAccessControlEntryImpl(impl.getPrincipalId(), expandPermission(toAdd.getFirst()), impl.getPosition(), toAdd.getSecond()));
|
|
}
|
|
|
|
}
|
|
return answer;
|
|
}
|
|
|
|
private String getPermission(PermissionReference permissionReference)
|
|
{
|
|
if (permissionModelDao.isUnique(permissionReference))
|
|
{
|
|
return permissionReference.getName();
|
|
}
|
|
else
|
|
{
|
|
return permissionReference.toString();
|
|
}
|
|
}
|
|
|
|
private String expandPermission(String permission)
|
|
{
|
|
if (permission.equals(CMIS_ALL_PERMISSION))
|
|
{
|
|
return permission;
|
|
}
|
|
else if (permission.equals(CMIS_READ_PERMISSION))
|
|
{
|
|
return permission;
|
|
}
|
|
else if (permission.equals(CMIS_WRITE_PERMISSION))
|
|
{
|
|
return permission;
|
|
|
|
}
|
|
else if (permission.startsWith("{"))
|
|
{
|
|
return permission;
|
|
}
|
|
else
|
|
{
|
|
PermissionReference permissionReference = permissionModelDao.getPermissionReference(null, permission);
|
|
return permissionReference.toString();
|
|
}
|
|
}
|
|
|
|
private String compressPermission(String permission) {
|
|
int sepIndex;
|
|
if (permission.equals(CMIS_ALL_PERMISSION) || permission.equals(CMIS_READ_PERMISSION)
|
|
|| permission.equals(CMIS_WRITE_PERMISSION) || !permission.startsWith("{")
|
|
|| (sepIndex = permission.lastIndexOf('.')) == -1) {
|
|
return permission;
|
|
}
|
|
return permission.substring(sepIndex + 1);
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see org.alfresco.cmis.CMISAccessControlService#getAclCapability()
|
|
*/
|
|
public CMISAclCapabilityEnum getAclCapability()
|
|
{
|
|
return aclCapabilityEnum;
|
|
}
|
|
|
|
/**
|
|
* Set the acl capability enum.
|
|
*
|
|
* @param aclCapabilityEnum
|
|
*/
|
|
public void setAclCapability(CMISAclCapabilityEnum aclCapabilityEnum)
|
|
{
|
|
this.aclCapabilityEnum = aclCapabilityEnum;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see org.alfresco.cmis.CMISAccessControlService#getSupportedPermissions()
|
|
*/
|
|
public CMISAclSupportedPermissionEnum getSupportedPermissions()
|
|
{
|
|
return this.aclSupportedPermissionEnum;
|
|
}
|
|
|
|
/**
|
|
* Sets the supported permissions.
|
|
*
|
|
* @param aclSupportedPermissionEnum
|
|
* the supported permissions
|
|
*/
|
|
public void setSupportedPermissions(CMISAclSupportedPermissionEnum aclSupportedPermissionEnum)
|
|
{
|
|
this.aclSupportedPermissionEnum = aclSupportedPermissionEnum;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see org.alfresco.cmis.CMISAccessControlService#getAclPropagation()
|
|
*/
|
|
public CMISAclPropagationEnum getAclPropagation()
|
|
{
|
|
return aclPropagationEnum;
|
|
}
|
|
|
|
/**
|
|
* Set the acl propagation enum.
|
|
*
|
|
* @param aclPropagationEnum
|
|
*/
|
|
public void setAclPropagation(CMISAclPropagationEnum aclPropagationEnum)
|
|
{
|
|
this.aclPropagationEnum = aclPropagationEnum;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see org.alfresco.cmis.CMISAccessControlService#getPermissionMappings()
|
|
*/
|
|
public List<? extends CMISPermissionMapping> getPermissionMappings()
|
|
{
|
|
ArrayList<CMISPermissionMappingImpl> mappings = new ArrayList<CMISPermissionMappingImpl>();
|
|
for(CMISAllowedActionEnum e : EnumSet.allOf(CMISAllowedActionEnum.class))
|
|
{
|
|
Map<String, List<String>> enumMappings = e.getPermissionMapping();
|
|
for(String key : enumMappings.keySet())
|
|
{
|
|
List<String> list = enumMappings.get(key);
|
|
CMISPermissionMappingImpl mapping = new CMISPermissionMappingImpl(key, list);
|
|
mappings.add(mapping);
|
|
}
|
|
}
|
|
return mappings;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see org.alfresco.cmis.CMISAccessControlService#getRepositoryPermissions()
|
|
*/
|
|
public List<CMISPermissionDefinition> getRepositoryPermissions()
|
|
{
|
|
ArrayList<CMISPermissionDefinition> answer = new ArrayList<CMISPermissionDefinition>();
|
|
PermissionReference allPermission = permissionModelDao.getPermissionReference(null, PermissionService.ALL_PERMISSIONS);
|
|
Set<PermissionReference> all = permissionModelDao.getAllExposedPermissions();
|
|
for (PermissionReference pr : all)
|
|
{
|
|
addPermissionDefinition(answer, pr);
|
|
}
|
|
// Add All
|
|
addPermissionDefinition(answer, allPermission);
|
|
// Add CMIS permissions
|
|
answer.add(new CMISPermissionDefinitionImpl(CMIS_ALL_PERMISSION));
|
|
answer.add(new CMISPermissionDefinitionImpl(CMIS_READ_PERMISSION));
|
|
answer.add(new CMISPermissionDefinitionImpl(CMIS_WRITE_PERMISSION));
|
|
return answer;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see org.alfresco.cmis.CMISAccessControlService#getPrincipalAnonymous()
|
|
*/
|
|
public String getPrincipalAnonymous()
|
|
{
|
|
return AuthenticationUtil.getGuestUserName();
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
* @see org.alfresco.cmis.CMISAccessControlService#getPrincipalAnyone()
|
|
*/
|
|
public String getPrincipalAnyone()
|
|
{
|
|
return PermissionService.ALL_AUTHORITIES;
|
|
}
|
|
|
|
private void addPermissionDefinition(ArrayList<CMISPermissionDefinition> list, PermissionReference pr)
|
|
{
|
|
CMISPermissionDefinitionImpl def = new CMISPermissionDefinitionImpl(getPermissionString(pr));
|
|
list.add(def);
|
|
}
|
|
|
|
private String getPermissionString(PermissionReference pr)
|
|
{
|
|
StringBuilder builder = new StringBuilder();
|
|
builder.append(pr.getQName().toString());
|
|
builder.append(".");
|
|
builder.append(pr.getName());
|
|
return builder.toString();
|
|
}
|
|
|
|
public static class AccessPermissionComparator implements Comparator<AccessPermission>
|
|
{
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
|
|
*/
|
|
public int compare(AccessPermission left, AccessPermission right)
|
|
{
|
|
if (left.getPosition() != right.getPosition())
|
|
{
|
|
return right.getPosition() - left.getPosition();
|
|
}
|
|
else
|
|
{
|
|
if (left.getAccessStatus() != right.getAccessStatus())
|
|
{
|
|
return (left.getAccessStatus() == AccessStatus.DENIED) ? -1 : 1;
|
|
}
|
|
else
|
|
{
|
|
int compare = left.getAuthority().compareTo(right.getAuthority());
|
|
if (compare != 0)
|
|
{
|
|
return compare;
|
|
}
|
|
else
|
|
{
|
|
return (left.getPermission().compareTo(right.getPermission()));
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|