001 /** 002 * Copyright 2005-2012 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.rice.ksb.messaging.web; 017 018 import org.apache.commons.lang.StringUtils; 019 import org.apache.struts.action.ActionErrors; 020 import org.apache.struts.action.ActionForm; 021 import org.apache.struts.action.ActionForward; 022 import org.apache.struts.action.ActionMapping; 023 import org.apache.struts.action.ActionMessages; 024 import org.apache.struts.actions.DispatchAction; 025 import org.kuali.rice.core.api.util.RiceConstants; 026 import org.kuali.rice.coreservice.framework.parameter.ParameterService; 027 import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator; 028 import org.kuali.rice.kim.api.KimConstants; 029 import org.kuali.rice.kim.api.services.KimApiServiceLocator; 030 import org.kuali.rice.kns.util.WebUtils; 031 import org.kuali.rice.kns.web.struts.form.KualiForm; 032 import org.kuali.rice.krad.exception.AuthorizationException; 033 import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 034 import org.kuali.rice.krad.service.KualiModuleService; 035 import org.kuali.rice.krad.service.ModuleService; 036 import org.kuali.rice.krad.util.GlobalVariables; 037 import org.kuali.rice.krad.util.KRADConstants; 038 import org.kuali.rice.krad.util.KRADUtils; 039 040 import javax.servlet.http.HttpServletRequest; 041 import javax.servlet.http.HttpServletResponse; 042 import java.util.HashMap; 043 import java.util.Iterator; 044 import java.util.Map; 045 046 /** 047 * An abstract super class for all Struts Actions in KEW. Adds some custom 048 * dispatch behavior by extending the Struts DispatchAction. 049 * 050 * @author Kuali Rice Team (rice.collab@kuali.org) 051 */ 052 public abstract class KSBAction extends DispatchAction { 053 054 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KSBAction.class); 055 056 @Override 057 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 058 059 checkAuthorization(form, ""); 060 061 if(isModuleLocked(form, findMethodToCall(form, request), request)) { 062 return mapping.findForward(RiceConstants.MODULE_LOCKED_MAPPING); 063 } 064 065 try { 066 067 068 ActionMessages messages = null; 069 messages = establishRequiredState(request, form); 070 if (messages != null && !messages.isEmpty()) { 071 // XXX: HACK: FIXME: 072 // obviously this implies that we can't return both ActionErrors 073 // and ActionMessages... :( 074 // probably establishRequiredState should be refactored to have 075 // a generic 'should-we-continue' 076 // boolean return, so that control flow can be more explicitly 077 // specified by the subclass 078 if (messages instanceof ActionErrors) { 079 saveErrors(request, messages); 080 } else { 081 saveMessages(request, messages); 082 } 083 return mapping.findForward("requiredStateError"); 084 } 085 LOG.info(request.getQueryString()); 086 ActionForward returnForward = null; 087 088 if (request.getParameterMap() != null) { 089 for (Iterator iter = request.getParameterMap().entrySet().iterator(); iter.hasNext();) { 090 String parameterName = (String) ((Map.Entry) iter.next()).getKey(); 091 if (parameterName.startsWith("methodToCall.") && parameterName.endsWith(".x")) { 092 String methodToCall = parameterName.substring(parameterName.indexOf("methodToCall.") + 13, parameterName.lastIndexOf(".x")); 093 if (methodToCall != null && methodToCall.length() > 0) { 094 returnForward = this.dispatchMethod(mapping, form, request, response, methodToCall); 095 } 096 } 097 } 098 } 099 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 }