Coverage Report - org.openpermis.policy.bean.basic.BasicRoleAssignmentRule
 
Classes in this File Line Coverage Branch Coverage Complexity
BasicRoleAssignmentRule
88%
94/106
77%
48/62
2.667
 
 1  
 /*
 2  
  * Copyright (c) 2009, Swiss Federal Department of Defence Civil Protection and Sport
 3  
  *                     (http://www.vbs.admin.ch)
 4  
  * Copyright (c) 2009, Ergon Informatik AG (http://www.ergon.ch)
 5  
  * All rights reserved.
 6  
  *
 7  
  * Licensed under the Open Permis License which accompanies this distribution,
 8  
  * and is available at http://www.openpermis.org/BSDlicenceKent.txt
 9  
  */
 10  
 package org.openpermis.policy.bean.basic;
 11  
 
 12  
 import static org.openpermis.policy.bean.basic.BasicUtilities.equalObjects;
 13  
 import static org.openpermis.policy.bean.basic.BasicUtilities.getIdentityDetails;
 14  
 import static org.openpermis.policy.bean.basic.BasicUtilities.getStringDetails;
 15  
 import static org.openpermis.policy.bean.basic.BasicUtilities.multiHashCode;
 16  
 
 17  
 import java.util.Collection;
 18  
 import java.util.Collections;
 19  
 import java.util.HashSet;
 20  
 import java.util.Set;
 21  
 
 22  
 import org.openpermis.Subject;
 23  
 import org.openpermis.basic.TimePeriod;
 24  
 import org.openpermis.basic.TimePeriodConstraint;
 25  
 import org.openpermis.policy.Domain;
 26  
 import org.openpermis.policy.PartProblemReporter;
 27  
 import org.openpermis.policy.Role;
 28  
 import org.openpermis.policy.TimeStamp;
 29  
 import org.openpermis.policy.PartProblemReporter.ProblemMessage;
 30  
 import org.openpermis.policy.bean.AuthorityBean;
 31  
 import org.openpermis.policy.bean.DomainBean;
 32  
 import org.openpermis.policy.bean.PartBean;
 33  
 import org.openpermis.policy.bean.RoleAssignmentRuleBean;
 34  
 import org.openpermis.policy.bean.RoleCollection;
 35  
 import org.openpermis.policy.bean.SerialNumber;
 36  
 
 37  
 /**
 38  
  * A rule for assigning roles to subjects.
 39  
  * @since 0.1.0
 40  
  */
 41  
 public class BasicRoleAssignmentRule
 42  
         extends BasicPartBean
 43  
         implements RoleAssignmentRuleBean
 44  
 {
 45  
 
 46  
         //---- Static
 47  
 
 48  
         private static final long serialVersionUID = 9152170606273777506L;
 49  
 
 50  
         //---- State
 51  
 
 52  
         private AuthorityBean authority;
 53  
 
 54  
         private DomainBean subjectDomain;
 55  
 
 56  
         private RoleCollection roles;
 57  
         
 58  
         private TimePeriodConstraint constraint;
 59  
 
 60  
         private int delegationDepth;
 61  
 
 62  
         //---- Constructors
 63  
 
 64  
         /**
 65  
          * Creates a role assignment rule.
 66  
          * @param serialNumber the serial number of this part.
 67  
          * @param authority the {@link AuthorityBean} authorizing the role assignment.
 68  
          * @param subjectDomain the {@link Domain} to which the rule applies.
 69  
          * @param roles the {@link Role roles} that subjects are allowed to assign.
 70  
          * @param delegationDepth the delegation depth that applies.
 71  
          * @since 0.1.0
 72  
          */
 73  
         protected BasicRoleAssignmentRule (
 74  
                 SerialNumber serialNumber,
 75  
                 AuthorityBean authority,
 76  
                 DomainBean subjectDomain,
 77  
                 Collection<Role> roles,
 78  
                 TimePeriodConstraint constraint,
 79  
                 int delegationDepth
 80  
         ) {
 81  290
                 super(RoleAssignmentRuleBean.class, serialNumber);
 82  
 
 83  290
                 this.roles = RoleCollection.EMPTY;
 84  290
                 setAuthority(authority);
 85  290
                 setSubjectDomain(subjectDomain);
 86  290
                 setRoles(RoleCollection.create(roles));
 87  290
                 setConstraint(constraint);
 88  290
                 setDelegationDepth(delegationDepth);
 89  290
         }
 90  
 
 91  
         //---- Methods
 92  
         
 93  
         //---- RoleAssignmentRule
 94  
         
 95  
         /**
 96  
          * @since 0.1.0
 97  
          */
 98  
         public Set<Role> verifyRoleAssignment (
 99  
                 Subject subject, Set<Role> assertedRoles, TimeStamp timeStamp
 100  
         ) {
 101  15
                 if (subject == null || assertedRoles == null || timeStamp == null) {
 102  0
                         throw new IllegalArgumentException("Subject, assertedRoles or time is null.");
 103  
                 }
 104  15
                 if (assertedRoles.isEmpty()) {
 105  0
                         throw new IllegalArgumentException("No asserted roles");
 106  
                 }
 107  
                 // Must check that the subject is only asked about issuer of roles that it possess.
 108  
                 // May be asked in the interface of this function, so this line could be removed.
 109  15
                 final Set<Role> tmp = subject.getAssignedRoles(timeStamp, assertedRoles);
 110  
 
 111  
                 // Check validity of this roles according to the time constraint of this rule.
 112  15
                 final Set<Role> result = new HashSet<Role>();
 113  15
                 for (Role role : verifyRoleAssignment(subject, tmp, timeStamp, 0)) {
 114  15
                         for (Subject issuer : subject.getIssuersOf(role)) {
 115  15
                                 final TimePeriod period = 
 116  
                                         subject.getValidityOf(role, issuer).constrain(this.constraint, timeStamp);
 117  15
                                 if (period.contains(timeStamp)) {
 118  14
                                         result.add(role);
 119  14
                                         break;
 120  
                                 }
 121  1
                         }
 122  
                 }
 123  15
                 return result;
 124  
         }
 125  
         
 126  
         /**
 127  
          * @since 0.1.0
 128  
          */
 129  
         private Set<Role> verifyRoleAssignment (
 130  
                 Subject subject,
 131  
                 Set<Role> assertedExplicitRoles,
 132  
                 TimeStamp timeStamp,
 133  
                 int minimumDelegationDepth)
 134  
         {
 135  
                 // Test if the subject is in the subject domain of this rule.
 136  26
                 if (!this.subjectDomain.contains(subject.getIdentity())) {
 137  0
                         return Collections.emptySet();
 138  
                 }
 139  
 
 140  
                 // Only consider roles (including subordinate roles) that are covered by this rule.
 141  26
                 final Set<Role> candidateRoles = new HashSet<Role>();
 142  26
                 for (Role role : getRoles()) {
 143  26
                         candidateRoles.addAll(role.getSubRoles());
 144  
                 }
 145  
 
 146  
                 // Only consider roles of this rule that are asserted for the subject.
 147  26
                 candidateRoles.retainAll(assertedExplicitRoles);
 148  
                 
 149  26
                 final Set<Role> result = new HashSet<Role>();
 150  26
                 ROLE: for (Role role : candidateRoles) {
 151  26
                         final Role roleRef = role;
 152  26
                         for (Subject issuer : subject.getIssuersOf(roleRef)) {
 153  
                                 // Delegation chain ends with authority.
 154  26
                                 if (issuer.getIdentity().equals(this.authority.getIdentity())) {
 155  15
                                         result.add(role);
 156  15
                                         continue ROLE;
 157  
                                 // Delegation chain.
 158  11
                                 } else if (minimumDelegationDepth <= getDelegationDepth()) {
 159  
 
 160  
                                         // The current role is extended by the super roles, because it is also allowed
 161  
                                         // that the issuer only delegates a subrole.
 162  11
                                         final Set<Role> issuerCandidateRoles =
 163  
                                                 issuer.getAssignedRoles(timeStamp, role.getSuperRoles());
 164  
 
 165  11
                                         final Set<Role> verifiedIssuerRoles = verifyRoleAssignment(
 166  
                                                 issuer,
 167  
                                                 issuerCandidateRoles,
 168  
                                                 timeStamp,
 169  
                                                 minimumDelegationDepth + 1
 170  
                                         );
 171  11
                                         for (Role superRole : verifiedIssuerRoles) {
 172  11
                                                 if (isSubRole(superRole, role)) {
 173  11
                                                         result.add(role);
 174  11
                                                         continue ROLE;
 175  
                                                 }
 176  
                                         }
 177  0
                                 }
 178  
                         }
 179  0
                 }
 180  26
                 return result;
 181  
         }
 182  
 
 183  
         /**
 184  
          * @since 0.3.0
 185  
          */
 186  
         private boolean isSubRole (Role superRole, Role subRole) {
 187  11
                 return superRole.getSubRoles().contains(subRole);
 188  
         }
 189  
         
 190  
         //---- RoleAssignmentRuleBean
 191  
         
 192  
         /**
 193  
          * @since 0.1.0
 194  
          */
 195  
         public AuthorityBean getAuthority () {
 196  687
                 return this.authority;
 197  
         }
 198  
 
 199  
         /**
 200  
          * @since 0.1.0
 201  
          */
 202  
         public void setAuthority (AuthorityBean authority) {
 203  290
                 final AuthorityBean oldAuthority = getAuthority();
 204  290
                 this.authority = authority;
 205  290
                 firePropertyChange("authority", oldAuthority, getAuthority());
 206  290
         }
 207  
 
 208  
         /**
 209  
          * @since 0.1.0
 210  
          */
 211  
         public DomainBean getSubjectDomain () {
 212  689
                 return this.subjectDomain;
 213  
         }
 214  
 
 215  
         /**
 216  
          * @since 0.1.0
 217  
          */
 218  
         public void setSubjectDomain (DomainBean subjectDomain) {
 219  290
                 final Domain oldSubjectDomain = getSubjectDomain();
 220  290
                 this.subjectDomain = subjectDomain;
 221  290
                 firePropertyChange("subjectDomain", oldSubjectDomain, getSubjectDomain());
 222  290
         }
 223  
 
 224  
         /**
 225  
          * @since 0.1.0
 226  
          */
 227  
         public int getDelegationDepth () {
 228  671
                 return this.delegationDepth;
 229  
         }
 230  
 
 231  
         /**
 232  
          * @since 0.1.0
 233  
          */
 234  
         public void setDelegationDepth (int delegationDepth) {
 235  290
                 final int oldDelegationDepth = getDelegationDepth();
 236  290
                 this.delegationDepth = delegationDepth;
 237  290
                 firePropertyChange(
 238  
                         "delegationDepth",
 239  
                         Integer.valueOf(oldDelegationDepth),
 240  
                         Integer.valueOf(getDelegationDepth())
 241  
                 );
 242  290
         }
 243  
 
 244  
         /**
 245  
          * @since 0.1.0
 246  
          */
 247  
         public RoleCollection getRoles () {
 248  686
                 return this.roles;
 249  
         }
 250  
 
 251  
         /**
 252  
          * @since 0.1.0
 253  
          */
 254  
         public void setRoles (RoleCollection roles) {
 255  290
                 final RoleCollection oldRoles = getRoles();
 256  290
                 if (roles == null) {
 257  0
                         this.roles = RoleCollection.EMPTY;
 258  
                 } else {
 259  290
                         this.roles = roles;
 260  
                 }
 261  290
                 firePropertyChange("roles", oldRoles, getRoles());
 262  290
         }
 263  
         
 264  
         /**
 265  
          * @since 0.3.0
 266  
          */
 267  
         public TimePeriodConstraint getConstraint () {
 268  656
                 return this.constraint;
 269  
         }
 270  
 
 271  
         /**
 272  
          * @since 0.3.0
 273  
          */
 274  
         public void setConstraint (TimePeriodConstraint constraint) {
 275  290
                 TimePeriodConstraint oldConstraint = getConstraint();
 276  290
                 if (constraint == null) {
 277  23
                         this.constraint = TimePeriodConstraint.UNCONSTRAINED;
 278  
                 } else {
 279  267
                         this.constraint = constraint;
 280  
                 }
 281  290
                 firePropertyChange("constraint", oldConstraint, getConstraint());
 282  290
         }        
 283  
 
 284  
         //---- BasicPart
 285  
         
 286  
         /**
 287  
          * @since 0.1.0
 288  
          */
 289  
         @Override
 290  
         public boolean isPartValid (PartProblemReporter reporter) {
 291  
                 boolean valid;
 292  
 
 293  7
                 valid = true;
 294  
 
 295  
                 // Check authority.
 296  7
                 if (!isChildValid(reporter, getAuthority())) {
 297  1
                         valid = false;
 298  1
                         reportProblem(reporter, ProblemMessage.illegalAuthority);
 299  
                 }
 300  
 
 301  
                 // Check subject domain.
 302  7
                 if (!isChildValid(reporter, getSubjectDomain())) {
 303  1
                         valid = false;
 304  1
                         reportProblem(reporter, ProblemMessage.illegalSubjectDomain);
 305  
                 }
 306  
                 
 307  
                 // Check roles.
 308  7
                 if (getRoles().isEmpty()) {
 309  1
                         valid = false;
 310  1
                         reportProblem(reporter, ProblemMessage.illegalRoles);
 311  
                 }
 312  
                 
 313  
                 // Check delegation depth.
 314  7
                 if (getDelegationDepth() < 0) {
 315  1
                         valid = false;
 316  1
                         reportProblem(reporter, ProblemMessage.illegalDelegationDepth);
 317  
                 }
 318  
 
 319  7
                 return valid;
 320  
         }
 321  
 
 322  
         /**
 323  
          * @since 0.1.0
 324  
          */
 325  
         @Override
 326  
         protected boolean comparablePart (BasicPart part) {
 327  60
                 return part instanceof RoleAssignmentRuleBean;
 328  
         }
 329  
 
 330  
         /**
 331  
          * @since 0.1.0
 332  
          */
 333  
         @Override
 334  
         protected boolean equalPart (BasicPart part) {
 335  30
                 final RoleAssignmentRuleBean other = (RoleAssignmentRuleBean) part;
 336  30
                 return
 337  
                         equalObjects(getAuthority(), other.getAuthority()) &&
 338  
                         equalObjects(getSubjectDomain(), other.getSubjectDomain()) &&
 339  
                         getDelegationDepth() == other.getDelegationDepth() &&
 340  
                         getRoles().equals(other.getRoles()) &&
 341  
                         getConstraint().equals(other.getConstraint());
 342  
         }
 343  
 
 344  
         /**
 345  
          * @since 0.1.0
 346  
 
 347  
          *
 348  
          *
 349  
          */
 350  
         @Override
 351  
         protected int partHashCode () {
 352  12
                 return multiHashCode(
 353  
                         getAuthority() != null ? getAuthority().hashCode() : 0,
 354  
                         getSubjectDomain() != null ? getSubjectDomain().hashCode() : 0,
 355  
                         getDelegationDepth(),
 356  
                         getRoles().hashCode(),
 357  
                         getConstraint() != null ? getConstraint().hashCode() : 0
 358  
                 );
 359  
         }
 360  
 
 361  
         /**
 362  
          * @since 0.1.0
 363  
          */
 364  
         @Override
 365  
         protected String getSimpleClassName () {
 366  0
                 return RoleAssignmentRuleBean.class.getSimpleName();
 367  
         }
 368  
 
 369  
         /**
 370  
          * @since 0.1.0
 371  
          */
 372  
         @Override
 373  
         protected void appendPartDetails (StringBuilder sb) {
 374  0
                 appendDetails(sb, "authority", getIdentityDetails(getAuthority()));
 375  0
                 appendDetails(sb, "subjectDomain", getIdentityDetails(getSubjectDomain()));
 376  0
                 appendDetails(sb, "roles", getStringDetails(getRoles()));
 377  0
                 appendDetails(sb, "delegationStrategy", Integer.valueOf(getDelegationDepth()));
 378  0
         }
 379  
         
 380  
         //---- BasicPartBean
 381  
 
 382  
         /**
 383  
          * @since 0.1.0
 384  
          */
 385  
         @Override
 386  
         public PartBean findBySerialNumber (SerialNumber partSerialNumber) {
 387  3
                 PartBean bean = getAuthority().findBySerialNumber(partSerialNumber);
 388  3
                 if (bean != null) {
 389  1
                         return bean;
 390  
                 }
 391  
 
 392  2
                 bean = getSubjectDomain().findBySerialNumber(partSerialNumber);
 393  2
                 if (bean != null) {
 394  1
                         return bean;
 395  
                 }
 396  
 
 397  1
                 return super.findBySerialNumber(partSerialNumber);
 398  
         }
 399  
 
 400  
 }