/* * Copyright (C) 2009 eXo Platform SAS. * * This 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 2.1 of * the License, or (at your option) any later version. * * This software 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 this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.exoplatform.services.jcr.access; import org.exoplatform.services.ext.action.InvocationContext; import org.exoplatform.services.jcr.config.RepositoryEntry; import org.exoplatform.services.jcr.config.SimpleParameterEntry; import org.exoplatform.services.jcr.config.WorkspaceEntry; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.exoplatform.services.security.Identity; import org.exoplatform.services.security.IdentityConstants; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import javax.jcr.RepositoryException; /** * Created by The eXo Platform SAS<br> * * The AccessManager can be queried to determine whether permission is granted * to perform a specific action on a specific item. * * @author Gennady Azarenkov * @version $Id: AccessManager.java 14518 2008-05-20 13:27:19Z ksm $ * @LevelAPI Experimental */ public abstract class AccessManager { protected static final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.AccessManager"); protected final Map<String, String> parameters; private static ThreadLocal<InvocationContext> contextHolder = new ThreadLocal<InvocationContext>(); protected AccessManager(RepositoryEntry config, WorkspaceEntry wsConfig) throws RepositoryException { this.parameters = new HashMap<String, String>(); if (wsConfig != null && wsConfig.getAccessManager() != null) { Collection<SimpleParameterEntry> paramList = wsConfig.getAccessManager().getParameters(); for (SimpleParameterEntry param : paramList) parameters.put(param.getName(), param.getValue()); } } protected final InvocationContext context() { return contextHolder.get(); } public final void setContext(InvocationContext context) { contextHolder.set(context); } /** * Has permission. * * @param acl * access control list * @param permission * permission * @param user * user Identity * @return boolean * @throws RepositoryException */ public final boolean hasPermission(AccessControlList acl, String permission, Identity user) throws RepositoryException { return hasPermission(acl, parseStringPermissions(permission), user); } /** * Has permission. * * @param acl * access control list * @param permission * permissions array * @param user * user Identity * @return boolean */ public boolean hasPermission(AccessControlList acl, String[] permission, Identity user) { String userId = user.getUserId(); if (userId.equals(IdentityConstants.SYSTEM)) { // SYSTEM has permission everywhere return true; } else if (userId.equals(acl.getOwner())) { // Current user is owner of node so has all privileges return true; } else if (userId.equals(IdentityConstants.ANONIM)) { List<String> anyPermissions = acl.getPermissions(IdentityConstants.ANY); if (anyPermissions.size() < permission.length) return false; for (int i = 0; i < permission.length; i++) { if (!anyPermissions.contains(permission[i])) return false; } return true; } else { if (acl.getPermissionsSize() > 0 && permission.length > 0) { // check permission to perform all of the listed actions for (int i = 0; i < permission.length; i++) { // check specific actions if (!isPermissionMatch(acl.getPermissionsList(), permission[i], user)) return false; } return true; } return false; } } private static String[] parseStringPermissions(String str) throws RepositoryException { List<String> permissions = new ArrayList<String>(); int fromIndex = 0; int index; do { index = str.indexOf(',', fromIndex); String token = index == -1 ? str.substring(fromIndex) : str.substring(fromIndex, index); token = token.trim(); fromIndex = index + 1; if (token.isEmpty()) continue; if (PermissionType.READ.equals(token) || PermissionType.ADD_NODE.equals(token) || PermissionType.REMOVE.equals(token) || PermissionType.SET_PROPERTY.equals(token)) { permissions.add(token); } else { throw new RepositoryException("Unknown permission entry " + token); } } while (index != -1); return permissions.toArray(new String[permissions.size()]); } private boolean isPermissionMatch(List<AccessControlEntry> existedPermission, String testPermission, Identity user) { for (int i = 0, length = existedPermission.size(); i < length; i++) { AccessControlEntry ace = existedPermission.get(i); // match action if (ace.getPermission().equals(testPermission)) { // match any if (ace.getIdentity().equals(IdentityConstants.ANY)) return true; else if (ace.getIdentity().indexOf(":") == -1) { // just user if (ace.getIdentity().equals(user.getUserId())) return true; } else if (user.isMemberOf(ace.getMembershipEntry())) { return true; } } } return false; } }