/**
* Copyright (c) Codice Foundation
* <p>
* This 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 3 of the
* License, or any later version.
* <p>
* This program 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. A copy of the GNU Lesser General Public License
* is distributed along with this program and can be found at
* <http://www.gnu.org/licenses/lgpl.html>.
*/
package ddf.security.permission;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.apache.shiro.authz.Permission;
/**
* Permission class handling a collection of permissions and handling the logic to determine if one
* collection of permissions can imply another collection of permissions. Assumes the underlying
* permissions can handle instances of differing permission types.
*/
public class CollectionPermission implements Permission {
public static final String CREATE_ACTION = "create";
public static final String READ_ACTION = "read";
public static final String UPDATE_ACTION = "update";
public static final String DELETE_ACTION = "delete";
public static final String UNKNOWN_ACTION = "unknown-action";
protected static final String PERMISSION_START_MSG = "Permission [";
protected static final String PERMISSION_IMPLIES_MSG = "] implies permission [";
protected static final String PERMISSION_NOT_IMPLIES_MSG = "] does not imply permission [";
protected static final String PERMISSION_END_MSG = "].";
protected List<Permission> permissionList = new ArrayList<Permission>();
protected String action;
/**
* Default constructor creating an empty collection of permissions.
*/
public CollectionPermission() {
}
/**
* @param action Action associated with this collection of permissions
*/
public CollectionPermission(String action) {
this.action = action;
}
/**
* Creates a new collection of permissions and adds the provided permissions to the collection.
*
* @param action Action associated with this collection of permissions
* @param permissions permission objects to be added to the newly created collection
*/
public CollectionPermission(String action, Permission... permissions) {
this.action = action;
Collections.addAll(permissionList, permissions);
}
/**
* Creates a new collection of permissions from an existing collection of permissions. All
* permissions in the provided collection are added to the newly created collection.
*
* @param action Action associated with this collection of permissions
* @param permissions existing collection of permission objects
*/
public CollectionPermission(String action, Collection<? extends Permission> permissions) {
this.action = action;
addAll(permissions);
}
/**
* Returns {@code true} if this current instance <em>implies</em> all the functionality and/or
* resource access described by the specified {@code Permission} argument, {@code false}
* otherwise.
* <p>
* <p>
* That is, this current instance must be exactly equal to or a <em>superset</em> of the
* functionalty and/or resource access described by the given {@code Permission} argument. Yet
* another way of saying this would be:
* <p>
* <p>
* If "permission1 implies permission2", i.e.
* <code>permission1.implies(permission2)</code> , then any Subject granted {@code permission1}
* would have ability greater than or equal to that defined by {@code permission2}.
*
* @param p the permission to check for behavior/functionality comparison.
* @return {@code true} if this current instance <em>implies</em> all the functionality and/or
* resource access described by the specified {@code Permission} argument, {@code false}
* otherwise.
*/
@Override
public boolean implies(Permission p) {
if (permissionList.isEmpty()) {
return false;
}
if (p instanceof CollectionPermission) {
for (Permission perm : ((CollectionPermission) p).getPermissionList()) {
boolean result = false;
for (Permission ourPerm : permissionList) {
if (ourPerm.implies(perm)) {
result = true;
break;
}
}
if (!result) {
return false;
}
}
return true;
}
for (Permission permission : permissionList) {
if (permission.implies(p)) {
return true;
}
}
return false;
}
/**
* Returns this collection as an unmodifiable list of permissions.
*
* @return unmodifiable List of permissions corresponding to this collection
*/
public List<Permission> getPermissionList() {
return Collections.unmodifiableList(permissionList);
}
/**
* Returns true if the internal permissions list is empty otherwise returns false
*
* @return
*/
public boolean isEmpty() {
return permissionList.isEmpty();
}
/**
* String representation of this collection of permissions. Depends on the toString method of
* each permission.
*
* @return String representation of this collection of permissions
*/
public String toString() {
StringBuilder sb = new StringBuilder();
for (Permission perm : permissionList) {
sb.append('[');
sb.append(perm.toString());
sb.append("] ");
}
return sb.toString();
}
/**
* Clears out all of the permissions currently in this collection.
*/
public void clear() {
permissionList.clear();
}
/**
* Adds all of the incoming permissions to this collection.
*
* @param permissions The permissions that should be added.
*/
public void addAll(Collection<? extends Permission> permissions) {
permissionList.addAll(permissions);
}
/**
* Returns the action associated with this collection of permissions
*
* @return
*/
public String getAction() {
return action;
}
/**
* Sets the action for this collection of permissions
*
* @param action
*/
public void setAction(String action) {
this.action = action;
}
}