View Javadoc

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