All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bazaarvoice.emodb.auth.permissions.MatchingPermission Maven / Gradle / Ivy

There is a newer version: 6.5.190
Show newest version
package com.bazaarvoice.emodb.auth.permissions;

import com.bazaarvoice.emodb.auth.permissions.matching.AnyPart;
import com.bazaarvoice.emodb.auth.permissions.matching.ConstantPart;
import com.bazaarvoice.emodb.auth.permissions.matching.MatchingPart;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.permission.InvalidPermissionStringException;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;

import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;

/**
 * Similar to {@link org.apache.shiro.authz.permission.WildcardPermission} with the following differences:
 * 
    *
  1. Parts are separated by "|" instead of ":", since ":" occurs commonly in emo table names
  2. *
  3. Provides basic wildcard support, although the implementation is extensible to provide further wildcard capabilities.
  4. *
  5. Provides methods for escaping separators and wildcards.
  6. *
*/ public class MatchingPermission implements Permission, Serializable { private final static String SEPARATOR = "|"; private final static String UNESCAPED_SEPARATOR_REGEX = "\\|"; private final static String SEPARATOR_ESCAPE = "\\\\|"; private final static String ESCAPED_SEPARATOR_REGEX = "\\\\\\|"; private final static Pattern SEPARATOR_SPLIT_PATTERN = Pattern.compile("(? _parts; public MatchingPermission(String permission) { this(permission, true); } protected MatchingPermission(String permission, boolean initializePermission) { _permission = requireNonNull(permission, "permission"); if ("".equals(permission.trim())) { throw new InvalidPermissionStringException("Permission must be a non-null, non-empty string", permission); } if (initializePermission) { initializePermission(); } } /** * Parses and initializes the permission's parts. By default this is performed by the constructor. If a subclass * needs to perform its own initialization prior to initializing the permissions then it should call the constructor * with the initialization parameter set to false and then call this method when ready. */ protected void initializePermission() { try { List parts = Lists.newArrayList(); for (String partString : split(_permission)) { partString = partString.trim(); checkArgument(!"".equals(partString), "Permission cannot contain empty parts"); MatchingPart part = toPart(Collections.unmodifiableList(parts), partString); parts.add(part); } _parts = ImmutableList.copyOf(parts); } catch (InvalidPermissionStringException e) { throw e; } catch (Exception e) { // Rethrow any uncaught exception as being caused by an invalid permission string throw new InvalidPermissionStringException(e.getMessage(), _permission); } } public MatchingPermission(String... parts) { this(Joiner.on(SEPARATOR).join(parts)); } private Iterable split(String permission) { // Use the split pattern to avoid splitting on escaped separators. return Arrays.asList(SEPARATOR_SPLIT_PATTERN.split(permission)); } /** * Converts a String part into the corresponding {@link MatchingPart}. */ protected MatchingPart toPart(List leadingParts, String part) { if (ANY_INDICATOR.equals(part)) { return getAnyPart(); } // This part is a constant string return createConstantPart(part); } @Override public boolean implies(Permission p) { if (!(p instanceof MatchingPermission)) { return false; } MatchingPermission other = (MatchingPermission) p; int commonLength = Math.min(_parts.size(), other._parts.size()); for (int i=0; i < commonLength; i++) { if (!_parts.get(i).implies(other._parts.get(i), other._parts.subList(0, i))) { return false; } } // If this had more parts than the other permission then only pass if all remaining parts are wildcards while (commonLength < _parts.size()) { if (!_parts.get(commonLength++).impliesAny()) { return false; } } // It's possible the other also has more parts, but in this case it's narrower than this permission and // hence is still implied by it. return true; } /** * Some permissions fall into one of the following categories: * *
    *
  1. The permission is intended for validation purposes only, such as for creating a table.
  2. *
  3. The permission format is deprecated and no new permissions of the format are allowed.
  4. *
* * This method returns true if the permission should be assignable to a user/role, false otherwise. */ public boolean isAssignable() { for (MatchingPart part : _parts) { if (!part.isAssignable()) { return false; } } return true; } /** * Returns a string escaped so it will be interpreted literally by the matcher. Specifically it converts all * '|' and '*' characters to "\|" and "\*" respectively. */ public static String escape(String raw) { requireNonNull(raw, "raw"); String escaped = raw; escaped = escaped.replaceAll(UNESCAPED_WILDCARD_REGEX, WILDCARD_ESCAPE); escaped = escapeSeparators(escaped); return escaped; } /** * Returns a string with only the separators escaped, unlike {@link #escape(String)} which also protects * wildcards. This is useful for subclasses which have their own formatting that needs to be protected from being split. */ public static String escapeSeparators(String raw) { return raw.replaceAll(UNESCAPED_SEPARATOR_REGEX, SEPARATOR_ESCAPE); } /** * Returns a string with the modifications made by {@link #escapeSeparators(String)} reversed. */ public static String unescapeSeparators(String escaped) { return escaped.replaceAll(ESCAPED_SEPARATOR_REGEX, SEPARATOR); } protected final List getParts() { return _parts; } protected ConstantPart createConstantPart(String value) { return new ConstantPart(value); } protected AnyPart getAnyPart() { return AnyPart.instance(); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } MatchingPermission that = (MatchingPermission) o; return _permission.equals(that._permission); } @Override public int hashCode() { return _permission.hashCode(); } @Override public String toString() { return _permission; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy