/* * This library is part of OpenCms - * the Open Source Content Management System * * Copyright (c) Alkacon Software GmbH (http://www.alkacon.com) * * This library 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 library 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. * * For further information about Alkacon Software GmbH, please see the * company website: http://www.alkacon.com * * For further information about OpenCms, please see the * project website: http://www.opencms.org * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.opencms.workplace.explorer; import org.opencms.file.CmsGroup; import org.opencms.file.CmsObject; import org.opencms.file.CmsResource; import org.opencms.file.CmsUser; import org.opencms.main.CmsException; import org.opencms.main.CmsLog; import org.opencms.main.OpenCms; import org.opencms.security.CmsAccessControlEntry; import org.opencms.security.CmsAccessControlList; import org.opencms.security.CmsPermissionSet; import org.opencms.security.CmsPermissionSetCustom; import org.opencms.security.CmsRole; import org.opencms.security.I_CmsPrincipal; import org.opencms.util.CmsCollectionsGenericWrapper; import org.opencms.util.CmsUUID; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; /** * Explorer type access object, encapsulates access control entries and lists of a explorer type.<p> * * @since 6.0.0 */ public class CmsExplorerTypeAccess { /** Principal key name for the default permission settings. */ public static final String PRINCIPAL_DEFAULT = "DEFAULT"; /** The log object for this class. */ private static final Log LOG = CmsLog.getLog(CmsExplorerTypeAccess.class); /** The map of configured access control entries. */ private Map<String, String> m_accessControl; /** The acl based on the map of configured access control entries. */ private CmsAccessControlList m_accessControlList; /** Cached permissions based on roles. */ private Map<String, CmsPermissionSetCustom> m_permissionsCache; /** * Constructor, creates an empty, CmsExplorerTypeAccess object.<p> */ public CmsExplorerTypeAccess() { m_accessControl = new HashMap<String, String>(); } /** * Adds a single access entry to the map of access entries of the explorer type setting.<p> * * This stores the configuration data in a map which is used in the initialize process * to create the access control list.<p> * * @param key the principal of the ace * @param value the permissions for the principal */ public void addAccessEntry(String key, String value) { m_accessControl.put(key, value); if (LOG.isDebugEnabled()) { LOG.debug(Messages.get().getBundle().key(Messages.LOG_ADD_ACCESS_ENTRY_2, key, value)); } } /** * Creates the access control list from the temporary map.<p> * * @param resourceType the name of the resource type * * @throws CmsException if something goes wrong */ public void createAccessControlList(String resourceType) throws CmsException { if (OpenCms.getRunLevel() < OpenCms.RUNLEVEL_2_INITIALIZING) { // we don't need this for simple test cases return; } if (m_permissionsCache == null) { Map<String, CmsPermissionSetCustom> lruMap = CmsCollectionsGenericWrapper.createLRUMap(2048); m_permissionsCache = Collections.synchronizedMap(lruMap); OpenCms.getMemoryMonitor().register(this.getClass().getName() + "." + resourceType, lruMap); } else { m_permissionsCache.clear(); } m_accessControlList = new CmsAccessControlList(); Iterator<String> i = m_accessControl.keySet().iterator(); while (i.hasNext()) { String key = i.next(); if (!PRINCIPAL_DEFAULT.equals(key)) { String value = m_accessControl.get(key); // get the principal name from the principal String String principal = key.substring(key.indexOf('.') + 1, key.length()); // create an OpenCms user context with "Guest" permissions CmsObject cms = OpenCms.initCmsObject(OpenCms.getDefaultUsers().getUserGuest()); CmsUUID principalId = null; if (key.startsWith(I_CmsPrincipal.PRINCIPAL_GROUP)) { // read the group principal = OpenCms.getImportExportManager().translateGroup(principal); try { principalId = cms.readGroup(principal).getId(); } catch (CmsException e) { if (LOG.isErrorEnabled()) { LOG.error(e.getLocalizedMessage(), e); } } } else if (key.startsWith(I_CmsPrincipal.PRINCIPAL_USER)) { // read the user principal = OpenCms.getImportExportManager().translateUser(principal); try { principalId = cms.readUser(principal).getId(); } catch (CmsException e) { if (LOG.isErrorEnabled()) { LOG.error(e.getLocalizedMessage(), e); } } } else { // read the role with role name CmsRole role = CmsRole.valueOfRoleName(principal); if (role == null) { // try to read the role in the old fashion with group name role = CmsRole.valueOfGroupName(principal); } principalId = role.getId(); } if (principalId != null) { // create a new entry for the principal CmsAccessControlEntry entry = new CmsAccessControlEntry(null, principalId, value); m_accessControlList.add(entry); } } } } /** * Returns the computed access Control List.<p> * * @return the computed access Control List */ public CmsAccessControlList getAccessControlList() { return m_accessControlList; } /** * Returns the map of access entries of the explorer type setting.<p> * * @return the map of access entries of the explorer type setting */ public Map<String, String> getAccessEntries() { return m_accessControl; } /** * Calculates the permissions for this explorer type settings * for the user in the given OpenCms user context.<p> * * @param cms the OpenCms user context to calculate the permissions for * @param resource the resource to check the permissions for * * @return the permissions for this explorer type settings for the user in the given OpenCms user context */ public CmsPermissionSet getPermissions(CmsObject cms, CmsResource resource) { String cacheKey = getPermissionsCacheKey(cms, resource); CmsPermissionSetCustom permissions; if (cacheKey != null) { permissions = m_permissionsCache.get(cacheKey); if (permissions != null) { return permissions; } } CmsAccessControlList acl = (CmsAccessControlList)m_accessControlList.clone(); CmsUser user = cms.getRequestContext().getCurrentUser(); List<CmsGroup> groups = null; try { groups = cms.getGroupsOfUser(user.getName(), false); } catch (CmsException e) { // error reading the groups of the current user LOG.error(Messages.get().getBundle().key(Messages.LOG_READ_GROUPS_OF_USER_FAILED_1, user.getName()), e); } List<CmsRole> roles = null; try { roles = OpenCms.getRoleManager().getRolesForResource(cms, user.getName(), cms.getSitePath(resource)); } catch (CmsException e) { // error reading the roles of the current user LOG.error(Messages.get().getBundle().key(Messages.LOG_READ_GROUPS_OF_USER_FAILED_1, user.getName()), e); } String defaultPermissions = m_accessControl.get(PRINCIPAL_DEFAULT); // add the default permissions to the acl if ((defaultPermissions != null) && !user.isGuestUser()) { boolean found = false; if (acl.getPermissions(user.getId()) != null) { // acl already contains the user, no need for default found = true; } if (!found && (groups != null)) { // look up all groups to see if we need the default Iterator<CmsGroup> itGroups = groups.iterator(); while (itGroups.hasNext()) { CmsGroup group = itGroups.next(); if (acl.getPermissions(group.getId()) != null) { // acl already contains the group, no need for default found = true; break; } } } if (!found && (roles != null)) { // look up all roles to see if we need the default Iterator<CmsRole> itRoles = roles.iterator(); while (itRoles.hasNext()) { CmsRole role = itRoles.next(); if (acl.getPermissions(role.getId()) != null) { // acl already contains the group, no need for default found = true; break; } } } if (!found) { // add default access control settings for current user CmsAccessControlEntry entry = new CmsAccessControlEntry(null, user.getId(), defaultPermissions); acl.add(entry); } } permissions = acl.getPermissions(user, groups, roles); if (cacheKey != null) { m_permissionsCache.put(cacheKey, permissions); } return permissions; } /** * Tests if there are any access information stored.<p> * * @return true or false */ public boolean isEmpty() { return m_accessControl.isEmpty(); } /** * Returns the cache key for the roles and groups of the current user and the given resource.<p> * * In this way, it does not matter if the resource and/or user permissions changes, so we never need to clean the cache.<p> * * And since the cache is a LRU map, old trash entries will be automatically removed.<p> * * @param cms the current cms context * @param resource the resource * * @return the cache key */ private String getPermissionsCacheKey(CmsObject cms, CmsResource resource) { try { String userName = cms.getRequestContext().getCurrentUser().getName(); StringBuffer key = new StringBuffer(256); key.append(resource.getRootPath()).append("_"); Iterator<?> itGroups = cms.getGroupsOfUser(userName, true).iterator(); while (itGroups.hasNext()) { CmsGroup group = (CmsGroup)itGroups.next(); key.append(group.getName()).append("_"); } Iterator<?> itRoles = OpenCms.getRoleManager().getRolesOfUser(cms, userName, "", true, true, false).iterator(); while (itRoles.hasNext()) { CmsRole role = (CmsRole)itRoles.next(); key.append(role.getGroupName()).append("_"); } return key.toString(); } catch (CmsException e) { return null; } } }