CCM NG: JavaDoc for the recursive permissions behaviour.

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4541 8810af33-2d31-482b-a856-94f89814c4df

Former-commit-id: 255516772f
pull/2/head
jensp 2017-01-28 14:13:56 +00:00
parent 454a097c5c
commit a1f26f283c
4 changed files with 109 additions and 16 deletions

View File

@ -20,10 +20,11 @@ package org.librecms.contentsection.privileges;
import org.libreccm.categorization.Category; import org.libreccm.categorization.Category;
import org.libreccm.categorization.Domain; import org.libreccm.categorization.Domain;
import org.libreccm.security.Role;
import org.libreccm.web.CcmApplication; import org.libreccm.web.CcmApplication;
import org.libreccm.workflow.WorkflowTemplate; import org.libreccm.workflow.WorkflowTemplate;
import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentSection;
import org.librecms.lifecycle.Lifecycle; import org.librecms.contentsection.ContentType;
import org.librecms.lifecycle.LifecycleDefinition; import org.librecms.lifecycle.LifecycleDefinition;
/** /**

View File

@ -70,11 +70,16 @@ public class PermissionManager {
/** /**
* Grants a privilege on an object to a role. If the privilege was already * Grants a privilege on an object to a role. If the privilege was already
* granted, the method does nothing. * granted, the method does nothing. If the object on which the privilege is
* granted has fields which an annotated with {@link RecursivePermissions}
* the method is also applied to these fields. For more details please refer
* to the description of the {@link RecursivePermissions} annotation.
* *
* @param privilege The privilege to grant. * @param privilege The privilege to grant.
* @param grantee The role to which the privilege is granted. * @param grantee The role to which the privilege is granted.
* @param object The object on which the privilege is granted. * @param object The object on which the privilege is granted.
*
* @see RecursivePermissions
*/ */
@AuthorizationRequired @AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@ -114,6 +119,20 @@ public class PermissionManager {
} }
} }
/**
* Helper method for recursive permissions
*
* @param privilege The privilege to grant.
* @param grantee The role to which the privilege is granted.
* @param object The current object for recursive granting.
* @param clazz The current class analysed for fields annotated with
* {@link RecursivePermissions}. Is the class of
* {@code object} or a superclass of the class of
* {@code object}.
* @param inheritedFrom The object on which
* {@link #grantPrivilege(java.lang.String, org.libreccm.security.Role, org.libreccm.core.CcmObject)}
* was invoked.
*/
private void grantRecursive(final String privilege, private void grantRecursive(final String privilege,
final Role grantee, final Role grantee,
final CcmObject object, final CcmObject object,
@ -133,6 +152,7 @@ public class PermissionManager {
grantRecursive(privilege, grantee, field, object, inheritedFrom); grantRecursive(privilege, grantee, field, object, inheritedFrom);
}); });
// Repeat for superclass of the current class.
if (clazz.getSuperclass() != null) { if (clazz.getSuperclass() != null) {
grantRecursive(privilege, grantRecursive(privilege,
grantee, grantee,
@ -142,14 +162,41 @@ public class PermissionManager {
} }
} }
/**
* Helper method for checking if the
* {@link RecursivePermissions#privileges()} property of an
* {@link RecursivePermissions} annotation is either empty or contains the
* provided {@link privilege}.
*
* @param annotation The annotation to check.
* @param privilege The privilege to check.
*
* @return {code true} if the {@link RecursivePermissions#privileges()}
* property of the provided {@code annotation} if empty or contains
* the provided {@code privilege}, {@code false} otherwise.
*/
private boolean checkIfPrivilegeIsRecursive( private boolean checkIfPrivilegeIsRecursive(
final RecursivePermissions annotation, final RecursivePermissions annotation,
final String privilege) { final String privilege) {
if (annotation.privileges() == null
|| annotation.privileges().length == 0) {
return true;
} else {
return Arrays.stream(annotation.privileges()) return Arrays.stream(annotation.privileges())
.anyMatch(privilege::equals); .anyMatch(privilege::equals);
} }
}
/**
* Helper method for granting a recursive permission.
*
* @param privilege The privilege to grant.
* @param grantee The role to which the privilege is granted.
* @param field The current field.
* @param owner The object which own the provided {@code field}.
* @param inheritedFrom The object from which the permission is inherited.
*/
private void grantRecursive(final String privilege, private void grantRecursive(final String privilege,
final Role grantee, final Role grantee,
final Field field, final Field field,
@ -167,6 +214,8 @@ public class PermissionManager {
} }
if (Collection.class.isAssignableFrom(field.getType())) { if (Collection.class.isAssignableFrom(field.getType())) {
// For a collection field grant a permission on each CCMObject in
// the collection.
final Collection<?> collection = (Collection<?>) value; final Collection<?> collection = (Collection<?>) value;
collection.stream() collection.stream()
.filter(obj -> obj instanceof CcmObject) .filter(obj -> obj instanceof CcmObject)
@ -175,6 +224,10 @@ public class PermissionManager {
grantee, grantee,
obj, obj,
inheritedFrom)); inheritedFrom));
// Relations between two CcmObjects with attributes or n:m relations
// use an object to represent the relation. The object must implement
// the Relation interface. For each Relation object in the collection
// an inherited permission on the related object is created.
collection.stream() collection.stream()
.filter(obj -> obj instanceof Relation) .filter(obj -> obj instanceof Relation)
.map(obj -> (Relation) obj) .map(obj -> (Relation) obj)
@ -185,11 +238,15 @@ public class PermissionManager {
obj, obj,
inheritedFrom)); inheritedFrom));
} else if (CcmObject.class.isAssignableFrom(field.getType())) { } else if (CcmObject.class.isAssignableFrom(field.getType())) {
// If the provided object is a CcmObject create an inherited
// permission for this object.
grantInherited(privilege, grantInherited(privilege,
grantee, grantee,
(CcmObject) value, (CcmObject) value,
inheritedFrom); inheritedFrom);
} else if (Relation.class.isAssignableFrom(field.getType())) { } else if (Relation.class.isAssignableFrom(field.getType())) {
// If the provided field is a Relation object created an inherited
// permission on the related object.
final Relation relation = (Relation) value; final Relation relation = (Relation) value;
if (relation.getRelatedObject() != null) { if (relation.getRelatedObject() != null) {
grantInherited(privilege, grantInherited(privilege,
@ -206,6 +263,14 @@ public class PermissionManager {
} }
} }
/**
* Helper method for creating an inherited permission.
*
* @param privilege The privilege to grant.
* @param grantee The role to which {@code privilege} is granted.
* @param object The object on which the {@code privilege} is granted.
* @param inheritedFrom The object from which the permission is inherited.
*/
private void grantInherited(final String privilege, private void grantInherited(final String privilege,
final Role grantee, final Role grantee,
final CcmObject object, final CcmObject object,

View File

@ -18,17 +18,40 @@
*/ */
package org.libreccm.security; package org.libreccm.security;
import org.libreccm.core.CcmObject;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.util.Collection;
/** /**
* Marker interface which an be added to a property to indicate that permissions * Marker interface which an be added to a property to indicate that permissions
* granted on the owing object should recursivly applied to the child objects. * granted on the owing object should recursivly applied to the child objects.
* *
* The privileges for which this applied can be defined using * The privileges for which this applied can be limited using the
* {@link #privileges()}. * {@link #privileges()} property. If {@link #privileges()} is empty, all
* permissions are applied recursivly. Otherwise only permissions granting one
* of the listed privileges are applied recursivly.
*
* This annotation can only applied to fields of the following types:
* <ul>
* <li>{@link CcmObject}</li>
* <li>{@link Collection}</li>
* <li>{@link Relation}</li>
* </ul>
*
* If applied to a {@link Collection} field the permissions are only recursivly
* applied for members of the types {@link CcmObject} and {@link Relation}.
*
* If an association between two {@link CcmObject}s is modelled using a relation
* object the relation object must implement the {@link Relation} interface to
* apply to permissions recursivly.
*
* @see Relation
* @see PermissionManager#grantPrivilege(java.lang.String,
* org.libreccm.security.Role, org.libreccm.core.CcmObject)}.
* *
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */

View File

@ -18,13 +18,14 @@
*/ */
package org.libreccm.security; package org.libreccm.security;
import org.apache.log4j.Category;
import org.libreccm.categorization.Categorization;
import org.libreccm.core.CcmObject; import org.libreccm.core.CcmObject;
import org.libreccm.security.RecursivePermissions;
/** /**
* If N:M or relation with attributes is annotated with {@link RecursivePermissions} and the * If N:M or relation with attributes is annotated with
* relation object is not a {@link CcmObject} the relation object must * {@link RecursivePermissions} and the relation object is not a
* implement this interface. * {@link CcmObject} the relation object must implement this interface.
* *
* An example are {@link Category#objects} and {@link Categorization}. * An example are {@link Category#objects} and {@link Categorization}.
* *
@ -34,11 +35,14 @@ public interface Relation {
/** /**
* Get the owning object of the relation. * Get the owning object of the relation.
*
* @return * @return
*/ */
CcmObject getOwner(); CcmObject getOwner();
/** /**
* Get the related object of the relation. * Get the related object of the relation.
*
* @return * @return
*/ */
CcmObject getRelatedObject(); CcmObject getRelatedObject();