/*
This file is part of Cyclos (www.cyclos.org).
A project of the Social Trade Organisation (www.socialtrade.org).
Cyclos is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Cyclos 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Cyclos; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package nl.strohalm.cyclos.services.permissions;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import nl.strohalm.cyclos.access.AdminAdminPermission;
import nl.strohalm.cyclos.access.MemberPermission;
import nl.strohalm.cyclos.access.Module;
import nl.strohalm.cyclos.access.ModuleType;
import nl.strohalm.cyclos.access.OperatorPermission;
import nl.strohalm.cyclos.access.Permission;
import nl.strohalm.cyclos.access.PermissionCheck;
import nl.strohalm.cyclos.entities.Entity;
import nl.strohalm.cyclos.entities.groups.AdminGroup;
import nl.strohalm.cyclos.entities.groups.BrokerGroup;
import nl.strohalm.cyclos.entities.groups.Group;
import nl.strohalm.cyclos.entities.groups.GroupQuery;
import nl.strohalm.cyclos.entities.groups.MemberGroup;
import nl.strohalm.cyclos.entities.groups.OperatorGroup;
import nl.strohalm.cyclos.entities.members.Administrator;
import nl.strohalm.cyclos.entities.members.Element;
import nl.strohalm.cyclos.entities.members.Member;
import nl.strohalm.cyclos.entities.members.Operator;
import nl.strohalm.cyclos.exceptions.PermissionDeniedException;
import nl.strohalm.cyclos.services.access.AbstractPermissionCheck;
import nl.strohalm.cyclos.services.fetch.FetchServiceLocal;
import nl.strohalm.cyclos.services.groups.GroupServiceLocal;
import nl.strohalm.cyclos.services.permissions.exceptions.PermissionCatalogInitializationException;
import nl.strohalm.cyclos.utils.DataIteratorHelper;
import nl.strohalm.cyclos.utils.EntityHelper;
import nl.strohalm.cyclos.utils.RelationshipHelper;
import nl.strohalm.cyclos.utils.access.LoggedUser;
import nl.strohalm.cyclos.utils.access.LoggedUser.AccessType;
import nl.strohalm.cyclos.utils.access.PermissionCatalogHandler;
import nl.strohalm.cyclos.utils.access.PermissionHelper;
import nl.strohalm.cyclos.utils.cache.Cache;
import nl.strohalm.cyclos.utils.cache.CacheCallback;
import nl.strohalm.cyclos.utils.cache.CacheManager;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* Implementation class for permission services.
* @author rafael
*/
public class PermissionServiceImpl implements PermissionServiceLocal, ApplicationContextAware {
private static class CacheKey implements Serializable {
private static final long serialVersionUID = -7967894427520131064L;
public static CacheKey fromLoggedUser() {
return fromLoggedUser(null);
}
public static CacheKey fromLoggedUser(final Serializable qualifier) {
AccessType accessType = LoggedUser.getAccessType();
Group group = LoggedUser.hasUser() ? LoggedUser.group() : null;
return new CacheKey(accessType, group, qualifier);
}
private final AccessType accessType;
private final Group group;
private final Serializable qualifier;
public CacheKey(final AccessType accessType, final Group group, final Serializable qualifier) {
this.accessType = accessType;
this.group = group;
this.qualifier = qualifier;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof CacheKey)) {
return false;
}
CacheKey key = (CacheKey) obj;
return accessType == key.accessType && ObjectUtils.equals(group, key.group) && ObjectUtils.equals(qualifier, key.qualifier);
}
@Override
public int hashCode() {
return 13 * (accessType == null ? 1 : accessType.hashCode()) * (group == null ? 1 : group.hashCode() * (qualifier == null ? 1 : qualifier.hashCode()));
}
@Override
public String toString() {
return (accessType == null ? "Guest" : accessType.name()) + (group == null ? "" : "#" + group.getId());
}
}
private static final Log LOG = LogFactory.getLog(PermissionServiceImpl.class);
private static void debug(final Group group, final List<Permission> permissions, final boolean result) {
if (LOG.isDebugEnabled()) {
StringBuilder sb = new StringBuilder("Checked [");
for (int i = 0; i < permissions.size(); i++) {
if (i > 0) {
sb.append(", ");
}
sb.append(permissions.get(i).getValue());
}
sb.append("] for group id=" + group.getId() + " (" + group.getName() + ")");
sb.append(" with result ").append(result);
LOG.debug(sb.toString());
}
}
private static void debug(final String message) {
if (LOG.isDebugEnabled()) {
LOG.debug(message);
}
}
private FetchServiceLocal fetchService;
private GroupServiceLocal groupService;
private CacheManager cacheManager;
private ApplicationContext applicationContext;
@Override
public void checkManages(final Element element) throws PermissionDeniedException {
if (!manages(element)) {
throw new PermissionDeniedException();
}
}
@Override
public void checkManages(final Group group) throws PermissionDeniedException {
if (!manages(group)) {
throw new PermissionDeniedException();
}
}
@Override
public void checkRelatesTo(final Element element) throws PermissionDeniedException {
if (!relatesTo(element)) {
throw new PermissionDeniedException();
}
}
@Override
public void evictCache(Group group) {
// We must invalidate all other caches (for visibility / management) whenever a group changes
getAllVisibleGroupsCache().clear();
getManagedMemberGroupsCache().clear();
getVisibleMemberGroupsCache().clear();
// Evict this group's permission cache
group = fetchService.fetch(group);
Cache cache = getPermissionsCache();
cache.remove(group.getId());
if (group instanceof MemberGroup) {
// When a member group, refresh the cache for all operator groups of members of that group
final MemberGroup memberGroup = (MemberGroup) group;
final List<OperatorGroup> operatorGroups = groupService.iterateOperatorGroups(memberGroup);
try {
for (final OperatorGroup operatorGroup : operatorGroups) {
cache.remove(operatorGroup.getId());
}
} finally {
DataIteratorHelper.close(operatorGroups);
}
}
}
@Override
public Collection<Group> getAllVisibleGroups() {
// Get from cache all visible groups, except for operator groups
CacheKey cacheKey = CacheKey.fromLoggedUser();
Collection<Group> groups = getAllVisibleGroupsCache().get(cacheKey, new CacheCallback() {
@Override
public Object retrieve() {
if (LoggedUser.getAccessType() == null) {
// Guests can only see initial groups
return groupService.getPossibleInitialGroups(null);
}
Collection<Group> result = new ArrayList<Group>();
if (LoggedUser.isSystem() || hasPermission(AdminAdminPermission.ADMINS_REGISTER, AdminAdminPermission.ADMINS_CHANGE_PROFILE)) {
GroupQuery query = new GroupQuery();
query.setNatures(Group.Nature.ADMIN);
result.addAll(groupService.search(query));
}
if (LoggedUser.hasUser()) {
// No matter what, the own group is always visible
result.add(LoggedUser.group());
}
result.addAll(getVisibleMemberGroups());
return result;
}
});
if (hasPermission(MemberPermission.OPERATORS_MANAGE)) {
// As the cache is by logged user's group, and operator groups are per logged member,
// we simply list the operator groups for members which can manage operators
GroupQuery query = new GroupQuery();
query.setNature(Group.Nature.OPERATOR);
query.setMember(LoggedUser.member());
groups.addAll(groupService.search(query));
}
return groups;
}
@Override
public Collection<MemberGroup> getManagedMemberGroups() {
CacheKey cacheKey = CacheKey.fromLoggedUser();
return getManagedMemberGroupsCache().get(cacheKey, new CacheCallback() {
@Override
public Object retrieve() {
if (LoggedUser.isSystemOrUnrestrictedClient() || LoggedUser.isAdministrator()) {
return getVisibleMemberGroups();
} else if (LoggedUser.isBroker()) {
// Make sure the own group, plus the initial groups are present
Set<MemberGroup> groups = new HashSet<MemberGroup>();
groups.addAll(getVisibleMemberGroups());
MemberGroup group = LoggedUser.group();
groups.add(group);
return groups;
} else { // member or operator
return Collections.<MemberGroup> singleton(LoggedUser.member().getMemberGroup());
}
}
});
}
@Override
public PermissionCatalogHandler getPermissionCatalogHandler(final Group group) {
final AutowireCapableBeanFactory factory = applicationContext.getAutowireCapableBeanFactory();
try {
PermissionCatalogHandlerImpl handler = (PermissionCatalogHandlerImpl) factory.createBean(PermissionCatalogHandlerImpl.class, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false);
handler.load(group);
return handler;
} catch (Exception e) {
throw new PermissionCatalogInitializationException(group.getNature(), e.getMessage(), e);
}
}
@Override
public Collection<MemberGroup> getVisibleMemberGroups() {
return getVisibleMemberGroups(true);
}
@Override
public Collection<MemberGroup> getVisibleMemberGroups(final boolean addLoggedMemberGroup) {
CacheKey cacheKey = CacheKey.fromLoggedUser(addLoggedMemberGroup);
return getVisibleMemberGroupsCache().get(cacheKey, new CacheCallback() {
@Override
public Object retrieve() {
if (LoggedUser.getAccessType() == null) {
// Guests can only see initial groups
return groupService.getPossibleInitialGroups(null);
}
// Will show all groups for either
boolean isSystem = LoggedUser.isSystem();
boolean isUnrestrictedClient = LoggedUser.isUnrestrictedClient();
if (isSystem || isUnrestrictedClient) {
// System can view all member / broker groups
GroupQuery query = new GroupQuery();
query.setNatures(Group.Nature.MEMBER, Group.Nature.BROKER);
if (isUnrestrictedClient) {
// For web services, removed groups don't count
query.setStatus(Group.Status.NORMAL);
query.setOnlyActive(true);
}
return groupService.search(query);
}
Group group = LoggedUser.group();
if (group instanceof AdminGroup) {
return fetchService.fetch((AdminGroup) group, AdminGroup.Relationships.MANAGES_GROUPS).getManagesGroups();
} else {
Set<MemberGroup> memberGroups = new HashSet<MemberGroup>();
MemberGroup memberGroup = fetchService.fetch(LoggedUser.member().getMemberGroup(), MemberGroup.Relationships.CAN_VIEW_PROFILE_OF_GROUPS);
if (addLoggedMemberGroup) {
memberGroups.add(memberGroup);
}
memberGroups.addAll(memberGroup.getCanViewProfileOfGroups());
// For brokers, ensure all possible initial groups are visible
if (LoggedUser.isBroker()) {
BrokerGroup brokerGroup = fetchService.fetch(LoggedUser.<BrokerGroup> group(), BrokerGroup.Relationships.POSSIBLE_INITIAL_GROUPS);
memberGroups.addAll(brokerGroup.getPossibleInitialGroups());
}
return memberGroups;
}
}
});
}
@Override
public boolean hasPermission(final Group group, final Module module) {
return ensureGroupPermissions(group).containsKey(module);
}
@Override
public boolean hasPermission(final Group group, final Permission... permissions) {
return hasPermission(group, Arrays.asList(permissions), Collections.<Permission, AbstractPermissionCheck.RequiredValuesBean> emptyMap());
}
@Override
public boolean hasPermission(final Module module) {
if (LoggedUser.isSystem()) {
return true;
} else if (LoggedUser.isUnrestrictedClient()) {
return module.getType() == ModuleType.MEMBER;
} else {
return hasPermission(LoggedUser.group(), module);
}
}
@Override
public boolean hasPermission(final Permission... permissions) {
if (LoggedUser.isSystem()) {
return true;
} else if (LoggedUser.isUnrestrictedClient()) {
if (permissions == null || permissions.length == 0) {
return false;
} else {
// at least one permission must be a member permission
for (Permission p : permissions) {
if (p.getModule().getType() == ModuleType.MEMBER) {
return true;
}
}
return false;
}
} else {
return hasPermission(LoggedUser.group(), permissions);
}
}
@Override
public boolean hasPermissionFor(final Group group, final Permission permission, final Entity... required) {
if (permission.relationship() == null) {
throw new IllegalArgumentException(String.format("Invalid permission: %1$s.%2$s. The permission must has a relationship to allow ensuring entity membership", permission.getClass().getSimpleName(), permission));
}
return hasPermission(group, Collections.singletonList(permission), Collections.singletonMap(permission, new AbstractPermissionCheck.RequiredValuesBean(permission, required)));
}
@Override
public boolean hasPermissionFor(final Permission permission, final Entity... required) {
if (permission.relationship() == null) {
throw new IllegalArgumentException(String.format("Invalid permission: %1$s.%2$s. The permission must has a relationship to allow ensuring entity membership", permission.getClass().getSimpleName(), permission));
}
boolean hasPermission = hasPermission(permission);
if (!hasPermission) {
return false;
} else if (LoggedUser.isSystemOrUnrestrictedClient()) {
return true; // nothing to do with the required in this case
} else {
return checkRequiredValues(LoggedUser.group(), permission, required);
}
}
@Override
public boolean manages(Element element) {
if (element == null) {
throw new NullPointerException();
}
// System access manages all users
if (LoggedUser.isSystem()) {
return true;
}
element = fetchService.fetch(element, Element.Relationships.GROUP);
if (LoggedUser.isUnrestrictedClient()) {
return element instanceof Member && ((Member) element).isActive();
}
// Check the logged user
Element logged = LoggedUser.element();
if (logged.equals(element)) {
// Logged as the user himself
return true;
} else if (logged instanceof Administrator) {
// Logged as admin
AdminGroup group = LoggedUser.group();
if (element instanceof Administrator) {
// For other admins, there is no group restriction - only a permission check
return hasPermission(group, AdminAdminPermission.ADMINS_VIEW);
} else if (element instanceof Member) {
// Administrators can view or manage specific member groups
Collection<MemberGroup> managedGroups = fetchService.fetch(group, AdminGroup.Relationships.MANAGES_GROUPS).getManagesGroups();
return managedGroups.contains(element.getGroup());
}
} else if (logged instanceof Member) {
// Logged as member - may manage other member if is his broker, or can manage his own operators
if (element instanceof Member) {
return logged.equals(((Member) element).getBroker());
} else if (element instanceof Operator) {
return logged.equals(((Operator) element).getMember());
}
} else if (logged instanceof Operator) {
// Logged as operator - only manages his own member
return ((Operator) logged).getMember().equals(element);
}
return false;
}
@Override
public boolean manages(final Group group) {
if (group instanceof AdminGroup) {
return permission().admin(AdminAdminPermission.ADMINS_REGISTER, AdminAdminPermission.ADMINS_CHANGE_PROFILE).hasPermission();
} else if (group instanceof MemberGroup) {
return getManagedMemberGroups().contains(group);
} else if (group instanceof OperatorGroup) {
OperatorGroup operatorGroup = (OperatorGroup) group;
return LoggedUser.isSystem() || (LoggedUser.isMember() && LoggedUser.element().equals(operatorGroup.getMember()));
}
return false;
}
@Override
public PermissionCheck permission() {
if (LoggedUser.isSystemOrUnrestrictedClient()) {
return new AbstractPermissionCheck() {
@Override
protected boolean doHasPermission() {
if (LoggedUser.isSystem()) {
// System have all permissions
return true;
} else { // unrestricted client
// unrestricted clients has only member permissions
return memberPermissions != null;
}
}
};
} else {
// Get the permissions for the logged user's group
return permission(LoggedUser.group());
}
}
@Override
public PermissionCheck permission(final Element element) {
return new AbstractPermissionCheck() {
@Override
public boolean doHasPermission() {
if (element == null) {
throw new NullPointerException("Checking permission over a null element");
}
// There is no need to check permission as system
if (LoggedUser.isSystem()) {
debug("Checking permission as system. Assuming true");
return true;
}
// Check management over the given element
boolean canManage = manages(element);
debug("Checking management over " + element + (LoggedUser.isWebService() ? " (as webservice)" : "") + ". Result is " + canManage);
if (!canManage) {
return false;
} else if (LoggedUser.isUnrestrictedClient()) {
return memberPermissions != null;
} else {
// Get the logged user's group, which is used to check the permissions
Element logged = LoggedUser.element();
Group group = logged.getGroup();
ModuleType onlyOfType = getModuleTypeFilter(logged, element);
List<Permission> permissions = getPermissions(group.getNature(), onlyOfType);
return hasPermissionOrIsEmpty(group, permissions, requiredValuesMap);
}
}
/**
* According to the given logged user and reference element, returns the ModuleType which should be used to filter the permissions to
* check, or null if no filter should be applied
*/
private ModuleType getModuleTypeFilter(final Element logged, final Element element) {
if (logged instanceof Administrator) {
if (element instanceof Administrator) {
return ModuleType.ADMIN_ADMIN;
} else if (element instanceof Member) {
return ModuleType.ADMIN_MEMBER;
}
} else if (logged instanceof Member) {
if (element instanceof Operator) {
return ModuleType.MEMBER;
}
Member toCheck = fetchService.fetch((Member) element, Member.Relationships.BROKER);
if (logged.equals(toCheck.getBroker())) {
return ModuleType.BROKER;
} else {
return ModuleType.MEMBER;
}
}
return null;
}
};
}
@Override
public PermissionCheck permission(final Group group) {
return new AbstractPermissionCheck() {
@Override
public boolean doHasPermission() {
return hasPermissionOrIsEmpty(group, getPermissions(group.getNature(), null), requiredValuesMap);
}
};
}
@Override
public boolean relatesTo(Element element) {
if (manages(element)) {
return true;
} else if (LoggedUser.isUnrestrictedClient()) {
// in case of unrestricted clients the manages and the relatesTo relationships are the same
return false;
}
element = fetchService.fetch(element, Element.Relationships.GROUP);
// When not manages, there are a few other cases where an used can be related to another one...
Element logged = LoggedUser.element();
if (element instanceof Member) {
// A member or his operators are allowed to view other member's by group
Member loggedMember = null;
if (logged instanceof Member) {
loggedMember = (Member) logged;
} else if (logged instanceof Operator) {
loggedMember = ((Operator) logged).getMember();
}
if (loggedMember != null) {
MemberGroup memberGroup = fetchService.fetch(loggedMember, RelationshipHelper.nested(Element.Relationships.GROUP, MemberGroup.Relationships.CAN_VIEW_PROFILE_OF_GROUPS)).getMemberGroup();
return memberGroup.getCanViewProfileOfGroups().contains(element.getGroup());
}
} else if (element instanceof Operator && logged instanceof Operator) {
// Operators of the same member are related
return ((Operator) element).getMember().equals(((Operator) logged).getMember());
}
return false;
}
@Override
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public void setCacheManager(final CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
public void setFetchServiceLocal(final FetchServiceLocal fetchService) {
this.fetchService = fetchService;
}
public void setGroupServiceLocal(final GroupServiceLocal groupService) {
this.groupService = groupService;
}
/**
* Checks if every required entity is an allowed one. If permission is a MemberPermission then it ensure the required entities for the memberGroup
*/
private boolean checkRequiredValues(Group group, final MemberGroup memberGroup, final Permission permission, final Map<Permission, AbstractPermissionCheck.RequiredValuesBean> requiredValues) {
if (requiredValues == null) {
return true;
} else {
AbstractPermissionCheck.RequiredValuesBean required = requiredValues.get(permission);
if (required == null) {
return true;
} else {
if (group.getNature() == Group.Nature.OPERATOR && required.getPermission().getModule().getType() == ModuleType.MEMBER) {
group = memberGroup;
}
return checkRequiredValues(group, required.getPermission(), required.getEntities());
}
}
}
/**
* Checks if every required entity is an allowed one
*/
private boolean checkRequiredValues(Group group, final Permission permission, final Entity[] required) {
if (required == null || required.length == 0) {
return true;
}
group = fetchService.fetch(group, permission.relationship());
Collection<? extends Entity> allowed = PermissionHelper.getAllowedValues(group, permission);
boolean found = true;
for (int i = 0; i < required.length && found; i++) {
found = allowed.contains(required[i]);
}
return found;
}
/**
* Returns the permissions, keyed by module, for the given group
*/
private Map<Module, SortedSet<Permission>> ensureGroupPermissions(final Group group) {
final Long id = group.getId();
return getPermissionsCache().get(id, new CacheCallback() {
@Override
public Object retrieve() {
Map<Module, SortedSet<Permission>> groupPermissions = new HashMap<Module, SortedSet<Permission>>();
Group group = EntityHelper.reference(Group.class, id);
group = fetchService.reload(group, Group.Relationships.PERMISSIONS, RelationshipHelper.nested(OperatorGroup.Relationships.MEMBER, Element.Relationships.GROUP));
boolean isOperatorGroup = group.getNature() == Group.Nature.OPERATOR;
for (final Permission permission : group.getPermissions()) {
SortedSet<Permission> modulePermissions = groupPermissions.get(permission.getModule());
if (modulePermissions == null) {
modulePermissions = new TreeSet<Permission>();
groupPermissions.put(permission.getModule(), modulePermissions);
}
boolean addPermission = true;
if (isOperatorGroup) {
if (!ModuleType.getModuleTypes(group.getNature()).contains(permission.getModule().getType())) {
throw new IllegalStateException("Invalid permission for operator group: " + permission);
} else {
final MemberGroup memberGroup = ((OperatorGroup) group).getMember().getMemberGroup();
if (hasPermission(memberGroup, MemberPermission.OPERATORS_MANAGE)) { // if the member doesn't have the manage permission
// then his operators can't operate!
if (permission instanceof OperatorPermission) {
for (Permission memberPermission : ((OperatorPermission) permission).getParentPermissions()) {
addPermission = hasPermission(memberGroup, memberPermission);
if (addPermission) { // if the member has one of them then the operator too
break;
}
}
}
} else {
addPermission = false;
}
}
}
if (addPermission) {
modulePermissions.add(permission);
}
}
return groupPermissions;
}
});
}
private Cache getAllVisibleGroupsCache() {
return cacheManager.getCache("cyclos.AllVisibleGroups");
}
private Cache getManagedMemberGroupsCache() {
return cacheManager.getCache("cyclos.ManagedMemberGroups");
}
private Cache getPermissionsCache() {
return cacheManager.getCache("cyclos.Permissions");
}
private Cache getVisibleMemberGroupsCache() {
return cacheManager.getCache("cyclos.VisibleMemberGroups");
}
private boolean hasPermission(final Group group, final List<Permission> permissions, final Map<Permission, AbstractPermissionCheck.RequiredValuesBean> requiredValues) {
boolean result = false;
Group groupToCheck;
if (permissions != null) {
MemberGroup memberGroup = null;
if (group.getNature() == Group.Nature.OPERATOR) {
// fetch the operator's owner member group outside the loop
final OperatorGroup operatorGroup = fetchService.fetch((OperatorGroup) group, RelationshipHelper.nested(OperatorGroup.Relationships.MEMBER, Element.Relationships.GROUP));
memberGroup = operatorGroup.getMember().getMemberGroup();
}
for (Permission permission : permissions) {
groupToCheck = group;
// When an operator is logged in and the module is member, test the operator's member's permissions
if (group.getNature() == Group.Nature.OPERATOR && permission.getModule().getType() == ModuleType.MEMBER) {
groupToCheck = memberGroup;
}
// Get the permissions from the cache
Map<Module, SortedSet<Permission>> groupPermissions = ensureGroupPermissions(groupToCheck);
SortedSet<Permission> permissionsSet = groupPermissions.get(permission.getModule());
if (permissionsSet != null && permissionsSet.contains(permission)) {
// at this point the group has the permission, now we must ensure the permission was granted to the required entities (if any)
result = checkRequiredValues(groupToCheck, memberGroup, permission, requiredValues);
if (result) {
break;
}
}
}
}
return result;
}
/**
* Like {@link #hasPermission(Permission...)}, but returns true if permissions is not null and empty. It stills returns false if permissions is
* null, as the semantics is that there is no possible permissions, while if empty is like no permission check is needed
*/
private boolean hasPermissionOrIsEmpty(final Group group, final List<Permission> permissions, final Map<Permission, AbstractPermissionCheck.RequiredValuesBean> requiredValues) {
if (permissions == null) {
return false;
} else if (permissions.isEmpty()) {
debug("Passing with empty permissions on group id=" + group.getId() + " (" + group.getName() + ")");
return true;
} else {
boolean result = hasPermission(group, permissions, requiredValues);
debug(group, permissions, result);
return result;
}
}
}