1. Project Clover database Sat Feb 2 2019 06:45:20 CET
  2. Package org.xwiki.security.authorization

File Right.java

 

Coverage histogram

../../../../img/srcFileCovDistChart8.png
56% of files have more coverage

Code metrics

30
82
23
1
442
248
44
0.54
3.57
23
1.91

Classes

Class Line # Actions
45 82 0% 44 28
0.792592679.3%
 

Contributing tests

This file is covered by 101 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: 93acb41b02b7837032480791d45620109b58a4d2 $
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  96 toggle static {
127  96 LOGIN = new Right("login", ALLOW, ALLOW, true, null, WIKI_ONLY, true);
128  96 VIEW = new Right("view", ALLOW, DENY, true, null, WIKI_SPACE_DOCUMENT, true);
129  96 EDIT = new Right("edit", ALLOW, DENY, true, new RightSet(VIEW), WIKI_SPACE_DOCUMENT, false);
130  96 DELETE = new Right("delete", DENY, DENY, true, null, WIKI_SPACE_DOCUMENT, false);
131  96 CREATOR =
132    new Right("creator", DENY, ALLOW, false, new RightSet(DELETE), EnumSet.of(EntityType.DOCUMENT), false);
133  96 REGISTER = new Right("register", ALLOW, ALLOW, true, null, WIKI_ONLY, false);
134  96 COMMENT = new Right("comment", ALLOW, DENY, true, null, WIKI_SPACE_DOCUMENT, false);
135  96 SCRIPT = new Right("script", DENY, DENY, true, null, WIKI_SPACE_DOCUMENT, true);
136   
137  96 ADMIN = new Right("admin", DENY, ALLOW, false,
138    new RightSet(LOGIN, VIEW, SCRIPT, EDIT, DELETE, REGISTER, COMMENT), WIKI_SPACE, true);
139   
140  96 CREATE_WIKI = new Right("createwiki", DENY, DENY, true, null, FARM_ONLY, false);
141   
142  96 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  96 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  1163 toggle private Right(String name, RuleState defaultState, RuleState tieResolutionPolicy,
195    boolean inheritanceOverridePolicy, Set<Right> impliedRights, Set<EntityType> validEntityTypes,
196    boolean isReadOnly)
197    {
198  1163 checkIllegalArguments(name, defaultState, tieResolutionPolicy);
199   
200  1163 this.name = name;
201  1163 this.defaultState = defaultState;
202  1163 this.tieResolutionPolicy = tieResolutionPolicy;
203  1163 this.inheritanceOverridePolicy = inheritanceOverridePolicy;
204  1163 this.impliedRights = cloneImpliedRights(impliedRights);
205  1163 this.isReadOnly = isReadOnly;
206   
207  1163 synchronized (VALUES) {
208  1163 this.value = VALUES.size();
209  1163 if (this.value >= 64) {
210  0 throw new IndexOutOfBoundsException();
211    }
212  1163 VALUES.add(this);
213  1163 if (!name.equals(ILLEGAL_RIGHT_NAME)) {
214  1067 ALL_RIGHTS.add(name);
215    }
216  1163 if (validEntityTypes != null) {
217  875 for (EntityType type : validEntityTypes) {
218  1953 if (type == EntityType.WIKI) {
219    // If enabled on a wiki, enable also on main wiki.
220  779 enableFor(FARM);
221    }
222  1953 enableFor(type);
223    }
224    } else {
225    // If enabled on a wiki, enable also on main wiki.
226  288 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  3020 toggle private void enableFor(EntityType type)
236    {
237  3020 Set<Right> rights = ENABLED_RIGHTS.get(type);
238  3020 if (rights == null) {
239  384 rights = new RightSet();
240  384 ENABLED_RIGHTS.put(type, rights);
241  384 UNMODIFIABLE_ENABLED_RIGHTS.put(type, Collections.unmodifiableSet(rights));
242    }
243  3020 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  1163 toggle private void checkIllegalArguments(String name, RuleState defaultState, RuleState tieResolutionPolicy)
254    {
255  1163 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  1163 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  1163 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  1163 toggle private Set<Right> cloneImpliedRights(Set<Right> impliedRights)
276    {
277  1163 if (impliedRights == null || impliedRights.size() == 0) {
278  777 return null;
279    }
280   
281  386 Set<Right> implied = new RightSet(impliedRights);
282   
283  386 if (implied.size() > 0) {
284  386 return Collections.unmodifiableSet(implied);
285    } else {
286  0 return null;
287    }
288    }
289   
290    /**
291    * @return an unmodifiable list of available Right
292    */
 
293  604318 toggle public static List<Right> values()
294    {
295  604428 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  1625360 toggle public static Right toRight(String string)
304    {
305  1626130 for (Right right : VALUES) {
306  7827043 if (right.name.equals(string)) {
307  1626421 return right;
308    }
309    }
310  163 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  1721337 toggle public static Set<Right> getEnabledRights(EntityType entityType)
320    {
321  1721401 Set<Right> enabledRights = UNMODIFIABLE_ENABLED_RIGHTS.get(entityType);
322  1721373 if (enabledRights == null) {
323  231 enabledRights = Collections.<Right>emptySet();
324    }
325  1721356 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  3260640 toggle public static Right get(int ordinal) {
334  3260701 return VALUES.get(ordinal);
335    }
336   
337    /**
338    * @return the count of all existing rights
339    */
 
340  568566 toggle public static int size() {
341  568645 return values().size();
342    }
343   
344    /**
345    * @return a list of the string representation of all valid rights.
346    */
 
347  44 toggle public static List<String> getAllRightsAsString()
348    {
349  44 return UNMODIFIABLE_ALL_RIGHTS;
350    }
351   
352    /**
353    * @return The numeric value of this access right.
354    */
 
355  17616197 toggle public int ordinal()
356    {
357  17616245 return value;
358    }
359   
 
360  477322 toggle @Override
361    public String getName()
362    {
363  477336 return name;
364    }
365   
 
366  3477 toggle @Override
367    public String toString()
368    {
369  3477 return getName();
370    }
371   
 
372  293684 toggle @Override
373    public Set<Right> getImpliedRights()
374    {
375  293682 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)) {
388  0 if (levels.contains(EntityType.WIKI)) {
389  0 levels.remove(null);
390    } else {
391  0 return null;
392    }
393    }
394  0 return EnumSet.copyOf(levels);
395    }
396   
 
397  505628 toggle @Override
398    public boolean getInheritanceOverridePolicy()
399    {
400  505627 return inheritanceOverridePolicy;
401    }
402   
 
403  505643 toggle @Override
404    public RuleState getTieResolutionPolicy()
405    {
406  505645 return tieResolutionPolicy;
407    }
408   
 
409  88844 toggle @Override
410    public RuleState getDefaultState()
411    {
412  88859 return this.defaultState;
413    }
414   
 
415  1349798 toggle @Override
416    public boolean isReadOnly()
417    {
418  1349894 return this.isReadOnly;
419    }
420   
 
421  94 toggle @Override
422    public int compareTo(Right other)
423    {
424  94 return this.ordinal() - other.ordinal();
425    }
426   
427    /**
428    * @param description a right description to compare this right to.
429    * @return true if the right is equivalent to the provided description.
430    */
 
431  0 toggle boolean like(RightDescription description)
432    {
433  0 return new EqualsBuilder()
434    .append(this.isReadOnly(), description.isReadOnly())
435    .append(this.getDefaultState(), description.getDefaultState())
436    .append(this.getTieResolutionPolicy(), description.getTieResolutionPolicy())
437    .append(this.getInheritanceOverridePolicy(), description.getInheritanceOverridePolicy())
438    .append(this.getTargetedEntityType(), description.getTargetedEntityType())
439    .append(this.getImpliedRights(), description.getImpliedRights())
440    .isEquals();
441    }
442    }