/* Index ECM Engine - A system for managing the capture (when created * or received), classification (cataloguing), storage, retrieval, * revision, sharing, reuse and disposition of documents. * * Copyright (C) 2008 Regione Piemonte * Copyright (C) 2008 Provincia di Torino * Copyright (C) 2008 Comune di Torino * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package it.doqui.index.ecmengine.business.personalization.security; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; import org.alfresco.model.ContentModel; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.permissions.PermissionReference; import org.alfresco.repo.security.permissions.impl.ModelDAO; import org.alfresco.service.cmr.repository.ChildAssociationRef; 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.AuthorityService; import org.alfresco.service.cmr.security.OwnableService; import org.alfresco.service.cmr.security.PermissionService; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.lucene.index.Term; import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; import org.springframework.beans.factory.InitializingBean; public class ReadersServiceImpl implements ReadersService, InitializingBean { private static Log logger = LogFactory.getLog(ECMENGINE_PERSONALIZATION_READERS); private static PermissionReference readPermission; /** Node service to get parents. */ private NodeService nodeService; /** Permission service to get ACLs. */ private PermissionService permissionService; /** Authority service to read authority relations. */ private AuthorityService authorityService; /** Ownable service to read node owner. */ private OwnableService ownableService; /** Permission model DAO. */ private ModelDAO permissionModelDAO; public void afterPropertiesSet() throws Exception { logger.debug("[ReadersServiceImpl::afterPropertiesSet] BEGIN"); try { readPermission = permissionModelDAO.getPermissionReference( ContentModel.TYPE_BASE, "Read"); } finally { logger.debug("[ReadersServiceImpl::afterPropertiesSet] END"); } } public Set<String> getReaders(NodeRef nodeRef) { logger.debug("[ReadersServiceImpl::getReaders] BEGIN"); try { if (!nodeRef.getStoreRef().getProtocol().equals("workspace") && !nodeRef.getStoreRef().getProtocol().equals("avm")) { logger.debug("[ReadersServiceImpl::getReaders] Ignoring node from store: " + nodeRef.getStoreRef()); return Collections.<String>emptySet(); } Set<String> results = new HashSet<String>(); final Set<AccessPermission> nodeAcl = permissionService.getAllSetPermissions(nodeRef); for (AccessPermission aclEntry: nodeAcl) { // Il primo parametro (QName type) non e` utilizzato in Alfresco 2.1 PermissionReference permGroup = permissionModelDAO.getPermissionReference(null, aclEntry.getPermission()); final String authority = aclEntry.getAuthority(); if (permissionModelDAO.getGranteePermissions(permGroup).contains(readPermission) && authority != null) { results.add(authority); } } /* Se il nodo eredita i permessi dal padre e` necessario risalire l'albero per ottenere * una lista completa dei permessi. */ while (permissionService.getInheritParentPermissions(nodeRef)) { final ChildAssociationRef parentAssocRef = nodeService.getPrimaryParent(nodeRef); final NodeRef parentRef = parentAssocRef.getParentRef(); if (parentRef == null) { // Non possiamo risalire oltre il root node dello store break; } final Set<AccessPermission> parentAcl = permissionService.getAllSetPermissions(parentRef); for (AccessPermission aclEntry: parentAcl) { // Il primo parametro (QName type) non e` utilizzato in Alfresco 2.1 PermissionReference permGroup = permissionModelDAO.getPermissionReference(null, aclEntry.getPermission()); final String authority = aclEntry.getAuthority(); if (permissionModelDAO.getGranteePermissions(permGroup).contains(readPermission) && authority != null) { results.add(authority); } } nodeRef = parentRef; // Risali lungo l'albero } // L'owner puo` sempre leggere final String owner = ownableService.getOwner(nodeRef); if (owner != null) { results.add(owner); } // ATTENZIONE: si suppone che l'amministratore abbia accesso, almeno in lettura, su tutto il repository if (authorityService instanceof AdministrableAuthorityServiceImpl) { Set<String> adminUsers = ((AdministrableAuthorityServiceImpl) authorityService).getAdminUsers(); for (String admin : adminUsers) { results.add(admin); } } if (logger.isDebugEnabled()) { logger.debug("[ReadersServiceImpl::getReaders] Reader authorities: " + results.size()); logger.debug("[ReadersServiceImpl::getReaders] Authorities: " + results); } return results; } finally { logger.debug("[ReadersServiceImpl::getReaders] END"); } } public Set<String> getAuthoritiesForCurrentUser() { logger.debug("[ReadersServiceImpl::getAuthoritiesForCurrentUser] BEGIN"); try { final String currentUser = AuthenticationUtil.getCurrentUserName(); if (currentUser.equals(AuthenticationUtil.getSystemUserName())) { // L'utente system puo` vedere tutto --> predicato vuoto return null; } if (authorityService.hasAdminAuthority()) { return null; } Set<String> authorities = new LinkedHashSet<String>(); if (currentUser.equals(AuthenticationUtil.getGuestUserName())) { // L'utente guest puo` vedere solo cio` che gli e` esplicitamente assegnato via ACL authorities.add(currentUser); return authorities; } authorities.add(currentUser); authorities.add(PermissionService.ALL_AUTHORITIES); authorities.addAll(authorityService.getContainingAuthorities(null, currentUser, false)); logger.debug("[ReadersServiceImpl::getAuthoritiesForCurrentUser] Authorities: " + authorities); return authorities; } finally { logger.debug("[ReadersServiceImpl::getAuthoritiesForCurrentUser] END"); } } public String getLuceneFilterPredicate() { logger.debug("[ReadersServiceImpl::getLuceneFilterPredicate] BEGIN"); try { final String currentUser = AuthenticationUtil.getCurrentUserName(); if (currentUser.equals(AuthenticationUtil.getSystemUserName())) { // L'utente system puo` vedere tutto --> predicato vuoto logger.debug("[ReadersServiceImpl::getLuceneFilterPredicate] System user can see everything!"); return ""; } if (currentUser.equals(AuthenticationUtil.getGuestUserName())) { // L'utente guest puo` vedere solo cio` che gli e` esplicitamente assegnato via ACL logger.debug("[ReadersServiceImpl::getLuceneFilterPredicate] Got predicate for guest user."); return " AND ACL_READER:" + currentUser; } StringBuilder filter = new StringBuilder(); Set<String> authorities = authorityService.getContainingAuthorities(null, currentUser, false); logger.debug("[ReadersServiceImpl::getLuceneFilterPredicate] Building predicate for authorities: " + authorities); filter.append(" AND ("); boolean first = true; for (String authority : authorities) { filter.append((first) ? "" : " OR ").append("ACL_READER:").append(authority); first = false; } filter.append(")"); logger.debug("[ReadersServiceImpl::getLuceneFilterPredicate] Predicate: \"" + filter + "\""); return filter.toString(); } finally { logger.debug("[ReadersServiceImpl::getLuceneFilterPredicate] END"); } } public Query getLuceneFilterQuery() { logger.debug("[ReadersServiceImpl::getLuceneFilterQuery] BEGIN"); try { final String currentUser = AuthenticationUtil.getCurrentUserName(); if (currentUser == null) { /* * Nessun utente autenticato. Probabilmente l'autenticazione e` in corso: non impostiamo alcun filtro * per consentire la corretta ricerca degli utenti. */ logger.debug("[ReadersServiceImpl::getLuceneFilterQuery] Authentication still in progress!"); return null; } if (currentUser.equals(AuthenticationUtil.getSystemUserName())) { // L'utente system puo` vedere tutto --> predicato vuoto logger.debug("[ReadersServiceImpl::getLuceneFilterQuery] System user can see everything!"); return null; } if (currentUser.equals(AuthenticationUtil.getGuestUserName())) { // L'utente guest puo` vedere solo cio` che gli e` esplicitamente assegnato via ACL logger.debug("[ReadersServiceImpl::getLuceneFilterQuery] Got predicate for guest user."); return new TermQuery(new Term("ACL_READER", currentUser)); } BooleanQuery query = new BooleanQuery(); query.add(new TermQuery(new Term("ACL_READER", currentUser)), BooleanClause.Occur.SHOULD); query.add(new TermQuery(new Term("ACL_READER", PermissionService.ALL_AUTHORITIES)), BooleanClause.Occur.SHOULD); Set<String> authorities = authorityService.getContainingAuthorities(null, currentUser, false); logger.debug("[ReadersServiceImpl::getLuceneFilterQuery] Building predicate for authorities: " + authorities); for (String authority : authorities) { query.add(new TermQuery(new Term("ACL_READER", authority)), BooleanClause.Occur.SHOULD); } if (logger.isDebugEnabled()) { logger.debug("[ReadersServiceImpl::getLuceneFilterQuery] Predicate: \"" + query.toString() + "\""); } return query; } finally { logger.debug("[ReadersServiceImpl::getLuceneFilterQuery] END"); } } public void setPermissionService(PermissionService permissionService) { this.permissionService = permissionService; } public void setAuthorityService(AuthorityService authorityService) { this.authorityService = authorityService; } public void setPermissionModelDAO(ModelDAO permissionModelDAO) { this.permissionModelDAO = permissionModelDAO; } public void setNodeService(NodeService nodeService) { this.nodeService = nodeService; } public void setOwnableService(OwnableService ownableService) { this.ownableService = ownableService; } }