You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by gp...@apache.org on 2012/02/02 15:12:29 UTC

svn commit: r1239633 - in /myfaces/extensions/cdi/trunk: core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/ core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/security/spi/ core/impl/src/main/java/org/apache/my...

Author: gpetracek
Date: Thu Feb  2 14:12:28 2012
New Revision: 1239633

URL: http://svn.apache.org/viewvc?rev=1239633&view=rev
Log:
EXTCDI-261 EXTCDI-262 @Secured for stereotypes and support of custom meta-data

Modified:
    myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/AccessDecisionVoterContext.java
    myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/Secured.java
    myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/security/spi/EditableAccessDecisionVoterContext.java
    myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/util/SecurityUtils.java
    myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/DefaultAccessDecisionVoterStateContext.java
    myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/DefaultSecurityStrategy.java
    myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/SecurityAwareViewHandler.java
    myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/SecurityViewListener.java

Modified: myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/AccessDecisionVoterContext.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/AccessDecisionVoterContext.java?rev=1239633&r1=1239632&r2=1239633&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/AccessDecisionVoterContext.java (original)
+++ myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/AccessDecisionVoterContext.java Thu Feb  2 14:12:28 2012
@@ -20,6 +20,7 @@ package org.apache.myfaces.extensions.cd
 
 import java.io.Serializable;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Optional context which allows to get the current state as well as the results of the security check.
@@ -38,4 +39,19 @@ public interface AccessDecisionVoterCont
      * @return found violations
      */
     List<SecurityViolation> getViolations();
+
+    /**
+     * Exposes the found meta-data
+     * @return found meta-data
+     */
+    Map<String, Object> getMetaData();
+
+    /**
+     * Exposes meta-data for the given key
+     * @param key meta-data key
+     * @param targetType target type
+     * @param <T> target type
+     * @return meta-data for the given key or null if there is no value for the given key
+     */
+    <T> T getMetaDataFor(String key, Class<T> targetType);
 }

Modified: myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/Secured.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/Secured.java?rev=1239633&r1=1239632&r2=1239633&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/Secured.java (original)
+++ myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/Secured.java Thu Feb  2 14:12:28 2012
@@ -29,12 +29,13 @@ import java.lang.annotation.Documented;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 import static java.lang.annotation.ElementType.TYPE;
 import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
 
 /**
  * Interceptor for securing beans.
  * It's also possible to use it as meta-annotation for type-safe view-configs.
  */
-@Target({TYPE, METHOD})
+@Target({TYPE, METHOD, ANNOTATION_TYPE})
 @Retention(RUNTIME)
 @Documented
 

Modified: myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/security/spi/EditableAccessDecisionVoterContext.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/security/spi/EditableAccessDecisionVoterContext.java?rev=1239633&r1=1239632&r2=1239633&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/security/spi/EditableAccessDecisionVoterContext.java (original)
+++ myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/security/spi/EditableAccessDecisionVoterContext.java Thu Feb  2 14:12:28 2012
@@ -28,6 +28,14 @@ import org.apache.myfaces.extensions.cdi
 public interface EditableAccessDecisionVoterContext extends AccessDecisionVoterContext
 {
     /**
+     * Allows to add custom meta-data. The default security strategy adds custom annotations of the intercepted method
+     * as well as class-level annotations. (Currently inherited annotations aren't supported)
+     * @param key key for the meta-data
+     * @param metaData meta-data which should be added
+     */
+    void addMetaData(String key, Object metaData);
+
+    /**
      * Updates the state of the context
      * @param accessDecisionVoterState current state
      */

Modified: myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/util/SecurityUtils.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/util/SecurityUtils.java?rev=1239633&r1=1239632&r2=1239633&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/util/SecurityUtils.java (original)
+++ myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/util/SecurityUtils.java Thu Feb  2 14:12:28 2012
@@ -50,11 +50,13 @@ public abstract class SecurityUtils
      * Helper for invoking the given {@link AccessDecisionVoter}s
      * @param invocationContext current invocation-context (might be null in case of secured views)
      * @param beanManager current bean-manager
+     * @param voterContext current access-decision-voter-context
      * @param accessDecisionVoters current access-decision-voters
      * @param errorView optional inline error view
      */
     public static void invokeVoters(InvocationContext invocationContext,
                                     BeanManager beanManager,
+                                    AccessDecisionVoterContext voterContext,
                                     List<Class<? extends AccessDecisionVoter>> accessDecisionVoters,
                                     Class<? extends ViewConfig> errorView)
     {
@@ -63,9 +65,6 @@ public abstract class SecurityUtils
             return;
         }
 
-        AccessDecisionVoterContext voterContext =
-                CodiUtils.getContextualReferenceByClass(beanManager, AccessDecisionVoterContext.class, true);
-
         AccessDecisionState voterState = AccessDecisionState.VOTE_IN_PROGRESS;
         try
         {

Modified: myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/DefaultAccessDecisionVoterStateContext.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/DefaultAccessDecisionVoterStateContext.java?rev=1239633&r1=1239632&r2=1239633&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/DefaultAccessDecisionVoterStateContext.java (original)
+++ myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/DefaultAccessDecisionVoterStateContext.java Thu Feb  2 14:12:28 2012
@@ -25,7 +25,9 @@ import org.apache.myfaces.extensions.cdi
 import javax.enterprise.context.RequestScoped;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * {@inheritDoc}
@@ -39,6 +41,8 @@ public class DefaultAccessDecisionVoterS
 
     private List<SecurityViolation> securityViolations;
 
+    private Map<String, Object> metaData = new HashMap<String, Object>();
+
     /**
      * {@inheritDoc}
      */
@@ -62,13 +66,45 @@ public class DefaultAccessDecisionVoterS
     /**
      * {@inheritDoc}
      */
+    public Map<String, Object> getMetaData()
+    {
+        return Collections.unmodifiableMap(this.metaData);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public <T> T getMetaDataFor(String key, Class<T> targetType)
+    {
+        return (T)this.metaData.get(key);
+    }
+
+    public void addMetaData(String key, Object metaData)
+    {
+        //TODO specify nested security calls
+        this.metaData.put(key, metaData);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
     public void setState(AccessDecisionState accessDecisionVoterState)
     {
         if(AccessDecisionState.VOTE_IN_PROGRESS.equals(accessDecisionVoterState))
         {
             this.securityViolations = new ArrayList<SecurityViolation>(); //lazy init
         }
+
         this.state = accessDecisionVoterState;
+
+        if(AccessDecisionState.INITIAL.equals(accessDecisionVoterState) ||
+                AccessDecisionState.VOTE_IN_PROGRESS.equals(accessDecisionVoterState))
+        {
+            return;
+        }
+
+        //meta-data is only needed until the end of a voting process
+        this.metaData.clear();
     }
 
     /**

Modified: myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/DefaultSecurityStrategy.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/DefaultSecurityStrategy.java?rev=1239633&r1=1239632&r2=1239633&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/DefaultSecurityStrategy.java (original)
+++ myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/DefaultSecurityStrategy.java Thu Feb  2 14:12:28 2012
@@ -18,6 +18,9 @@
  */
 package org.apache.myfaces.extensions.cdi.jsf.impl.security;
 
+import org.apache.myfaces.extensions.cdi.core.api.security.AccessDecisionVoterContext;
+import org.apache.myfaces.extensions.cdi.core.impl.security.spi.EditableAccessDecisionVoterContext;
+import org.apache.myfaces.extensions.cdi.core.impl.util.CodiUtils;
 import org.apache.myfaces.extensions.cdi.jsf.impl.security.spi.SecurityStrategy;
 import org.apache.myfaces.extensions.cdi.core.api.security.Secured;
 import org.apache.myfaces.extensions.cdi.core.api.security.AccessDecisionVoter;
@@ -27,8 +30,11 @@ import javax.inject.Inject;
 import javax.enterprise.inject.spi.BeanManager;
 import javax.enterprise.context.Dependent;
 import javax.interceptor.InvocationContext;
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.lang.reflect.Method;
+import java.util.List;
 
 /**
  * {@inheritDoc}
@@ -47,29 +53,66 @@ public class DefaultSecurityStrategy imp
      */
     public Object execute(InvocationContext invocationContext) throws Exception
     {
-        Secured secured = getSecuredAnnotation(invocationContext);
+        AccessDecisionVoterContext voterContext =
+                CodiUtils.getContextualReferenceByClass(beanManager, AccessDecisionVoterContext.class, true);
 
-        Class<? extends AccessDecisionVoter>[] voterClasses = secured.value();
+        Secured secured = null;
 
-        invokeVoters(invocationContext, this.beanManager, Arrays.asList(voterClasses), secured.errorView());
+        List<Annotation> annotatedTypeMetadata = extractMetadata(invocationContext);
+
+        for (Annotation annotation : annotatedTypeMetadata)
+        {
+            if(Secured.class.isAssignableFrom(annotation.annotationType()))
+            {
+                secured = (Secured)annotation;
+            }
+            else if(voterContext instanceof EditableAccessDecisionVoterContext)
+            {
+                ((EditableAccessDecisionVoterContext)voterContext)
+                        .addMetaData(annotation.annotationType().getName(), annotation);
+            }
+        }
+
+        if(secured != null)
+        {
+            Class<? extends AccessDecisionVoter>[] voterClasses = secured.value();
+
+            invokeVoters(invocationContext, this.beanManager, voterContext,
+                    Arrays.asList(voterClasses), secured.errorView());
+        }
 
         return invocationContext.proceed();
     }
 
-    //TODO refactor it to a generic impl. and move it to an util class
-    private Secured getSecuredAnnotation(InvocationContext invocationContext)
+    private List<Annotation> extractMetadata(InvocationContext invocationContext)
     {
-        Secured secured;
+        List<Annotation> result = new ArrayList<Annotation>();
+
         Method method = invocationContext.getMethod();
 
-        if(method.isAnnotationPresent(Secured.class))
-        {
-            secured = method.getAnnotation(Secured.class);
-        }
-        else
+        result.addAll(getAllAnnotations(method.getAnnotations()));
+        result.addAll(getAllAnnotations(method.getDeclaringClass().getAnnotations()));
+
+        return result;
+    }
+
+    private List<Annotation> getAllAnnotations(Annotation[] annotations)
+    {
+        List<Annotation> result = new ArrayList<Annotation>();
+
+        String annotationName;
+        for(Annotation annotation : annotations)
         {
-            secured = method.getDeclaringClass().getAnnotation(Secured.class);
+            annotationName = annotation.annotationType().getName();
+            if(annotationName.startsWith("java.") || annotationName.startsWith("javax."))
+            {
+                continue;
+            }
+
+            result.add(annotation);
+            result.addAll(getAllAnnotations(annotation.annotationType().getAnnotations()));
         }
-        return secured;
+
+        return result;
     }
 }

Modified: myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/SecurityAwareViewHandler.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/SecurityAwareViewHandler.java?rev=1239633&r1=1239632&r2=1239633&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/SecurityAwareViewHandler.java (original)
+++ myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/SecurityAwareViewHandler.java Thu Feb  2 14:12:28 2012
@@ -21,8 +21,10 @@ package org.apache.myfaces.extensions.cd
 import org.apache.myfaces.extensions.cdi.core.api.activation.Deactivatable;
 import org.apache.myfaces.extensions.cdi.core.api.config.view.ViewConfig;
 import org.apache.myfaces.extensions.cdi.core.api.provider.BeanManagerProvider;
+import org.apache.myfaces.extensions.cdi.core.api.security.AccessDecisionVoterContext;
 import org.apache.myfaces.extensions.cdi.core.api.security.AccessDeniedException;
 import org.apache.myfaces.extensions.cdi.core.impl.util.ClassDeactivation;
+import org.apache.myfaces.extensions.cdi.core.impl.util.CodiUtils;
 import org.apache.myfaces.extensions.cdi.jsf.api.config.view.ViewConfigDescriptor;
 import org.apache.myfaces.extensions.cdi.jsf.impl.config.view.ViewConfigCache;
 import org.apache.myfaces.extensions.cdi.jsf.impl.config.view.spi.EditableViewConfigDescriptor;
@@ -92,6 +94,9 @@ public class SecurityAwareViewHandler ex
             {
                 lazyInit();
 
+                AccessDecisionVoterContext voterContext =
+                        CodiUtils.getContextualReferenceByClass(beanManager, AccessDecisionVoterContext.class, true);
+
                 Class<? extends ViewConfig> errorView = null;
 
                 if(entry instanceof EditableViewConfigDescriptor)
@@ -99,7 +104,7 @@ public class SecurityAwareViewHandler ex
                     errorView = ((EditableViewConfigDescriptor)entry).getErrorView();
                 }
 
-                invokeVoters(null /*TODO*/, this.beanManager, entry.getAccessDecisionVoters(), errorView);
+                invokeVoters(null /*TODO*/, this.beanManager, voterContext, entry.getAccessDecisionVoters(), errorView);
             }
         }
         catch (AccessDeniedException accessDeniedException)

Modified: myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/SecurityViewListener.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/SecurityViewListener.java?rev=1239633&r1=1239632&r2=1239633&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/SecurityViewListener.java (original)
+++ myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/security/SecurityViewListener.java Thu Feb  2 14:12:28 2012
@@ -19,6 +19,8 @@
 package org.apache.myfaces.extensions.cdi.jsf.impl.security;
 
 import org.apache.myfaces.extensions.cdi.core.api.config.view.ViewConfig;
+import org.apache.myfaces.extensions.cdi.core.api.security.AccessDecisionVoterContext;
+import org.apache.myfaces.extensions.cdi.core.impl.util.CodiUtils;
 import org.apache.myfaces.extensions.cdi.jsf.api.listener.phase.AfterPhase;
 import org.apache.myfaces.extensions.cdi.jsf.api.listener.phase.BeforePhase;
 import static org.apache.myfaces.extensions.cdi.jsf.api.listener.phase.JsfPhaseId.*;
@@ -102,11 +104,14 @@ public class SecurityViewListener
         {
             Class<? extends ViewConfig> errorView = null;
 
+            AccessDecisionVoterContext voterContext =
+                    CodiUtils.getContextualReferenceByClass(beanManager, AccessDecisionVoterContext.class, true);
+
             if(entry instanceof EditableViewConfigDescriptor)
             {
                 errorView = ((EditableViewConfigDescriptor)entry).getErrorView();
             }
-            invokeVoters(null, beanManager, entry.getAccessDecisionVoters(), errorView);
+            invokeVoters(null, beanManager, voterContext, entry.getAccessDecisionVoters(), errorView);
         }
         catch (AccessDeniedException accessDeniedException)
         {