View Javadoc
1   /*
2    * Copyright 2009 The Kuali Foundation.
3    * 
4    * Licensed under the Educational Community License, Version 1.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    * http://www.opensource.org/licenses/ecl1.php
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.sec.document;
17  
18  import java.util.HashMap;
19  
20  import org.kuali.ole.sec.businessobject.SecurityDefinition;
21  import org.kuali.ole.sec.businessobject.SecurityModelMember;
22  import org.kuali.ole.sec.businessobject.SecurityPrincipal;
23  import org.kuali.ole.sec.businessobject.SecurityPrincipalDefinition;
24  import org.kuali.ole.sys.context.SpringContext;
25  import org.kuali.rice.core.api.membership.MemberType;
26  import org.kuali.rice.kew.api.exception.WorkflowException;
27  import org.kuali.rice.kim.api.role.Role;
28  import org.kuali.rice.kim.api.role.RoleMember;
29  import org.kuali.rice.kim.api.role.RoleService;
30  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
31  import org.kuali.rice.kns.document.MaintenanceDocument;
32  import org.kuali.rice.krad.bo.DocumentHeader;
33  import org.kuali.rice.krad.service.DocumentService;
34  import org.kuali.rice.krad.util.KRADConstants;
35  
36  
37  /**
38   * Maintainable implementation for the Security Principal maintenance document. Hooks into Post processing to create the KIM permissions for the principal and assign security role
39   * members
40   */
41  public class SecurityPrincipalMaintainableImpl extends AbstractSecurityModuleMaintainable {
42      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(SecurityPrincipalMaintainableImpl.class);
43  
44      /**
45       * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#doRouteStatusChange(org.kuali.rice.krad.bo.DocumentHeader)
46       */
47      @Override
48      public void doRouteStatusChange(DocumentHeader documentHeader) {
49          super.doRouteStatusChange(documentHeader);
50  
51          if (documentHeader.getWorkflowDocument().isProcessed()) {
52              DocumentService documentService = SpringContext.getBean(DocumentService.class);
53              try {
54                  MaintenanceDocument document = (MaintenanceDocument) documentService.getByDocumentHeaderId(documentHeader.getDocumentNumber());
55                  SecurityPrincipal oldSecurityPrincipal = (SecurityPrincipal) document.getOldMaintainableObject().getBusinessObject();
56                  SecurityPrincipal newSecurityPrincipal = (SecurityPrincipal) document.getNewMaintainableObject().getBusinessObject();
57  
58                  boolean newMaintenanceAction = getMaintenanceAction().equalsIgnoreCase(KRADConstants.MAINTENANCE_NEW_ACTION) || getMaintenanceAction().equalsIgnoreCase(KRADConstants.MAINTENANCE_COPY_ACTION);
59  
60                  assignOrUpdatePrincipalMembershipToDefinitionRoles(oldSecurityPrincipal, newSecurityPrincipal, newMaintenanceAction);
61                  assignOrUpdatePrincipalModelRoles(newSecurityPrincipal);
62              }
63              catch (WorkflowException e) {
64                  LOG.error("caught exception while handling handleRouteStatusChange -> documentService.getByDocumentHeaderId(" + documentHeader.getDocumentNumber() + "). ", e);
65                  throw new RuntimeException("caught exception while handling handleRouteStatusChange -> documentService.getByDocumentHeaderId(" + documentHeader.getDocumentNumber() + "). ", e);
66              }
67          }
68      }
69  
70      /**
71       * Iterates through the principal definition list and assigns the principal to the definition role if necessary or updates the current member assignment
72       * 
73       * @param oldSecurityPrincipal SecurityPrincipal before updates
74       * @param newSecurityPrincipal SecurityPrincipal which contains the definition list and principal
75       * @param newMaintenanceAction boolean indicating whether this is a new record (old side will not contain data)
76       */
77      protected void assignOrUpdatePrincipalMembershipToDefinitionRoles(SecurityPrincipal oldSecurityPrincipal, SecurityPrincipal newSecurityPrincipal, boolean newMaintenanceAction) {
78          RoleService roleService = KimApiServiceLocator.getRoleService();
79  
80          String principalId = newSecurityPrincipal.getPrincipalId();
81  
82          for (SecurityPrincipalDefinition securityPrincipalDefinition : newSecurityPrincipal.getPrincipalDefinitions()) {
83              SecurityDefinition securityDefinition = securityPrincipalDefinition.getSecurityDefinition();
84  
85              Role definitionRoleInfo = roleService.getRole(securityDefinition.getRoleId());
86              
87              RoleMember principalMembershipInfo = null;
88              if (!newMaintenanceAction) {
89                  SecurityPrincipalDefinition oldPrincipalDefinition = null;
90                  for (SecurityPrincipalDefinition principalDefinition : oldSecurityPrincipal.getPrincipalDefinitions()) {
91                     if ((principalDefinition.getPrincipalDefinitionId() != null) && principalDefinition.getPrincipalDefinitionId().equals(securityPrincipalDefinition.getPrincipalDefinitionId())) {
92                         oldPrincipalDefinition = principalDefinition;
93                     }
94                  }
95                  
96                  if (oldPrincipalDefinition != null) {
97                      principalMembershipInfo = getRoleMembershipForMemberType(definitionRoleInfo.getId(), principalId, MemberType.PRINCIPAL.getCode(), getRoleQualifiersFromSecurityModelDefinition(oldPrincipalDefinition));
98                  }
99              }
100 
101             // only create membership if principal definition record is active
102             boolean membershipActive = securityPrincipalDefinition.isActive();
103 
104             // if membership already exists, need to remove if the principal record is now inactive or the qualifications need updated
105             if (principalMembershipInfo != null) {
106                 boolean qualificationsMatch = doMembershipQualificationsMatchValues(principalMembershipInfo.getAttributes(), securityPrincipalDefinition.getConstraintCode(), securityPrincipalDefinition.getOperatorCode(), securityPrincipalDefinition.getAttributeValue());
107                 if (!membershipActive || !qualificationsMatch) {
108                     roleService.removePrincipalFromRole(principalMembershipInfo.getMemberId(), definitionRoleInfo.getNamespaceCode(), definitionRoleInfo.getName(), principalMembershipInfo.getAttributes());
109                 }
110             }
111 
112             // create of update role if membership should be active
113             if (membershipActive) {
114                 if ( principalMembershipInfo == null ) {
115                     principalMembershipInfo = roleService.assignPrincipalToRole( principalId, definitionRoleInfo.getNamespaceCode(), definitionRoleInfo.getName(), getRoleQualifiersFromSecurityModelDefinition(securityPrincipalDefinition));
116                 } else {
117                     RoleMember.Builder updatedRoleMember = RoleMember.Builder.create(principalMembershipInfo);
118                     updatedRoleMember.setAttributes(getRoleQualifiersFromSecurityModelDefinition(securityPrincipalDefinition));
119                     updatedRoleMember.setMemberId(principalId);
120                     roleService.updateRoleMember(updatedRoleMember.build());
121                 }
122             }
123         }
124     }
125 
126     /**
127      * Iterates through the principal model list and assigns the principal to the model role or updates the membership
128      * 
129      * @param securityPrincipal SecurityPrincipal which contains the model list and principal
130      */
131     protected void assignOrUpdatePrincipalModelRoles(SecurityPrincipal securityPrincipal) {
132         RoleService roleService = KimApiServiceLocator.getRoleService();
133         String principalId = securityPrincipal.getPrincipalId();
134 
135         for (SecurityModelMember principalModel : securityPrincipal.getPrincipalModels()) {
136             Role modelRole = roleService.getRole(principalModel.getSecurityModel().getRoleId());
137             updateSecurityModelRoleMember(modelRole, principalModel, MemberType.PRINCIPAL.getCode(), principalId, new HashMap<String, String>(0));
138         }
139     }
140 
141 }