package com.getperka.flatpack.security; /* * #%L * FlatPack serialization code * %% * Copyright (C) 2012 - 2013 Perka Inc. * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import static com.getperka.flatpack.security.SecurityTarget.Kind.ENTITY; import static com.getperka.flatpack.security.SecurityTarget.Kind.ENTITY_PROPERTY; import static com.getperka.flatpack.security.SecurityTarget.Kind.GLOBAL; import static com.getperka.flatpack.security.SecurityTarget.Kind.PROPERTY; import static com.getperka.flatpack.security.SecurityTarget.Kind.TYPE; import com.getperka.flatpack.HasUuid; import com.getperka.flatpack.ext.Property; /** * A carrier object for the various kinds of things that are the target of {@link SecurityAction}. */ public class SecurityTarget { public enum Kind { /** * A specific entity. */ ENTITY, /** * A property of a specific entity. */ ENTITY_PROPERTY, /** * A non-specific target for any global permissions. */ GLOBAL, /** * A {@link Property}. */ PROPERTY, /** * A {@link HasUuid} type. */ TYPE } private static final SecurityTarget GLOBAL_TARGET = new SecurityTarget(GLOBAL, null, null, null); public static SecurityTarget global() { return GLOBAL_TARGET; } public static SecurityTarget of(Class<? extends HasUuid> entityType) { return new SecurityTarget(TYPE, entityType, null, null); } public static SecurityTarget of(HasUuid entity) { return new SecurityTarget(ENTITY, entity.getClass(), entity, null); } public static SecurityTarget of(HasUuid entity, Property property) { return new SecurityTarget(ENTITY_PROPERTY, entity.getClass(), entity, property); } public static SecurityTarget of(Property property) { return new SecurityTarget(PROPERTY, null, null, property); } private final HasUuid entity; private final Class<? extends HasUuid> entityType; private final int hashCode; private final Kind kind; private final Property property; private SecurityTarget(Kind kind, Class<? extends HasUuid> entityType, HasUuid entity, Property property) { this.entity = entity; this.entityType = entityType; this.kind = kind; this.property = property; hashCode = (entity == null ? 0 : entity.hashCode() * 2) + (entityType == null ? 0 : entityType.hashCode() * 3) + (property == null ? 0 : property.hashCode() * 5); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof SecurityTarget)) { return false; } SecurityTarget other = (SecurityTarget) o; // Instance comparisons intentional return entity == other.entity && entityType == other.entityType && property == other.property; } public HasUuid getEntity() { return entity; } public Class<? extends HasUuid> getEntityType() { return entityType; } public Kind getKind() { return kind; } public Property getProperty() { return property; } @Override public int hashCode() { return hashCode; } /** * Returns {@code true} if {@code o} is described by the current target. */ public boolean matches(Object o) { switch (kind) { case ENTITY: // Object comparison intentional, want to talk about the same object return getEntity() == o; case ENTITY_PROPERTY: case PROPERTY: return getProperty().equals(o); case GLOBAL: // All objects match the global security domain return true; case TYPE: return getEntityType().isInstance(o); default: throw new UnsupportedOperationException(kind.name()); } } @Override public String toString() { String toReturn = kind.name() + " "; switch (kind) { case ENTITY: toReturn += entityType.getName() + " " + entity.getUuid(); break; case ENTITY_PROPERTY: toReturn += entityType.getName() + " " + entity.getUuid() + " " + property.getName(); break; case GLOBAL: break; case PROPERTY: toReturn += property; break; case TYPE: toReturn += entityType.getName(); break; default: toReturn += "Unknown kind"; } return toReturn; } }