001: /*
002: * Copyright 2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.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/ecl1.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.core.document.authorization;
017:
018: import java.util.HashMap;
019: import java.util.Map;
020: import java.util.Set;
021:
022: import org.apache.commons.lang.StringUtils;
023: import org.apache.commons.logging.Log;
024: import org.apache.commons.logging.LogFactory;
025: import org.kuali.RiceConstants;
026: import org.kuali.core.authorization.AuthorizationConstants;
027: import org.kuali.core.bo.user.UniversalUser;
028: import org.kuali.core.document.Document;
029: import org.kuali.core.exceptions.DocumentInitiationAuthorizationException;
030: import org.kuali.core.service.AuthorizationService;
031: import org.kuali.core.service.KualiConfigurationService;
032: import org.kuali.core.workflow.service.KualiWorkflowDocument;
033: import org.kuali.core.workflow.service.KualiWorkflowInfo;
034: import org.kuali.rice.KNSServiceLocator;
035:
036: import edu.iu.uis.eden.EdenConstants;
037: import edu.iu.uis.eden.clientapp.vo.ActionRequestVO;
038: import edu.iu.uis.eden.clientapp.vo.UserVO;
039: import edu.iu.uis.eden.clientapp.vo.ValidActionsVO;
040: import edu.iu.uis.eden.exception.WorkflowException;
041:
042: /**
043: * DocumentAuthorizer containing common, reusable document-level authorization code.
044: */
045: public class DocumentAuthorizerBase implements DocumentAuthorizer {
046: private static Log LOG = LogFactory
047: .getLog(DocumentAuthorizerBase.class);
048:
049: private static AuthorizationService authorizationService;
050: private static KualiWorkflowInfo kualiWorkflowInfo;
051: private static KualiConfigurationService kualiConfigurationService;
052:
053: /**
054: * @see org.kuali.core.authorization.DocumentAuthorizer#getEditMode(org.kuali.core.document.Document,
055: * org.kuali.core.bo.user.KualiUser)
056: */
057: public Map getEditMode(Document d, UniversalUser u) {
058: Map editModeMap = new HashMap();
059: String editMode = AuthorizationConstants.EditMode.VIEW_ONLY;
060:
061: KualiWorkflowDocument workflowDocument = d.getDocumentHeader()
062: .getWorkflowDocument();
063: if (workflowDocument.stateIsInitiated()
064: || workflowDocument.stateIsSaved()) {
065: if (hasInitiateAuthorization(d, u)) {
066: editMode = AuthorizationConstants.EditMode.FULL_ENTRY;
067: }
068: } else if (workflowDocument.stateIsEnroute()
069: && workflowDocument.isApprovalRequested()) {
070: editMode = AuthorizationConstants.EditMode.FULL_ENTRY;
071: }
072:
073: editModeMap.put(editMode, "TRUE");
074:
075: return editModeMap;
076: }
077:
078: /**
079: * Individual document families will need to reimplement this according to their own needs; this version should be good enough
080: * to be usable during initial development.
081: *
082: * @see org.kuali.core.authorization.DocumentAuthorizer#getDocumentActionFlags(org.kuali.core.document.Document,
083: * org.kuali.core.bo.user.KualiUser)
084: */
085: public DocumentActionFlags getDocumentActionFlags(
086: Document document, UniversalUser user) {
087: LOG
088: .debug("calling DocumentAuthorizerBase.getDocumentActionFlags for document '"
089: + document.getDocumentNumber()
090: + "'. user '"
091: + user.getPersonUserIdentifier() + "'");
092:
093: DocumentActionFlags flags = new DocumentActionFlags(); // all flags default to false
094:
095: KualiWorkflowDocument workflowDocument = document
096: .getDocumentHeader().getWorkflowDocument();
097: boolean hasInitiateAuthorization = hasInitiateAuthorization(
098: document, user);
099:
100: flags.setCanClose(true); // can always close a document
101:
102: // if a document is canceled, everything other than close should be set to false
103: // if a document is NOT canceled, then we want to process the rest
104: if (!workflowDocument.stateIsCanceled()) {
105: flags.setCanReload(!workflowDocument.stateIsInitiated());
106:
107: flags.setCanBlanketApprove(workflowDocument
108: .isBlanketApproveCapable());
109:
110: // The only exception to the supervisor user canSupervise is when the supervisor
111: // user is also the initiator, and does NOT have an approval request. In other words if they
112: // are the document initiator, and its still in Initiated or Saved phase, they cant have access
113: // to the supervisor buttons. If they're the initiator, but for some reason they are also
114: // approving the document, then they can have the supervisor button & functions.
115: boolean canSuperviseAsInitiator = !(hasInitiateAuthorization && !workflowDocument
116: .isApprovalRequested());
117: flags.setCanSupervise(user.isSupervisorUser()
118: && canSuperviseAsInitiator);
119:
120: // default normal documents to be unable to copy
121: flags.setCanCopy(false);
122: // default route report to false and set individually based on workflow doc status below
123: flags.setCanPerformRouteReport(allowsPerformRouteReport(
124: document, user));
125:
126: if (workflowDocument.stateIsInitiated()
127: || workflowDocument.stateIsSaved()) {
128: ValidActionsVO validActions = workflowDocument
129: .getRouteHeader().getValidActions();
130: flags
131: .setCanCancel(hasInitiateAuthorization
132: && validActions
133: .contains(EdenConstants.ACTION_TAKEN_CANCELED_CD));
134:
135: flags
136: .setCanSave(hasInitiateAuthorization
137: && validActions
138: .contains(EdenConstants.ACTION_TAKEN_SAVED_CD));
139:
140: flags
141: .setCanRoute(hasInitiateAuthorization
142: && validActions
143: .contains(EdenConstants.ACTION_TAKEN_ROUTED_CD));
144:
145: flags.setCanAcknowledge(workflowDocument
146: .isAcknowledgeRequested());
147: flags.setCanFYI(workflowDocument.isFYIRequested());
148:
149: flags.setCanAdHocRoute(flags.getCanSave()
150: || flags.getCanRoute());
151: } else if (workflowDocument.stateIsEnroute()) {
152: flags.setCanApprove(workflowDocument
153: .isApprovalRequested());
154:
155: flags.setCanDisapprove(workflowDocument
156: .isApprovalRequested());
157:
158: flags.setCanAcknowledge(workflowDocument
159: .isAcknowledgeRequested());
160: flags.setCanFYI(workflowDocument.isFYIRequested());
161:
162: flags.setCanAdHocRoute(workflowDocument
163: .isApprovalRequested()
164: || workflowDocument.isAcknowledgeRequested());
165: } else if (workflowDocument.stateIsApproved()
166: || workflowDocument.stateIsFinal()
167: || workflowDocument.stateIsDisapproved()) {
168: flags.setCanAcknowledge(workflowDocument
169: .isAcknowledgeRequested());
170: flags.setCanFYI(workflowDocument.isFYIRequested());
171:
172: flags.setCanAdHocRoute(false);
173: } else if (workflowDocument.stateIsException()) {
174: try {
175: ActionRequestVO[] requests = getKualiWorkflowInfo()
176: .getActionRequests(
177: workflowDocument.getRouteHeaderId());
178: boolean reqFound = false;
179: for (ActionRequestVO req : requests) {
180: if (req.isExceptionRequest()
181: && req.getActionTakenId() == null) {
182: if (req.getWorkgroupVO() != null) {
183: UserVO[] users = req.getWorkgroupVO()
184: .getMembers();
185: for (UserVO usr : users) {
186: if (usr
187: .getUuId()
188: .equals(
189: user
190: .getPersonUniversalIdentifier())) {
191: flags.setCanCancel(true);
192: flags.setCanApprove(true);
193: flags.setCanDisapprove(true);
194: reqFound = true; // used to break out of outer loop
195: break;
196: }
197: }
198: if (reqFound) {
199: break;
200: }
201: } else {
202: LOG
203: .error("Unable to retrieve user list for exception workgroup. ActionRequestVO.getWorkgroupVO() returned null");
204: LOG.error("request: " + req);
205: }
206: }
207: }
208: } catch (WorkflowException ex) {
209: LOG.error(
210: "Unable to retrieve action requests for document: "
211: + document.getDocumentNumber(), ex);
212: }
213:
214: flags.setCanAdHocRoute(false);
215: }
216: }
217:
218: setAnnotateFlag(flags);
219:
220: return flags;
221: }
222:
223: protected KualiConfigurationService getKualiConfigurationService() {
224: if (kualiConfigurationService == null) {
225: kualiConfigurationService = KNSServiceLocator
226: .getKualiConfigurationService();
227: }
228: return kualiConfigurationService;
229: }
230:
231: protected AuthorizationService getAuthorizationService() {
232: if (authorizationService == null) {
233: authorizationService = KNSServiceLocator
234: .getAuthorizationService();
235: }
236: return authorizationService;
237: }
238:
239: protected KualiWorkflowInfo getKualiWorkflowInfo() {
240: if (kualiWorkflowInfo == null) {
241: kualiWorkflowInfo = KNSServiceLocator
242: .getWorkflowInfoService();
243: }
244: return kualiWorkflowInfo;
245: }
246:
247: /**
248: * Helper method to disallow the perform route report button globally for a particular authorizer class
249: * @param document - current document
250: * @param user - current user
251: * @return boolean to allow or disallow route report button to show for user
252: */
253: public boolean allowsPerformRouteReport(Document document,
254: UniversalUser user) {
255: KualiConfigurationService kualiConfigurationService = KNSServiceLocator
256: .getKualiConfigurationService();
257: return kualiConfigurationService
258: .getIndicatorParameter(
259: RiceConstants.KNS_NAMESPACE,
260: RiceConstants.DetailTypes.DOCUMENT_DETAIL_TYPE,
261: RiceConstants.SystemGroupParameterNames.DEFAULT_CAN_PERFORM_ROUTE_REPORT_IND);
262: }
263:
264: /**
265: * Helper method to set the annotate flag based on other workflow tags
266: * @param flags
267: */
268: public void setAnnotateFlag(DocumentActionFlags flags) {
269: boolean canWorkflow = flags.getCanSave() || flags.getCanRoute()
270: || flags.getCanCancel() || flags.getCanBlanketApprove()
271: || flags.getCanApprove() || flags.getCanDisapprove()
272: || flags.getCanAcknowledge()
273: || flags.getCanAdHocRoute();
274: flags.setCanAnnotate(canWorkflow);
275: }
276:
277: /**
278: * DocumentTypeAuthorizationException can be extended to customize the initiate error message
279: * @see org.kuali.core.authorization.DocumentAuthorizer#canInitiate(java.lang.String, org.kuali.core.bo.user.KualiUser)
280: */
281: public void canInitiate(String documentTypeName, UniversalUser user) {
282: if (!getAuthorizationService().isAuthorized(user, "initiate",
283: documentTypeName)) {
284: // build authorized workgroup list for error message
285: Set authorizedWorkgroups = getAuthorizationService()
286: .getAuthorizedWorkgroups("initiate",
287: documentTypeName);
288: String workgroupList = StringUtils.join(
289: authorizedWorkgroups.toArray(), ",");
290: throw new DocumentInitiationAuthorizationException(
291: new String[] { workgroupList, documentTypeName });
292: }
293: }
294:
295: /**
296: * Default implementation here is if a user cannot initiate a document they cannot copy one.
297: * @see org.kuali.core.authorization.DocumentAuthorizer#canCopy(java.lang.String, org.kuali.core.bo.user.KualiUser)
298: */
299: public boolean canCopy(String documentTypeName, UniversalUser user) {
300: return getAuthorizationService().isAuthorized(user, "initiate",
301: documentTypeName);
302: }
303:
304: /**
305: * Determines whether the given user should have initiate permissions on the given document.
306: * @param document - current document
307: * @param user - current user
308: * @return boolean (true if they should have permissions)
309: */
310: public boolean hasInitiateAuthorization(Document document,
311: UniversalUser user) {
312: KualiWorkflowDocument workflowDocument = document
313: .getDocumentHeader().getWorkflowDocument();
314: return workflowDocument.getInitiatorNetworkId()
315: .equalsIgnoreCase(user.getPersonUserIdentifier());
316: }
317:
318: /**
319: * Determines whether the given user should be able to view the attachment on the given document
320: * and the attachment type
321: * @param attachmentTypeName - the attachment type
322: * @param document - current document
323: * @param user - current user
324: * @return boolean (true if they should have permissions)
325: */
326: public boolean canViewAttachment(String attachmentTypeName,
327: Document document, UniversalUser user) {
328: return true;
329: }
330: }
|