001 /* 002 * Copyright 2011 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.kfs.sec.document.web; 017 018 import java.util.ArrayList; 019 import java.util.Iterator; 020 import java.util.List; 021 import java.util.Map; 022 023 import javax.servlet.jsp.JspException; 024 import javax.servlet.jsp.PageContext; 025 import javax.servlet.jsp.tagext.Tag; 026 027 import org.apache.struts.Globals; 028 import org.apache.struts.action.ActionMessage; 029 import org.apache.struts.action.ActionMessages; 030 import org.kuali.kfs.sec.SecConstants; 031 import org.kuali.kfs.sec.SecKeyConstants; 032 import org.kuali.kfs.sec.service.AccessSecurityService; 033 import org.kuali.kfs.sys.context.SpringContext; 034 import org.kuali.kfs.sys.document.AccountingDocument; 035 import org.kuali.kfs.sys.document.datadictionary.AccountingLineGroupDefinition; 036 import org.kuali.kfs.sys.document.web.DefaultAccountingLineGroupImpl; 037 import org.kuali.kfs.sys.document.web.RenderableAccountingLineContainer; 038 import org.kuali.kfs.sys.document.web.renderers.GroupErrorsRenderer; 039 import org.kuali.rice.kim.bo.Person; 040 import org.kuali.rice.kns.util.GlobalVariables; 041 042 043 /** 044 * Integrates with access security module to check security on accounting lines before rendering 045 */ 046 public class SecAccountingLineGroupImpl extends DefaultAccountingLineGroupImpl { 047 protected boolean hasEditRestrictions; 048 protected boolean hasViewRestrictions; 049 050 /** 051 * Constructs a SecAccountingLineGroupImpl 052 */ 053 public SecAccountingLineGroupImpl() { 054 hasEditRestrictions = false; 055 hasViewRestrictions = false; 056 } 057 058 /** 059 * Performs access security edit check and sets edit flag on container line to false if access is not allowed or removes 060 * container if view is not allowed 061 * 062 * @see org.kuali.kfs.sys.document.web.DefaultAccountingLineGroupImpl#initialize(org.kuali.kfs.sys.document.datadictionary.AccountingLineGroupDefinition, 063 * org.kuali.kfs.sys.document.AccountingDocument, java.util.List, java.lang.String, java.lang.String, java.util.Map, 064 * java.util.Map, java.util.Map, boolean) 065 */ 066 @Override 067 public void initialize(AccountingLineGroupDefinition groupDefinition, AccountingDocument accountingDocument, List<RenderableAccountingLineContainer> containers, String collectionPropertyName, String collectionItemPropertyName, Map<String, Object> displayedErrors, Map<String, Object> displayedWarnings, Map<String, Object> displayedInfo, boolean canEdit) { 068 AccessSecurityService accessSecurityService = SpringContext.getBean(AccessSecurityService.class); 069 Person currentUser = GlobalVariables.getUserSession().getPerson(); 070 071 // check view and edit access 072 List<RenderableAccountingLineContainer> unviewableContainers = new ArrayList<RenderableAccountingLineContainer>(); 073 for (RenderableAccountingLineContainer container : containers) { 074 boolean lineHasError = false; 075 for (Object errorKeyAsObject : GlobalVariables.getMessageMap().keySet()) { 076 if (((String) errorKeyAsObject).startsWith(collectionItemPropertyName)) 077 lineHasError = true; 078 } 079 080 if (lineHasError || container.isNewLine()) { 081 container.setEditableLine(true); 082 continue; 083 } 084 085 boolean viewAllowed = accessSecurityService.canViewDocumentAccountingLine(accountingDocument, container.getAccountingLine(), currentUser); 086 if (!viewAllowed) { 087 unviewableContainers.add(container); 088 hasViewRestrictions = true; 089 } 090 else { 091 boolean editAllowed = accessSecurityService.canEditDocumentAccountingLine(accountingDocument, container.getAccountingLine(), currentUser); 092 093 if (container.isEditableLine() && !editAllowed) { 094 container.setEditableLine(false); 095 hasEditRestrictions = true; 096 } 097 } 098 } 099 100 // remove containers that are not viewable 101 for (RenderableAccountingLineContainer container : unviewableContainers) { 102 containers.remove(container); 103 } 104 105 super.initialize(groupDefinition, accountingDocument, containers, collectionPropertyName, collectionItemPropertyName, displayedErrors, displayedWarnings, displayedInfo, canEdit); 106 } 107 108 /** 109 * Adds info message if we have restricted view of any accounting lines and adds an additional key to match on 110 * 111 * @see org.kuali.kfs.sys.document.web.DefaultAccountingLineGroupImpl#renderErrors(javax.servlet.jsp.PageContext, 112 * javax.servlet.jsp.tagext.Tag) 113 */ 114 @Override 115 protected void renderErrors(PageContext pageContext, Tag parentTag) throws JspException { 116 renderSecurityMessage(pageContext, parentTag); 117 118 renderMessages(pageContext, parentTag, groupDefinition.getErrorKey()); 119 } 120 121 /** 122 * Helper method for outputting messages 123 * 124 * @param pageContext 125 * @param parentTag 126 * @param messageKey - key for messages to display 127 * @throws JspException 128 */ 129 protected void renderMessages(PageContext pageContext, Tag parentTag, String messageKey) throws JspException { 130 GroupErrorsRenderer errorRenderer = getErrorRenderer(); 131 errorRenderer.setErrorKeyMatch(messageKey); 132 errorRenderer.setColSpan(getWidthInCells()); 133 errorRenderer.render(pageContext, parentTag); 134 135 moveListToMap(errorRenderer.getErrorsRendered(), getDisplayedErrors()); 136 moveListToMap(errorRenderer.getWarningsRendered(), getDisplayedWarnings()); 137 moveListToMap(errorRenderer.getInfoRendered(), getDisplayedInfo()); 138 139 errorRenderer.clear(); 140 } 141 142 /** 143 * Adds info message for any security restrictions that have been applied 144 * 145 * @param pageContext 146 * @param parentTag 147 * @throws JspException 148 */ 149 protected void renderSecurityMessage(PageContext pageContext, Tag parentTag) throws JspException { 150 String secErrorKey = SecConstants.ACCOUNTING_GROUP_ERROR_KEY_PREFIX + collectionItemPropertyName + collectionPropertyName; 151 152 // add info message if we are restricting any lines from view 153 if (hasEditRestrictions || hasViewRestrictions) { 154 List pageWarnings = (List) pageContext.getRequest().getAttribute("InfoPropertyList"); 155 if (pageWarnings == null) { 156 pageWarnings = new ArrayList(); 157 } 158 pageWarnings.add(secErrorKey); 159 pageContext.getRequest().setAttribute("InfoPropertyList", pageWarnings); 160 161 ActionMessages requestErrors = (ActionMessages) pageContext.getRequest().getAttribute("InfoActionMessages"); 162 if (requestErrors == null) { 163 requestErrors = new ActionMessages(); 164 } 165 166 if (hasViewRestrictions) { 167 requestErrors.add(secErrorKey, new ActionMessage(SecKeyConstants.MESSAGE_ACCOUNTING_LINE_VIEW_RESTRICTED)); 168 } 169 else { 170 requestErrors.add(secErrorKey, new ActionMessage(SecKeyConstants.MESSAGE_ACCOUNTING_LINE_EDIT_RESTRICTED)); 171 } 172 173 pageContext.getRequest().setAttribute(Globals.ERROR_KEY, requestErrors); 174 } 175 176 renderMessages(pageContext, parentTag, secErrorKey); 177 } 178 179 }