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.validation.impl;
017    
018    import org.apache.commons.lang.StringUtils;
019    import org.kuali.kfs.sec.SecConstants;
020    import org.kuali.kfs.sec.SecKeyConstants;
021    import org.kuali.kfs.sec.SecPropertyConstants;
022    import org.kuali.kfs.sec.businessobject.SecurityModelDefinition;
023    import org.kuali.kfs.sec.businessobject.SecurityModelMember;
024    import org.kuali.kfs.sec.businessobject.SecurityPrincipal;
025    import org.kuali.kfs.sec.businessobject.SecurityPrincipalDefinition;
026    import org.kuali.kfs.sys.context.SpringContext;
027    import org.kuali.rice.kim.bo.entity.dto.KimPrincipalInfo;
028    import org.kuali.rice.kim.bo.group.dto.GroupInfo;
029    import org.kuali.rice.kim.bo.role.dto.KimRoleInfo;
030    import org.kuali.rice.kim.service.GroupService;
031    import org.kuali.rice.kim.service.IdentityManagementService;
032    import org.kuali.rice.kim.service.RoleManagementService;
033    import org.kuali.rice.kim.util.KimConstants;
034    import org.kuali.rice.kns.bo.PersistableBusinessObject;
035    import org.kuali.rice.kns.document.MaintenanceDocument;
036    import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase;
037    import org.kuali.rice.kns.util.GlobalVariables;
038    import org.kuali.rice.kns.util.KNSConstants;
039    import org.kuali.rice.kns.util.ObjectUtils;
040    
041    
042    /**
043     * Implements business rules checks on the SecurityPrincipal maintenance document
044     */
045    public class SecurityPrincipalRule extends MaintenanceDocumentRuleBase {
046        protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(SecurityPrincipalRule.class);
047    
048        private SecurityPrincipal oldSecurityPrincipal;
049        private SecurityPrincipal newSecurityPrincipal;
050    
051        public SecurityPrincipalRule() {
052            super();
053        }
054    
055        /**
056         * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomApproveDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument)
057         */
058        @Override
059        protected boolean processCustomApproveDocumentBusinessRules(MaintenanceDocument document) {
060            boolean isValid = super.processCustomApproveDocumentBusinessRules(document);
061    
062            isValid &= validateSecurityPrincipal();
063    
064            return isValid;
065        }
066    
067        /**
068         * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument)
069         */
070        @Override
071        protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) {
072            boolean isValid = super.processCustomRouteDocumentBusinessRules(document);
073    
074            isValid &= validateSecurityPrincipal();
075    
076            return isValid;
077        }
078    
079        /**
080         * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomAddCollectionLineBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument,
081         *      java.lang.String, org.kuali.rice.kns.bo.PersistableBusinessObject)
082         */
083        @Override
084        public boolean processCustomAddCollectionLineBusinessRules(MaintenanceDocument document, String collectionName, PersistableBusinessObject line) {
085            boolean isValid = super.processCustomAddCollectionLineBusinessRules(document, collectionName, line);
086    
087            if (SecPropertyConstants.PRINCIPAL_DEFINITIONS.equals(collectionName)) {
088                isValid &= validatePrincipalDefinition((SecurityPrincipalDefinition) line, "");
089            }
090    
091            return isValid;
092        }
093    
094        /**
095         * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#setupConvenienceObjects()
096         */
097        @Override
098        public void setupConvenienceObjects() {
099            oldSecurityPrincipal = (SecurityPrincipal) super.getOldBo();
100            newSecurityPrincipal = (SecurityPrincipal) super.getNewBo();
101        }
102    
103        /**
104         * Validates the new security principal record
105         * 
106         * @return boolean true if validation was successful, false if there are errors
107         */
108        protected boolean validateSecurityPrincipal() {
109            boolean isValid = true;
110    
111            int index = 0;
112            for (SecurityPrincipalDefinition principalDefinition : newSecurityPrincipal.getPrincipalDefinitions()) {
113                String errorKeyPrefix = KNSConstants.MAINTENANCE_NEW_MAINTAINABLE + SecPropertyConstants.PRINCIPAL_DEFINITIONS + "[" + index + "].";
114    
115                boolean principalDefinitionValid = validatePrincipalDefinition(principalDefinition, errorKeyPrefix);
116                if (!principalDefinitionValid) {
117                    isValid = false;
118                }
119    
120                index++;
121            }
122    
123            return isValid;
124        }
125    
126        /**
127         * Validates a definition assignment to the principal
128         * 
129         * @param principalDefinition SecurityPrincipalDefinition to validate
130         * @param errorKeyPrefix String errorPrefix to use if any errors are found
131         * @return boolean true if validation was successful, false if there are errors
132         */
133        protected boolean validatePrincipalDefinition(SecurityPrincipalDefinition principalDefinition, String errorKeyPrefix) {
134            boolean isValid = true;
135    
136            principalDefinition.refreshNonUpdateableReferences();
137            
138            if (ObjectUtils.isNull(principalDefinition.getSecurityDefinition())) {
139                return false;
140            }
141    
142            String attributeName = principalDefinition.getSecurityDefinition().getSecurityAttribute().getName();
143            String attributeValue = principalDefinition.getAttributeValue();
144            
145            // if value is blank (which is allowed) no need to validate
146            if (StringUtils.isBlank(attributeValue)) {
147                return true;
148            }
149    
150            // descend attributes do not allow multiple values or wildcards, and operator must be equal
151            if (SecConstants.SecurityAttributeNames.CHART_DESCEND_HIERARCHY.equals(attributeName) || SecConstants.SecurityAttributeNames.ORGANIZATION_DESCEND_HIERARCHY.equals(attributeName)) {
152                if (StringUtils.contains(attributeValue, SecConstants.SecurityValueSpecialCharacters.MULTI_VALUE_SEPERATION_CHARACTER)) {
153                    GlobalVariables.getMessageMap().putError(errorKeyPrefix + SecPropertyConstants.ATTRIBUTE_VALUE, SecKeyConstants.ERROR_MODEL_DEFINITION_MULTI_ATTR_VALUE, attributeName);
154                    isValid = false;
155                }
156    
157                if (StringUtils.contains(attributeValue, SecConstants.SecurityValueSpecialCharacters.WILDCARD_CHARACTER)) {
158                    GlobalVariables.getMessageMap().putError(errorKeyPrefix + SecPropertyConstants.ATTRIBUTE_VALUE, SecKeyConstants.ERROR_MODEL_DEFINITION_WILDCARD_ATTR_VALUE, attributeName);
159                    isValid = false;
160                }
161    
162                if (!SecConstants.SecurityDefinitionOperatorCodes.EQUAL.equals(principalDefinition.getOperatorCode())) {
163                    GlobalVariables.getMessageMap().putError(errorKeyPrefix + SecPropertyConstants.OPERATOR_CODE, SecKeyConstants.ERROR_MODEL_DEFINITION_OPERATOR_CODE_NOT_EQUAL, attributeName);
164                    isValid = false;
165                }
166            }
167    
168            // validate attribute value for existence
169            isValid = isValid && SecurityValidationUtil.validateAttributeValue(attributeName, attributeValue, errorKeyPrefix);
170    
171            return isValid;
172        }
173    
174    }