Coverage Report - nu.localhost.tapestry.acegi.components.IfRole
 
Classes in this File Line Coverage Branch Coverage Complexity
IfRole
0%
0/100
0%
0/33
0
 
 1  
 /*
 2  
  * Copyright 2007 Robin Helgelin
 3  
  * Copyright 2008 Jonathan Barker
 4  
  *
 5  
  * Licensed under the Apache License, Version 2.0 (the "License");
 6  
  * you may not use this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  0
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  0
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 package nu.localhost.tapestry.acegi.components;
 19  
 
 20  
 import java.util.Arrays;
 21  
 import java.util.Collection;
 22  
 import java.util.Collections;
 23  
 import java.util.HashSet;
 24  
 import java.util.Iterator;
 25  0
 import java.util.Set;
 26  
 
 27  
 import org.acegisecurity.Authentication;
 28  
 import org.acegisecurity.GrantedAuthority;
 29  0
 import org.acegisecurity.GrantedAuthorityImpl;
 30  0
 import org.acegisecurity.context.SecurityContextHolder;
 31  
 import org.apache.tapestry.Block;
 32  0
 import org.apache.tapestry.annotations.Parameter;
 33  
 import org.springframework.util.StringUtils;
 34  
 
 35  
 /**
 36  
  * Render it's body depending whether the user is in a specific role or not.
 37  0
  * 
 38  
  * @author Jonathan Barker
 39  
  * @author Robin Helgelin
 40  0
  * @author Tapestry Project (doc comments)
 41  
  */
 42  0
 public class IfRole {
 43  0
 
 44  0
     /** 
 45  0
      * If the logged in user matches this role, then the body of the IfRole component is rendered. If false, the body is
 46  
      * omitted.  This is retained for backward compatibility, and corresponds to a single entry in ifAnyGranted
 47  
      */
 48  0
     @Parameter(required = false, defaultPrefix = "literal", principal=true)
 49  0
     private String role;
 50  
 
 51  0
     /**
 52  
      * A comma-separated list of roles is supplied to one or more of the
 53  
      * following parameters. If none are supplied, the default behavior is to
 54  
      * permit access. Behavior should be self-explanatory.
 55  
      */
 56  
     @Parameter(required = false, defaultPrefix = "literal")
 57  
     private String ifAllGranted;
 58  
 
 59  
     @Parameter(required = false, defaultPrefix = "literal")
 60  0
     private String ifAnyGranted;
 61  
 
 62  
     @Parameter(required = false, defaultPrefix = "literal")
 63  
     private String ifNotGranted;
 64  0
 
 65  0
     /**
 66  0
      * Optional parameter to invert the test. If true, then the body is rendered when the test
 67  0
      * parameter is false (not true).
 68  0
      */
 69  
     @Parameter
 70  
     private boolean negate;
 71  
 
 72  
     /**
 73  
      * An alternate {@link Block} to render if the test parameter is false. The default, null, means
 74  
      * render nothing in that situation.
 75  
      */
 76  
     @Parameter(name = "else")
 77  
     private Block elseBlock;
 78  
 
 79  
     private boolean test;
 80  
 
 81  
     @SuppressWarnings("unchecked")
 82  
     private Collection getPrincipalAuthorities() {
 83  0
         Authentication currentUser = null;
 84  0
         currentUser = SecurityContextHolder.getContext().getAuthentication();
 85  
 
 86  0
         if (null == currentUser) {
 87  0
             return Collections.EMPTY_LIST;
 88  
         }
 89  
 
 90  0
         if ((null == currentUser.getAuthorities()) || (currentUser.getAuthorities().length < 1)) {
 91  0
             return Collections.EMPTY_LIST;
 92  
         }
 93  
 
 94  0
         Collection granted = Arrays.asList(currentUser.getAuthorities());
 95  0
         return granted;
 96  
     }
 97  
 
 98  
     @SuppressWarnings("unchecked")
 99  
     private Set authoritiesToRoles(Collection c) {
 100  0
         Set target = new HashSet();
 101  
 
 102  0
         for (Iterator iterator = c.iterator(); iterator.hasNext();) {
 103  0
             GrantedAuthority authority = (GrantedAuthority) iterator.next();
 104  
 
 105  0
             if (null == authority.getAuthority()) {
 106  0
                 throw new IllegalArgumentException(
 107  0
                     "Cannot process GrantedAuthority objects which return null from getAuthority() - attempting to process "
 108  0
                     + authority.toString());
 109  
             }
 110  
 
 111  0
             target.add(authority.getAuthority());
 112  
         }
 113  
 
 114  0
         return target;
 115  
     }
 116  
 
 117  
     @SuppressWarnings("unchecked")
 118  
     private Set parseAuthoritiesString(String authorizationsString) {
 119  0
         final Set requiredAuthorities = new HashSet();
 120  0
         final String[] authorities = StringUtils.commaDelimitedListToStringArray(authorizationsString);
 121  
 
 122  0
         for (int i = 0; i < authorities.length; i++) {
 123  0
             String authority = authorities[i];
 124  
 
 125  
             // Remove the role's whitespace characters without depending on JDK 1.4+
 126  
             // Includes space, tab, new line, carriage return and form feed.
 127  0
             String role = StringUtils.replace(authority, " ", "");
 128  0
             role = StringUtils.replace(role, "\t", "");
 129  0
             role = StringUtils.replace(role, "\r", "");
 130  0
             role = StringUtils.replace(role, "\n", "");
 131  0
             role = StringUtils.replace(role, "\f", "");
 132  
 
 133  0
             requiredAuthorities.add(new GrantedAuthorityImpl(role));
 134  
         }
 135  
 
 136  0
         return requiredAuthorities;
 137  
     }
 138  
 
 139  
     /**
 140  
      * Find the common authorities between the current authentication's {@link
 141  
      * GrantedAuthority} and the ones that have been specified in the tag's
 142  
      * ifAny, ifNot or ifAllGranted attributes.
 143  
      * 
 144  
      * <p>
 145  
      * We need to manually iterate over both collections, because the granted
 146  
      * authorities might not implement {@link Object#equals(Object)} and
 147  
      * {@link Object#hashCode()} in the same way as {@link
 148  
      * GrantedAuthorityImpl}, thereby invalidating {@link
 149  
      * Collection#retainAll(java.util.Collection)} results.
 150  
      * </p>
 151  
      * 
 152  
      * <p>
 153  
      * <strong>CAVEAT</strong>: This method <strong>will not</strong> work if
 154  
      * the granted authorities returns a <code>null</code> string as the
 155  
      * return value of {@link
 156  
      * org.acegisecurity.GrantedAuthority#getAuthority()}.
 157  
      * </p>
 158  
      * 
 159  
      * <p>
 160  
      * Reported by rawdave, on Fri Feb 04, 2005 2:11 pm in the Acegi Security
 161  
      * System for Spring forums.
 162  
      * </p>
 163  
      * 
 164  
      * @param granted
 165  
      *            The authorities granted by the authentication. May be any
 166  
      *            implementation of {@link GrantedAuthority} that does
 167  
      *            <strong>not</strong> return <code>null</code> from {@link
 168  
      *            org.acegisecurity.GrantedAuthority#getAuthority()}.
 169  
      * @param required
 170  
      *            A {@link Set} of {@link GrantedAuthorityImpl}s that have been
 171  
      *            built using ifAny, ifAll or ifNotGranted.
 172  
      * 
 173  
      * @return A set containing only the common authorities between <var>granted</var>
 174  
      *         and <var>required</var>.
 175  
      * 
 176  
      */
 177  
     @SuppressWarnings("unchecked")
 178  
     private Set retainAll(final Collection granted, final Set required) {
 179  0
         Set grantedRoles = authoritiesToRoles(granted);
 180  0
         Set requiredRoles = authoritiesToRoles(required);
 181  0
         grantedRoles.retainAll(requiredRoles);
 182  
 
 183  0
         return rolesToAuthorities(grantedRoles, granted);
 184  
     }
 185  
 
 186  
     /**
 187  
      * @param grantedRoles
 188  
      * @param granted
 189  
      * @return a Set of Authorities corresponding to the roles in the grantedRoles
 190  
      * that are also in the granted Set of Authorities
 191  
      */
 192  
     @SuppressWarnings("unchecked")
 193  
     private Set rolesToAuthorities(Set grantedRoles, Collection granted) {
 194  0
         Set target = new HashSet();
 195  
 
 196  0
         for (Iterator iterator = grantedRoles.iterator(); iterator.hasNext();) {
 197  0
             String role = (String) iterator.next();
 198  
 
 199  0
             for (Iterator grantedIterator = granted.iterator(); grantedIterator.hasNext();) {
 200  0
                 GrantedAuthority authority = (GrantedAuthority) grantedIterator.next();
 201  
 
 202  0
                 if (authority.getAuthority().equals(role)) {
 203  0
                     target.add(authority);
 204  0
                     break;
 205  
                 }
 206  
             }
 207  
         }
 208  
 
 209  0
         return target;
 210  
     }
 211  
 
 212  
     /**
 213  
      * @return false as the default.  Returns true if all non-null role expressions are 
 214  
      * satisfied.  Typically, only one will be used, but if more than one are used, then 
 215  
      * the conditions are effectively AND'd 
 216  
      */
 217  
     @SuppressWarnings("unchecked")
 218  
     private boolean checkPermission() {
 219  0
         if (((null == ifAllGranted) || "".equals(ifAllGranted))
 220  0
          && ((null == ifAnyGranted) || "".equals(ifAnyGranted))
 221  0
          && ((null == role) || "".equals(role))
 222  0
          && ((null == ifNotGranted) || "".equals(ifNotGranted))) {
 223  0
             return false;
 224  0
         }
 225  
 
 226  0
         final Collection granted = getPrincipalAuthorities();
 227  0
 
 228  0
         if ((null != role) && !"".equals(role)) {
 229  0
             Set grantedCopy = retainAll(granted, parseAuthoritiesString(role));
 230  0
             if (grantedCopy.isEmpty()) {
 231  0
                 return false;
 232  0
             }
 233  
         }
 234  
 
 235  0
         if ((null != ifNotGranted) && !"".equals(ifNotGranted)) {
 236  0
             Set grantedCopy = retainAll(granted, parseAuthoritiesString(ifNotGranted));
 237  0
 
 238  0
             if (!grantedCopy.isEmpty()) {
 239  0
                 return false;
 240  0
             }
 241  
         }
 242  
 
 243  0
         if ((null != ifAllGranted) && !"".equals(ifAllGranted)) {
 244  0
             if (!granted.containsAll(parseAuthoritiesString(ifAllGranted))) {
 245  0
                 return false;
 246  0
             }
 247  
         }
 248  
 
 249  0
         if ((null != ifAnyGranted) && !"".equals(ifAnyGranted)) {
 250  0
             Set grantedCopy = retainAll(granted, parseAuthoritiesString(ifAnyGranted));
 251  0
 
 252  0
             if (grantedCopy.isEmpty()) {
 253  0
                 return false;
 254  0
             }
 255  
         }
 256  
 
 257  0
         return true;
 258  0
     }
 259  
 
 260  
 
 261  
     void setupRender() {
 262  0
         test = checkPermission();
 263  0
     }
 264  0
 
 265  
     /**
 266  
      * Returns null if the test method returns true, which allows normal
 267  
      * rendering (of the body). If the test parameter is false, returns the else
 268  
      * parameter (this may also be null).
 269  
      */
 270  
     Object beginRender() {
 271  0
         return test != negate ? null : elseBlock;
 272  0
     }
 273  
 
 274  
     /**
 275  
      * If the test method returns true, then the body is rendered, otherwise not. The component does
 276  
      * not have a template or do any other rendering besides its body.
 277  
      */
 278  
     boolean beforeRenderBody() {
 279  0
         return test != negate;
 280  0
     }
 281  
 }