Project

General

Profile

Download (8.22 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2012 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
package eu.etaxonomy.cdm.persistence.hibernate.permission;
10

    
11
import java.util.EnumSet;
12
import java.util.UUID;
13
import java.util.regex.Matcher;
14
import java.util.regex.Pattern;
15

    
16
import org.apache.log4j.Logger;
17
import org.springframework.security.access.ConfigAttribute;
18
import org.springframework.security.core.GrantedAuthority;
19

    
20
import sun.security.provider.PolicyParser.ParsingException;
21
import eu.etaxonomy.cdm.model.common.CdmBase;
22
import eu.etaxonomy.cdm.model.common.GrantedAuthorityImpl;
23

    
24
/**
25
 * A <code>CdmAuthority</code> consists basically of two parts which are separated
26
 * by a dot character '.'.
27
 *
28
 * <ul>
29
 * <li><code>permissionClass</code>: an {@link CdmPermissionClass} instance with represents a cdm
30
 * type or a part of the cdm type hierarchy. The className is always represented
31
 * as an upper case string.</li>
32
 * <li><code>property</code>: The <code>CdmAuthority</code> only applies to instances
33
 * which satisfy the specified property. Interpretation is up to type specific voters.</li>
34
 * <li><code>operation</code>: A string enclosed in brackets <code>[]</code>
35
 * which specifies one {@link Operation} or
36
 * multiple on that set of cdm types. Multiple {@link Operation} must be comma
37
 * separated.</li>
38
 * <li><code>targetUuid</code>: The <code>operation</code> may be restricted to a specific cdm entity by adding
39
 * the entity uuid to the <code>operation</code>. The uuid string is enclosed in curly brackets '<code>{</code>'
40
 * , '<code>}</code>' and appended to the end of the <code>operation</code>.</li>
41
 * </ul>
42
 *
43
 * <h3>Examples for permissionStrings</h3>
44
 *
45
 * <pre>
46
 * TAXONBASE.[CREATE]
47
 * TAXONBASE.[READ]
48
 * TAXONBASE.[UPDATE]
49
 * TAXONBASE.[DELETE]
50
 * DESCRIPTIONBASE.[UPDATE]
51
 * DESCRIPTIONBASE.[CREATE,UPDATE,DELETE,READ]
52
 * DESCRIPTIONELEMENTBASE(Ecology).[UPDATE]
53
 * TAXONNODE.[UPDATE]{20c8f083-5870-4cbd-bf56-c5b2b98ab6a7}
54
 * </pre>
55
 *
56
 * The method {@link #getPermissionString(String)} parses a full authority and returns  permissionString and
57
 * the {@link CdmAuthority} from the <code>authority</code>.
58
 *
59
 *
60
 * @author k.luther
61
 * @author Andreas Kohlbecker
62
 */
63
public class CdmAuthority implements GrantedAuthority, ConfigAttribute, IGrantedAuthorityConverter {
64

    
65
    private static final long serialVersionUID = 1L;
66

    
67
    public static final Logger logger = Logger.getLogger(CdmAuthority.class);
68

    
69
    CdmPermissionClass permissionClass;
70
    String property;
71
    EnumSet<CRUD> operation;
72
    UUID targetUuid;
73

    
74
    public CdmAuthority(CdmBase targetDomainObject, EnumSet<CRUD> operation, UUID uuid){
75
        this.permissionClass = CdmPermissionClass.getValueOf(targetDomainObject);
76
        this.property = null;
77
        this.operation = operation;
78
        this.targetUuid = uuid;
79
    }
80

    
81
     public CdmAuthority(CdmBase targetDomainObject, String property, EnumSet<CRUD> operation, UUID uuid){
82
       this.permissionClass = CdmPermissionClass.getValueOf(targetDomainObject);
83
        this.property = property;
84
        this.operation = operation;
85
        this.targetUuid = uuid;
86
    }
87

    
88

    
89
    public CdmAuthority(CdmPermissionClass permissionClass, String property, EnumSet<CRUD> operation, UUID uuid){
90
        this.permissionClass = permissionClass;
91
        this.property = property;
92
        this.operation = operation;
93
        this.targetUuid = uuid;
94
    }
95

    
96
    private CdmAuthority (String authority) throws ParsingException{
97

    
98
        String[] tokens = parse(authority);
99
        // className must never be null
100
        permissionClass = CdmPermissionClass.valueOf(tokens[0]);
101
        property = tokens[1];
102
        if(tokens[2] != null){
103
            try {
104
                operation = Operation.fromString(tokens[2]);
105
            } catch (IllegalArgumentException e) {
106
                logger.warn("cannot parse Operation " + tokens[2]);
107
                throw e;
108
            }
109
        }
110
        if(tokens[3] != null){
111
            targetUuid = UUID.fromString(tokens[3]);
112
        }
113
    }
114

    
115
    public CdmPermissionClass getPermissionClass(){
116
        return permissionClass;
117
    }
118

    
119
    public String getProperty(){
120
        return property;
121
    }
122

    
123
    public EnumSet<CRUD> getOperation(){
124
        return operation;
125
    }
126

    
127
    public void setOperation(EnumSet<CRUD> operation) {
128
        this.operation = operation;
129
    }
130

    
131
    public UUID getTargetUUID(){
132
        return targetUuid;
133
    }
134

    
135
    public boolean hasTargetUuid() {
136
        return targetUuid != null;
137
    }
138

    
139
    public boolean hasProperty() {
140
        return property != null;
141
    }
142

    
143
    /**
144
     * Parses the given <code>authority</code> and returns an array of tokens.
145
     * The array has a length of four elements whereas the elements can be null.
146
     * The elements in the array correspond to the fields of {@link CdmAuthority}:
147
     * <ol>
148
     * <li>{@link CdmAuthority#permissionClass}</li>
149
     * <li>{@link CdmAuthority#property}</li>
150
     * <li>{@link CdmAuthority#operation}</li>
151
     * <li>{@link CdmAuthority#targetUuid}</li>
152
     * </ol>
153
     * @param authority
154
     * @return an array of tokens
155
     * @throws ParsingException
156
     */
157
    protected String[] parse(String authority) throws ParsingException {
158
        //
159
        // regex pattern explained:
160
        //  (\\w*)             -> classname
161
        //  (?:\\((\\w*)\\))?  -> (property)
162
        //  \\.?               -> .
163
        //  (?:(\\w*))(?:\\{([\\da-z\\-]+)\\})? -> Permmission and targetUuid
164
        //
165
        String regex = "(\\w*)(?:\\((\\w*)\\))?\\.?(?:\\[(\\D*)\\])?(?:\\{([\\da-z\\-]+)\\})?";
166
        Pattern pattern = Pattern.compile(regex);
167
        String[] tokens = new String[4];
168
        logger.debug("parsing '" + authority + "'");
169
        Matcher m = pattern.matcher(authority);
170

    
171
        if (m.find() && m.groupCount() == 4 ) {
172
            for (int i = 0; i < m.groupCount(); i++) {
173
                tokens[i] = m.group(i+1);
174
                // normalize empty strings to null
175
                if(tokens[i] != null && tokens[i].length() == 0){
176
                    tokens[i] = null;
177
                }
178
                logger.debug("[" + i + "]: " + tokens[i]+ "\n");
179
            }
180
        } else {
181
            logger.debug("no match");
182
            throw new ParsingException("Unsupported authority string: '" + authority + "'");
183
        }
184

    
185
        return tokens;
186
    }
187

    
188
    /**
189
     * {@inheritDoc}
190
     *
191
     * same as {@link #toString()} and  {@link #getAttribute()}
192
     */
193
    @Override
194
    public String getAuthority() {
195
        return toString();
196
    }
197

    
198
    /**
199
     * {@inheritDoc}
200
     *
201
     * same as {@link #toString()} and  {@link #getAuthority()}
202
     */
203
    @Override
204
    public String getAttribute() {
205
        return toString();
206
    }
207

    
208
    @Override
209
    public String toString() {
210
        StringBuilder sb = new StringBuilder();
211
        sb.append(permissionClass.toString());
212
        if(property != null){
213
            sb.append('(').append(property).append(')');
214
        }
215
        sb.append('.').append(operation.toString());
216
        if(targetUuid != null){
217
            sb.append('{').append(targetUuid.toString()).append('}');
218
        }
219
        return sb.toString() ;
220
    }
221

    
222
    /**
223
     * Constructs a new CdmAuthority by parsing the authority string.
224
     * For details on the syntax please refer to the class
225
     * documentation above.
226
     *
227
     *
228
     * @param authority
229
     * @throws ParsingException
230
     */
231
    public static CdmAuthority fromGrantedAuthority(GrantedAuthority authority) throws ParsingException {
232
        return new CdmAuthority(authority.getAuthority());
233
    }
234

    
235
    /* (non-Javadoc)
236
     * @see eu.etaxonomy.cdm.persistence.hibernate.permission.IGrantedAuthorityConverter#asNewGrantedAuthority()
237
     */
238
    @Override
239
    public GrantedAuthorityImpl asNewGrantedAuthority() throws ParsingException {
240
        GrantedAuthorityImpl grantedAuthority = GrantedAuthorityImpl.NewInstance();
241
        grantedAuthority.setAuthority(getAuthority());
242
        return grantedAuthority;
243
    }
244

    
245

    
246

    
247
}
(2-2/8)