001/*
002 * (C) Copyright 2012 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
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 * Contributors:
017 *     Nuxeo - initial API and implementation
018 */
019package org.nuxeo.ecm.platform.routing.core.listener;
020
021import java.util.List;
022
023import org.nuxeo.ecm.core.api.CoreSession;
024import org.nuxeo.ecm.core.api.DocumentModel;
025import org.nuxeo.ecm.core.api.IdRef;
026import org.nuxeo.ecm.core.api.security.ACE;
027import org.nuxeo.ecm.core.api.security.ACL;
028import org.nuxeo.ecm.core.api.security.ACP;
029import org.nuxeo.ecm.core.api.security.SecurityConstants;
030import org.nuxeo.ecm.core.event.Event;
031import org.nuxeo.ecm.core.event.EventContext;
032import org.nuxeo.ecm.core.event.EventListener;
033import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
034import org.nuxeo.ecm.platform.ec.notification.NotificationConstants;
035import org.nuxeo.ecm.platform.routing.api.DocumentRoutingConstants;
036import org.nuxeo.ecm.platform.routing.api.DocumentRoutingService;
037import org.nuxeo.ecm.platform.task.Task;
038import org.nuxeo.ecm.platform.task.TaskEventNames;
039import org.nuxeo.runtime.api.Framework;
040
041/**
042 * Grants the READ/WRITE permissions on the route instance to all task actors. This is needed beacuse an user having a
043 * task assigned should be able to see the relatedRoute and to set global workflow variables.
044 *
045 * @author mcedica
046 */
047public class RoutingTaskSecurityUpdaterListener implements EventListener {
048
049    @Override
050    public void handleEvent(Event event) {
051        EventContext eventCtx = event.getContext();
052        if (!(eventCtx instanceof DocumentEventContext)) {
053            return;
054        }
055        DocumentEventContext docEventCtx = (DocumentEventContext) eventCtx;
056        Task task = (Task) docEventCtx.getProperties().get("taskInstance");
057        if (task == null) {
058            return;
059        }
060        CoreSession session = eventCtx.getCoreSession();
061        List<String> actors = null;
062
063        if (TaskEventNames.WORKFLOW_TASK_ASSIGNED.equals(event.getName())
064                || TaskEventNames.WORKFLOW_TASK_REASSIGNED.equals(event.getName())) {
065            actors = task.getActors();
066        }
067
068        if (TaskEventNames.WORKFLOW_TASK_DELEGATED.equals(event.getName())) {
069            actors = task.getDelegatedActors();
070        }
071        if (actors == null || actors.isEmpty()) {
072            return;
073        }
074        String routeDocId = task.getVariables().get(DocumentRoutingConstants.TASK_ROUTE_INSTANCE_DOCUMENT_ID_KEY);
075        if (routeDocId == null) {
076            return;
077        }
078        DocumentModel routeDoc = session.getDocument(new IdRef(routeDocId));
079        for (String userName : actors) {
080            if (userName.startsWith(NotificationConstants.GROUP_PREFIX)
081                    || userName.startsWith(NotificationConstants.USER_PREFIX)) {
082                // prefixed assignees with "user:" or "group:"
083                userName = userName.substring(userName.indexOf(":") + 1);
084            }
085
086            ACP acp = routeDoc.getACP();
087            ACL routeACL = acp.getOrCreateACL(DocumentRoutingConstants.ROUTE_TASK_LOCAL_ACL);
088            ACE ace = new ACE(userName, SecurityConstants.READ_WRITE, true);
089            if (!routeACL.contains(ace)) {
090                routeACL.add(ace);
091            }
092            acp.addACL(routeACL);
093            session.setACP(routeDoc.getRef(), acp, false);
094        }
095        session.saveDocument(routeDoc);
096    }
097
098    protected DocumentRoutingService getDocumentRoutingService() {
099        return Framework.getService(DocumentRoutingService.class);
100    }
101
102}