001/* 002 * Copyright 2009 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 1.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl1.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.ole.sec.document; 017 018import java.util.HashMap; 019 020import org.kuali.ole.sec.businessobject.SecurityDefinition; 021import org.kuali.ole.sec.businessobject.SecurityModelMember; 022import org.kuali.ole.sec.businessobject.SecurityPrincipal; 023import org.kuali.ole.sec.businessobject.SecurityPrincipalDefinition; 024import org.kuali.ole.sys.context.SpringContext; 025import org.kuali.rice.core.api.membership.MemberType; 026import org.kuali.rice.kew.api.exception.WorkflowException; 027import org.kuali.rice.kim.api.role.Role; 028import org.kuali.rice.kim.api.role.RoleMember; 029import org.kuali.rice.kim.api.role.RoleService; 030import org.kuali.rice.kim.api.services.KimApiServiceLocator; 031import org.kuali.rice.kns.document.MaintenanceDocument; 032import org.kuali.rice.krad.bo.DocumentHeader; 033import org.kuali.rice.krad.service.DocumentService; 034import org.kuali.rice.krad.util.KRADConstants; 035 036 037/** 038 * Maintainable implementation for the Security Principal maintenance document. Hooks into Post processing to create the KIM permissions for the principal and assign security role 039 * members 040 */ 041public class SecurityPrincipalMaintainableImpl extends AbstractSecurityModuleMaintainable { 042 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(SecurityPrincipalMaintainableImpl.class); 043 044 /** 045 * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#doRouteStatusChange(org.kuali.rice.krad.bo.DocumentHeader) 046 */ 047 @Override 048 public void doRouteStatusChange(DocumentHeader documentHeader) { 049 super.doRouteStatusChange(documentHeader); 050 051 if (documentHeader.getWorkflowDocument().isProcessed()) { 052 DocumentService documentService = SpringContext.getBean(DocumentService.class); 053 try { 054 MaintenanceDocument document = (MaintenanceDocument) documentService.getByDocumentHeaderId(documentHeader.getDocumentNumber()); 055 SecurityPrincipal oldSecurityPrincipal = (SecurityPrincipal) document.getOldMaintainableObject().getBusinessObject(); 056 SecurityPrincipal newSecurityPrincipal = (SecurityPrincipal) document.getNewMaintainableObject().getBusinessObject(); 057 058 boolean newMaintenanceAction = getMaintenanceAction().equalsIgnoreCase(KRADConstants.MAINTENANCE_NEW_ACTION) || getMaintenanceAction().equalsIgnoreCase(KRADConstants.MAINTENANCE_COPY_ACTION); 059 060 assignOrUpdatePrincipalMembershipToDefinitionRoles(oldSecurityPrincipal, newSecurityPrincipal, newMaintenanceAction); 061 assignOrUpdatePrincipalModelRoles(newSecurityPrincipal); 062 } 063 catch (WorkflowException e) { 064 LOG.error("caught exception while handling handleRouteStatusChange -> documentService.getByDocumentHeaderId(" + documentHeader.getDocumentNumber() + "). ", e); 065 throw new RuntimeException("caught exception while handling handleRouteStatusChange -> documentService.getByDocumentHeaderId(" + documentHeader.getDocumentNumber() + "). ", e); 066 } 067 } 068 } 069 070 /** 071 * Iterates through the principal definition list and assigns the principal to the definition role if necessary or updates the current member assignment 072 * 073 * @param oldSecurityPrincipal SecurityPrincipal before updates 074 * @param newSecurityPrincipal SecurityPrincipal which contains the definition list and principal 075 * @param newMaintenanceAction boolean indicating whether this is a new record (old side will not contain data) 076 */ 077 protected void assignOrUpdatePrincipalMembershipToDefinitionRoles(SecurityPrincipal oldSecurityPrincipal, SecurityPrincipal newSecurityPrincipal, boolean newMaintenanceAction) { 078 RoleService roleService = KimApiServiceLocator.getRoleService(); 079 080 String principalId = newSecurityPrincipal.getPrincipalId(); 081 082 for (SecurityPrincipalDefinition securityPrincipalDefinition : newSecurityPrincipal.getPrincipalDefinitions()) { 083 SecurityDefinition securityDefinition = securityPrincipalDefinition.getSecurityDefinition(); 084 085 Role definitionRoleInfo = roleService.getRole(securityDefinition.getRoleId()); 086 087 RoleMember principalMembershipInfo = null; 088 if (!newMaintenanceAction) { 089 SecurityPrincipalDefinition oldPrincipalDefinition = null; 090 for (SecurityPrincipalDefinition principalDefinition : oldSecurityPrincipal.getPrincipalDefinitions()) { 091 if ((principalDefinition.getPrincipalDefinitionId() != null) && principalDefinition.getPrincipalDefinitionId().equals(securityPrincipalDefinition.getPrincipalDefinitionId())) { 092 oldPrincipalDefinition = principalDefinition; 093 } 094 } 095 096 if (oldPrincipalDefinition != null) { 097 principalMembershipInfo = getRoleMembershipForMemberType(definitionRoleInfo.getId(), principalId, MemberType.PRINCIPAL.getCode(), getRoleQualifiersFromSecurityModelDefinition(oldPrincipalDefinition)); 098 } 099 } 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}