View Javadoc
1   /**
2    * Copyright 2005-2014 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.ksb.messaging.web;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.apache.struts.action.ActionErrors;
20  import org.apache.struts.action.ActionForm;
21  import org.apache.struts.action.ActionForward;
22  import org.apache.struts.action.ActionMapping;
23  import org.apache.struts.action.ActionMessages;
24  import org.apache.struts.actions.DispatchAction;
25  import org.kuali.rice.core.api.util.RiceConstants;
26  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
27  import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator;
28  import org.kuali.rice.kim.api.KimConstants;
29  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
30  import org.kuali.rice.kns.util.WebUtils;
31  import org.kuali.rice.kns.web.struts.form.KualiForm;
32  import org.kuali.rice.krad.exception.AuthorizationException;
33  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
34  import org.kuali.rice.krad.service.KualiModuleService;
35  import org.kuali.rice.krad.service.ModuleService;
36  import org.kuali.rice.krad.util.GlobalVariables;
37  import org.kuali.rice.krad.util.KRADConstants;
38  import org.kuali.rice.krad.util.KRADUtils;
39  
40  import javax.servlet.http.HttpServletRequest;
41  import javax.servlet.http.HttpServletResponse;
42  import java.util.HashMap;
43  import java.util.Iterator;
44  import java.util.Map;
45  
46  /**
47   * An abstract super class for all Struts Actions in KEW.  Adds some custom
48   * dispatch behavior by extending the Struts DispatchAction.
49   *
50   * @author Kuali Rice Team (rice.collab@kuali.org)
51   */
52  public abstract class KSBAction extends DispatchAction {
53  
54  	private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KSBAction.class);
55  
56  	@Override
57  	public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
58  
59  		checkAuthorization(form, "");
60  		
61  		if(isModuleLocked(form, findMethodToCall(form, request), request)) {
62  		    return mapping.findForward(RiceConstants.MODULE_LOCKED_MAPPING);
63  		}
64  		
65  		try {
66  
67  			
68  			ActionMessages messages = null;
69  			messages = establishRequiredState(request, form);
70  			if (messages != null && !messages.isEmpty()) {
71  				// XXX: HACK: FIXME:
72  				// obviously this implies that we can't return both ActionErrors
73  				// and ActionMessages... :(
74  				// probably establishRequiredState should be refactored to have
75  				// a generic 'should-we-continue'
76  				// boolean return, so that control flow can be more explicitly
77  				// specified by the subclass
78  				if (messages instanceof ActionErrors) {
79  					saveErrors(request, messages);
80  				} else {
81  					saveMessages(request, messages);
82  				}
83  				return mapping.findForward("requiredStateError");
84  			}
85  			LOG.info(request.getQueryString());
86  			ActionForward returnForward = null;
87  
88  			if (request.getParameterMap() != null) {
89  				for (Iterator iter = request.getParameterMap().entrySet().iterator(); iter.hasNext();) {
90  					String parameterName = (String) ((Map.Entry) iter.next()).getKey();
91  					if (parameterName.startsWith("methodToCall.") && parameterName.endsWith(".x")) {
92  						String methodToCall = parameterName.substring(parameterName.indexOf("methodToCall.") + 13, parameterName.lastIndexOf(".x"));
93  						if (methodToCall != null && methodToCall.length() > 0) {
94  							returnForward = this.dispatchMethod(mapping, form, request, response, methodToCall);
95  						}
96  					}
97  				}
98  			}
99  			if (returnForward == null) {
100 				if (request.getParameter("methodToCall") != null && !"".equals(request.getParameter("methodToCall")) && !"execute".equals(request.getParameter("methodToCall"))) {
101 					LOG.info("dispatch to methodToCall " + request.getParameter("methodToCall") + " called");
102 					returnForward = super.execute(mapping, form, request, response);
103 				} else {
104 					LOG.info("dispatch to default start methodToCall");
105 					returnForward = start(mapping, form, request, response);
106 				}
107 			}
108 
109 			
110 			
111 			messages = establishFinalState(request, form);
112 			if (messages != null && !messages.isEmpty()) {
113 				saveMessages(request, messages);
114 				return mapping.findForward("finalStateError");
115 			}
116 			return returnForward;
117 		} catch (Exception e) {
118 			LOG.error("Error processing action " + mapping.getPath(), e);
119 			throw new RuntimeException(e);
120 		}
121 	}
122 	
123 	protected void checkAuthorization( ActionForm form, String methodToCall) throws AuthorizationException 
124     {
125     	String principalId = GlobalVariables.getUserSession().getPrincipalId();
126     	Map<String, String> roleQualifier = new HashMap<String, String>(getRoleQualification(form, methodToCall));
127     	Map<String, String> permissionDetails = KRADUtils.getNamespaceAndActionClass(this.getClass());
128     	
129         if (!KimApiServiceLocator.getPermissionService().isAuthorizedByTemplate(principalId,
130                 KRADConstants.KNS_NAMESPACE, KimConstants.PermissionTemplateNames.USE_SCREEN, permissionDetails,
131                 roleQualifier))
132         {
133         	throw new AuthorizationException(GlobalVariables.getUserSession().getPrincipalName(), 
134             		methodToCall,
135             		this.getClass().getSimpleName());
136         }
137     }
138     
139     /** 
140      * override this method to add data from the form for role qualification in the authorization check
141      */
142     protected Map<String,String> getRoleQualification(ActionForm form, String methodToCall) {
143     	return new HashMap<String,String>();
144     }
145 
146 	public abstract ActionForward start(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception;
147 
148 	public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
149 		return start(mapping, form, request, response);
150 	}
151 
152 	public abstract ActionMessages establishRequiredState(HttpServletRequest request, ActionForm form) throws Exception;
153 
154 	public ActionMessages establishFinalState(HttpServletRequest request, ActionForm form) throws Exception {
155 		return null;
156 	}
157 
158 	public ActionForward noOp(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
159 		return mapping.findForward("basic");
160 	}
161 	
162 	protected static KualiModuleService getKualiModuleService() {
163         return KRADServiceLocatorWeb.getKualiModuleService();
164     }
165 	
166 	protected String findMethodToCall(ActionForm form, HttpServletRequest request) throws Exception {
167 	    String methodToCall;
168 	    if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getMethodToCall())) {
169 	        methodToCall = ((KualiForm) form).getMethodToCall();
170 	    }
171 	    else {
172 	        // call utility method to parse the methodToCall from the request.
173 	        methodToCall = WebUtils.parseMethodToCall(form, request);
174 	    }
175 	    return methodToCall;
176 	}
177 
178 	protected boolean isModuleLocked(ActionForm form, String methodToCall, HttpServletRequest request) {
179 	    String boClass = request.getParameter(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE);
180 	    ModuleService moduleService = null;
181 	    if(StringUtils.isNotBlank(boClass)) {
182 	        try {
183 	            moduleService = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(Class.forName(boClass));
184 	        } catch (ClassNotFoundException e) {
185 	            LOG.warn("Module locking mechanism experienced a class not found exception while trying to load " + boClass, e);
186 	        }
187 	    } else {
188 	        moduleService = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(this.getClass());
189 	    }
190 	    if(moduleService != null && moduleService.isLocked()) {
191 	        String principalId = GlobalVariables.getUserSession().getPrincipalId();
192 	        String namespaceCode = KRADConstants.KUALI_RICE_SYSTEM_NAMESPACE;
193             String permissionName = KimConstants.PermissionNames.ACCESS_LOCKED_MODULE;
194 	        Map<String, String> permissionDetails = new HashMap<String, String>();
195 	        Map<String, String> qualification = new HashMap<String, String>(getRoleQualification(form, methodToCall));
196 	        if(!KimApiServiceLocator.getPermissionService().isAuthorized(principalId, namespaceCode, permissionName, qualification)) {
197                 ParameterService parameterSerivce = CoreFrameworkServiceLocator.getParameterService();
198                 String messageParamNamespaceCode = moduleService.getModuleConfiguration().getNamespaceCode();
199                 String messageParamComponentCode = KRADConstants.DetailTypes.ALL_DETAIL_TYPE;
200                 String messageParamName = KRADConstants.SystemGroupParameterNames.OLTP_LOCKOUT_MESSAGE_PARM;
201                 String lockoutMessage = parameterSerivce.getParameterValueAsString(messageParamNamespaceCode, messageParamComponentCode, messageParamName);
202                 
203                 if(StringUtils.isBlank(lockoutMessage)) {
204                     String defaultMessageParamName = KRADConstants.SystemGroupParameterNames.OLTP_LOCKOUT_DEFAULT_MESSAGE;
205                     lockoutMessage = parameterSerivce.getParameterValueAsString(KRADConstants.KNS_NAMESPACE, messageParamComponentCode, defaultMessageParamName);
206                 }
207                 request.setAttribute(KRADConstants.MODULE_LOCKED_MESSAGE_REQUEST_PARAMETER, lockoutMessage);
208                 return true;
209             }
210 	    }
211 	    return false;
212 	}
213 }