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 }