/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.sec.document; import java.util.HashMap; import org.kuali.kfs.sec.businessobject.SecurityDefinition; import org.kuali.kfs.sec.businessobject.SecurityModelMember; import org.kuali.kfs.sec.businessobject.SecurityPrincipal; import org.kuali.kfs.sec.businessobject.SecurityPrincipalDefinition; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.rice.core.api.membership.MemberType; import org.kuali.rice.kew.api.exception.WorkflowException; import org.kuali.rice.kim.api.role.Role; import org.kuali.rice.kim.api.role.RoleMember; import org.kuali.rice.kim.api.role.RoleService; import org.kuali.rice.kim.api.services.KimApiServiceLocator; import org.kuali.rice.kns.document.MaintenanceDocument; import org.kuali.rice.krad.bo.DocumentHeader; import org.kuali.rice.krad.service.DocumentService; import org.kuali.rice.krad.util.KRADConstants; /** * Maintainable implementation for the Security Principal maintenance document. Hooks into Post processing to create the KIM permissions for the principal and assign security role * members */ public class SecurityPrincipalMaintainableImpl extends AbstractSecurityModuleMaintainable { private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(SecurityPrincipalMaintainableImpl.class); /** * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#doRouteStatusChange(org.kuali.rice.krad.bo.DocumentHeader) */ @Override public void doRouteStatusChange(DocumentHeader documentHeader) { super.doRouteStatusChange(documentHeader); if (documentHeader.getWorkflowDocument().isProcessed()) { DocumentService documentService = SpringContext.getBean(DocumentService.class); try { MaintenanceDocument document = (MaintenanceDocument) documentService.getByDocumentHeaderId(documentHeader.getDocumentNumber()); SecurityPrincipal oldSecurityPrincipal = (SecurityPrincipal) document.getOldMaintainableObject().getBusinessObject(); SecurityPrincipal newSecurityPrincipal = (SecurityPrincipal) document.getNewMaintainableObject().getBusinessObject(); boolean newMaintenanceAction = getMaintenanceAction().equalsIgnoreCase(KRADConstants.MAINTENANCE_NEW_ACTION) || getMaintenanceAction().equalsIgnoreCase(KRADConstants.MAINTENANCE_COPY_ACTION); assignOrUpdatePrincipalMembershipToDefinitionRoles(oldSecurityPrincipal, newSecurityPrincipal, newMaintenanceAction); assignOrUpdatePrincipalModelRoles(newSecurityPrincipal); } catch (WorkflowException e) { LOG.error("caught exception while handling handleRouteStatusChange -> documentService.getByDocumentHeaderId(" + documentHeader.getDocumentNumber() + "). ", e); throw new RuntimeException("caught exception while handling handleRouteStatusChange -> documentService.getByDocumentHeaderId(" + documentHeader.getDocumentNumber() + "). ", e); } } } /** * Iterates through the principal definition list and assigns the principal to the definition role if necessary or updates the current member assignment * * @param oldSecurityPrincipal SecurityPrincipal before updates * @param newSecurityPrincipal SecurityPrincipal which contains the definition list and principal * @param newMaintenanceAction boolean indicating whether this is a new record (old side will not contain data) */ protected void assignOrUpdatePrincipalMembershipToDefinitionRoles(SecurityPrincipal oldSecurityPrincipal, SecurityPrincipal newSecurityPrincipal, boolean newMaintenanceAction) { RoleService roleService = KimApiServiceLocator.getRoleService(); String principalId = newSecurityPrincipal.getPrincipalId(); for (SecurityPrincipalDefinition securityPrincipalDefinition : newSecurityPrincipal.getPrincipalDefinitions()) { SecurityDefinition securityDefinition = securityPrincipalDefinition.getSecurityDefinition(); Role definitionRoleInfo = roleService.getRole(securityDefinition.getRoleId()); RoleMember principalMembershipInfo = null; if (!newMaintenanceAction) { SecurityPrincipalDefinition oldPrincipalDefinition = null; for (SecurityPrincipalDefinition principalDefinition : oldSecurityPrincipal.getPrincipalDefinitions()) { if ((principalDefinition.getPrincipalDefinitionId() != null) && principalDefinition.getPrincipalDefinitionId().equals(securityPrincipalDefinition.getPrincipalDefinitionId())) { oldPrincipalDefinition = principalDefinition; } } if (oldPrincipalDefinition != null) { principalMembershipInfo = getRoleMembershipForMemberType(definitionRoleInfo.getId(), principalId, MemberType.PRINCIPAL.getCode(), getRoleQualifiersFromSecurityModelDefinition(oldPrincipalDefinition)); } } // only create membership if principal definition record is active boolean membershipActive = securityPrincipalDefinition.isActive(); // if membership already exists, need to remove if the principal record is now inactive or the qualifications need updated if (principalMembershipInfo != null) { boolean qualificationsMatch = doMembershipQualificationsMatchValues(principalMembershipInfo.getAttributes(), securityPrincipalDefinition.getConstraintCode(), securityPrincipalDefinition.getOperatorCode(), securityPrincipalDefinition.getAttributeValue()); if (!membershipActive || !qualificationsMatch) { roleService.removePrincipalFromRole(principalMembershipInfo.getMemberId(), definitionRoleInfo.getNamespaceCode(), definitionRoleInfo.getName(), principalMembershipInfo.getAttributes()); } } // create of update role if membership should be active if (membershipActive) { if ( principalMembershipInfo == null ) { principalMembershipInfo = roleService.assignPrincipalToRole( principalId, definitionRoleInfo.getNamespaceCode(), definitionRoleInfo.getName(), getRoleQualifiersFromSecurityModelDefinition(securityPrincipalDefinition)); } else { RoleMember.Builder updatedRoleMember = RoleMember.Builder.create(principalMembershipInfo); updatedRoleMember.setAttributes(getRoleQualifiersFromSecurityModelDefinition(securityPrincipalDefinition)); updatedRoleMember.setMemberId(principalId); roleService.updateRoleMember(updatedRoleMember.build()); } } } } /** * Iterates through the principal model list and assigns the principal to the model role or updates the membership * * @param securityPrincipal SecurityPrincipal which contains the model list and principal */ protected void assignOrUpdatePrincipalModelRoles(SecurityPrincipal securityPrincipal) { RoleService roleService = KimApiServiceLocator.getRoleService(); String principalId = securityPrincipal.getPrincipalId(); for (SecurityModelMember principalModel : securityPrincipal.getPrincipalModels()) { Role modelRole = roleService.getRole(principalModel.getSecurityModel().getRoleId()); updateSecurityModelRoleMember(modelRole, principalModel, MemberType.PRINCIPAL.getCode(), principalId, new HashMap<String, String>(0)); } } }