package com.wesabe.grendel.resources; import java.security.SecureRandom; import javax.ws.rs.DELETE; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import com.google.inject.Inject; import com.google.inject.Provider; import com.wesabe.grendel.auth.Credentials; import com.wesabe.grendel.auth.Session; import com.wesabe.grendel.entities.Document; import com.wesabe.grendel.entities.User; import com.wesabe.grendel.entities.dao.DocumentDAO; import com.wesabe.grendel.entities.dao.UserDAO; import com.wesabe.grendel.openpgp.CryptographicException; import com.wesabe.grendel.openpgp.UnlockedKeySet; import com.wideplay.warp.persist.Transactional; @Path("/users/{user_id}/documents/{name}/links/{reader_id}") public class LinkResource { private final UserDAO userDAO; private final DocumentDAO documentDAO; private final Provider<SecureRandom> randomProvider; @Inject public LinkResource(UserDAO userDAO, DocumentDAO documentDAO, Provider<SecureRandom> randomProvider) { this.userDAO = userDAO; this.documentDAO = documentDAO; this.randomProvider = randomProvider; } @PUT @Transactional public Response createLink(@Context Credentials credentials, @PathParam("user_id") String userId, @PathParam("name") String name, @PathParam("reader_id") String readerId) { final Session session = credentials.buildSession(userDAO, userId); final User reader = findUser(readerId); final Document doc = findDocument(session.getUser(), name); doc.linkUser(reader); reEncrypt(doc, session.getKeySet()); documentDAO.saveOrUpdate(doc); return Response.noContent().build(); } @DELETE @Transactional public Response deleteLink(@Context Credentials credentials, @PathParam("user_id") String userId, @PathParam("name") String name, @PathParam("reader_id") String readerId) { final Session session = credentials.buildSession(userDAO, userId); final User reader = findUser(readerId); final Document doc = findDocument(session.getUser(), name); doc.unlinkUser(reader); reEncrypt(doc, session.getKeySet()); documentDAO.saveOrUpdate(doc); return Response.noContent().build(); } private void reEncrypt(Document doc, UnlockedKeySet ownerKeySet) { try { final byte[] body = doc.decryptBody(ownerKeySet); doc.encryptAndSetBody( ownerKeySet, randomProvider.get(), body ); } catch (CryptographicException e) { throw new RuntimeException(e); } } private Document findDocument(User owner, String name) { final Document doc = documentDAO.findByOwnerAndName(owner, name); if (doc == null) { throw new WebApplicationException(Status.NOT_FOUND); } return doc; } private User findUser(String id) { final User reader = userDAO.findById(id); if (reader == null) { throw new WebApplicationException(Status.NOT_FOUND); } return reader; } }