View Javadoc
1   /**
2    * Copyright 2005-2016 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.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/ecl2.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.rice.kim.document.rule;
17  
18  import java.util.List;
19  import java.util.Map;
20  import java.util.regex.Matcher;
21  import java.util.regex.Pattern;
22  
23  import javax.xml.namespace.QName;
24  
25  import org.apache.commons.lang.StringUtils;
26  import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
27  import org.kuali.rice.core.api.uif.RemotableAttributeError;
28  import org.kuali.rice.core.api.util.RiceKeyConstants;
29  import org.kuali.rice.kim.api.common.template.Template;
30  import org.kuali.rice.kim.api.permission.Permission;
31  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
32  import org.kuali.rice.kim.api.type.KimType;
33  import org.kuali.rice.kim.framework.permission.PermissionTypeService;
34  import org.kuali.rice.kim.impl.permission.GenericPermissionBo;
35  import org.kuali.rice.kns.document.MaintenanceDocument;
36  import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase;
37  import org.kuali.rice.krad.util.GlobalVariables;
38  
39  /**
40   * This is a description of what this class does - kellerj don't forget to fill this in. 
41   * 
42   * @author Kuali Rice Team (rice.collab@kuali.org)
43   *
44   */
45  public class GenericPermissionMaintenanceDocumentRule extends MaintenanceDocumentRuleBase {
46      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(GenericPermissionMaintenanceDocumentRule.class);    
47      
48  	protected static final String DETAIL_VALUES_PROPERTY = "detailValues";
49      protected static final String NAMESPACE_CODE_PROPERTY = "namespaceCode";
50  	protected static final String ERROR_MESSAGE_PREFIX = "error.document.kim.genericpermission.";
51  	protected static final String ERROR_MISSING_TEMPLATE = ERROR_MESSAGE_PREFIX + "missingtemplate";
52  	protected static final String ERROR_UNKNOWN_ATTRIBUTE = ERROR_MESSAGE_PREFIX + "unknownattribute";
53  	protected static final String ERROR_ATTRIBUTE_VALIDATION = ERROR_MESSAGE_PREFIX + "attributevalidation";
54      protected static final String ERROR_NAMESPACE_AND_NAME_VALIDATION = ERROR_MESSAGE_PREFIX + "namespaceandnamevalidation";
55  
56  	
57  	@Override
58  	protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) {
59  		boolean rulesPassed = super.processCustomRouteDocumentBusinessRules( document );
60  		try {
61  			GenericPermissionBo newPerm = (GenericPermissionBo)getNewBo();
62              GenericPermissionBo oldPerm = (GenericPermissionBo)getOldBo();
63  			rulesPassed &= validateDetailValuesFormat(newPerm.getDetailValues());
64              if(StringUtils.isNotBlank(newPerm.getNamespaceCode()) && StringUtils.isNotBlank(newPerm.getName()) && StringUtils.isBlank(newPerm.getId())){
65                  rulesPassed &= validateNamespaceCodeAndName(newPerm.getNamespaceCode(), newPerm.getName());
66              }
67              // rule case for copy
68              if(StringUtils.isNotBlank(newPerm.getNamespaceCode()) &&
69                 StringUtils.isNotBlank(newPerm.getName()) &&
70                 StringUtils.isNotBlank(oldPerm.getId()) &&
71                 StringUtils.isNotBlank(newPerm.getId()) &&
72                 !StringUtils.equals(oldPerm.getId(), newPerm.getId())){
73                    rulesPassed &= validateNamespaceCodeAndName(newPerm.getNamespaceCode(), newPerm.getName());
74              }
75              // rule case for edit
76              if(StringUtils.isNotBlank(newPerm.getNamespaceCode()) &&
77                      StringUtils.isNotBlank(newPerm.getName()) &&
78                      StringUtils.isNotBlank(oldPerm.getId()) &&
79                      StringUtils.isNotBlank(newPerm.getId()) &&
80                      StringUtils.equals(oldPerm.getId(), newPerm.getId()) &&
81                      ( !StringUtils.equals(oldPerm.getNamespaceCode(), newPerm.getNamespaceCode()) ||
82                        !StringUtils.equals(oldPerm.getName(), newPerm.getName())
83                      )
84                 ) {
85                  rulesPassed &= validateNamespaceCodeAndName(newPerm.getNamespaceCode(), newPerm.getName());
86              }
87  			// detailValues
88  			// get the type from the template for validation
89              if(StringUtils.isNotBlank(newPerm.getTemplateId())){
90                  Template template = KimApiServiceLocator.getPermissionService().getPermissionTemplate(newPerm.getTemplateId());
91                  if ( template == null ) {
92                      GlobalVariables.getMessageMap().addToErrorPath( MAINTAINABLE_ERROR_PATH );
93                      GlobalVariables.getMessageMap().putError( DETAIL_VALUES_PROPERTY, ERROR_MISSING_TEMPLATE, newPerm.getTemplateId() );
94                      GlobalVariables.getMessageMap().removeFromErrorPath( MAINTAINABLE_ERROR_PATH );
95                      rulesPassed &= false;
96                  } else {
97                      KimType kimType = KimApiServiceLocator.getKimTypeInfoService().getKimType(template.getKimTypeId());
98                      Map<String, String> details = newPerm.getDetails();
99                      // check that add passed attributes are defined
100                     for ( String attributeName : details.keySet() ) {
101                         if ( kimType.getAttributeDefinitionByName(attributeName) == null ) {
102                             GlobalVariables.getMessageMap().addToErrorPath( MAINTAINABLE_ERROR_PATH );
103                             GlobalVariables.getMessageMap().putError( DETAIL_VALUES_PROPERTY, ERROR_UNKNOWN_ATTRIBUTE, attributeName, template.getNamespaceCode(), template.getName() );
104                             GlobalVariables.getMessageMap().removeFromErrorPath( MAINTAINABLE_ERROR_PATH );
105                             rulesPassed &= false;
106                         }
107                     }
108                     // if all attributes are known, pass to the service for validation
109                     if ( !GlobalVariables.getMessageMap().hasErrors() ) {
110                         PermissionTypeService service = getPermissionTypeService( kimType.getServiceName() );
111                         if ( service != null ) {
112                             List<RemotableAttributeError> validationErrors = service.validateAttributes( kimType.getId(), details);
113                             if ( validationErrors != null && !validationErrors.isEmpty() ) {
114                                 for ( RemotableAttributeError error : validationErrors ) {
115                                     GlobalVariables.getMessageMap().addToErrorPath( MAINTAINABLE_ERROR_PATH );
116                                     for (String errMsg : error.getErrors()) {
117                                         GlobalVariables.getMessageMap().putError( DETAIL_VALUES_PROPERTY, ERROR_ATTRIBUTE_VALIDATION, error.getAttributeName(), errMsg );
118                                     }
119                                     GlobalVariables.getMessageMap().removeFromErrorPath( MAINTAINABLE_ERROR_PATH );
120                                 }
121                                 rulesPassed &= false;
122                             }
123                         }
124                     }
125 
126                 }
127 
128             }
129 			// check each permission name against the type
130 		} catch ( RuntimeException ex ) {
131 			LOG.error( "Error in processCustomRouteDocumentBusinessRules()", ex );
132 			throw ex;
133 		}
134 		return rulesPassed;
135 	}
136 
137 	protected boolean validateDetailValuesFormat(String permissionDetailValues){
138 		if(permissionDetailValues != null){
139 			Pattern pattern = Pattern.compile(".+"+"="+".+");
140 			// ensure that all line delimiters are single linefeeds
141 			permissionDetailValues = permissionDetailValues.replace( "\r\n", "\n" );
142 			permissionDetailValues = permissionDetailValues.replace( '\r', '\n' );
143 			if(StringUtils.isNotBlank(permissionDetailValues)){
144 				String[] values = permissionDetailValues.split( "\n" );
145 				for(String attrib : values){
146                     Matcher matcher = pattern.matcher(attrib);
147                     if (!matcher.matches()) {
148                         GlobalVariables.getMessageMap().putError(
149                                 MAINTAINABLE_ERROR_PATH + "." + DETAIL_VALUES_PROPERTY,
150                                 RiceKeyConstants.ERROR_INVALID_FORMAT,
151                                 new String[]{"Detail Values", permissionDetailValues});
152                         return false;
153                     }
154 				}
155 			}
156 		}
157 		return true;
158 	}
159     protected boolean validateNamespaceCodeAndName(String namespaceCode,String name){
160         Permission permission = KimApiServiceLocator.getPermissionService().findPermByNamespaceCodeAndName(namespaceCode,name);
161         if(null != permission){
162             GlobalVariables.getMessageMap().putError(MAINTAINABLE_ERROR_PATH+"."+NAMESPACE_CODE_PROPERTY,ERROR_NAMESPACE_AND_NAME_VALIDATION,namespaceCode,name);
163             return false;
164         } else{
165             return true;
166         }
167     }
168 	
169 	protected PermissionTypeService getPermissionTypeService( String serviceName ) {
170     	if ( StringUtils.isBlank( serviceName ) ) {
171     		return null;
172     	}
173     	try {
174 	    	Object service = GlobalResourceLoader.getService(QName.valueOf(serviceName));
175 	    	// if we have a service name, it must exist
176 	    	if ( service == null ) {
177 				LOG.warn("null returned for permission type service for service name: " + serviceName);
178 	    	} else {
179 		    	// whatever we retrieved must be of the correct type
180 		    	if ( !(service instanceof PermissionTypeService)  ) {
181 		    		LOG.warn( "Service " + serviceName + " was not a KimPermissionTypeService.  Was: " + service.getClass().getName() );
182 		    		service = null;
183 		    	}
184 	    	}
185 	    	return (PermissionTypeService)service;
186     	} catch( Exception ex ) {
187     		LOG.error( "Error retrieving service: " + serviceName + " from the KimImplServiceLocator.", ex );
188     	}
189     	return null;
190     }
191 
192 }