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}