/** * 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.jcommune.service.security.acl; import org.jtalks.common.model.dao.GroupDao; import org.jtalks.common.model.entity.Branch; import org.jtalks.common.model.entity.Entity; import org.jtalks.common.model.entity.Group; import org.jtalks.common.model.entity.User; import org.jtalks.common.model.permissions.JtalksPermission; import org.jtalks.jcommune.service.security.acl.sids.UserGroupSid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.acls.domain.ObjectIdentityImpl; import org.springframework.security.acls.model.*; import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.List; /** * Contains coarse-grained operations with Spring ACL to manage the permissions of Groups & Users for the actions on * entities like Branch or Topic. * * @author Kirill Afonin */ public class AclManager { private final Logger logger = LoggerFactory.getLogger(getClass()); private final MutableAclService mutableAclService; private GroupDao groupDao; private AclUtil aclUtil; public AclManager(@Nonnull MutableAclService mutableAclService) { this.mutableAclService = mutableAclService; aclUtil = new AclUtil(mutableAclService); } /** * Gets only group permissions (where sid is {@link UserGroupSid}) and returns them for the specified entity (object * identity). Note, that if there are other records with sids different than {@link UserGroupSid}, they will be * filtered out. * * @param entity an object for which the permissions were given * @return permissions assigned on {@link Group}s without any other permissions. Returns empty collection if there * are no group permissions given on the specified object identity */ public List<GroupAce> getGroupPermissionsOn(@Nonnull Entity entity) { MutableAcl branchAcl = aclUtil.getAclFor(entity); return getGroupPermissions(branchAcl); } /** * Gets only group permissions (where sid is {@link UserGroupSid}) and returns them for the specified entity (object * identity). Note, that if there are other records with sids different than {@link UserGroupSid}, they will be * filtered out. * * @param entity an object identity for which the permissions were given * @return permissions assigned on {@link Group}s without any other permissions. Returns empty collection if there * are no group permissions given on the specified object identity */ public List<GroupAce> getGroupPermissionsOn(@Nonnull ObjectIdentity entity) { MutableAcl branchAcl = aclUtil.getAclFor(entity); return getGroupPermissions(branchAcl); } public List<GroupAce> getGroupPermissionsFilteredByPermissionOn(@Nonnull ObjectIdentity entity, JtalksPermission permission) { MutableAcl branchAcl = aclUtil.getAclFor(entity); return getGroupPermissionsFilteredByPermission(branchAcl, permission); } private List<GroupAce> getGroupPermissions(MutableAcl branchAcl) { List<AccessControlEntry> originalAces = branchAcl.getEntries(); List<GroupAce> resultingAces = new ArrayList<GroupAce>(originalAces.size()); for (AccessControlEntry originalAce : originalAces) { if (originalAce.getSid() instanceof UserGroupSid) { resultingAces.add(new GroupAce(originalAce)); } } return resultingAces; } private List<GroupAce> getGroupPermissionsFilteredByPermission(MutableAcl branchAcl, JtalksPermission permission) { List<AccessControlEntry> originalAces = branchAcl.getEntries(); List<GroupAce> resultingAces = new ArrayList<GroupAce>(originalAces.size()); int permissionMask = permission.getMask(); for (AccessControlEntry originalAce : originalAces) { if (originalAce.getSid() instanceof UserGroupSid && originalAce.getPermission().getMask() == permissionMask) { resultingAces.add(new GroupAce(originalAce)); } } return resultingAces; } /** * @deprecated use {@link #getGroupPermissionsOn} */ @Deprecated() public List<GroupAce> getBranchPermissions(Branch branch) { MutableAcl branchAcl = aclUtil.getAclFor(branch); List<AccessControlEntry> originalAces = branchAcl.getEntries(); List<GroupAce> resultingAces = new ArrayList<GroupAce>(originalAces.size()); for (AccessControlEntry entry : originalAces) { resultingAces.add(new GroupAce(entry)); } return resultingAces; } /** * TODO: NOT FINISHED! TO BE IMPLEMENTED * * @param user * @param branch * @return */ public List<Permission> getPermissions(User user, Branch branch) { throw new UnsupportedOperationException(); // List<Permission> permissions = new ArrayList<Permission>(); // // List<Group> groups = groupDao.getGroupsOfUser(user); // // MutableAcl branchAcl = aclUtil.getAclFor(branch); // List<AccessControlEntry> originalAces = branchAcl.getEntries(); // // for (AccessControlEntry entry : originalAces) { // GroupAce groupAce = new GroupAce(entry); // if (groups.contains(groupAce.getGroup(groupDao))) { // permissions.add(groupAce.getBranchPermission()); // } // } // // return permissions; } /** * Grant permissions from list to every sid in list on {@code target} object. * * @param sids list of sids * @param permissions list of permissions * @param target secured object */ public void grant(List<? extends Sid> sids, List<Permission> permissions, Entity target) { MutableAcl acl = aclUtil.grant(sids, permissions, target); mutableAclService.updateAcl(acl); } /** * Revoke permissions from lists for every sid in list on {@code target} entity * * @param sids list of sids * @param permissions list of permissions * @param target secured object */ public void restrict(List<? extends Sid> sids, List<Permission> permissions, Entity target) { MutableAcl acl = aclUtil.restrict(sids, permissions, target); mutableAclService.updateAcl(acl); } /** * Delete permissions from list for every sid in list on {@code target} object. * * @param sids list of sids * @param permissions list of permissions * @param target secured object */ public void delete(List<? extends Sid> sids, List<Permission> permissions, Entity target) { MutableAcl acl = aclUtil.delete(sids, permissions, target); mutableAclService.updateAcl(acl); } /** * Deletes all ACEs defined in the acl_entry table, wired with the presented SID, also wires owner_sid of OID * belongs to SID to another SID, deletes given SID defined in acl_sid. * * @param sid to ACL delete * @param sidHeir will became the owner of ObjectIdentities belongs to sid */ public void deleteSid(Sid sid, Sid sidHeir){ mutableAclService.deleteEntriesForSid(sid, sidHeir); } /** * Delete object from acl. All permissions will be removed. * * @param clazz object {@code Class} * @param id object id */ public void deleteFromAcl(Class clazz, long id) { if (id <= 0) { throw new IllegalStateException("Object id must be greater then 0."); } ObjectIdentity oid = new ObjectIdentityImpl(clazz, id); mutableAclService.deleteAcl(oid, true); logger.debug("Deleted securedObject" + clazz.getSimpleName() + " with id:" + id); } public void setAclUtil(AclUtil aclUtil) { this.aclUtil = aclUtil; } }