/** * 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.Collection; import org.apache.shiro.authz.Permission; /** * Permission class handling the match one case. Shiro permissions always "match all" attributes. * This class extends the CollectionPermission and overrides the implies method to perform the * implies for a "match one" condition. */ public class MatchOneCollectionPermission extends CollectionPermission { public MatchOneCollectionPermission(Collection<Permission> permissions) { super(null, permissions); } /** * Overrides the implies method to handle checking for the existence of one attribute - the * "match one" scenario rather than the "match all" behavior of the overridden classes. * Specifically, this permission will imply another permission if that permission matches at * least one of our permission attributes. * * @param p * the permission to check for behavior/functionality comparison. * @return {@code true} if this current instance <em>implies</em> 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) { // we only care about the key value permission here, because that one can have // multiple values // mapped to a single key. In the case of "match one" we only need one of those // values to satisfy // the permission. if (ourPerm instanceof KeyValuePermission) { for (String value : ((KeyValuePermission) ourPerm).getValues()) { // Since this is "match one" we know that only one of these values needs // to match in order // for the entire permission at that key to be implied // So here we loop through all of the values assigned to that key and // create new // single valued key value permissions KeyValuePermission kvp = new KeyValuePermission(((KeyValuePermission) ourPerm).getKey()); kvp.addValue(value); if (perm.implies(kvp)) { result = true; break; } } // Currently we use key value permissions for everything. However, we still need // to be able to handle // permissions other than KV, so this else block will serve as the catch all for // everything else. } else { // Shiro permissions are always a "match all" condition so we need to flip // the implies to make it match one if (perm.implies(ourPerm)) { result = true; break; } } } if (!result) { return false; } } return true; } // default catch all permission check for (Permission permission : permissionList) { // Shiro permissions are always a "match all" condition so we need to flip the implies // to make it match one if (p.implies(permission)) { return true; } } return false; } }