001/**
002 * Copyright 2005-2016 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 */
016package org.kuali.rice.krad.document;
017
018import org.kuali.rice.kew.api.KewApiConstants;
019import org.kuali.rice.kew.api.KewApiServiceLocator;
020import org.kuali.rice.kew.api.WorkflowDocument;
021import org.kuali.rice.kew.api.action.ActionType;
022import org.kuali.rice.kew.api.doctype.ProcessDefinition;
023import org.kuali.rice.kew.api.doctype.RoutePath;
024import org.kuali.rice.kim.api.KimConstants;
025import org.kuali.rice.kim.api.identity.Person;
026import org.kuali.rice.krad.bo.DataObjectAuthorizerBase;
027import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
028import org.kuali.rice.krad.util.KRADConstants;
029
030import java.util.Collections;
031import java.util.HashMap;
032import java.util.Map;
033
034/**
035 * Default implementation for {@link DocumentAuthorizer} that perform KIM permission checks to authorize the actions
036 *
037 * @author Kuali Rice Team (rice.collab@kuali.org)
038 */
039public class DocumentAuthorizerBase extends DataObjectAuthorizerBase implements DocumentAuthorizer {
040    private static final long serialVersionUID = -5354518767379472681L;
041
042    public static final String PRE_ROUTING_ROUTE_NAME = "PreRoute";
043
044    public final boolean canInitiate(String documentTypeName, Person user) {
045        String nameSpaceCode = KRADConstants.KUALI_RICE_SYSTEM_NAMESPACE;
046        Map<String, String> permissionDetails = new HashMap<String, String>();
047        permissionDetails.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, documentTypeName);
048
049        return getPermissionService().isAuthorizedByTemplate(user.getPrincipalId(), nameSpaceCode,
050                KimConstants.PermissionTemplateNames.INITIATE_DOCUMENT, permissionDetails,
051                Collections.<String, String>emptyMap());
052    }
053
054    public boolean canOpen(Document document, Person user) {
055        return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
056                KimConstants.PermissionTemplateNames.OPEN_DOCUMENT, user.getPrincipalId());
057    }
058
059    public boolean canEdit(Document document, Person user) {
060        return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
061                KimConstants.PermissionTemplateNames.EDIT_DOCUMENT, user.getPrincipalId());
062    }
063
064    public boolean canAnnotate(Document document, Person user) {
065        return canEdit(document, user);
066    }
067
068    public boolean canReload(Document document, Person user) {
069        return true;
070    }
071
072    public boolean canClose(Document document, Person user) {
073        return true;
074    }
075
076    public boolean canSave(Document document, Person user) {
077        return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
078                KimConstants.PermissionTemplateNames.SAVE_DOCUMENT, user.getPrincipalId());
079    }
080
081    public boolean canRoute(Document document, Person user) {
082        return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
083                KimConstants.PermissionTemplateNames.ROUTE_DOCUMENT, user.getPrincipalId());
084    }
085
086    public boolean canCancel(Document document, Person user) {
087        return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
088                KimConstants.PermissionTemplateNames.CANCEL_DOCUMENT, user.getPrincipalId());
089    }
090
091    public boolean canRecall(Document document, Person user) {
092        return KewApiServiceLocator.getWorkflowDocumentActionsService().determineValidActions(document.getDocumentNumber(), user.getPrincipalId()).getValidActions().contains(ActionType.RECALL);
093    }
094
095    public boolean canCopy(Document document, Person user) {
096        return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
097                KimConstants.PermissionTemplateNames.COPY_DOCUMENT, user.getPrincipalId());
098    }
099
100    public boolean canPerformRouteReport(Document document, Person user) {
101        return true;
102    }
103
104    public boolean canBlanketApprove(Document document, Person user) {
105        return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
106                KimConstants.PermissionTemplateNames.BLANKET_APPROVE_DOCUMENT, user.getPrincipalId());
107    }
108
109    public boolean canApprove(Document document, Person user) {
110        return canTakeRequestedAction(document, KewApiConstants.ACTION_REQUEST_APPROVE_REQ, user);
111    }
112
113    public boolean canDisapprove(Document document, Person user) {
114        return canApprove(document, user);
115    }
116
117    public boolean canSendNoteFyi(Document document, Person user) {
118        return canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_FYI_REQ, user);
119    }
120
121    public boolean canFyi(Document document, Person user) {
122        return canTakeRequestedAction(document, KewApiConstants.ACTION_REQUEST_FYI_REQ, user);
123    }
124
125    public boolean canAcknowledge(Document document, Person user) {
126        return canTakeRequestedAction(document, KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, user);
127    }
128
129    public boolean canReceiveAdHoc(Document document, Person user, String actionRequestCode) {
130        Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
131        additionalPermissionDetails.put(KimConstants.AttributeConstants.ACTION_REQUEST_CD, actionRequestCode);
132
133        return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
134                KimConstants.PermissionTemplateNames.AD_HOC_REVIEW_DOCUMENT, user.getPrincipalId(),
135                additionalPermissionDetails, null);
136    }
137
138    public boolean canAddNoteAttachment(Document document, String attachmentTypeCode, Person user) {
139        Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
140        if (attachmentTypeCode != null) {
141            additionalPermissionDetails.put(KimConstants.AttributeConstants.ATTACHMENT_TYPE_CODE, attachmentTypeCode);
142        }
143
144        return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
145                KimConstants.PermissionTemplateNames.ADD_NOTE_ATTACHMENT, user.getPrincipalId(),
146                additionalPermissionDetails, null);
147    }
148
149    public boolean canDeleteNoteAttachment(Document document, String attachmentTypeCode,
150            String authorUniversalIdentifier, Person user) {
151        boolean canDeleteNoteAttachment = false;
152
153        Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
154        if (attachmentTypeCode != null) {
155            additionalPermissionDetails.put(KimConstants.AttributeConstants.ATTACHMENT_TYPE_CODE, attachmentTypeCode);
156        }
157
158        // first check permissions that does not restrict on the author
159        additionalPermissionDetails.put(KimConstants.AttributeConstants.CREATED_BY_SELF, "false");
160        canDeleteNoteAttachment = isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
161                KimConstants.PermissionTemplateNames.DELETE_NOTE_ATTACHMENT, user.getPrincipalId(),
162                additionalPermissionDetails, null);
163
164        if (!canDeleteNoteAttachment) {
165            // check for permissions restricted by author
166            additionalPermissionDetails.put(KimConstants.AttributeConstants.CREATED_BY_SELF, "true");
167            canDeleteNoteAttachment = isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
168                    KimConstants.PermissionTemplateNames.DELETE_NOTE_ATTACHMENT, user.getPrincipalId(),
169                    additionalPermissionDetails, null);
170
171            // if permission has been granted user must be the author
172            if (canDeleteNoteAttachment && !authorUniversalIdentifier.equals(user.getPrincipalId())) {
173                canDeleteNoteAttachment = false;
174            }
175        }
176
177        return canDeleteNoteAttachment;
178    }
179
180    public boolean canViewNoteAttachment(Document document, String attachmentTypeCode, String authorUniversalIdentifier,
181            Person user) {
182        Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
183        if (attachmentTypeCode != null) {
184            additionalPermissionDetails.put(KimConstants.AttributeConstants.ATTACHMENT_TYPE_CODE, attachmentTypeCode);
185        }
186
187        return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
188                KimConstants.PermissionTemplateNames.VIEW_NOTE_ATTACHMENT, user.getPrincipalId(),
189                additionalPermissionDetails, null);
190    }
191
192    public boolean canSendAdHocRequests(Document document, String actionRequestCd, Person user) {
193        Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
194        if (actionRequestCd != null) {
195            additionalPermissionDetails.put(KimConstants.AttributeConstants.ACTION_REQUEST_CD, actionRequestCd);
196        }
197
198        return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
199                KimConstants.PermissionTemplateNames.SEND_AD_HOC_REQUEST, user.getPrincipalId(),
200                additionalPermissionDetails, null);
201    }
202
203    public boolean canEditDocumentOverview(Document document, Person user) {
204        return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
205                KimConstants.PermissionTemplateNames.EDIT_DOCUMENT, user.getPrincipalId()) && this.isDocumentInitiator(
206                document, user);
207    }
208
209    public boolean canSendAnyTypeAdHocRequests(Document document, Person user) {
210        if (canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_FYI_REQ, user)) {
211            RoutePath routePath = KewApiServiceLocator.getDocumentTypeService().getRoutePathForDocumentTypeName(
212                    document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
213            ProcessDefinition processDefinition = routePath.getPrimaryProcess();
214            if (processDefinition != null) {
215                if (processDefinition.getInitialRouteNode() == null) {
216                    return false;
217                }
218            } else {
219                return false;
220            }
221
222            return true;
223        } else if (canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, user)) {
224            return true;
225        }
226
227        return canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_APPROVE_REQ, user);
228    }
229
230    public boolean canTakeRequestedAction(Document document, String actionRequestCode, Person user) {
231        Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
232        additionalPermissionDetails.put(KimConstants.AttributeConstants.ACTION_REQUEST_CD, actionRequestCode);
233
234        return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
235                KimConstants.PermissionTemplateNames.TAKE_REQUESTED_ACTION, user.getPrincipalId(),
236                additionalPermissionDetails, null);
237    }
238
239    @Override
240    protected void addPermissionDetails(Object dataObject, Map<String, String> attributes) {
241        super.addPermissionDetails(dataObject, attributes);
242
243        if (dataObject instanceof Document) {
244            addStandardAttributes((Document) dataObject, attributes);
245        }
246    }
247
248    @Override
249    protected void addRoleQualification(Object dataObject, Map<String, String> attributes) {
250        super.addRoleQualification(dataObject, attributes);
251
252        if (dataObject instanceof Document) {
253            addStandardAttributes((Document) dataObject, attributes);
254        }
255    }
256
257    protected void addStandardAttributes(Document document, Map<String, String> attributes) {
258        WorkflowDocument wd = document.getDocumentHeader().getWorkflowDocument();
259        attributes.put(KimConstants.AttributeConstants.DOCUMENT_NUMBER, document.getDocumentNumber());
260        attributes.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, wd.getDocumentTypeName());
261
262        if (wd.isInitiated() || wd.isSaved()) {
263            attributes.put(KimConstants.AttributeConstants.ROUTE_NODE_NAME, PRE_ROUTING_ROUTE_NAME);
264        } else {
265            attributes.put(KimConstants.AttributeConstants.ROUTE_NODE_NAME,
266                    KRADServiceLocatorWeb.getWorkflowDocumentService().getCurrentRouteNodeNames(wd));
267        }
268
269        attributes.put(KimConstants.AttributeConstants.ROUTE_STATUS_CODE, wd.getStatus().getCode());
270    }
271
272    protected boolean isDocumentInitiator(Document document, Person user) {
273        WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
274
275        return workflowDocument.getInitiatorPrincipalId().equalsIgnoreCase(user.getPrincipalId());
276    }
277}