1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.security.authorization

File Right.java

 

Coverage histogram

../../../../img/srcFileCovDistChart9.png
38% of files have more coverage

Code metrics

28
81
23
1
440
246
44
0.54
3.52
23
1.91

Classes

Class Line # Actions
45 81 0% 44 25
0.8106060681.1%
 

Contributing tests

This file is covered by 95 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.security.authorization;
21   
22    import java.io.Serializable;
23    import java.util.ArrayList;
24    import java.util.Collections;
25    import java.util.EnumSet;
26    import java.util.HashMap;
27    import java.util.LinkedList;
28    import java.util.List;
29    import java.util.Map;
30    import java.util.Set;
31   
32    import org.apache.commons.lang3.builder.EqualsBuilder;
33    import org.xwiki.model.EntityType;
34   
35    import static org.xwiki.security.SecurityReference.FARM;
36    import static org.xwiki.security.authorization.RuleState.ALLOW;
37    import static org.xwiki.security.authorization.RuleState.DENY;
38    import static org.xwiki.security.authorization.RuleState.UNDETERMINED;
39   
40    /**
41    * Enumeration of the possible rights.
42    * @version $Id: 1bfe6527696a5e53b6ad94a0161560bf39282e15 $
43    * @since 4.0M2
44    */
 
45    public class Right implements RightDescription, Serializable, Comparable<Right>
46    {
47    /** The login access right. */
48    public static final Right LOGIN;
49   
50    /** The view access right. */
51    public static final Right VIEW;
52   
53    /** The edit access right. */
54    public static final Right EDIT;
55   
56    /** The delete access right. */
57    public static final Right DELETE;
58   
59    /** Imply rights provided to creator of a document. */
60    public static final Right CREATOR;
61   
62    /** The Admin access right. */
63    public static final Right ADMIN;
64   
65    /** The program access right. */
66    public static final Right PROGRAM;
67   
68    /** The script access right. */
69    public static final Right SCRIPT;
70   
71    /** The register access right. */
72    public static final Right REGISTER;
73   
74    /** The comment access right. */
75    public static final Right COMMENT;
76   
77    /** The creation of a Wiki right. */
78    public static final Right CREATE_WIKI;
79   
80    /** Illegal value. */
81    public static final Right ILLEGAL;
82   
83    /** Illegal right name. */
84    public static final String ILLEGAL_RIGHT_NAME = "illegal";
85   
86    /** Targeted entity type list to target only the main wiki. */
87    public static final Set<EntityType> FARM_ONLY = null;
88   
89    /** Targeted entity type list to target only wikis (including main wiki). */
90    public static final Set<EntityType> WIKI_ONLY = EnumSet.of(EntityType.WIKI);
91   
92    /** Targeted entity type list to target wikis and spaces. */
93    public static final Set<EntityType> WIKI_SPACE = EnumSet.of(EntityType.WIKI, EntityType.SPACE);
94   
95    /** Targeted entity type list to target wikis, spaces and documents. */
96    public static final Set<EntityType> WIKI_SPACE_DOCUMENT
97    = EnumSet.of(EntityType.WIKI, EntityType.SPACE, EntityType.DOCUMENT);
98   
99    /** Serialization identifier. */
100    private static final long serialVersionUID = 1L;
101   
102    /** Internal list of existing instances. */
103    private static final List<Right> VALUES = new ArrayList<Right>();
104   
105    /** Unmodifiable list of existing instance for public dissemination. */
106    private static final List<Right> UNMODIFIABLE_VALUES = Collections.unmodifiableList(VALUES);
107   
108    /** List of all rights, as strings. */
109    private static final List<String> ALL_RIGHTS = new LinkedList<String>();
110   
111    /** List of all rights, as strings. */
112    private static final List<String> UNMODIFIABLE_ALL_RIGHTS = Collections.unmodifiableList(ALL_RIGHTS);
113   
114    /**
115    * The enabled rights by entity types. There is a special case hardcoded : The PROGRAM
116    * right should only be enabled for the main wiki, not for wikis in general.
117    */
118    private static final Map<EntityType, Set<Right>> ENABLED_RIGHTS = new HashMap<EntityType, Set<Right>>();
119   
120    /**
121    * The enabled rights by entity types, but with unmodifiable list for getters.
122    */
123    private static final Map<EntityType, Set<Right>> UNMODIFIABLE_ENABLED_RIGHTS
124    = new HashMap<EntityType, Set<Right>>();
125   
 
126  75 toggle static {
127  75 LOGIN = new Right("login", ALLOW, ALLOW, true, null, WIKI_ONLY, true);
128  75 VIEW = new Right("view", ALLOW, DENY, true, null, WIKI_SPACE_DOCUMENT, true);
129  75 EDIT = new Right("edit", ALLOW, DENY, true, new RightSet(VIEW), WIKI_SPACE_DOCUMENT, false);
130  75 DELETE = new Right("delete", DENY, DENY, true, null, WIKI_SPACE_DOCUMENT, false);
131  75 CREATOR =
132    new Right("creator", DENY, ALLOW, false, new RightSet(DELETE), EnumSet.of(EntityType.DOCUMENT), false);
133  75 REGISTER = new Right("register", ALLOW, ALLOW, true, null, WIKI_ONLY, false);
134  75 COMMENT = new Right("comment", ALLOW, DENY, true, null, WIKI_SPACE_DOCUMENT, false);
135  75 SCRIPT = new Right("script", DENY, DENY, true, null, WIKI_SPACE_DOCUMENT, true);
136   
137  75 ADMIN = new Right("admin", DENY, ALLOW, false,
138    new RightSet(LOGIN, VIEW, SCRIPT, EDIT, DELETE, REGISTER, COMMENT), WIKI_SPACE, true);
139   
140  75 CREATE_WIKI = new Right("createwiki", DENY, DENY, true, null, FARM_ONLY, false);
141   
142  75 PROGRAM = new Right("programming", DENY, ALLOW, false,
143    new RightSet(LOGIN, VIEW, SCRIPT, EDIT, DELETE, REGISTER, COMMENT, ADMIN, CREATE_WIKI), FARM_ONLY, true);
144   
145  75 ILLEGAL = new Right(ILLEGAL_RIGHT_NAME, DENY, DENY, false, null, null, false);
146    }
147   
148    /** The numeric value of this access right. */
149    private final int value;
150   
151    /** The string representation. */
152    private final String name;
153   
154    /** The string representation. */
155    private final RuleState defaultState;
156   
157    /** Whether this right should be allowed or denied in case of a tie. */
158    private final RuleState tieResolutionPolicy;
159   
160    /** Policy on how this right should be overridden by lower levels. */
161    private final boolean inheritanceOverridePolicy;
162   
163    /** Additional rights implied by this right. */
164    private final Set<Right> impliedRights;
165   
166    /** Additional rights implied by this right. */
167    private final boolean isReadOnly;
168   
169    /**
170    * Construct a new Right from its description.
171    * This is a package private constructor, the registration of a new right should be done using
172    * the {@link AuthorizationManager}
173    *
174    * @param description Description of the right to create.
175    */
 
176  11 toggle Right(RightDescription description)
177    {
178  11 this(description.getName(), description.getDefaultState(), description.getTieResolutionPolicy(),
179    description.getInheritanceOverridePolicy(),
180    description.getImpliedRights(),
181    description.getTargetedEntityType(), description.isReadOnly());
182    }
183   
184    /**
185    * Construct a new Right.
186    * @param name The string representation of this right.
187    * @param defaultState The default state, in case no matching right is found at any level.
188    * @param tieResolutionPolicy Whether this right should be allowed or denied in case of a tie.
189    * @param inheritanceOverridePolicy Policy on how this right should be overridden by lower levels.
190    * @param impliedRights Additional rights implied by this right.
191    * @param validEntityTypes The type of entity where this right should be enabled.
192    * @param isReadOnly If true, this right could be allowed when the wiki is in read-only mode.
193    */
 
194  911 toggle private Right(String name, RuleState defaultState, RuleState tieResolutionPolicy,
195    boolean inheritanceOverridePolicy, Set<Right> impliedRights, Set<EntityType> validEntityTypes,
196    boolean isReadOnly)
197    {
198  911 checkIllegalArguments(name, defaultState, tieResolutionPolicy);
199   
200  911 this.name = name;
201  911 this.defaultState = defaultState;
202  911 this.tieResolutionPolicy = tieResolutionPolicy;
203  911 this.inheritanceOverridePolicy = inheritanceOverridePolicy;
204  911 this.impliedRights = cloneImpliedRights(impliedRights);
205  911 this.isReadOnly = isReadOnly;
206   
207  911 synchronized (VALUES) {
208  911 this.value = VALUES.size();
209  911 if (this.value >= 64) {
210  0 throw new IndexOutOfBoundsException();
211    }
212  911 VALUES.add(this);
213  911 if (!name.equals(ILLEGAL_RIGHT_NAME)) {
214  836 ALL_RIGHTS.add(name);
215    }
216  911 if (validEntityTypes != null) {
217  686 for (EntityType type : validEntityTypes) {
218  1533 if (type == EntityType.WIKI) {
219    // If enabled on a wiki, enable also on main wiki.
220  611 enableFor(FARM);
221    }
222  1533 enableFor(type);
223    }
224    } else {
225    // If enabled on a wiki, enable also on main wiki.
226  225 enableFor(FARM);
227    }
228    }
229    }
230   
231    /**
232    * Enable this right for the given entity type.
233    * @param type the entity type, null for the the main wiki.
234    */
 
235  2369 toggle private void enableFor(EntityType type)
236    {
237  2369 Set<Right> rights = ENABLED_RIGHTS.get(type);
238  2369 if (rights == null) {
239  300 rights = new RightSet();
240  300 ENABLED_RIGHTS.put(type, rights);
241  300 UNMODIFIABLE_ENABLED_RIGHTS.put(type, Collections.unmodifiableSet(rights));
242    }
243  2369 rights.add(this);
244    }
245   
246    /**
247    * Check for illegal arguments.
248    *
249    * @param name The string representation of this right.
250    * @param defaultState The default state, in case no matching right is found at any level.
251    * @param tieResolutionPolicy Whether this right should be allowed or denied in case of a tie.
252    */
 
253  911 toggle private void checkIllegalArguments(String name, RuleState defaultState, RuleState tieResolutionPolicy)
254    {
255  911 if (name == null || ALL_RIGHTS.contains(name) || (ILLEGAL != null && name.equals(ILLEGAL_RIGHT_NAME))) {
256  0 throw new IllegalArgumentException(String.format("Duplicate name for right [%s]", name));
257    }
258   
259  911 if (defaultState == null || defaultState == UNDETERMINED) {
260  0 throw new IllegalArgumentException(
261    String.format("Invalid default state [%s] for right [%s]", defaultState, name));
262    }
263   
264  911 if (tieResolutionPolicy == null || tieResolutionPolicy == UNDETERMINED) {
265  0 throw new IllegalArgumentException(
266    String.format("Invalid tie resolution policy [%s] for right [%s]", tieResolutionPolicy, name));
267    }
268    }
269   
270    /**
271    * Clone implied Rights.
272    * @param impliedRights the collection of rights to clone.
273    * @return the cloned collection or null if no valid implied right has been provided.
274    */
 
275  911 toggle private Set<Right> cloneImpliedRights(Set<Right> impliedRights)
276    {
277  911 if (impliedRights == null || impliedRights.size() == 0) {
278  609 return null;
279    }
280   
281  302 Set<Right> implied = new RightSet(impliedRights);
282   
283  302 if (implied.size() > 0) {
284  302 return Collections.unmodifiableSet(implied);
285    } else {
286  0 return null;
287    }
288    }
289   
290    /**
291    * @return an unmodifiable list of available Right
292    */
 
293  41287 toggle public static List<Right> values()
294    {
295  41290 return UNMODIFIABLE_VALUES;
296    }
297   
298    /**
299    * Convert a string to a right.
300    * @param string String representation of right.
301    * @return The corresponding Right instance, or {@code ILLEGAL}.
302    */
 
303  151015 toggle public static Right toRight(String string)
304    {
305  151015 for (Right right : VALUES) {
306  706721 if (right.name.equals(string)) {
307  151012 return right;
308    }
309    }
310  1 return ILLEGAL;
311    }
312   
313    /**
314    * Returns the list of rights available for a given entity type.
315    *
316    * @param entityType the entity type, or null for main wiki.
317    * @return a list of {@code Right} enabled of this entity type
318    */
 
319  88641 toggle public static Set<Right> getEnabledRights(EntityType entityType)
320    {
321  88643 Set<Right> enabledRights = UNMODIFIABLE_ENABLED_RIGHTS.get(entityType);
322  88642 if (enabledRights == null) {
323  2 enabledRights = Collections.<Right>emptySet();
324    }
325  88643 return enabledRights;
326    }
327   
328    /**
329    * Retrieve a right based on its ordinal.
330    * @param ordinal the ordinal of the right
331    * @return the {@code Right}
332    */
 
333  124530 toggle public static Right get(int ordinal) {
334  124529 return VALUES.get(ordinal);
335    }
336   
337    /**
338    * @return the count of all existing rights
339    */
 
340  38615 toggle public static int size() {
341  38616 return values().size();
342    }
343   
344    /**
345    * @return a list of the string representation of all valid rights.
346    */
 
347  2 toggle public static List<String> getAllRightsAsString()
348    {
349  2 return UNMODIFIABLE_ALL_RIGHTS;
350    }
351   
352    /**
353    * @return The numeric value of this access right.
354    */
 
355  474385 toggle public int ordinal()
356    {
357  474390 return value;
358    }
359   
 
360  19527 toggle @Override
361    public String getName()
362    {
363  19528 return name;
364    }
365   
 
366  10176 toggle @Override
367    public String toString()
368    {
369  10176 return getName();
370    }
371   
 
372  1385 toggle @Override
373    public Set<Right> getImpliedRights()
374    {
375  1385 return impliedRights;
376    }
377   
 
378  0 toggle @Override
379    public Set<EntityType> getTargetedEntityType()
380    {
381  0 List<EntityType> levels = new ArrayList<EntityType>();
382  0 for (Map.Entry<EntityType, Set<Right>> entry : ENABLED_RIGHTS.entrySet()) {
383  0 if (entry.getValue().contains(this)) {
384  0 levels.add(entry.getKey());
385    }
386    }
387  0 if (levels.contains(null) && levels.contains(EntityType.WIKI)) {
388  0 levels.remove(null);
389    } else {
390  0 return null;
391    }
392  0 return EnumSet.copyOf(levels);
393    }
394   
 
395  1438 toggle @Override
396    public boolean getInheritanceOverridePolicy()
397    {
398  1438 return inheritanceOverridePolicy;
399    }
400   
 
401  1446 toggle @Override
402    public RuleState getTieResolutionPolicy()
403    {
404  1446 return tieResolutionPolicy;
405    }
406   
 
407  23840 toggle @Override
408    public RuleState getDefaultState()
409    {
410  23840 return this.defaultState;
411    }
412   
 
413  61460 toggle @Override
414    public boolean isReadOnly()
415    {
416  61459 return this.isReadOnly;
417    }
418   
 
419  76 toggle @Override
420    public int compareTo(Right other)
421    {
422  76 return this.ordinal() - other.ordinal();
423    }
424   
425    /**
426    * @param description a right description to compare this right to.
427    * @return true if the right is equivalent to the provided description.
428    */
 
429  0 toggle boolean like(RightDescription description)
430    {
431  0 return new EqualsBuilder()
432    .append(this.isReadOnly(), description.isReadOnly())
433    .append(this.getDefaultState(), description.getDefaultState())
434    .append(this.getTieResolutionPolicy(), description.getTieResolutionPolicy())
435    .append(this.getInheritanceOverridePolicy(), description.getInheritanceOverridePolicy())
436    .append(this.getTargetedEntityType(), description.getTargetedEntityType())
437    .append(this.getImpliedRights(), description.getImpliedRights())
438    .isEquals();
439    }
440    }