diff --git a/voila-runtime-core/src/main/java/it/mice/voila/runtime/entity/OperationLogMessage.java b/voila-runtime-core/src/main/java/it/mice/voila/runtime/entity/OperationLogMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..f658e13b57a2f1fbe632d88ffbeed0ec58ba2bae --- /dev/null +++ b/voila-runtime-core/src/main/java/it/mice/voila/runtime/entity/OperationLogMessage.java @@ -0,0 +1,79 @@ +package it.mice.voila.runtime.entity; + +import java.io.Serializable; + +import org.apache.commons.lang.StringUtils; + +public class OperationLogMessage implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -780557000199729696L; + + private String applicationId; + private Integer operationId; + private String operationName; + private String ipAddress; + private String logDescription; + private String createUser; + + + public OperationLogMessage() { + super(); + } + + public OperationLogMessage(String message) { + String[] array = StringUtils.splitByWholeSeparatorPreserveAllTokens(message, "|"); + int ctr = 0; + setCreateUser(array[ctr++]); + setIpAddress(array[ctr++]); + setApplicationId(array[ctr++]); + setOperationId(Integer.parseInt(array[ctr++])); + setOperationName(array[ctr++]); + setLogDescription(array[ctr++]); + } + + public String getApplicationId() { + return applicationId; + } + public void setApplicationId(String applicationId) { + this.applicationId = applicationId; + } + public Integer getOperationId() { + return operationId; + } + public void setOperationId(Integer operationId) { + this.operationId = operationId; + } + public String getOperationName() { + return operationName; + } + public void setOperationName(String operationName) { + this.operationName = operationName; + } + public String getIpAddress() { + return ipAddress; + } + public void setIpAddress(String ipAddress) { + this.ipAddress = ipAddress; + } + public String getLogDescription() { + return logDescription; + } + public void setLogDescription(String logDescription) { + this.logDescription = logDescription; + } + public String getCreateUser() { + return createUser; + } + public void setCreateUser(String createUser) { + this.createUser = createUser; + } + @Override + public String toString() { + StringBuffer result = new StringBuffer(); + result.append(createUser).append("|").append(ipAddress).append("|").append(applicationId).append("|").append(operationId).append("|").append(operationName).append("|").append(logDescription); + return result.toString(); + } +} diff --git a/voila-runtime-core/src/main/java/it/mice/voila/runtime/events/OperationSuccessEvent.java b/voila-runtime-core/src/main/java/it/mice/voila/runtime/events/OperationSuccessEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..1a2c30f0c9a3e5448b61202a13ed2f036eaf8206 --- /dev/null +++ b/voila-runtime-core/src/main/java/it/mice/voila/runtime/events/OperationSuccessEvent.java @@ -0,0 +1,27 @@ +package it.mice.voila.runtime.events; + +import org.springframework.context.ApplicationEvent; + +public class OperationSuccessEvent extends ApplicationEvent { + + /** + * + */ + private static final long serialVersionUID = 287900488693677498L; + + private Object form; + + public OperationSuccessEvent(Object source, Object form) { + super(source); + this.form = form; + } + + public Object getForm() { + return form; + } + + public void setForm(Object form) { + this.form = form; + } + +} diff --git a/voila-runtime-core/src/main/java/it/mice/voila/runtime/log4j/AbstractAuditLoggerJdbcAppender.java b/voila-runtime-core/src/main/java/it/mice/voila/runtime/log4j/AbstractAuditLoggerJdbcAppender.java new file mode 100644 index 0000000000000000000000000000000000000000..8cdcc294fab674c28256ab1656d7a93010709311 --- /dev/null +++ b/voila-runtime-core/src/main/java/it/mice/voila/runtime/log4j/AbstractAuditLoggerJdbcAppender.java @@ -0,0 +1,96 @@ +/* + * Copyright 2009-2010 The MICE Project Team. + * Licensed under the MICE s.r.l. + * End User License Agreement + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.micegroup.it/voila/license.html + */ +package it.mice.voila.runtime.log4j; + +import java.util.ArrayList; + +import org.apache.log4j.spi.LoggingEvent; + +/** + * Logger provider che opportunamente pluggato tramite Log4J, consente di storicizzare gli audit records + * direttamente nella tabella di sicurezza: Security Operation Log. + */ +public abstract class AbstractAuditLoggerJdbcAppender extends org.apache.log4j.AppenderSkeleton + implements org.apache.log4j.Appender { + /** + * size of LoggingEvent buffer before writting to the database. + * Default is 1. + */ + protected int bufferSize = 1; + /** + * ArrayList holding the buffer of Logging Events. + */ + protected ArrayList buffer; + /** + * Helper object for clearing out the buffer + */ + protected ArrayList removes; + + public AbstractAuditLoggerJdbcAppender() { + super(); + buffer = new ArrayList(bufferSize); + removes = new ArrayList(bufferSize); + } + + /** + * {@inheritDoc} + * + * @see org.apache.log4j.Appender#close() + */ + public void close() { + } + + /** + * {@inheritDoc} + * + * @see org.apache.log4j.Appender#requiresLayout() + */ + public boolean requiresLayout() { + return false; + } + + /** + * {@inheritDoc} + * + * @see org.apache.log4j.AppenderSkeleton#append(org.apache.log4j.spi.LoggingEvent) + */ + @Override + protected void append(LoggingEvent event) { + event.getNDC(); + event.getThreadName(); + // Get a copy of this thread's MDC. + event.getMDCCopy(); + event.getRenderedMessage(); + event.getThrowableStrRep(); + buffer.add(event); + if (buffer.size() >= bufferSize) + flushBuffer(); + } + + /** + * loops through the buffer of LoggingEvents, gets a + * sql string from getLogStatement() and sends it to execute(). + * Errors are sent to the errorHandler. + * + * If a statement fails the LoggingEvent stays in the buffer! + */ + public abstract void flushBuffer(); + + /** + * By default getLogStatement sends the event to the required Layout object. + * The layout will format the given pattern into a workable SQL string. + * + * Overriding this provides direct access to the LoggingEvent + * when constructing the logging statement. + * + */ + protected String getLogStatement(LoggingEvent event) { + return event.getRenderedMessage(); + } +} \ No newline at end of file diff --git a/voila-runtime-mail/src/main/java/it/mice/voila/runtime/mail/listeners/MailEventConsumerListener.java b/voila-runtime-mail/src/main/java/it/mice/voila/runtime/mail/listeners/MailEventConsumerListener.java new file mode 100644 index 0000000000000000000000000000000000000000..6b5d6a8d826139b11bafabdf1121ffec9bf713b5 --- /dev/null +++ b/voila-runtime-mail/src/main/java/it/mice/voila/runtime/mail/listeners/MailEventConsumerListener.java @@ -0,0 +1,50 @@ +package it.mice.voila.runtime.mail.listeners; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; + +import it.mice.voila.runtime.events.OperationSuccessEvent; +import it.mice.voila.runtime.mail.beans.MailEvent; +import it.mice.voila.runtime.mail.manager.MailManager; + +public class MailEventConsumerListener implements ApplicationListener { + /** + * default logger. + */ + private static final Log LOGGER = LogFactory.getLog(MailEventConsumerListener.class); + + @Autowired + private MailManager mailManager; + + public void onApplicationEvent(OperationSuccessEvent event) { + String operationName = (String)event.getSource(); + String eventId = null; + if (operationName.startsWith("/manage/")) { + eventId = operationName.substring(8).replaceAll("\\/", "_").replaceAll("\\*", ""); + if (eventId.endsWith("_")) { + eventId = eventId.substring(0, eventId.length() - 1); + } + } else { + eventId = operationName; + } + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Received operation success event name " + operationName + ", resolved to mail event id " + eventId); + } + if (eventId != null) { + MailEvent mailEvent = mailManager.getMailEvents().get(eventId); + if (mailEvent != null) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Found mail event " + eventId + " for operation " + operationName + ", executing..."); + } + Map ctx = new HashMap(); + ctx.put("form", event.getForm()); + mailManager.sendEmailByEvent(mailEvent, ctx, null); + } + } + } +} diff --git a/voila-runtime-springmvc/src/main/java/it/mice/voila/runtime/springmvc/interceptors/AdvancedSecurityCheckInterceptor.java b/voila-runtime-springmvc/src/main/java/it/mice/voila/runtime/springmvc/interceptors/AdvancedSecurityCheckInterceptor.java index bccf2baeb99d965548f25abdea5c676da0c72796..ef80498ff0da2f337ca4c76312d6a73bdd0db09b 100644 --- a/voila-runtime-springmvc/src/main/java/it/mice/voila/runtime/springmvc/interceptors/AdvancedSecurityCheckInterceptor.java +++ b/voila-runtime-springmvc/src/main/java/it/mice/voila/runtime/springmvc/interceptors/AdvancedSecurityCheckInterceptor.java @@ -1,86 +1,70 @@ -package it.mice.voila.runtime.springmvc.interceptors; - -import it.mice.voila.runtime.exception.BusinessException; -import it.mice.voila.runtime.security.ProcessSecurityBean; -import it.mice.voila.runtime.springmvc.controller.DefaultController; -import it.mice.voila.runtime.springmvc.form.JfFormBean; -import it.mice.voila.runtime.springmvc.util.SpringMvcUtil; -import it.mice.voila.runtime.util.UserMessage; -import it.mice.voila.runtime.web.menu.MenuFilterManager; - -import java.util.Enumeration; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.core.MethodParameter; -import org.springframework.web.bind.support.WebRequestDataBinder; -import org.springframework.web.context.request.ServletWebRequest; -import org.springframework.web.context.request.WebRequest; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; - -public class AdvancedSecurityCheckInterceptor extends HandlerInterceptorAdapter { - Log log = LogFactory.getLog(AdvancedSecurityCheckInterceptor.class); - public static final String PERFORM_AUTH_RULE_SECURITY_CHECK = "performAuthRuleSecurityCheck"; - private MenuFilterManager menuFilterManager; - - /** - * @return the menuFilterManager - */ - public MenuFilterManager getMenuFilterManager() { - return menuFilterManager; - } - - /** - * @param menuFilterManager the menuFilterManager to set - */ - public void setMenuFilterManager(MenuFilterManager menuFilterManager) { - this.menuFilterManager = menuFilterManager; - } - - @Override - public boolean preHandle(HttpServletRequest request, - HttpServletResponse response, Object handler) throws Exception { - - Object handlerBean = SpringMvcUtil.getHandlerBean(handler); - if (handlerBean instanceof DefaultController) { - Boolean check = (Boolean)request.getAttribute(PERFORM_AUTH_RULE_SECURITY_CHECK); - if (check != null) { - JfFormBean form = getForm((HandlerMethod)handler); - if (form != null) { - ProcessSecurityBean bean = new ProcessSecurityBean(request.getServletPath(), null); - WebRequest webRequest = new ServletWebRequest(request, response); - WebRequestDataBinder binder = new WebRequestDataBinder(form); - binder.bind(webRequest); - - request.removeAttribute(PERFORM_AUTH_RULE_SECURITY_CHECK); - boolean isAuthorizationDenied = menuFilterManager.disableMenuItem(bean); - if (isAuthorizationDenied) { - UserMessage userMessage = new UserMessage("message.notAuthorizedUser"); - throw new BusinessException(userMessage); - } - } - } - } - return true; - } - - private JfFormBean getForm(HandlerMethod handler) { - Enumeration e = SpringMvcUtil.getSession().getAttributeNames(); - while (e.hasMoreElements()) { - String name = (String) e.nextElement(); - Object value = SpringMvcUtil.getSession().getAttribute(name); - if (value instanceof JfFormBean) { - for (MethodParameter method : handler.getMethodParameters()) { - if (method.getParameterType().isAssignableFrom(value.getClass())) { - return (JfFormBean)value; - } - } - } - } - return null; - } -} +package it.mice.voila.runtime.springmvc.interceptors; + +import it.mice.voila.runtime.exception.BusinessException; +import it.mice.voila.runtime.security.ProcessSecurityBean; +import it.mice.voila.runtime.springmvc.controller.DefaultController; +import it.mice.voila.runtime.springmvc.form.JfFormBean; +import it.mice.voila.runtime.springmvc.util.SpringMvcUtil; +import it.mice.voila.runtime.util.UserMessage; +import it.mice.voila.runtime.web.menu.MenuFilterManager; + +import java.util.Enumeration; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.core.MethodParameter; +import org.springframework.web.bind.support.WebRequestDataBinder; +import org.springframework.web.context.request.ServletWebRequest; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +public class AdvancedSecurityCheckInterceptor extends HandlerInterceptorAdapter { + Log log = LogFactory.getLog(AdvancedSecurityCheckInterceptor.class); + public static final String PERFORM_AUTH_RULE_SECURITY_CHECK = "performAuthRuleSecurityCheck"; + private MenuFilterManager menuFilterManager; + + /** + * @return the menuFilterManager + */ + public MenuFilterManager getMenuFilterManager() { + return menuFilterManager; + } + + /** + * @param menuFilterManager the menuFilterManager to set + */ + public void setMenuFilterManager(MenuFilterManager menuFilterManager) { + this.menuFilterManager = menuFilterManager; + } + + @Override + public boolean preHandle(HttpServletRequest request, + HttpServletResponse response, Object handler) throws Exception { + + Object handlerBean = SpringMvcUtil.getHandlerBean(handler); + if (handlerBean instanceof DefaultController) { + Boolean check = (Boolean)request.getAttribute(PERFORM_AUTH_RULE_SECURITY_CHECK); + if (check != null) { + JfFormBean form = SpringMvcUtil.getForm((HandlerMethod)handler); + if (form != null) { + ProcessSecurityBean bean = new ProcessSecurityBean(request.getServletPath(), null); + WebRequest webRequest = new ServletWebRequest(request, response); + WebRequestDataBinder binder = new WebRequestDataBinder(form); + binder.bind(webRequest); + + request.removeAttribute(PERFORM_AUTH_RULE_SECURITY_CHECK); + boolean isAuthorizationDenied = menuFilterManager.disableMenuItem(bean); + if (isAuthorizationDenied) { + UserMessage userMessage = new UserMessage("message.notAuthorizedUser"); + throw new BusinessException(userMessage); + } + } + } + } + return true; + } +} diff --git a/voila-runtime-springmvc/src/main/java/it/mice/voila/runtime/springmvc/interceptors/OperationAuditInterceptor.java b/voila-runtime-springmvc/src/main/java/it/mice/voila/runtime/springmvc/interceptors/OperationAuditInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..bb194322a5af02d956af35443c866f9a8cd1c8c6 --- /dev/null +++ b/voila-runtime-springmvc/src/main/java/it/mice/voila/runtime/springmvc/interceptors/OperationAuditInterceptor.java @@ -0,0 +1,100 @@ +package it.mice.voila.runtime.springmvc.interceptors; + +import java.io.StringWriter; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +import it.mice.voila.runtime.entity.OperationLogMessage; +import it.mice.voila.runtime.security.OperationConfigAttribute; +import it.mice.voila.runtime.security.SecurityUtils; +import it.mice.voila.runtime.springmvc.controller.DefaultController; +import it.mice.voila.runtime.springmvc.flashmap.FlashMap; +import it.mice.voila.runtime.springmvc.form.JfFormBean; +import it.mice.voila.runtime.springmvc.util.SpringMvcUtil; +import it.mice.voila.runtime.util.VelocityContextUtils; + +/** + * Spring mvc interceptor that mantain the path stack chain for go back facility. + */ +public class OperationAuditInterceptor extends HandlerInterceptorAdapter { + public static final String OPERATION_CONFIG_ATTRIBUTE = "OPERATION_CONFIG_ATTRIBUTE"; + /** + * default logger. + */ + Log log = LogFactory.getLog(OperationAuditInterceptor.class); + + @Autowired + private VelocityEngine velocityEngine; + + /* (non-Javadoc) + * @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter#afterCompletion(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception) + */ + @Override + public void afterCompletion(HttpServletRequest request, + HttpServletResponse response, Object handler, Exception ex) + throws Exception { + + OperationConfigAttribute operationConfigAttribute = (OperationConfigAttribute)SpringMvcUtil.getRequestParameterOrAttribute(OPERATION_CONFIG_ATTRIBUTE); + if (operationConfigAttribute == null) { + return; + } +// request.removeAttribute(OPERATION_CONFIG_ATTRIBUTE); + Object handlerBean = SpringMvcUtil.getHandlerBean(handler); + if (FlashMap.getMessages().hasErrors()) { + return; + } + if (handlerBean instanceof DefaultController) { + JfFormBean form = SpringMvcUtil.getForm((HandlerMethod)handler); + if (form != null && operationConfigAttribute.isAuditEnabled() && operationConfigAttribute.getAuditData() != null) { + try { + Map ctx = new HashMap(); + VelocityContext context = new VelocityContext(VelocityContextUtils.getVelocityContextToolsMap()); + ctx.put("form", form); +// ctx.put("user", authentication.getPrincipal()); +// ctx.put("roles", authentication.getAuthorities()); +// ctx.put("currentRole", currentRole); + + context.put("ctx", ctx); + + String logString = "AuditLog"; + StringWriter sw = new StringWriter(); + if (velocityEngine.evaluate(context, sw, logString, operationConfigAttribute.getAuditData())) { + if (log.isDebugEnabled()) + log.debug("Template value:\n" + operationConfigAttribute.getAuditData() + "\nWas converted to:" + sw.toString()); + + Log auditLog = LogFactory.getLog("voila.auditing." + operationConfigAttribute.getOperationName()); + + OperationLogMessage operationLogMessage = new OperationLogMessage(); + operationLogMessage.setApplicationId(operationConfigAttribute.getApplicationId()); + operationLogMessage.setOperationId(operationConfigAttribute.getOperationId()); + operationLogMessage.setOperationName(operationConfigAttribute.getOperationName()); + operationLogMessage.setIpAddress(SpringMvcUtil.getRequest().getRemoteHost()); + operationLogMessage.setLogDescription(sw.toString()); + operationLogMessage.setCreateUser(SecurityUtils.getCurrentUserId()); + + auditLog.info(operationLogMessage); + } else { + log.error("Failed to parse Velocity content for Auditing Data field template:" + operationConfigAttribute.getAuditData() + + ". Check content into column 'Audit Data' of the table 'Adf Elementary Operation' for operation id " + operationConfigAttribute.getOperationId() + ". Probably the content is not a valid Velocity script language."); + log.error("Error description:" + logString); + } + } catch (Exception e) { + log.error("Failed to parse Velocity content for Authorization Rule field template:\n" + operationConfigAttribute.getAuditData() + "\n" + + ". Check content into column 'Authorization Rule' of the table 'Adf Elementary Operation' for operation id " + operationConfigAttribute.getOperationId() + ". Probably the content is not a valid Velocity script language. Error:" + e.getLocalizedMessage()); + } + } + } + super.afterCompletion(request, response, handler, ex); + } +} diff --git a/voila-runtime-springmvc/src/main/java/it/mice/voila/runtime/springmvc/interceptors/PublishOperationSuccessEventInterceptor.java b/voila-runtime-springmvc/src/main/java/it/mice/voila/runtime/springmvc/interceptors/PublishOperationSuccessEventInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..a3424c3cc1cfa50d32f9f1880d2aee92b8254ec6 --- /dev/null +++ b/voila-runtime-springmvc/src/main/java/it/mice/voila/runtime/springmvc/interceptors/PublishOperationSuccessEventInterceptor.java @@ -0,0 +1,61 @@ +package it.mice.voila.runtime.springmvc.interceptors; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +import it.mice.voila.runtime.events.OperationSuccessEvent; +import it.mice.voila.runtime.security.OperationConfigAttribute; +import it.mice.voila.runtime.springmvc.controller.DefaultController; +import it.mice.voila.runtime.springmvc.flashmap.FlashMap; +import it.mice.voila.runtime.springmvc.form.JfFormBean; +import it.mice.voila.runtime.springmvc.util.SpringMvcUtil; + +/** + * Spring mvc interceptor that mantain the path stack chain for go back facility. + */ +public class PublishOperationSuccessEventInterceptor extends HandlerInterceptorAdapter implements ApplicationContextAware { + /** + * default logger. + */ + private static final Log LOGGER = LogFactory.getLog(PublishOperationSuccessEventInterceptor.class); + private ApplicationContext applicationContext; + /* (non-Javadoc) + * @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter#afterCompletion(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception) + */ + @Override + public void afterCompletion(HttpServletRequest request, + HttpServletResponse response, Object handler, Exception ex) + throws Exception { + + Object handlerBean = SpringMvcUtil.getHandlerBean(handler); + if (FlashMap.getMessages().hasErrors()) { + return; + } + OperationConfigAttribute operationConfigAttribute = (OperationConfigAttribute)SpringMvcUtil.getRequestParameterOrAttribute(OperationAuditInterceptor.OPERATION_CONFIG_ATTRIBUTE); + if (operationConfigAttribute == null) { + return; + } + if (handlerBean instanceof DefaultController) { + JfFormBean form = SpringMvcUtil.getForm((HandlerMethod)handler); + if (form != null) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Publish new operation success event for " + operationConfigAttribute); + } + applicationContext.publishEvent(new OperationSuccessEvent(operationConfigAttribute.getOperationName(), form)); + } + } + super.afterCompletion(request, response, handler, ex); + } + + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } +} diff --git a/voila-runtime-springmvc/src/main/java/it/mice/voila/runtime/springmvc/security/FilteredRoleAndOperationVoter.java b/voila-runtime-springmvc/src/main/java/it/mice/voila/runtime/springmvc/security/FilteredRoleAndOperationVoter.java index 899b6259c637f7bb6fabda4349969ac23defc2a3..944321910c9c57dabfc7af8a91ba9ce1305991cf 100644 --- a/voila-runtime-springmvc/src/main/java/it/mice/voila/runtime/springmvc/security/FilteredRoleAndOperationVoter.java +++ b/voila-runtime-springmvc/src/main/java/it/mice/voila/runtime/springmvc/security/FilteredRoleAndOperationVoter.java @@ -1,404 +1,398 @@ -/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package it.mice.voila.runtime.springmvc.security; - -import it.mice.voila.runtime.security.AbstractVoter; -import it.mice.voila.runtime.security.OperationConfigAttribute; -import it.mice.voila.runtime.security.OperationPerProfileConfigAttribute; -import it.mice.voila.runtime.security.RenderSecurityBean; -import it.mice.voila.runtime.security.SecurityBean; -import it.mice.voila.runtime.security.UserProfileGrantedAuthorityImpl; -import it.mice.voila.runtime.springmvc.flashmap.FlashMap; -import it.mice.voila.runtime.springmvc.interceptors.AdvancedSecurityCheckInterceptor; -import it.mice.voila.runtime.springmvc.util.SpringMvcUtil; -import it.mice.voila.runtime.util.UserMessage; -import it.mice.voila.runtime.util.UserMessages; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.security.access.AccessDecisionVoter; -import org.springframework.security.access.ConfigAttribute; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.web.FilterInvocation; - - - -/** - *

Votes if any {@link org.acegisecurity.ConfigAttribute#getAttribute()} starts with a prefix indicating that it is a role. The - * default prefix string is ROLE_, but this may be overriden to any value. It may also be set to empty, - * which means that essentially any attribute will be voted on. As described further below, the effect of an empty - * prefix may not be quite desireable.

- *

Abstains from voting if no configuration attribute commences with the role prefix. Votes to grant access if - * there is an exact matching {@link org.acegisecurity.GrantedAuthority} to a ConfigAttribute starting - * with the role prefix. Votes to deny access if there is no exact matching GrantedAuthority to a - * ConfigAttribute starting with the role prefix.

- *

An empty role prefix means that the voter will vote for every ConfigAttribute. When there are different - * categories of ConfigAttributes used, this will not be optimal since the voter will be voting for attributes which - * do not represent roles. However, this option may be of some use when using preexisting role names without a prefix, - * and no ability exists to prefix them with a role prefix on reading them in, such as provided for example in {@link - * org.acegisecurity.userdetails.jdbc.JdbcDaoImpl}.

- *

All comparisons and prefixes are case sensitive.

- * - * @author Ben Alex - * @author colin sampaleanu - * @version $Id: FilteredRoleAndOperationVoter.java,v 1.1 2007/02/27 00:18:05 zzy9v4 Exp $ - */ -public class FilteredRoleAndOperationVoter extends AbstractVoter implements AccessDecisionVoter { - private static final Log logger = LogFactory.getLog(FilteredRoleAndOperationVoter.class); - //~ Instance fields ================================================================================================ - private String alwaysEnabledOperationCode = "Y"; - private String disabledOperationCode = "N"; - - //~ Methods ======================================================================================================== - - public String getAlwaysEnabledOperationCode() { - return alwaysEnabledOperationCode; - } - - public void setAlwaysEnabledOperationCode(String alwaysEnabledOperationCode) { - this.alwaysEnabledOperationCode = alwaysEnabledOperationCode; - } - - public String getDisabledOperationCode() { - return disabledOperationCode; - } - - public void setDisabledOperationCode(String disabledOperationCode) { - this.disabledOperationCode = disabledOperationCode; - } - - public boolean supports(ConfigAttribute attribute) { - if ((attribute != null) && attribute instanceof OperationConfigAttribute) { - return true; - } else { - return false; - } - } - - /** - * This implementation supports any type of class, because it does not query the presented secure object. - * - * @param clazz the secure object - * @return always true - */ - public boolean supports(Class clazz) { - return true; - } - - public int vote(Authentication authentication, Object object, Collection config) { - int result = ACCESS_ABSTAIN; - if (getAuthenticationTrustResolver().isAnonymous(authentication)) { - return result; - } - UserMessages msgs = new UserMessages(); - //for each config attribute defined for the current operation... - Iterator iter = config.iterator(); - while (iter.hasNext()) { - ConfigAttribute attribute = iter.next(); - //if the attribute is supported (generally if start with ROLE_ prefix... - if (this.supports(attribute)) { - OperationConfigAttribute operationConfigAttribute = (OperationConfigAttribute) attribute; - if (operationConfigAttribute.isAuditEnabled()) { -// JfActionContext ctx = extractContext(object); -// if (ctx != null) { -// ctx.setApplicationId(operationConfigAttribute.getApplicationId()); -// ctx.setIdOperation(operationConfigAttribute.getOperationId()); -// ctx.setOperationName(operationConfigAttribute.getOperationName()); -// ctx.setAuditData(operationConfigAttribute.getAuditData()); -// ctx.setEnableAudit(operationConfigAttribute.isAuditEnabled()); -// } - } - - if (this.alwaysEnabledOperationCode.equals(operationConfigAttribute.getAllowDeniedFlag())) { - return ACCESS_GRANTED; - } - if (this.disabledOperationCode.equals(operationConfigAttribute.getAllowDeniedFlag())) { - //msgs.add(new UserMessage("authorization.disabledOperation")); - return finalizeMessageAndReturn(ACCESS_DENIED, msgs); - } - - //assume no match found - result = ACCESS_DENIED; - //ActionMessages actionMessages = new ActionMessages(); - UserProfileGrantedAuthorityImpl[] filteredGrantedAuthorities; - try { - filteredGrantedAuthorities = filterAuthenticationRoles(authentication); - } catch (Exception e) { - return result; - } - - // Attempt to find a matching granted authority - //Cycle thru the user profiles... - for (int i = 0; i < filteredGrantedAuthorities.length; i++) { - //Cycle thru the current operation enabled profiles... - for (int j = 0; j < operationConfigAttribute.getProfiles().length; j++) { - //Check if two profiles match. - if (operationConfigAttribute.getProfiles()[j].getProfileName().equals(filteredGrantedAuthorities[i].getJfAuthority().getProfileName())) { - //match found !!! - //Now check against operation rules... - if (checkForOperation( - filteredGrantedAuthorities[i], - authentication, object, - operationConfigAttribute, - operationConfigAttribute.getProfiles()[j], - msgs)) { - //Access granted !!! - return ACCESS_GRANTED; - } - } - } - } - //addActionMessageToExecutionContext(object, actionMessages); - } - } - return finalizeMessageAndReturn(result, msgs); - } - - private int finalizeMessageAndReturn(int result, UserMessages msgs) { - if (msgs.size() > 0) { - FlashMap.getMessages().addUserMessages(msgs); - } - return result; - } - - private boolean checkForOperation( - UserProfileGrantedAuthorityImpl userProfileGrantedAuthorityImpl, - Authentication authentication, - Object object, - OperationConfigAttribute operationConfigAttribute, - OperationPerProfileConfigAttribute operationPerProfileConfigAttribute, - UserMessages actionMessages) { - - boolean result = false; - //Determine authorization rule to be used by looking in the chain... - AuthorizationRule authorizationRule = determineAuthorizationRule(operationConfigAttribute, operationPerProfileConfigAttribute, object); - if (authorizationRule != null) { - if (object instanceof FilterInvocation && authorizationRule.authorizationRuleString != null) { - //La richiesta di autorizzazione è sata fatta da spring security, ma in questo preciso istante - //il form non è stato completamente popolato, pertanto viene bypassato tale controllato, ma viene - //ricordato all'interceptor di spring di intervenire uccessivamente in tal senso. - SpringMvcUtil.getRequest().setAttribute(AdvancedSecurityCheckInterceptor.PERFORM_AUTH_RULE_SECURITY_CHECK, Boolean.TRUE); - result = true; - } else { - result = checkForAuthRule(authorizationRule, object, - userProfileGrantedAuthorityImpl, authentication, - operationConfigAttribute, - operationPerProfileConfigAttribute, actionMessages); - } - } else { - //No authorization rule found, access granted. - if (logger.isDebugEnabled()) - logger.debug("Access granted without authorization rule evaluation!"); - result = true; - } - - return result; - } - - public boolean checkForAuthRule( - AuthorizationRule authorizationRule, - Object object, - UserProfileGrantedAuthorityImpl userProfileGrantedAuthorityImpl, - Authentication authentication, - OperationConfigAttribute operationConfigAttribute, - OperationPerProfileConfigAttribute operationPerProfileConfigAttribute, - UserMessages actionMessages) { - - boolean result = false; - //Authorization rule found, proceed... - Object ctx = extractContext(object); - if (ctx == null && - authorizationRule.authorizationRuleString != null && - authorizationRule.authorizationRuleString.indexOf("ctx.") > -1) - { - //This case cover situation where check authorization from menu render tag and submit button render tag is performed. - //In fact, in this situation, there is not an action context. - //In any case we ensure that the authorization rule contain reference with ctx to assume that the check - //need to be by-passed (to support auth check for auth rules with no run-time reference formulas). - result = true; - } else { - //build properties chain - StringBuffer propertySetters = preparePropertySetters(userProfileGrantedAuthorityImpl, authentication, operationConfigAttribute, operationPerProfileConfigAttribute); - - if (logger.isDebugEnabled()) - logger.debug("Evaluating elementary operation execution using velocity engine"); - - //evaluate authorization rule by using Velocity... - String velocityResult = evaluateVelocityTemplate(ctx, authorizationRule.authorizationRuleString, propertySetters, authentication, userProfileGrantedAuthorityImpl); - if (velocityResult == null || velocityResult.trim().length() == 0) { - //Velocity don't give a feedback, abstaining... - if (logger.isDebugEnabled()) - logger.debug("Abstaining for " + object + ". Velocity content for Authorization Rule field template:" + authorizationRule + " on profile " + userProfileGrantedAuthorityImpl); - result = true; - } else { - //Velocity give a feedback, check it... - if (velocityResult.equalsIgnoreCase("true")) { - //Velocity said TRUE !!! - if (logger.isDebugEnabled()) - logger.debug("Access granted after authorization rule evaluation!"); - result = true; - } else { - if (!(object instanceof RenderSecurityBean)) { - actionMessages.add(new UserMessage(authorizationRule.msgKey, authorizationRule.msgText)); - } - result = false; - } - } - } - return result; - } - - public UserProfileGrantedAuthorityImpl[] filterAuthenticationRoles(Authentication authentication) { - Collection filteredAuth = new ArrayList(); - Collection grantedAuthorities = authentication.getAuthorities(); - for (Iterator iterator = grantedAuthorities.iterator(); iterator - .hasNext();) { - GrantedAuthority grantedAuthority = (GrantedAuthority) iterator.next(); - if (checkProfileAssociation(authentication, (UserProfileGrantedAuthorityImpl) grantedAuthority)) { - filteredAuth.add(grantedAuthority); - } else { - if (logger.isInfoEnabled()) - logger.info("User profile filtered! Details:" + grantedAuthority); -// addActionMessage(actionMessages, -// "authorization.filteredProfile", -// null, -// new String[]{ -// ((UserProfileGrantedAuthorityImpl) grantedAuthorities[i]).getProfileName() -// } -// ); - } - } - if (filteredAuth.size() > 0) { - return (UserProfileGrantedAuthorityImpl[]) filteredAuth.toArray(new UserProfileGrantedAuthorityImpl[]{}); - } - return new UserProfileGrantedAuthorityImpl[]{}; - } - - private boolean checkProfileAssociation(Authentication authentication, UserProfileGrantedAuthorityImpl userProfileGrantedAuthority) { - //decide wich profile association rule must be processed - String profileAssociationRule = getQualifiedProfileAssociationRule(userProfileGrantedAuthority); - if (profileAssociationRule == null) { - if (logger.isTraceEnabled()) - logger.trace("No profile association rules found at any level for: " + userProfileGrantedAuthority + ", no check to perform."); - return true; - } - //Profile association rule found, execute it to verify if the profile is supported. - StringBuffer propertySetters = preparePropertySetters(userProfileGrantedAuthority, authentication, null, null); - if (logger.isDebugEnabled()) - logger.debug("Evaluating profile association using velocity engine for: " + userProfileGrantedAuthority); - String velocityResult = evaluateVelocityTemplate(null, profileAssociationRule, propertySetters, authentication, userProfileGrantedAuthority); - if (velocityResult == null || velocityResult.trim().length() == 0) { - return true; - } else { - return velocityResult.equalsIgnoreCase("true"); - } - } - - private String getQualifiedProfileAssociationRule(UserProfileGrantedAuthorityImpl userProfileGrantedAuthority) { - //If user/profile association level rule was found use this - if (userProfileGrantedAuthority.getProfilePerUserAssociationRule() != null) { - if (logger.isDebugEnabled()) - logger.debug("Check profile association using custom Profile Per User Association Rule:" + userProfileGrantedAuthority.getProfilePerUserAssociationRule()); - return userProfileGrantedAuthority.getProfilePerUserAssociationRule(); - } - //If profile level rule was found use this - if (userProfileGrantedAuthority.getProfileAssociationRule() != null) { - if (logger.isDebugEnabled()) - logger.debug("Check profile association using custom Profile Association Rule:" + userProfileGrantedAuthority.getProfileAssociationRule()); - return userProfileGrantedAuthority.getProfileAssociationRule(); - } - //If application level rule was found use this - if (getApplicationHolder() != null && getApplicationHolder().getProfileAssociationRule() != null) { - if (logger.isDebugEnabled()) - logger.debug("Check profile association using default Profile Association Rule at application level:" + getApplicationHolder().getProfileAssociationRule()); - return getApplicationHolder().getProfileAssociationRule(); - } - - //No profile association rules found at any level, no check to perform. - return null; - } - - private AuthorizationRule determineAuthorizationRule(OperationConfigAttribute operationConfigAttribute, OperationPerProfileConfigAttribute operationPerProfileConfigAttribute, Object object) { - String authorizationRule = null; - String msgKey = null; - String msgText = null; - if (object instanceof RenderSecurityBean) { - if (operationPerProfileConfigAttribute.getAuthorizationRuleRender() != null) { - authorizationRule = operationPerProfileConfigAttribute.getAuthorizationRuleRender(); - if (logger.isDebugEnabled()) - logger.debug("Vote using custom operation per profile authorization rule:" + authorizationRule + " on security config:" + operationConfigAttribute); - } else if (operationConfigAttribute.getAuthorizationRuleRender() != null) { - authorizationRule = operationConfigAttribute.getAuthorizationRuleRender(); - if (logger.isDebugEnabled()) - logger.debug("Vote using custom elementary operation authorization rule:" + authorizationRule + " on security config:" + operationConfigAttribute); - } else if (getApplicationHolder() != null) { - authorizationRule = getApplicationHolder().getAuthorizationRuleRender(); - if (logger.isDebugEnabled()) - logger.debug("Vote using default application level authorization rule:" + authorizationRule + " on security config:" + operationConfigAttribute); - } - } else { - if (operationPerProfileConfigAttribute.getAuthorizationRule() != null) { - authorizationRule = operationPerProfileConfigAttribute.getAuthorizationRule(); - if (logger.isDebugEnabled()) - logger.debug("Vote using custom operation per profile authorization rule:" + authorizationRule + " on security config:" + operationConfigAttribute); - } else if (operationConfigAttribute.getAuthorizationRule() != null) { - authorizationRule = operationConfigAttribute.getAuthorizationRule(); - if (logger.isDebugEnabled()) - logger.debug("Vote using custom elementary operation authorization rule:" + authorizationRule + " on security config:" + operationConfigAttribute); - } else if (getApplicationHolder() != null) { - authorizationRule = getApplicationHolder().getAuthorizationRule(); - if (logger.isDebugEnabled()) - logger.debug("Vote using default application level authorization rule:" + authorizationRule + " on security config:" + operationConfigAttribute); - } - } - - if (operationPerProfileConfigAttribute.getMsgKey() != null || operationPerProfileConfigAttribute.getMsgText() != null) { - msgKey = operationPerProfileConfigAttribute.getMsgKey(); - msgText = operationPerProfileConfigAttribute.getMsgText(); - } else if (operationConfigAttribute.getMsgKey() != null || operationConfigAttribute.getMsgText() != null) { - msgKey = operationConfigAttribute.getMsgKey(); - msgText = operationConfigAttribute.getMsgText(); - } - return new AuthorizationRule(authorizationRule, msgKey, msgText); - } - - private class AuthorizationRule { - private String authorizationRuleString; - private String msgKey; - private String msgText; - public AuthorizationRule(String authorizationRuleString, String msgKey, String msgText) { - this.authorizationRuleString = authorizationRuleString; - this.msgKey = msgKey; - this.msgText = msgText; - } - } - - protected Object extractContext(Object object) { - if (object instanceof SkyGenSecurityContext) { - return object; - } - if (object instanceof SecurityBean) { - return new SkyGenSecurityContext(((SecurityBean)object).getContext()); - } - SkyGenSecurityContext ctx = new SkyGenSecurityContext(); - return ctx; - } -} +/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package it.mice.voila.runtime.springmvc.security; + +import it.mice.voila.runtime.security.AbstractVoter; +import it.mice.voila.runtime.security.OperationConfigAttribute; +import it.mice.voila.runtime.security.OperationPerProfileConfigAttribute; +import it.mice.voila.runtime.security.RenderSecurityBean; +import it.mice.voila.runtime.security.SecurityBean; +import it.mice.voila.runtime.security.UserProfileGrantedAuthorityImpl; +import it.mice.voila.runtime.springmvc.flashmap.FlashMap; +import it.mice.voila.runtime.springmvc.interceptors.AdvancedSecurityCheckInterceptor; +import it.mice.voila.runtime.springmvc.interceptors.OperationAuditInterceptor; +import it.mice.voila.runtime.springmvc.util.SpringMvcUtil; +import it.mice.voila.runtime.util.UserMessage; +import it.mice.voila.runtime.util.UserMessages; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.security.access.AccessDecisionVoter; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.web.FilterInvocation; + + + +/** + *

Votes if any {@link org.acegisecurity.ConfigAttribute#getAttribute()} starts with a prefix indicating that it is a role. The + * default prefix string is ROLE_, but this may be overriden to any value. It may also be set to empty, + * which means that essentially any attribute will be voted on. As described further below, the effect of an empty + * prefix may not be quite desireable.

+ *

Abstains from voting if no configuration attribute commences with the role prefix. Votes to grant access if + * there is an exact matching {@link org.acegisecurity.GrantedAuthority} to a ConfigAttribute starting + * with the role prefix. Votes to deny access if there is no exact matching GrantedAuthority to a + * ConfigAttribute starting with the role prefix.

+ *

An empty role prefix means that the voter will vote for every ConfigAttribute. When there are different + * categories of ConfigAttributes used, this will not be optimal since the voter will be voting for attributes which + * do not represent roles. However, this option may be of some use when using preexisting role names without a prefix, + * and no ability exists to prefix them with a role prefix on reading them in, such as provided for example in {@link + * org.acegisecurity.userdetails.jdbc.JdbcDaoImpl}.

+ *

All comparisons and prefixes are case sensitive.

+ * + * @author Ben Alex + * @author colin sampaleanu + * @version $Id: FilteredRoleAndOperationVoter.java,v 1.1 2007/02/27 00:18:05 zzy9v4 Exp $ + */ +public class FilteredRoleAndOperationVoter extends AbstractVoter implements AccessDecisionVoter { + private static final Log logger = LogFactory.getLog(FilteredRoleAndOperationVoter.class); + //~ Instance fields ================================================================================================ + private String alwaysEnabledOperationCode = "Y"; + private String disabledOperationCode = "N"; + + //~ Methods ======================================================================================================== + + public String getAlwaysEnabledOperationCode() { + return alwaysEnabledOperationCode; + } + + public void setAlwaysEnabledOperationCode(String alwaysEnabledOperationCode) { + this.alwaysEnabledOperationCode = alwaysEnabledOperationCode; + } + + public String getDisabledOperationCode() { + return disabledOperationCode; + } + + public void setDisabledOperationCode(String disabledOperationCode) { + this.disabledOperationCode = disabledOperationCode; + } + + public boolean supports(ConfigAttribute attribute) { + if ((attribute != null) && attribute instanceof OperationConfigAttribute) { + return true; + } else { + return false; + } + } + + /** + * This implementation supports any type of class, because it does not query the presented secure object. + * + * @param clazz the secure object + * @return always true + */ + public boolean supports(Class clazz) { + return true; + } + + public int vote(Authentication authentication, Object object, Collection config) { + int result = ACCESS_ABSTAIN; + if (getAuthenticationTrustResolver().isAnonymous(authentication)) { + return result; + } + UserMessages msgs = new UserMessages(); + //for each config attribute defined for the current operation... + Iterator iter = config.iterator(); + while (iter.hasNext()) { + ConfigAttribute attribute = iter.next(); + //if the attribute is supported (generally if start with ROLE_ prefix... + if (this.supports(attribute)) { + OperationConfigAttribute operationConfigAttribute = (OperationConfigAttribute) attribute; + if (object instanceof FilterInvocation) { + SpringMvcUtil.getRequest().setAttribute(OperationAuditInterceptor.OPERATION_CONFIG_ATTRIBUTE, operationConfigAttribute); + } + + if (this.alwaysEnabledOperationCode.equals(operationConfigAttribute.getAllowDeniedFlag())) { + return ACCESS_GRANTED; + } + if (this.disabledOperationCode.equals(operationConfigAttribute.getAllowDeniedFlag())) { + //msgs.add(new UserMessage("authorization.disabledOperation")); + return finalizeMessageAndReturn(ACCESS_DENIED, msgs); + } + + //assume no match found + result = ACCESS_DENIED; + //ActionMessages actionMessages = new ActionMessages(); + UserProfileGrantedAuthorityImpl[] filteredGrantedAuthorities; + try { + filteredGrantedAuthorities = filterAuthenticationRoles(authentication); + } catch (Exception e) { + return result; + } + + // Attempt to find a matching granted authority + //Cycle thru the user profiles... + for (int i = 0; i < filteredGrantedAuthorities.length; i++) { + //Cycle thru the current operation enabled profiles... + for (int j = 0; j < operationConfigAttribute.getProfiles().length; j++) { + //Check if two profiles match. + if (operationConfigAttribute.getProfiles()[j].getProfileName().equals(filteredGrantedAuthorities[i].getJfAuthority().getProfileName())) { + //match found !!! + //Now check against operation rules... + if (checkForOperation( + filteredGrantedAuthorities[i], + authentication, object, + operationConfigAttribute, + operationConfigAttribute.getProfiles()[j], + msgs)) { + //Access granted !!! + return ACCESS_GRANTED; + } + } + } + } + //addActionMessageToExecutionContext(object, actionMessages); + } + } + return finalizeMessageAndReturn(result, msgs); + } + + private int finalizeMessageAndReturn(int result, UserMessages msgs) { + if (msgs.size() > 0) { + FlashMap.getMessages().addUserMessages(msgs); + } + return result; + } + + private boolean checkForOperation( + UserProfileGrantedAuthorityImpl userProfileGrantedAuthorityImpl, + Authentication authentication, + Object object, + OperationConfigAttribute operationConfigAttribute, + OperationPerProfileConfigAttribute operationPerProfileConfigAttribute, + UserMessages actionMessages) { + + boolean result = false; + //Determine authorization rule to be used by looking in the chain... + AuthorizationRule authorizationRule = determineAuthorizationRule(operationConfigAttribute, operationPerProfileConfigAttribute, object); + if (authorizationRule != null) { + if (object instanceof FilterInvocation && authorizationRule.authorizationRuleString != null) { + //La richiesta di autorizzazione è sata fatta da spring security, ma in questo preciso istante + //il form non è stato completamente popolato, pertanto viene bypassato tale controllato, ma viene + //ricordato all'interceptor di spring di intervenire uccessivamente in tal senso. + SpringMvcUtil.getRequest().setAttribute(AdvancedSecurityCheckInterceptor.PERFORM_AUTH_RULE_SECURITY_CHECK, Boolean.TRUE); + result = true; + } else { + result = checkForAuthRule(authorizationRule, object, + userProfileGrantedAuthorityImpl, authentication, + operationConfigAttribute, + operationPerProfileConfigAttribute, actionMessages); + } + } else { + //No authorization rule found, access granted. + if (logger.isDebugEnabled()) + logger.debug("Access granted without authorization rule evaluation!"); + result = true; + } + + return result; + } + + public boolean checkForAuthRule( + AuthorizationRule authorizationRule, + Object object, + UserProfileGrantedAuthorityImpl userProfileGrantedAuthorityImpl, + Authentication authentication, + OperationConfigAttribute operationConfigAttribute, + OperationPerProfileConfigAttribute operationPerProfileConfigAttribute, + UserMessages actionMessages) { + + boolean result = false; + //Authorization rule found, proceed... + Object ctx = extractContext(object); + if (ctx == null && + authorizationRule.authorizationRuleString != null && + authorizationRule.authorizationRuleString.indexOf("ctx.") > -1) + { + //This case cover situation where check authorization from menu render tag and submit button render tag is performed. + //In fact, in this situation, there is not an action context. + //In any case we ensure that the authorization rule contain reference with ctx to assume that the check + //need to be by-passed (to support auth check for auth rules with no run-time reference formulas). + result = true; + } else { + //build properties chain + StringBuffer propertySetters = preparePropertySetters(userProfileGrantedAuthorityImpl, authentication, operationConfigAttribute, operationPerProfileConfigAttribute); + + if (logger.isDebugEnabled()) + logger.debug("Evaluating elementary operation execution using velocity engine"); + + //evaluate authorization rule by using Velocity... + String velocityResult = evaluateVelocityTemplate(ctx, authorizationRule.authorizationRuleString, propertySetters, authentication, userProfileGrantedAuthorityImpl); + if (velocityResult == null || velocityResult.trim().length() == 0) { + //Velocity don't give a feedback, abstaining... + if (logger.isDebugEnabled()) + logger.debug("Abstaining for " + object + ". Velocity content for Authorization Rule field template:" + authorizationRule + " on profile " + userProfileGrantedAuthorityImpl); + result = true; + } else { + //Velocity give a feedback, check it... + if (velocityResult.equalsIgnoreCase("true")) { + //Velocity said TRUE !!! + if (logger.isDebugEnabled()) + logger.debug("Access granted after authorization rule evaluation!"); + result = true; + } else { + if (!(object instanceof RenderSecurityBean)) { + actionMessages.add(new UserMessage(authorizationRule.msgKey, authorizationRule.msgText)); + } + result = false; + } + } + } + return result; + } + + public UserProfileGrantedAuthorityImpl[] filterAuthenticationRoles(Authentication authentication) { + Collection filteredAuth = new ArrayList(); + Collection grantedAuthorities = authentication.getAuthorities(); + for (Iterator iterator = grantedAuthorities.iterator(); iterator + .hasNext();) { + GrantedAuthority grantedAuthority = (GrantedAuthority) iterator.next(); + if (checkProfileAssociation(authentication, (UserProfileGrantedAuthorityImpl) grantedAuthority)) { + filteredAuth.add(grantedAuthority); + } else { + if (logger.isInfoEnabled()) + logger.info("User profile filtered! Details:" + grantedAuthority); +// addActionMessage(actionMessages, +// "authorization.filteredProfile", +// null, +// new String[]{ +// ((UserProfileGrantedAuthorityImpl) grantedAuthorities[i]).getProfileName() +// } +// ); + } + } + if (filteredAuth.size() > 0) { + return (UserProfileGrantedAuthorityImpl[]) filteredAuth.toArray(new UserProfileGrantedAuthorityImpl[]{}); + } + return new UserProfileGrantedAuthorityImpl[]{}; + } + + private boolean checkProfileAssociation(Authentication authentication, UserProfileGrantedAuthorityImpl userProfileGrantedAuthority) { + //decide wich profile association rule must be processed + String profileAssociationRule = getQualifiedProfileAssociationRule(userProfileGrantedAuthority); + if (profileAssociationRule == null) { + if (logger.isTraceEnabled()) + logger.trace("No profile association rules found at any level for: " + userProfileGrantedAuthority + ", no check to perform."); + return true; + } + //Profile association rule found, execute it to verify if the profile is supported. + StringBuffer propertySetters = preparePropertySetters(userProfileGrantedAuthority, authentication, null, null); + if (logger.isDebugEnabled()) + logger.debug("Evaluating profile association using velocity engine for: " + userProfileGrantedAuthority); + String velocityResult = evaluateVelocityTemplate(null, profileAssociationRule, propertySetters, authentication, userProfileGrantedAuthority); + if (velocityResult == null || velocityResult.trim().length() == 0) { + return true; + } else { + return velocityResult.equalsIgnoreCase("true"); + } + } + + private String getQualifiedProfileAssociationRule(UserProfileGrantedAuthorityImpl userProfileGrantedAuthority) { + //If user/profile association level rule was found use this + if (userProfileGrantedAuthority.getProfilePerUserAssociationRule() != null) { + if (logger.isDebugEnabled()) + logger.debug("Check profile association using custom Profile Per User Association Rule:" + userProfileGrantedAuthority.getProfilePerUserAssociationRule()); + return userProfileGrantedAuthority.getProfilePerUserAssociationRule(); + } + //If profile level rule was found use this + if (userProfileGrantedAuthority.getProfileAssociationRule() != null) { + if (logger.isDebugEnabled()) + logger.debug("Check profile association using custom Profile Association Rule:" + userProfileGrantedAuthority.getProfileAssociationRule()); + return userProfileGrantedAuthority.getProfileAssociationRule(); + } + //If application level rule was found use this + if (getApplicationHolder() != null && getApplicationHolder().getProfileAssociationRule() != null) { + if (logger.isDebugEnabled()) + logger.debug("Check profile association using default Profile Association Rule at application level:" + getApplicationHolder().getProfileAssociationRule()); + return getApplicationHolder().getProfileAssociationRule(); + } + + //No profile association rules found at any level, no check to perform. + return null; + } + + private AuthorizationRule determineAuthorizationRule(OperationConfigAttribute operationConfigAttribute, OperationPerProfileConfigAttribute operationPerProfileConfigAttribute, Object object) { + String authorizationRule = null; + String msgKey = null; + String msgText = null; + if (object instanceof RenderSecurityBean) { + if (operationPerProfileConfigAttribute.getAuthorizationRuleRender() != null) { + authorizationRule = operationPerProfileConfigAttribute.getAuthorizationRuleRender(); + if (logger.isDebugEnabled()) + logger.debug("Vote using custom operation per profile authorization rule:" + authorizationRule + " on security config:" + operationConfigAttribute); + } else if (operationConfigAttribute.getAuthorizationRuleRender() != null) { + authorizationRule = operationConfigAttribute.getAuthorizationRuleRender(); + if (logger.isDebugEnabled()) + logger.debug("Vote using custom elementary operation authorization rule:" + authorizationRule + " on security config:" + operationConfigAttribute); + } else if (getApplicationHolder() != null) { + authorizationRule = getApplicationHolder().getAuthorizationRuleRender(); + if (logger.isDebugEnabled()) + logger.debug("Vote using default application level authorization rule:" + authorizationRule + " on security config:" + operationConfigAttribute); + } + } else { + if (operationPerProfileConfigAttribute.getAuthorizationRule() != null) { + authorizationRule = operationPerProfileConfigAttribute.getAuthorizationRule(); + if (logger.isDebugEnabled()) + logger.debug("Vote using custom operation per profile authorization rule:" + authorizationRule + " on security config:" + operationConfigAttribute); + } else if (operationConfigAttribute.getAuthorizationRule() != null) { + authorizationRule = operationConfigAttribute.getAuthorizationRule(); + if (logger.isDebugEnabled()) + logger.debug("Vote using custom elementary operation authorization rule:" + authorizationRule + " on security config:" + operationConfigAttribute); + } else if (getApplicationHolder() != null) { + authorizationRule = getApplicationHolder().getAuthorizationRule(); + if (logger.isDebugEnabled()) + logger.debug("Vote using default application level authorization rule:" + authorizationRule + " on security config:" + operationConfigAttribute); + } + } + + if (operationPerProfileConfigAttribute.getMsgKey() != null || operationPerProfileConfigAttribute.getMsgText() != null) { + msgKey = operationPerProfileConfigAttribute.getMsgKey(); + msgText = operationPerProfileConfigAttribute.getMsgText(); + } else if (operationConfigAttribute.getMsgKey() != null || operationConfigAttribute.getMsgText() != null) { + msgKey = operationConfigAttribute.getMsgKey(); + msgText = operationConfigAttribute.getMsgText(); + } + return new AuthorizationRule(authorizationRule, msgKey, msgText); + } + + private class AuthorizationRule { + private String authorizationRuleString; + private String msgKey; + private String msgText; + public AuthorizationRule(String authorizationRuleString, String msgKey, String msgText) { + this.authorizationRuleString = authorizationRuleString; + this.msgKey = msgKey; + this.msgText = msgText; + } + } + + protected Object extractContext(Object object) { + if (object instanceof SkyGenSecurityContext) { + return object; + } + if (object instanceof SecurityBean) { + return new SkyGenSecurityContext(((SecurityBean)object).getContext()); + } + SkyGenSecurityContext ctx = new SkyGenSecurityContext(); + return ctx; + } +} diff --git a/voila-runtime-springmvc/src/main/java/it/mice/voila/runtime/springmvc/util/SpringMvcUtil.java b/voila-runtime-springmvc/src/main/java/it/mice/voila/runtime/springmvc/util/SpringMvcUtil.java index 128f7c1148985eae001a3696c2746a772678a52e..016e7d7a6b550905c66d8f5e47c39581ea379dca 100644 --- a/voila-runtime-springmvc/src/main/java/it/mice/voila/runtime/springmvc/util/SpringMvcUtil.java +++ b/voila-runtime-springmvc/src/main/java/it/mice/voila/runtime/springmvc/util/SpringMvcUtil.java @@ -1,291 +1,310 @@ -package it.mice.voila.runtime.springmvc.util; - -import it.mice.voila.runtime.springmvc.bean.PathStack; -import it.mice.voila.runtime.springmvc.bean.PathStackElement; -import it.mice.voila.runtime.springmvc.flashmap.FlashMap; - -import java.io.IOException; -import java.util.Enumeration; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.web.context.request.RequestAttributes; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; -import org.springframework.web.method.HandlerMethod; - -/** - * Spring MVC Utility class. - * - */ -public class SpringMvcUtil { - /** - * default logger. - */ - private static final Log log = LogFactory.getLog(SpringMvcUtil.class); - /** - * The path stack identifier. - */ - public static final String PATH_STACK = SpringMvcUtil.class.getName() + ".pathStackForm"; - /** - * The last view name identifier. - */ - public static final String LAST_VIEW_NAME = SpringMvcUtil.class.getName() + ".lastViewNameForm"; - - /** - * Return the current http request. - * @return the current http request. - */ - public static HttpServletRequest getRequest() { - RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes(); - return ((ServletRequestAttributes)requestAttributes).getRequest(); - } - - /** - * Return the current http session. - * @return the current http session. - */ - public static HttpSession getSession() { - return getRequest().getSession(); - } - - /** - * Return the current servlet context. - * @return the current servlet context. - */ - public static ServletContext getServletContext() { - return getSession().getServletContext(); - } - - /** - * Return the path stack. - * @return the path stack. - */ - public static PathStack getStack() { - HttpSession session = getRequest().getSession(); - PathStack stack = (PathStack)session.getAttribute(PATH_STACK); - if (stack == null) { - stack = new PathStack(); - session.setAttribute(PATH_STACK, stack); - } - return stack; - } - - /** - * Return the url of the last path stack. - * @return url of the last path stack. - */ - public static String popLastStackPath() { - PathStack stack = SpringMvcUtil.getStack(); - if (stack.empty()) { - log.warn("Stack is empty but a redirect:goBack was requested. Continue anyway..."); - return getRequest().getContextPath() + "/home"; - } - return stack.pop().getPath(); - } - - /** - * Perform a response riderection to the last path. - * @param request the http request. - * @param response the http response - * @param requestURI the http request URI - * @param popCounter the number of steps to undo. - */ - public static void doLastPathRedirect(HttpServletRequest request, - HttpServletResponse response, String requestURI, int popCounter) { - doLastPathRedirect(request, response, requestURI, popCounter, null); - } - - /** - * Perform a response riderection to the last path. - * @param request the http request. - * @param response the http response - * @param requestURI the http request URI - * @param popCounter the number of steps to undo. - */ - public static void doLastPathRedirect(HttpServletRequest request, - HttpServletResponse response, String requestURI, int popCounter, String currentUri) { - PathStack stack = SpringMvcUtil.getStack(); - String lastStackPath = null; - try { - lastStackPath = stack.lastElement().getPath(); - } catch (Exception e) { - //No elements - } - if (stack.size() < popCounter) { - log.warn("Stack contains " + stack.size() + " elements, so the go back cannot work properly. Redirecting to the home page..."); - lastStackPath = request.getContextPath() + "/"; - stack.clear(); - } else { - for (int i=0; i < popCounter; i++) { - lastStackPath = stack.pop().getPath(); - } - if (currentUri != null && request.getMethod().equals("GET")) { - try { - while (StringUtils.contains(lastStackPath, currentUri)) { - lastStackPath = stack.pop().getPath(); - } - } catch (Exception e) { - lastStackPath = request.getContextPath() + "/"; - } - } - } - if (log.isDebugEnabled()) { - log.debug("GoBack is about to redirect navigation to " + lastStackPath); - } - - doRedirection(response, requestURI, ((lastStackPath!=null)? lastStackPath : request.getContextPath()+"/"), request); - } - - /** - * Perform a response riderection to the path just before the new activated flow. - * @param request the http request. - * @param response the http response - * @param requestURI the http request URI - */ - public static void doPrevFlowRedirect(HttpServletRequest request, - HttpServletResponse response, String requestURI) { - String lastStackPath = null; - PathStack stack = SpringMvcUtil.getStack(); - - PathStackElement element = null; - if (!stack.isEmpty()) { - element = stack.pop(); - while (!element.isNewFlow() && !stack.isEmpty()) { - element = stack.pop(); - } - } - - if (element == null || !element.isNewFlow()) { - log.warn("No start flow found into path stack but a special.endFlow was requested, so the go back cannot work properly. Redirecting to the home page..."); - lastStackPath = request.getContextPath() + "/home"; - stack.clear(); - } else { - //element = stack.pop(); - lastStackPath = element.getPath(); - if (log.isDebugEnabled()) { - log.debug("GoBack is about to redirect navigation to " + lastStackPath); - } - } - - doRedirection(response, requestURI, lastStackPath, request); - } - - /** - * Return the request attribute or the request parameter of the given name. - * @param name request attribute or the request parameter name. - * @return the value of the request attribute or the request parameter of the given name. - */ - public static Object getRequestParameterOrAttribute(String name) { - Object result = getRequest().getAttribute(name); - if (result == null) { - result = getRequest().getParameter(name); - } - return result; - } - - /** - * Perform a response riderection to the given lastStackPath. - * @param response the http response - * @param requestURI the http request URI - * @param lastStackPath the last stack path to redirect to. - */ - private static void doRedirection(HttpServletResponse response, - String requestURI, String lastStackPath, HttpServletRequest request) { - int pos = requestURI.indexOf("?"); - if (pos > -1) { - lastStackPath = appendQueryString(lastStackPath, requestURI.substring(pos+1)); - } else { - if (!StringUtils.isEmpty(request.getQueryString())) { - lastStackPath = appendQueryString(lastStackPath, request.getQueryString()); - } - } - try { - response.sendRedirect(response.encodeRedirectURL(lastStackPath)); - FlashMap.recycleIntoSession(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - public static String appendQueryString(String target, String chunk) { - String result = target; - if (result.indexOf("?") > -1) { - result += "&" + chunk; - } else { - result += "?" + chunk; - } - return result; - } - /** - * NOT UNIT TESTED Returns the URL (including query parameters) minus the - * scheme, host, and context path. This method probably be moved to a more - * general purpose class. - */ - public static String getRelativeUrl() { - HttpServletRequest request = getRequest(); - String baseUrl = null; - - baseUrl = getBaseUrl(); - StringBuffer buf = request.getRequestURL(); - - if (request.getQueryString() != null) { - buf.append("?"); - buf.append(request.getQueryString()); - } - - return buf.substring(baseUrl.length()); - } - - /** - * NOT UNIT TESTED Returns the base url (e.g, - * http://myhost:8080/myapp) suitable for using in a base tag or - * building reliable urls. - */ - public static String getBaseUrl() { - return getServerBaseUrl() + getRequest().getContextPath(); - } - - /** - * @param request - * @return - */ - public static String getServerBaseUrl() { - HttpServletRequest request = getRequest(); - String baseUrl; - if ((request.getServerPort() == 80) || (request.getServerPort() == 443)) { - baseUrl = request.getScheme() + "://" + request.getServerName(); - } else { - baseUrl = request.getScheme() + "://" + request.getServerName() - + ":" + request.getServerPort(); - } - return baseUrl; - } - - public static Object getApplicationAttribute(String name) { - return getServletContext().getAttribute(name); - } - - public static void cleanupSessionAttrsStartingWith(String prefix) { - Enumeration e = getSession().getAttributeNames(); - while (e.hasMoreElements()) { - String sessionElementName = (String) e.nextElement(); - if (sessionElementName.startsWith(prefix)) { - getSession().removeAttribute(sessionElementName); - } - } - } - - public static Object getHandlerBean(Object handler) { - if (handler instanceof HandlerMethod) { - return ((HandlerMethod)handler).getBean(); - } - return handler; - } -} +package it.mice.voila.runtime.springmvc.util; + +import it.mice.voila.runtime.springmvc.bean.PathStack; +import it.mice.voila.runtime.springmvc.bean.PathStackElement; +import it.mice.voila.runtime.springmvc.flashmap.FlashMap; +import it.mice.voila.runtime.springmvc.form.JfFormBean; + +import java.io.IOException; +import java.util.Enumeration; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.core.MethodParameter; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.web.method.HandlerMethod; + +/** + * Spring MVC Utility class. + * + */ +public class SpringMvcUtil { + /** + * default logger. + */ + private static final Log log = LogFactory.getLog(SpringMvcUtil.class); + /** + * The path stack identifier. + */ + public static final String PATH_STACK = SpringMvcUtil.class.getName() + ".pathStackForm"; + /** + * The last view name identifier. + */ + public static final String LAST_VIEW_NAME = SpringMvcUtil.class.getName() + ".lastViewNameForm"; + + /** + * Return the current http request. + * @return the current http request. + */ + public static HttpServletRequest getRequest() { + RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes(); + return ((ServletRequestAttributes)requestAttributes).getRequest(); + } + + /** + * Return the current http session. + * @return the current http session. + */ + public static HttpSession getSession() { + return getRequest().getSession(); + } + + /** + * Return the current servlet context. + * @return the current servlet context. + */ + public static ServletContext getServletContext() { + return getSession().getServletContext(); + } + + /** + * Return the path stack. + * @return the path stack. + */ + public static PathStack getStack() { + HttpSession session = getRequest().getSession(); + PathStack stack = (PathStack)session.getAttribute(PATH_STACK); + if (stack == null) { + stack = new PathStack(); + session.setAttribute(PATH_STACK, stack); + } + return stack; + } + + /** + * Return the url of the last path stack. + * @return url of the last path stack. + */ + public static String popLastStackPath() { + PathStack stack = SpringMvcUtil.getStack(); + if (stack.empty()) { + log.warn("Stack is empty but a redirect:goBack was requested. Continue anyway..."); + return getRequest().getContextPath() + "/home"; + } + return stack.pop().getPath(); + } + + /** + * Perform a response riderection to the last path. + * @param request the http request. + * @param response the http response + * @param requestURI the http request URI + * @param popCounter the number of steps to undo. + */ + public static void doLastPathRedirect(HttpServletRequest request, + HttpServletResponse response, String requestURI, int popCounter) { + doLastPathRedirect(request, response, requestURI, popCounter, null); + } + + /** + * Perform a response riderection to the last path. + * @param request the http request. + * @param response the http response + * @param requestURI the http request URI + * @param popCounter the number of steps to undo. + */ + public static void doLastPathRedirect(HttpServletRequest request, + HttpServletResponse response, String requestURI, int popCounter, String currentUri) { + PathStack stack = SpringMvcUtil.getStack(); + String lastStackPath = null; + try { + lastStackPath = stack.lastElement().getPath(); + } catch (Exception e) { + //No elements + } + if (stack.size() < popCounter) { + log.warn("Stack contains " + stack.size() + " elements, so the go back cannot work properly. Redirecting to the home page..."); + lastStackPath = request.getContextPath() + "/"; + stack.clear(); + } else { + for (int i=0; i < popCounter; i++) { + lastStackPath = stack.pop().getPath(); + } + if (currentUri != null && request.getMethod().equals("GET")) { + try { + while (StringUtils.contains(lastStackPath, currentUri)) { + lastStackPath = stack.pop().getPath(); + } + } catch (Exception e) { + lastStackPath = request.getContextPath() + "/"; + } + } + } + if (log.isDebugEnabled()) { + log.debug("GoBack is about to redirect navigation to " + lastStackPath); + } + + doRedirection(response, requestURI, ((lastStackPath!=null)? lastStackPath : request.getContextPath()+"/"), request); + } + + /** + * Perform a response riderection to the path just before the new activated flow. + * @param request the http request. + * @param response the http response + * @param requestURI the http request URI + */ + public static void doPrevFlowRedirect(HttpServletRequest request, + HttpServletResponse response, String requestURI) { + String lastStackPath = null; + PathStack stack = SpringMvcUtil.getStack(); + + PathStackElement element = null; + if (!stack.isEmpty()) { + element = stack.pop(); + while (!element.isNewFlow() && !stack.isEmpty()) { + element = stack.pop(); + } + } + + if (element == null || !element.isNewFlow()) { + log.warn("No start flow found into path stack but a special.endFlow was requested, so the go back cannot work properly. Redirecting to the home page..."); + lastStackPath = request.getContextPath() + "/home"; + stack.clear(); + } else { + //element = stack.pop(); + lastStackPath = element.getPath(); + if (log.isDebugEnabled()) { + log.debug("GoBack is about to redirect navigation to " + lastStackPath); + } + } + + doRedirection(response, requestURI, lastStackPath, request); + } + + /** + * Return the request attribute or the request parameter of the given name. + * @param name request attribute or the request parameter name. + * @return the value of the request attribute or the request parameter of the given name. + */ + public static Object getRequestParameterOrAttribute(String name) { + Object result = getRequest().getAttribute(name); + if (result == null) { + result = getRequest().getParameter(name); + } + return result; + } + + /** + * Perform a response riderection to the given lastStackPath. + * @param response the http response + * @param requestURI the http request URI + * @param lastStackPath the last stack path to redirect to. + */ + private static void doRedirection(HttpServletResponse response, + String requestURI, String lastStackPath, HttpServletRequest request) { + int pos = requestURI.indexOf("?"); + if (pos > -1) { + lastStackPath = appendQueryString(lastStackPath, requestURI.substring(pos+1)); + } else { + if (!StringUtils.isEmpty(request.getQueryString())) { + lastStackPath = appendQueryString(lastStackPath, request.getQueryString()); + } + } + try { + response.sendRedirect(response.encodeRedirectURL(lastStackPath)); + FlashMap.recycleIntoSession(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static String appendQueryString(String target, String chunk) { + String result = target; + if (result.indexOf("?") > -1) { + result += "&" + chunk; + } else { + result += "?" + chunk; + } + return result; + } + /** + * NOT UNIT TESTED Returns the URL (including query parameters) minus the + * scheme, host, and context path. This method probably be moved to a more + * general purpose class. + */ + public static String getRelativeUrl() { + HttpServletRequest request = getRequest(); + String baseUrl = null; + + baseUrl = getBaseUrl(); + StringBuffer buf = request.getRequestURL(); + + if (request.getQueryString() != null) { + buf.append("?"); + buf.append(request.getQueryString()); + } + + return buf.substring(baseUrl.length()); + } + + /** + * NOT UNIT TESTED Returns the base url (e.g, + * http://myhost:8080/myapp) suitable for using in a base tag or + * building reliable urls. + */ + public static String getBaseUrl() { + return getServerBaseUrl() + getRequest().getContextPath(); + } + + /** + * @param request + * @return + */ + public static String getServerBaseUrl() { + HttpServletRequest request = getRequest(); + String baseUrl; + if ((request.getServerPort() == 80) || (request.getServerPort() == 443)) { + baseUrl = request.getScheme() + "://" + request.getServerName(); + } else { + baseUrl = request.getScheme() + "://" + request.getServerName() + + ":" + request.getServerPort(); + } + return baseUrl; + } + + public static Object getApplicationAttribute(String name) { + return getServletContext().getAttribute(name); + } + + public static void cleanupSessionAttrsStartingWith(String prefix) { + Enumeration e = getSession().getAttributeNames(); + while (e.hasMoreElements()) { + String sessionElementName = (String) e.nextElement(); + if (sessionElementName.startsWith(prefix)) { + getSession().removeAttribute(sessionElementName); + } + } + } + + public static Object getHandlerBean(Object handler) { + if (handler instanceof HandlerMethod) { + return ((HandlerMethod)handler).getBean(); + } + return handler; + } + + public static JfFormBean getForm(HandlerMethod handler) { + Enumeration e = getSession().getAttributeNames(); + while (e.hasMoreElements()) { + String name = (String) e.nextElement(); + Object value = getSession().getAttribute(name); + if (value instanceof JfFormBean) { + for (MethodParameter method : handler.getMethodParameters()) { + if (method.getParameterType().isAssignableFrom(value.getClass())) { + return (JfFormBean)value; + } + } + } + } + return null; + } + +} diff --git a/voila-runtime-style-responsive-adminlte/src/main/resources/META-INF/css/voila-theme.css b/voila-runtime-style-responsive-adminlte/src/main/resources/META-INF/css/voila-theme.css index b6467756f951503f37916d2f0f5f4b18545ba3b2..0c16a351291ca3f9e98644103e24bd0fb6c09708 100644 --- a/voila-runtime-style-responsive-adminlte/src/main/resources/META-INF/css/voila-theme.css +++ b/voila-runtime-style-responsive-adminlte/src/main/resources/META-INF/css/voila-theme.css @@ -1,4 +1,3 @@ -@import url(//fonts.googleapis.com/css?family=Kaushan+Script); /*! * AdminLTE v1.2 * Author: AlmsaeedStudio.com @@ -540,7 +539,6 @@ body > .header .logo { text-align: center; padding: 0 10px; width: 220px; - font-family: 'Kaushan Script', cursive; font-weight: 500; height: 50px; display: block;