001    /*
002     * Copyright 2002-2005 the original author or authors.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005     * use this file except in compliance with the License. You may obtain a copy of
006     * the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012     * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013     * License for the specific language governing permissions and limitations under
014     * the License.
015     */
016    package org.springframework.richclient.security.support;
017    
018    import java.util.Arrays;
019    
020    import org.springframework.security.ConfigAttributeDefinition;
021    import org.springframework.security.ConfigAttributeEditor;
022    import org.springframework.security.vote.AffirmativeBased;
023    import org.springframework.security.vote.RoleVoter;
024    
025    /**
026     * This class controls the authorization of other objects, that implement the
027     * {@link org.springframework.richclient.core.Authorizable}, according to the roles held
028     * by the currently authenticated user. If the current user holds one or more of the
029     * configured roles, then the associated objects are authorized. Otherwise, they are not
030     * authorized.
031     * <p>
032     * The roles on which to authorize the controlled objects are specified via the
033     * <code>roles</code> property. It should be a comma-separated list of role names.
034     * <p>
035     * No secured object is used in preparing the ConfigAttributeDefinition. This means that
036     * the configuration is not specific to a given object (no per-object ACL's). The access
037     * decision is made strictly on the roles held by the user.
038     * <p>
039     * The default access decision manager is an {@link AffirmativeBased} instance using a
040     * plain {@link RoleVoter}. You can override this by setting the
041     * <code>accessDecisionManager</code> property.
042     * <p>
043     * Below is an example configuration for this class:
044     * 
045     * <pre>
046     *   &lt;bean id=&quot;adminController&quot;
047     *         class=&quot;org.springframework.richclient.security.support.UserRoleSecurityController&quot;&gt;
048     *       &lt;property name=&quot;authorizingRoles&quot; value=&quot;ROLE_ADMIN&quot; /&gt;
049     *   &lt;/bean&gt;
050     * 
051     *   &lt;bean id=&quot;writeController&quot;
052     *         class=&quot;org.springframework.richclient.security.support.UserRoleSecurityController&quot;&gt;
053     *       &lt;property name=&quot;authorizingRoles&quot; value=&quot;ROLE_WRITE,ROLE_ADMIN&quot; /&gt;
054     *   &lt;/bean&gt;
055     * 
056     * </pre>
057     * 
058     * @author Larry Streepy
059     * 
060     */
061    public class UserRoleSecurityController extends AbstractSecurityController {
062    
063        /** The ConfigAttributeDefinition controlling our authorization decision. */
064        private ConfigAttributeDefinition roles = null;
065    
066        /** Roles as a string. */
067        private String rolesString;
068    
069        /**
070         * Constructor.
071         */
072        public UserRoleSecurityController() {
073            // Install the default decision manager
074            AffirmativeBased adm = new AffirmativeBased();
075            adm.setDecisionVoters( Arrays.asList( new RoleVoter[] { new RoleVoter() } ) );
076            setAccessDecisionManager( adm );
077        }
078    
079        /**
080         * Set the roles to compare against the current user's authenticated roles. The
081         * secured objects will be authorized if the user holds one or more of these roles.
082         * This should be specified as a simple list of comma separated role names.
083         * @param roles
084         */
085        public void setAuthorizingRoles(String roles) {
086            // The ConfigAttributeEditor is named incorrectly, so you can't use it
087            // to automatically convert the string to a ConfigAttributeDefinition.
088            // So, we do it manually :-(
089    
090            ConfigAttributeEditor editor = new ConfigAttributeEditor();
091            editor.setAsText( roles );
092            this.roles = (ConfigAttributeDefinition) editor.getValue();
093            rolesString = roles;
094        }
095    
096        /**
097         * Get the config attributes.
098         * @return config attrributes
099         */
100        public String getAuthorizingRoles() {
101            return rolesString;
102        }
103    
104        /**
105         * Get the secured object on which we are making the authorization decision. We return
106         * null as no specific object is to be considered in the decision.
107         * @return secured object
108         */
109        protected Object getSecuredObject() {
110            return null;
111        }
112    
113        /**
114         * Get the ConfigAttributeDefinition for the secured object. This will provide the
115         * authorization information to the access decision manager.
116         * @param securedObject Secured object for whom the config attribute definition is to
117         *            be retrieved. This may be null.
118         * @return attribute definition for the provided secured object
119         */
120        protected ConfigAttributeDefinition getConfigAttributeDefinition(Object securedObject) {
121            return roles;
122        }
123    
124    }