/** * Copyright (C) 2011 JTalks.org Team * 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. * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package org.jtalks.poulpe.logic; import org.jtalks.common.model.entity.Branch; import org.jtalks.common.model.entity.Component; import org.jtalks.common.model.entity.Entity; import org.jtalks.common.model.entity.Group; import org.jtalks.common.model.permissions.GeneralPermission; import org.jtalks.common.model.permissions.JtalksPermission; import org.jtalks.common.security.acl.AclManager; import org.jtalks.common.security.acl.AclUtil; import org.jtalks.common.security.acl.GroupAce; import org.jtalks.common.security.acl.builders.AclBuilders; import org.jtalks.common.security.acl.sids.UniversalSid; import org.jtalks.common.security.acl.sids.UserSid; import org.jtalks.poulpe.model.dao.GroupDao; import org.jtalks.poulpe.model.dto.AnonymousGroup; import org.jtalks.poulpe.model.dto.PermissionChanges; import org.jtalks.poulpe.model.dto.GroupsPermissions; import org.springframework.security.acls.model.AccessControlEntry; import org.springframework.security.acls.model.Permission; import org.springframework.security.acls.model.Sid; import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.List; import org.jtalks.common.model.permissions.ProfilePermission; /** * Responsible for allowing, restricting or deleting the permissions of the User Groups to actions. * * @author stanislav bashkirtsev * @author Vyacheslav Zhivaev */ public class PermissionManager { private final AclManager aclManager; private final AclUtil aclUtil; private final GroupDao groupDao; /** * Constructs {@link PermissionManager} with given {@link AclManager} and {@link GroupDao} * * @param aclManager manager instance * @param groupDao group dao instance */ public PermissionManager(@Nonnull AclManager aclManager, @Nonnull GroupDao groupDao, @Nonnull AclUtil aclUtil) { this.aclManager = aclManager; this.groupDao = groupDao; this.aclUtil = aclUtil; } /** * Changes the granted permissions according to the specified changes. * * @param entity the entity to change permissions to * @param changes contains a permission itself, a list of groups to be granted to the permission and the list of * groups to remove their granted privileges * @see org.jtalks.poulpe.model.dto.PermissionChanges#getNewlyAddedGroupsAsArray() * @see org.jtalks.poulpe.model.dto.PermissionChanges#getRemovedGroups() */ public void changeGrants(Entity entity, PermissionChanges changes) { for (Group group : changes.getNewlyAddedGroupsAsArray()) { changeGrantsOfGroup(group, changes.getPermission(), entity, true); } for (Group group : changes.getRemovedGroupsAsArray()) { deleteGrantsOfGroup(group, changes.getPermission(), entity); } } /** * Changes the restricting permissions according to the specified changes. * * @param entity the entity to change permissions to * @param changes contains a permission itself, a list of groups to be restricted from the permission and the list * of groups to remove their restricting privileges * @see org.jtalks.poulpe.model.dto.PermissionChanges#getNewlyAddedGroupsAsArray() * @see org.jtalks.poulpe.model.dto.PermissionChanges#getRemovedGroups() */ public void changeRestrictions(Entity entity, PermissionChanges changes) { for (Group group : changes.getNewlyAddedGroupsAsArray()) { changeGrantsOfGroup(group, changes.getPermission(), entity, false); } for (Group group : changes.getRemovedGroupsAsArray()) { deleteGrantsOfGroup(group, changes.getPermission(), entity); } } /** * Gets {@link org.jtalks.poulpe.model.dto.GroupsPermissions} for provided {@link Component}. * * @param component the component to obtain PermissionsMap for * @return {@link org.jtalks.poulpe.model.dto.GroupsPermissions} for {@link Component} */ public GroupsPermissions<GeneralPermission> getPermissionsMapFor(Component component) { return getPermissionsMapFor(GeneralPermission.getAllAsList(), component); } /** * Gets {@link PermissionsMap} for provided list of {@link Group}'s. * * * @param groups the List {@link Group}'s to obtain PermissionsMap for * @return {@link PermissionsMap} for {@link Group} */ public GroupsPermissions<ProfilePermission> getPermissionsMapFor(List<Group> groups) { GroupsPermissions<ProfilePermission> permissions = new GroupsPermissions<ProfilePermission>(ProfilePermission.getAllAsList()); for (Group group: groups){ GroupsPermissions<ProfilePermission> pmGroup = getPermissionsMapFor(ProfilePermission.getAllAsList(), group); for (ProfilePermission permission:pmGroup.getPermissions()){ for(Group groupInsert : pmGroup.getAllowed(permission)){ permissions.addAllowed(permission,groupInsert); } for(Group groupInsert : pmGroup.getRestricted(permission)){ permissions.addRestricted(permission,groupInsert); } } } return permissions; } /** * Gets {@link org.jtalks.poulpe.model.dto.GroupsPermissions} for provided {@link Entity}. * * @param permissions the list of permissions to get * @param entity the entity to get for * @return {@link org.jtalks.poulpe.model.dto.GroupsPermissions} for provided {@link Entity} */ public <T extends JtalksPermission> GroupsPermissions<T> getPermissionsMapFor(List<T> permissions, Entity entity) { GroupsPermissions<T> groupsPermissions = new GroupsPermissions<T>(permissions); List<GroupAce> groupAces = aclManager.getGroupPermissionsOn(entity); for (T permission : permissions) { for (GroupAce groupAce : groupAces) { if (groupAce.getPermissionMask() == permission.getMask()) { groupsPermissions.add(permission, getGroup(groupAce), groupAce.isGranting()); } } for (AccessControlEntry controlEntry : aclUtil.getAclFor(entity).getEntries()) { if (controlEntry.getPermission().equals(permission) && ((UniversalSid)controlEntry.getSid()).getSidId().equals(UserSid.createAnonymous().getSidId())) { groupsPermissions.add(permission, AnonymousGroup.ANONYMOUS_GROUP, controlEntry.isGranting()); } } } return groupsPermissions; } /** * @param groupAce from which if of group should be extracted * @return {@link Group} extracted from {@link GroupAce} */ private Group getGroup(GroupAce groupAce) { return groupDao.get(groupAce.getGroupId()); } /** * Changes the granted permission for group. If group is AnonymousGroup method changes permissions * for Anonymous Sid. * * @param group user group * @param permission permission * @param entity the entity to change permissions to * @param granted permission is granted or restricted */ private void changeGrantsOfGroup(Group group, JtalksPermission permission, Entity entity, boolean granted) { if (group instanceof AnonymousGroup) { changeGrantsOfAnonymousGroup(permission, entity, granted); } else { AclBuilders builders = new AclBuilders(); if (granted) { builders.newBuilder(aclManager).grant(permission).to(group).on(entity).flush(); } else { builders.newBuilder(aclManager).restrict(permission).to(group).on(entity).flush(); } } } /** * Changes permissions for Anonymous Sid. * * @param permission permission * @param entity the entity to change permissions to * @param granted permission is granted or restricted */ private void changeGrantsOfAnonymousGroup(JtalksPermission permission, Entity entity, boolean granted) { List<Permission> jtalksPermissions = new ArrayList<Permission>(); jtalksPermissions.add(permission); List<Sid> sids = new ArrayList<Sid>(); sids.add(UserSid.createAnonymous()); if (granted) { aclManager.grant(sids, jtalksPermissions, entity); } else { aclManager.restrict(sids, jtalksPermissions, entity); } } /** * Deletes the granted permission for group. If group is AnonymousGroup method deletes permissions * for Anonymous Sid. * * @param group user group * @param permission permission * @param entity the entity to change permissions to */ private void deleteGrantsOfGroup(Group group, JtalksPermission permission, Entity entity) { if (group instanceof AnonymousGroup) { deleteGrantsOfAnonymousGroup(permission, entity); } else { AclBuilders builders = new AclBuilders(); builders.newBuilder(aclManager).delete(permission).from(group).on(entity).flush(); } } /** * Deletes permissions for Anonymous Sid. * * @param permission permission * @param entity the entity to change permissions to */ private void deleteGrantsOfAnonymousGroup(JtalksPermission permission, Entity entity) { List<Permission> jtalksPermissions = new ArrayList<Permission>(); jtalksPermissions.add(permission); List<Sid> sids = new ArrayList<Sid>(); sids.add(UserSid.createAnonymous()); aclManager.delete(sids, jtalksPermissions, entity); } }