Project

General

Profile

« Previous | Next » 

Revision e24797e9

Added by Andreas Kohlbecker over 11 years ago

all test SUCCESSFUL - (concept of implicitPermission and voters discarded and disabled)

View differences:

cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/hibernate/permission/voter/CdmPermissionVoter.java
9 9
*/
10 10
package eu.etaxonomy.cdm.persistence.hibernate.permission.voter;
11 11

  
12
import java.util.Collection;
13

  
14
import org.apache.log4j.Logger;
12 15
import org.springframework.security.access.AccessDecisionVoter;
13 16
import org.springframework.security.access.ConfigAttribute;
17
import org.springframework.security.core.Authentication;
18
import org.springframework.security.core.GrantedAuthority;
14 19

  
15 20
import eu.etaxonomy.cdm.model.common.CdmBase;
16 21
import eu.etaxonomy.cdm.persistence.hibernate.permission.AuthorityPermission;
22
import eu.etaxonomy.cdm.persistence.hibernate.permission.CdmPermission;
23
import eu.etaxonomy.cdm.persistence.hibernate.permission.CdmPermissionClass;
17 24

  
18 25
/**
19 26
 * The <code>CdmPermissionVoter</code> provides access control votes for {@link CdmBase} objects.
......
24 31
 */
25 32
public abstract class CdmPermissionVoter implements AccessDecisionVoter {
26 33

  
34
    public static final Logger logger = Logger.getLogger(CdmPermissionVoter.class);
27 35

  
28 36
    /* (non-Javadoc)
29 37
     * @see org.springframework.security.access.AccessDecisionVoter#supports(org.springframework.security.access.ConfigAttribute)
......
39 47
     */
40 48
    @Override
41 49
    public boolean supports(Class<?> clazz) {
42
        // all CdmPermissionVoters must support CdmBase.class
50
        /* NOTE!!!
51
         * Do not change this, all CdmPermissionVoters must support CdmBase.class
52
         */
43 53
        return clazz.isInstance(CdmBase.class);
44 54
    }
45 55

  
56

  
57
    /**
58
     * Sets the Cdm type, or super type this Voter is responsible for.
59
     */
60
    abstract public Class<? extends CdmBase> getResponsibilityClass();
61

  
62

  
63
    protected boolean isResponsibleFor(Object securedObject) {
64
        return getResponsibilityClass().isAssignableFrom(securedObject.getClass());
65
    }
66

  
67
    protected boolean isResponsibleFor(CdmPermissionClass permissionClass) {
68
        return getResponsibility().equals(permissionClass);
69
    }
70

  
71
    /**
72
     * Get the according CdmPermissionClass matching {@link #getResponsibilityClass()} the cdm class this voter is responsible for.
73
     * @return
74
     */
75
    protected CdmPermissionClass getResponsibility() {
76
        return CdmPermissionClass.getValueOf(getResponsibilityClass());
77
    }
78

  
79
    /* (non-Javadoc)
80
     * @see org.springframework.security.access.AccessDecisionVoter#vote(org.springframework.security.core.Authentication, java.lang.Object, java.util.Collection)
81
     */
82
    @Override
83
    public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
84

  
85
        if(!isResponsibleFor(object)){
86
            logger.debug("class missmatch => ACCESS_ABSTAIN");
87
            return ACCESS_ABSTAIN;
88
        }
89

  
90
        if (logger.isDebugEnabled()){
91
            logger.debug("authentication: " + authentication.getName() + ", object : " + object.toString() + ", attribute[0]:" + ((AuthorityPermission)attributes.iterator().next()).getAttribute());
92
        }
93

  
94
        // loop over all attributes = permissions of which at least one must match
95
        // usually there is only one element in the collection!
96
        for(ConfigAttribute attribute : attributes){
97
            if(!(attribute instanceof AuthorityPermission)){
98
                throw new RuntimeException("attributes must contain only AuthorityPermission");
99
            }
100
            AuthorityPermission evalPermission = (AuthorityPermission)attribute;
101

  
102
            for (GrantedAuthority authority: authentication.getAuthorities()){
103
                AuthorityPermission authorityPermission= new AuthorityPermission(authority.getAuthority());
104

  
105
                // check if the voter is responsible for the permission to be evaluated
106
                if(!evalPermission.getClassName().equals(getResponsibility())){
107
                    logger.debug("not responsible for " + evalPermission.getClassName() + " -> skipping");
108
                    continue;
109
                }
110

  
111
//                CdmPermissionVoter impliedVoter = findImpliedVoter(authorityPermission.getClassName());
112
//                if(impliedVoter != null){
113
//                    Set<CdmBase> targetObjects = findTargetObjectsForVoter(impliedVoter, (CdmBase) object);
114
//                }
115
                ValidationResult validationResult = new ValidationResult();
116

  
117
                boolean isALL = authorityPermission.getClassName().equals(CdmPermissionClass.ALL);
118
                validationResult.isClassMatch = isALL || authorityPermission.getClassName().equals(evalPermission.getClassName());
119

  
120
                boolean isADMIN = authorityPermission.getPermission().equals(CdmPermission.ADMIN);
121
                validationResult.isPermissionMatch = isADMIN || authorityPermission.getPermission().equals(evalPermission.getPermission());
122

  
123
                validationResult.hasTargetUuid = authorityPermission.getTargetUUID() != null;
124
                validationResult.isUuidMatch = validationResult.hasTargetUuid && authorityPermission.getTargetUUID().equals(((CdmBase)object).getUuid());
125

  
126
                if ( !validationResult.hasTargetUuid && validationResult.isClassMatch && validationResult.isPermissionMatch){
127
                    logger.debug("no tragetUuid, class & permission match => ACCESS_GRANTED");
128
                    return ACCESS_GRANTED;
129
                }
130
                if ( validationResult.isUuidMatch  && validationResult.isClassMatch && validationResult.isPermissionMatch){
131
                    logger.debug("permission, class and uuid are matching => ACCESS_GRANTED");
132
                    return ACCESS_GRANTED;
133
                }
134

  
135
                // ask subclasses for further voting decisions
136
                Integer furtherVotingResult = furtherVotingDescisions(authorityPermission, object, attributes, validationResult);
137
                if(furtherVotingResult != null){
138
                    return furtherVotingResult;
139
                }
140

  
141
            } // END Authorities loop
142
        } // END attributes loop
143

  
144
        logger.debug("ACCESS_DENIED");
145
        return ACCESS_DENIED;
146
    }
147

  
148
    /**
149
     * Override this method to implement specific decisions.
150
     *
151
     * @param authorityPermission
152
     * @param object
153
     * @param attributes
154
     * @param validationResult
155
     * @return
156
     */
157
    protected Integer furtherVotingDescisions(AuthorityPermission authorityPermission, Object object, Collection<ConfigAttribute> attributes,
158
            ValidationResult validationResult) {
159
        return null;
160
    }
161

  
162
    protected class ValidationResult {
163
        boolean isPermissionMatch = false;
164
        boolean isUuidMatch = false;
165
        boolean isClassMatch = false;
166
        boolean hasTargetUuid = false;
167
    }
168

  
169
    /* ===================== implicitPermission a nd voters disabled ================ */
170
    /*implicitPermission
171
    protected Set<CdmPermissionVoter> implicitPermissionClasses = new HashSet<CdmPermissionVoter>();
172
    */
173
    /**
174
     * see {@link #setImplicitPermissionClasses(Set)}
175
     *
176
     * @return
177
    public Set<CdmPermissionVoter> getImplicitPermissionClasses() {
178
        return implicitPermissionClasses;
179
    }
180
     */
181

  
182
    /**
183
     * If the {@link GrantedAuthority} of an authentication contains {@link CdmPermission}s with
184
     * at least one of the CdmPermissionClass in {@link #implicitPermissionClasses}, this means that
185
     * this CdmPermission is treated as if it was a permission for the class this voter is responsible
186
     * for (see {@link #responsibilityClass}).
187
     * <p>
188
     * <h4>Schematic example<h4>
189
     * <ol>
190
     * <li>required CdmPermission: TAXON.UPDATE => requited CdmPermission class is TAXON</li>
191
     * <li>implicitPermissionClasses: {TAXONNODE}</li>
192
     * <li>user has CdmPermission: TAXONNODE.UPDATE</li>
193
     * <li>=> thus user also has implied permission TAXON.UPDATE</li>
194
     * </ol>
195
     *
196
     *
197
     * @param implicitPermissionClasses
198
    public void setImplicitPermissionClasses(Set<CdmPermissionVoter> implicitPermissionClasses) {
199
        this.implicitPermissionClasses = implicitPermissionClasses;
200
    }
201
     */
202

  
203
    /*
204
    protected CdmPermissionVoter findImpliedVoter(CdmPermissionClass assigned) {
205
        for(CdmPermissionVoter impliedVoter : implicitPermissionClasses){
206
            if(impliedVoter.isResponsibleFor(assigned)){
207
                if(logger.isDebugEnabled()){
208
                    logger.debug("* implicitClassMatch of " + assigned);
209
                }
210
                return impliedVoter;
211
            }
212
        }
213
        return null;
214
    }
215

  
216
    protected Set<CdmBase> findTargetObjectsForVoter(CdmPermissionVoter impliedVoter, CdmBase object){
217

  
218
        Set<CdmBase> targetObjects = new HashSet<CdmBase>();
219
        if(impliedVoter.isResponsibleFor(Taxon.class)){
220
            targetObjects.addAll(Taxon.class.cast(object).getTaxonNodes());
221
        } else {
222
            throw new RuntimeException("Not implemented for " + impliedVoter.getClass());
223
        }
224
        return targetObjects;
225
    }
226
    */
227

  
228

  
229

  
46 230
}

Also available in: Unified diff