diff --git a/ccm-core/src/main/java/org/libreccm/security/AuthorizationInterceptor.java b/ccm-core/src/main/java/org/libreccm/security/AuthorizationInterceptor.java
index 9d80d2655..8a553e6d1 100644
--- a/ccm-core/src/main/java/org/libreccm/security/AuthorizationInterceptor.java
+++ b/ccm-core/src/main/java/org/libreccm/security/AuthorizationInterceptor.java
@@ -31,9 +31,11 @@ import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
-import org.libreccm.security.PermissionChecker;
-
/**
+ * A CDI interceptor which can be used to secure methods of CDI beans. To use
+ * the interceptor annotation the method to secure with
+ * {@link AuthorizationRequired} and one or more {@link RequiresRole} and/or
+ * {@link RequiresPrivilege} annotations.
*
* @author Jens Pelzetter
*/
@@ -41,37 +43,68 @@ import org.libreccm.security.PermissionChecker;
@Interceptor
public class AuthorizationInterceptor {
+ /**
+ * A logger for providing some informations what the interceptor is doing.
+ */
private static final Logger LOGGER = LogManager.getLogger(
AuthorizationInterceptor.class);
+ /**
+ * The current subject
+ */
@Inject
private Subject subject;
+ /**
+ * An instance of the {@link PermissionChecker} bean. The interceptor uses
+ * the methods of the {@code PermissionChecker} class to check if the
+ * current subject has the required roles and permissions.
+ */
@Inject
private PermissionChecker permissionChecker;
+ /**
+ * Called by the CDI container when a method annotated with
+ * {@link AuthorizationRequired} is called.
+ *
+ * @param context The invocation context of the method.
+ *
+ * @return The return value of the called method.
+ *
+ * @throws Exception If any exception occurs.
+ */
@AroundInvoke
public Object intercept(final InvocationContext context) throws Exception {
LOGGER.debug("Intercepting method invocation");
+ //Get the method which call was intercepted.
final Method method = context.getMethod();
if (method == null) {
throw new IllegalArgumentException(
"The authoriziation interceptor can only be used for method");
}
+ // Check if the method has a RequiresRole annotation. If yes, check
+ // if the current subject is assigned to the required role.
if (method.isAnnotationPresent(RequiresRole.class)) {
final String requiredRole = method.getAnnotation(RequiresRole.class)
.value();
subject.checkRoles(requiredRole);
}
+ // Check if the RequiresPrivilege annotation is present on the
+ // method level. If yes check if the current subject has a permission
+ // granting the required privilege.
if (method.isAnnotationPresent(RequiresPrivilege.class)) {
final String requiredPrivilege = method.getAnnotation(
RequiresPrivilege.class).value();
permissionChecker.checkPermission(requiredPrivilege);
}
+ // Check if one or more parameters are annotated with the
+ // RequiredPrivilege annotation. If yes check if the parameter is
+ // of type CcmObject and check if the current subject has a permission
+ // granting the required privilege on the provided CcmObject instance.
final Annotation[][] annotations = method.getParameterAnnotations();
final Object[] parameters = context.getParameters();
if (parameters != null && parameters.length > 0
@@ -84,21 +117,27 @@ public class AuthorizationInterceptor {
return context.proceed();
}
+ /**
+ * Helper method for checking the parameter permissions.
+ *
+ * @param parameter The parameter to check.
+ * @param annotations All annotations of the parameter.
+ */
private void checkParameterPermission(final Object parameter,
final Annotation[] annotations) {
- if (parameter instanceof CcmObject
- && annotations != null
- && annotations.length > 0) {
+ if (parameter instanceof CcmObject
+ && annotations != null
+ && annotations.length > 0) {
final CcmObject object = (CcmObject) parameter;
-
+
String requiredPrivilege = null;
- for(Annotation annotation : annotations) {
+ for (Annotation annotation : annotations) {
if (annotation instanceof RequiresPrivilege) {
requiredPrivilege = ((RequiresPrivilege) annotation).value();
break;
}
}
-
+
if (requiredPrivilege != null && !requiredPrivilege.isEmpty()) {
permissionChecker.checkPermission(requiredPrivilege, object);
}
diff --git a/ccm-core/src/main/java/org/libreccm/security/AuthorizationRequired.java b/ccm-core/src/main/java/org/libreccm/security/AuthorizationRequired.java
index f456accfd..eaa703acf 100644
--- a/ccm-core/src/main/java/org/libreccm/security/AuthorizationRequired.java
+++ b/ccm-core/src/main/java/org/libreccm/security/AuthorizationRequired.java
@@ -27,6 +27,8 @@ import java.lang.annotation.Target;
import javax.interceptor.InterceptorBinding;
/**
+ * Use this annotation to secure a method by the
+ * {@link AuthorizationInterceptor}.
*
* @author Jens Pelzetter
*/
diff --git a/ccm-core/src/main/java/org/libreccm/security/RequiresPrivilege.java b/ccm-core/src/main/java/org/libreccm/security/RequiresPrivilege.java
index 8765b0321..9a048d236 100644
--- a/ccm-core/src/main/java/org/libreccm/security/RequiresPrivilege.java
+++ b/ccm-core/src/main/java/org/libreccm/security/RequiresPrivilege.java
@@ -18,6 +18,8 @@
*/
package org.libreccm.security;
+import org.libreccm.core.CcmObject;
+
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
@@ -25,6 +27,17 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
+ * This annotation is used together with the {@link AuthorizationRequired}
+ * annotation to limit access to methods based on the permissions granted to a
+ * user. The annotation can be used to annotation an method or a parameter of
+ * the type {@link CcmObject}.
+ *
+ * If used on the method level the current subject must have a permission
+ * granting the privilege provided by this annotation to call the method.
+ *
+ * If used on a parameter of type {@link CcmObject} the current subject must
+ * have a permission granting the privilege provided by this annotation for the
+ * particular instance of {@code CcmObject}.
*
* @author Jens Pelzetter
*/
@@ -32,7 +45,7 @@ import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresPrivilege {
-
+
String value();
-
+
}
diff --git a/ccm-core/src/main/java/org/libreccm/security/RequiresRole.java b/ccm-core/src/main/java/org/libreccm/security/RequiresRole.java
index 6030f18f8..4afa4a82f 100644
--- a/ccm-core/src/main/java/org/libreccm/security/RequiresRole.java
+++ b/ccm-core/src/main/java/org/libreccm/security/RequiresRole.java
@@ -25,6 +25,10 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
+ * This annotation is used together with the {@link AuthorizationRequired}
+ * annotation to limit access to methods based on the roles assigned to a user.
+ * To call a method annotation with this annotation the current subject must be
+ * assigned to the role provided by this annotation.
*
* @author Jens Pelzetter
*/
@@ -32,7 +36,7 @@ import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresRole {
-
+
String value();
-
+
}