001/*
002 * (C) Copyright 2014 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 *     vpasquier <vpasquier@nuxeo.com>
018 */
019package org.nuxeo.box.api.collaboration;
020
021import org.apache.commons.lang.RandomStringUtils;
022import org.nuxeo.box.api.adapter.BoxAdapter;
023import org.nuxeo.box.api.folder.adapter.BoxFolderAdapter;
024import org.nuxeo.box.api.marshalling.dao.BoxCollaboration;
025import org.nuxeo.box.api.marshalling.dao.BoxUser;
026import org.nuxeo.box.api.marshalling.exceptions.BoxJSONException;
027import org.nuxeo.box.api.marshalling.exceptions.BoxRestException;
028import org.nuxeo.box.api.service.BoxService;
029import org.nuxeo.ecm.core.api.CoreSession;
030import org.nuxeo.ecm.core.api.DocumentModel;
031import org.nuxeo.ecm.core.api.DocumentNotFoundException;
032import org.nuxeo.ecm.core.api.DocumentRef;
033import org.nuxeo.ecm.core.api.IdRef;
034import org.nuxeo.ecm.core.api.NuxeoException;
035import org.nuxeo.ecm.core.api.security.ACE;
036import org.nuxeo.ecm.core.api.security.ACL;
037import org.nuxeo.ecm.core.api.security.ACP;
038import org.nuxeo.ecm.core.api.security.impl.ACLImpl;
039import org.nuxeo.ecm.webengine.WebException;
040import org.nuxeo.ecm.webengine.model.WebObject;
041import org.nuxeo.ecm.webengine.model.impl.AbstractResource;
042import org.nuxeo.ecm.webengine.model.impl.ResourceTypeImpl;
043import org.nuxeo.runtime.api.Framework;
044
045import javax.ws.rs.DELETE;
046import javax.ws.rs.GET;
047import javax.ws.rs.POST;
048import javax.ws.rs.PUT;
049import javax.ws.rs.Path;
050import javax.ws.rs.PathParam;
051import javax.ws.rs.Produces;
052import javax.ws.rs.core.MediaType;
053import javax.ws.rs.core.Response;
054
055/**
056 * WebObject for a Box Collaboration
057 *
058 * @since 5.9.3
059 */
060@WebObject(type = "collaborations")
061@Produces({ MediaType.APPLICATION_JSON })
062public class BoxCollaborationObject extends AbstractResource<ResourceTypeImpl> {
063
064    BoxService boxService;
065
066    BoxFolderAdapter boxFolder;
067
068    @Override
069    public void initialize(Object... args) {
070        boxService = Framework.getLocalService(BoxService.class);
071        if (args != null && args.length == 1) {
072            try {
073                String folderId = (String) args[0];
074                CoreSession session = ctx.getCoreSession();
075                DocumentModel folder = session.getDocument(new IdRef(folderId));
076                boxFolder = (BoxFolderAdapter) folder.getAdapter(BoxAdapter.class);
077            } catch (NuxeoException e) {
078                throw WebException.wrap(e);
079            }
080            setRoot(true);
081        }
082    }
083
084    @GET
085    public String doGetCollaborations() throws DocumentNotFoundException, BoxJSONException {
086        return boxService.toJSONString(boxFolder.getCollaborations());
087    }
088
089    @GET
090    @Path("/{collaborationId}")
091    public String doGetCollaboration(@PathParam("collaborationId") String collaborationId) throws
092            BoxJSONException {
093        CoreSession session = ctx.getCoreSession();
094        String[] collaborationIds = boxService.getCollaborationArrayIds(collaborationId);
095        DocumentModel folder = session.getDocument(new IdRef(collaborationIds[0]));
096        boxFolder = (BoxFolderAdapter) folder.getAdapter(BoxAdapter.class);
097        BoxCollaboration collaboration = boxFolder.getCollaboration(collaborationIds[1]);
098        if (collaboration == null) {
099            throw new BoxRestException("There is no collaboration with id " + collaborationId,
100                    Response.Status.NOT_FOUND.getStatusCode());
101        }
102        return boxService.toJSONString(collaboration);
103    }
104
105    /**
106     * Delete specific ACL for a given folder id
107     */
108    @DELETE
109    @Path("/{collaborationId}")
110    public void doRemoveCollaboration(@PathParam("collaborationId") String collaborationId)
111            throws DocumentNotFoundException, BoxJSONException {
112        CoreSession session = ctx.getCoreSession();
113        String[] collaborationIds = boxService.getCollaborationArrayIds(collaborationId);
114        DocumentRef docRef = new IdRef(collaborationIds[0]);
115        ACP acp = session.getACP(docRef);
116        acp.removeACL(collaborationIds[1]);
117        session.setACP(docRef, acp, true);
118        session.save();
119    }
120
121    @POST
122    public String doPostCollaboration(String jsonBoxCollaboration) throws BoxJSONException {
123        final CoreSession session = ctx.getCoreSession();
124        BoxCollaboration boxCollaboration = boxService.getBoxCollaboration(jsonBoxCollaboration);
125        String documentId = boxCollaboration.getFolder().getId();
126        DocumentModel targetDocument = session.getDocument(new IdRef(documentId));
127        // ACLs Setup
128        ACP acp = session.getACP(targetDocument.getRef());
129        String collaborationId = RandomStringUtils.random(6, false, true);
130        ACL acl = acp.getACL(collaborationId);
131        if (acl == null) {
132            acl = new ACLImpl(collaborationId);
133            acp.addACL(acl);
134        }
135        ACE ace = new ACE(boxCollaboration.getAccessibleBy().getId(), boxService.getNxBoxRole().inverse().get(
136                boxCollaboration.getRole()), true);
137        acl.add(ace);
138        session.setACP(targetDocument.getRef(), acp, true);
139        session.save();
140        // Return the new box collab json
141        BoxFolderAdapter boxFolderUpdated = (BoxFolderAdapter) targetDocument.getAdapter(BoxAdapter.class);
142        return boxService.toJSONString(boxService.getBoxCollaboration(boxFolderUpdated, ace, collaborationId));
143    }
144
145    @PUT
146    @Path("/{collaborationId}")
147    public String doPutCollaboration(@PathParam("collaborationId") String collaborationId, String jsonBoxCollaboration)
148            throws BoxJSONException {
149        final CoreSession session = ctx.getCoreSession();
150        BoxCollaboration boxCollaboration = boxService.getBoxCollaboration(jsonBoxCollaboration);
151        String[] collaborationIds = boxService.getCollaborationArrayIds(collaborationId);
152        DocumentRef docRef = new IdRef(collaborationIds[0]);
153        DocumentModel targetDocument = session.getDocument(docRef);
154        // ACLs Setup
155        ACP acp = session.getACP(targetDocument.getRef());
156        ACL acl = acp.getACL(collaborationIds[1]);
157        if (acl == null) {
158            return null;
159        }
160
161        // Get the changes
162        ACE existingACE = acl.getACEs()[0];
163        String updatedPermission = boxService.getNxBoxRole().inverse().get(boxCollaboration.getRole());
164        BoxUser updatedUser = boxCollaboration.getAccessibleBy();
165        String user = updatedUser != null ? updatedUser.getId() : existingACE.getUsername();
166        String permission = updatedPermission != null ? updatedPermission : existingACE.getPermission();
167        // Remove the existing ACE - creating the new one
168        acl.remove(0);
169        ACE ace = new ACE(user, permission, true);
170        acl.add(ace);
171        session.setACP(targetDocument.getRef(), acp, true);
172        session.save();
173        // Return the new box collab json
174        BoxFolderAdapter boxFolderUpdated = (BoxFolderAdapter) targetDocument.getAdapter(BoxAdapter.class);
175        return boxService.toJSONString(boxService.getBoxCollaboration(boxFolderUpdated, ace, collaborationIds[1]));
176    }
177
178}