Package org.jtalks.jcommune.service.security

Source Code of org.jtalks.jcommune.service.security.PermissionManager

/**
* 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;


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.BranchPermission;
import org.jtalks.common.model.permissions.GeneralPermission;
import org.jtalks.common.model.permissions.JtalksPermission;
import org.jtalks.common.model.permissions.ProfilePermission;
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.jcommune.model.dao.GroupDao;
import org.jtalks.jcommune.model.dto.GroupsPermissions;
import org.jtalks.jcommune.model.dto.PermissionChanges;
import org.jtalks.jcommune.model.entity.AnonymousGroup;
import org.jtalks.jcommune.plugin.api.PluginPermissionManager;
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.Collections;
import java.util.List;

/**
* 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;
    private final PluginPermissionManager pluginPermissionManager;

    /**
     * Constructs {@link org.jtalks.jcommune.service.security.PermissionManager} with given
     * {@link org.jtalks.common.security.acl.AclManager} and {@link GroupDao}
     *
     * @param aclManager manager instance
     * @param groupDao   group dao instance
     */
    public PermissionManager(@Nonnull AclManager aclManager, @Nonnull GroupDao groupDao,
                             @Nonnull AclUtil aclUtil, @Nonnull PluginPermissionManager pluginPermissionManager) {
        this.aclManager = aclManager;
        this.groupDao = groupDao;
        this.aclUtil = aclUtil;
        this.pluginPermissionManager = pluginPermissionManager;
    }

    /**
     * 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.jcommune.model.dto.PermissionChanges#getNewlyAddedGroupsAsArray()
     * @see org.jtalks.jcommune.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.jcommune.model.dto.PermissionChanges#getNewlyAddedGroupsAsArray()
     * @see org.jtalks.jcommune.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 list of branch permissions for specified branch. Performs search in both of common and plugin permissions
     *
     * @param branch object identity
     * @return {@link org.jtalks.jcommune.model.dto.GroupsPermissions <BranchPermission>} for given branch
     */
    public GroupsPermissions getPermissionsMapFor(Branch branch) {
        List<JtalksPermission> branchPermissions = new ArrayList<>();
        branchPermissions.addAll(BranchPermission.getAllAsList());
        branchPermissions.addAll(pluginPermissionManager.getPluginsBranchPermissions());
        return getPermissionsMapFor(branchPermissions, branch);
    }

    /**
     * Search branch permission by mask. Firstly looks in common permissions then in plugin permissions
     *
     * @param mask interested permission mask
     * @return permission with specified mask if it exist
     *         <b>null</b> otherwise
     */
    public JtalksPermission findBranchPermissionByMask(int mask) {
        JtalksPermission permission = BranchPermission.findByMask(mask);
        if (permission == null) {
            permission = pluginPermissionManager.findPluginsBranchPermissionByMask(mask);
        }
        return permission;
    }

    /**
     * Gets {@link org.jtalks.jcommune.model.dto.GroupsPermissions} for provided {@link org.jtalks.common.model.entity.Component}.
     *
     * @param component the component to obtain PermissionsMap for
     * @return {@link org.jtalks.jcommune.model.dto.GroupsPermissions} for {@link org.jtalks.common.model.entity.Component}
     */
    public GroupsPermissions getPermissionsMapFor(Component component) {
        List<JtalksPermission> generalPermissions = new ArrayList<>();
        generalPermissions.addAll(GeneralPermission.getAllAsList());
        return getPermissionsMapFor(generalPermissions, component);
    }

    /**
     * Gets for provided list of {@link org.jtalks.common.model.entity.Group}'s.
     *
     * @param groups the List {@link org.jtalks.common.model.entity.Group}'s to obtain PermissionsMap for
     * @return for {@link org.jtalks.common.model.entity.Group}
     */
    public GroupsPermissions getPermissionsMapFor(List<Group> groups) {
        List<JtalksPermission> profilePermissions = new ArrayList<>();
        profilePermissions.addAll(ProfilePermission.getAllAsList());

        GroupsPermissions permissions = new GroupsPermissions(profilePermissions);
        for (Group group : groups) {
            GroupsPermissions pmGroup = getPermissionsMapFor(profilePermissions, group);
            for (JtalksPermission 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.jcommune.model.dto.GroupsPermissions} for provided {@link org.jtalks.common.model.entity.Entity}.
     *
     * @param permissions the list of permissions to get
     * @param entity      the entity to get for
     * @return {@link org.jtalks.jcommune.model.dto.GroupsPermissions} for provided {@link org.jtalks.common.model.entity.Entity}
     */
    public GroupsPermissions getPermissionsMapFor(List<JtalksPermission> permissions, Entity entity) {
        GroupsPermissions groupsPermissions = new GroupsPermissions(permissions);
        List<GroupAce> groupAces = aclManager.getGroupPermissionsOn(entity);
        for (JtalksPermission 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;
    }

    /**
     * Gets the list of the all group existing in the System except the group in specified group list.
     * Note: we have Anonymous group which not stored in database and available only for VIEW_TOPICS permission.
     * @param excludedGroupsList groups which should be excluded from the result
     * @return the list of the all group existing in the System except the group in specified group list
     * @see org.jtalks.jcommune.model.entity.AnonymousGroup
     */
    public List<Group> getAllGroupsWithoutExcluded(List<Group> excludedGroupsList, JtalksPermission permission) {
        List<Group> allGroups = groupDao.getAll();
        allGroups.removeAll(excludedGroupsList);
        if (permission.equals(BranchPermission.VIEW_TOPICS) && !excludedGroupsList.contains(AnonymousGroup.ANONYMOUS_GROUP)) {
            allGroups.add(AnonymousGroup.ANONYMOUS_GROUP);
        }
        return allGroups;
    }

    /**
     * Gets the list of groups which IDs specified in parameter. If list of IDs contains 0L value result should
     * contain instance of AnonymousGroup
     * @param groupIds the list of IDs for which groups should be found
     * @return the list of found groups or empty list if list of IDs is empty
     * @see org.jtalks.jcommune.model.entity.AnonymousGroup
     */
    public List<Group> getGroupsByIds(List<Long> groupIds) {
        if (groupIds.isEmpty()) {
            return Collections.emptyList();
        } else {
            List<Group> groups = groupDao.getGroupsByIds(groupIds);
            if (groupIds.contains(0L)) {
                groups.add(AnonymousGroup.ANONYMOUS_GROUP);
            }
            return groups;
        }
    }

    /**
     * @param groupAce from which if of group should be extracted
     * @return {@link org.jtalks.common.model.entity.Group} extracted from {@link org.jtalks.common.security.acl.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<>();
        jtalksPermissions.add(permission);
        List<Sid> sids = new ArrayList<>();
        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<>();
        jtalksPermissions.add(permission);
        List<Sid> sids = new ArrayList<>();
        sids.add(UserSid.createAnonymous());
        aclManager.delete(sids, jtalksPermissions, entity);
    }
}
TOP

Related Classes of org.jtalks.jcommune.service.security.PermissionManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.