001 /*
002 * Copyright 2011 The Kuali Foundation.
003 *
004 * Licensed under the Educational Community License, Version 2.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/ecl2.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 */
016 package org.kuali.kfs.sec.document;
017
018 import java.util.Iterator;
019 import java.util.Map;
020
021 import org.apache.commons.lang.StringUtils;
022 import org.kuali.kfs.sec.SecConstants;
023 import org.kuali.kfs.sec.businessobject.SecurityDefinition;
024 import org.kuali.kfs.sec.businessobject.SecurityModelMember;
025 import org.kuali.kfs.sec.businessobject.SecurityPrincipal;
026 import org.kuali.kfs.sec.businessobject.SecurityPrincipalDefinition;
027 import org.kuali.kfs.sec.identity.SecKimAttributes;
028 import org.kuali.kfs.sec.util.KimUtil;
029 import org.kuali.kfs.sys.context.SpringContext;
030 import org.kuali.kfs.sys.document.FinancialSystemMaintainable;
031 import org.kuali.rice.kew.exception.WorkflowException;
032 import org.kuali.rice.kim.bo.role.dto.KimRoleInfo;
033 import org.kuali.rice.kim.bo.role.dto.RoleMembershipInfo;
034 import org.kuali.rice.kim.bo.types.dto.AttributeSet;
035 import org.kuali.rice.kim.service.IdentityManagementService;
036 import org.kuali.rice.kim.service.RoleManagementService;
037 import org.kuali.rice.kim.util.KimConstants;
038 import org.kuali.rice.kns.bo.DocumentHeader;
039 import org.kuali.rice.kns.bo.PersistableBusinessObject;
040 import org.kuali.rice.kns.document.MaintenanceDocument;
041 import org.kuali.rice.kns.service.DocumentService;
042 import org.kuali.rice.kns.util.KNSConstants;
043
044
045 /**
046 * Maintainable implementation for the Security Principal maintenance document. Hooks into Post processing to create the KIM permissions for the principal and assign security role
047 * members
048 */
049 public class SecurityPrincipalMaintainableImpl extends FinancialSystemMaintainable {
050 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(SecurityPrincipalMaintainableImpl.class);
051
052 /**
053 * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#refresh(java.lang.String, java.util.Map, org.kuali.rice.kns.document.MaintenanceDocument)
054 */
055 @Override
056 public void refresh(String refreshCaller, Map fieldValues, MaintenanceDocument document) {
057 super.refresh(refreshCaller, fieldValues, document);
058
059 this.getBusinessObject().refreshNonUpdateableReferences();
060 for (Iterator iterator = newCollectionLines.values().iterator(); iterator.hasNext();) {
061 PersistableBusinessObject businessObject = (PersistableBusinessObject) iterator.next();
062 businessObject.refreshNonUpdateableReferences();
063 }
064 }
065
066 /**
067 * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#doRouteStatusChange(org.kuali.rice.kns.bo.DocumentHeader)
068 */
069 @Override
070 public void doRouteStatusChange(DocumentHeader documentHeader) {
071 super.doRouteStatusChange(documentHeader);
072
073 if (documentHeader.getWorkflowDocument().stateIsProcessed()) {
074 DocumentService documentService = SpringContext.getBean(DocumentService.class);
075 try {
076 MaintenanceDocument document = (MaintenanceDocument) documentService.getByDocumentHeaderId(documentHeader.getDocumentNumber());
077 SecurityPrincipal oldSecurityPrincipal = (SecurityPrincipal) document.getOldMaintainableObject().getBusinessObject();
078 SecurityPrincipal newSecurityPrincipal = (SecurityPrincipal) document.getNewMaintainableObject().getBusinessObject();
079
080 boolean newMaintenanceAction = getMaintenanceAction().equalsIgnoreCase(KNSConstants.MAINTENANCE_NEW_ACTION) || getMaintenanceAction().equalsIgnoreCase(KNSConstants.MAINTENANCE_COPY_ACTION);
081
082 assignOrUpdatePrincipalMembershipToDefinitionRoles(oldSecurityPrincipal, newSecurityPrincipal, newMaintenanceAction);
083 assignOrUpdatePrincipalModelRoles(newSecurityPrincipal);
084
085 SpringContext.getBean(IdentityManagementService.class).flushAllCaches();
086 }
087 catch (WorkflowException e) {
088 LOG.error("caught exception while handling handleRouteStatusChange -> documentService.getByDocumentHeaderId(" + documentHeader.getDocumentNumber() + "). ", e);
089 throw new RuntimeException("caught exception while handling handleRouteStatusChange -> documentService.getByDocumentHeaderId(" + documentHeader.getDocumentNumber() + "). ", e);
090 }
091 }
092 }
093
094 /**
095 * Iterates through the principal definition list and assigns the principal to the definition role if necessary or updates the current member assignment
096 *
097 * @param oldSecurityPrincipal SecurityPrincipal before updates
098 * @param newSecurityPrincipal SecurityPrincipal which contains the definition list and principal
099 * @param newMaintenanceAction boolean indicating whether this is a new record (old side will not contain data)
100 */
101 protected void assignOrUpdatePrincipalMembershipToDefinitionRoles(SecurityPrincipal oldSecurityPrincipal, SecurityPrincipal newSecurityPrincipal, boolean newMaintenanceAction) {
102 RoleManagementService roleService = SpringContext.getBean(RoleManagementService.class);
103
104 String principalId = newSecurityPrincipal.getPrincipalId();
105
106 for (SecurityPrincipalDefinition securityPrincipalDefinition : newSecurityPrincipal.getPrincipalDefinitions()) {
107 SecurityDefinition securityDefinition = securityPrincipalDefinition.getSecurityDefinition();
108
109 KimRoleInfo definitionRoleInfo = roleService.getRole(securityDefinition.getRoleId());
110
111 RoleMembershipInfo principalMembershipInfo = null;
112 if (!newMaintenanceAction) {
113 SecurityPrincipalDefinition oldPrincipalDefinition = null;
114 for (SecurityPrincipalDefinition principalDefinition : oldSecurityPrincipal.getPrincipalDefinitions()) {
115 if ((principalDefinition.getPrincipalDefinitionId() != null) && principalDefinition.getPrincipalDefinitionId().equals(securityPrincipalDefinition.getPrincipalDefinitionId())) {
116 oldPrincipalDefinition = principalDefinition;
117 }
118 }
119
120 if (oldPrincipalDefinition != null) {
121 AttributeSet membershipQualifications = new AttributeSet();
122 membershipQualifications.put(SecKimAttributes.CONSTRAINT_CODE, oldPrincipalDefinition.getConstraintCode());
123 membershipQualifications.put(SecKimAttributes.OPERATOR, oldPrincipalDefinition.getOperatorCode());
124 membershipQualifications.put(SecKimAttributes.PROPERTY_VALUE, oldPrincipalDefinition.getAttributeValue());
125 membershipQualifications.put(SecKimAttributes.OVERRIDE_DENY, Boolean.toString(oldPrincipalDefinition.isOverrideDeny()));
126
127 principalMembershipInfo = KimUtil.getRoleMembershipInfoForMemberType(definitionRoleInfo.getRoleId(), principalId, KimConstants.KimUIConstants.MEMBER_TYPE_PRINCIPAL_CODE, membershipQualifications);
128 }
129 }
130
131 // only create membership if principal definition record is active
132 boolean membershipActive = securityPrincipalDefinition.isActive();
133
134 // if membership already exists, need to remove if the principal record is now inactive or the qualifications need updated
135 String principalMembershipId = "";
136 if (principalMembershipInfo != null) {
137 principalMembershipId = principalMembershipInfo.getRoleMemberId();
138 boolean qualificationsMatch = KimUtil.doMembershipQualificationsMatchValues(principalMembershipInfo.getQualifier(), securityPrincipalDefinition.getConstraintCode(), securityPrincipalDefinition.getOperatorCode(), securityPrincipalDefinition.getAttributeValue());
139 if (!membershipActive || !qualificationsMatch) {
140 roleService.removeRoleFromRole(principalMembershipInfo.getMemberId(), definitionRoleInfo.getNamespaceCode(), definitionRoleInfo.getRoleName(), principalMembershipInfo.getQualifier());
141 }
142 }
143
144 // create of update role if membership should be active
145 if (membershipActive) {
146 AttributeSet membershipQualifications = new AttributeSet();
147 membershipQualifications.put(SecKimAttributes.CONSTRAINT_CODE, securityPrincipalDefinition.getConstraintCode());
148 membershipQualifications.put(SecKimAttributes.OPERATOR, securityPrincipalDefinition.getOperatorCode());
149 membershipQualifications.put(SecKimAttributes.PROPERTY_VALUE, securityPrincipalDefinition.getAttributeValue());
150 membershipQualifications.put(SecKimAttributes.OVERRIDE_DENY, Boolean.toString(securityPrincipalDefinition.isOverrideDeny()));
151
152 roleService.saveRoleMemberForRole(principalMembershipId, principalId, KimConstants.KimUIConstants.MEMBER_TYPE_PRINCIPAL_CODE, definitionRoleInfo.getRoleId(), membershipQualifications, null, null);
153 }
154 }
155 }
156
157 /**
158 * Iterates through the principal model list and assigns the principal to the model role or updates the membership
159 *
160 * @param securityPrincipal SecurityPrincipal which contains the model list and principal
161 */
162 protected void assignOrUpdatePrincipalModelRoles(SecurityPrincipal securityPrincipal) {
163 RoleManagementService roleService = SpringContext.getBean(RoleManagementService.class);
164
165 String principalId = securityPrincipal.getPrincipalId();
166
167 for (SecurityModelMember principalModel : securityPrincipal.getPrincipalModels()) {
168 KimRoleInfo modelRoleInfo = roleService.getRole(principalModel.getSecurityModel().getRoleId());
169
170 RoleMembershipInfo membershipInfo = KimUtil.getRoleMembershipInfoForMemberType(modelRoleInfo.getRoleId(), principalId, KimConstants.KimUIConstants.MEMBER_TYPE_PRINCIPAL_CODE, null);
171
172 String membershipId = "";
173 if (membershipInfo != null) {
174 membershipId = membershipInfo.getRoleMemberId();
175 }
176
177 java.sql.Date fromDate = null;
178 java.sql.Date toDate = null;
179 if ( principalModel.getActiveFromDate() != null ) {
180 fromDate = new java.sql.Date( principalModel.getActiveFromDate().getTime() );
181 }
182 if ( principalModel.getActiveToDate() != null ) {
183 toDate = new java.sql.Date( principalModel.getActiveToDate().getTime() );
184 }
185 roleService.saveRoleMemberForRole(membershipId, principalId, KimConstants.KimUIConstants.MEMBER_TYPE_PRINCIPAL_CODE, modelRoleInfo.getRoleId(), new AttributeSet(), fromDate, toDate);
186 }
187 }
188
189 }