2 * This document is a part of the source code and related artifacts
3 * for CollectionSpace, an open source collections management system
4 * for museums and related institutions:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright 2009 University of California at Berkeley
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
16 * https://source.collectionspace.org/collection-space/LICENSE.txt
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
24 package org.collectionspace.services.authorization;
26 import javax.ws.rs.Consumes;
27 import javax.ws.rs.GET;
28 import javax.ws.rs.Path;
29 import javax.ws.rs.Produces;
30 import javax.ws.rs.DELETE;
31 import javax.ws.rs.POST;
32 import javax.ws.rs.PUT;
33 import javax.ws.rs.PathParam;
34 import javax.ws.rs.QueryParam;
35 import javax.ws.rs.WebApplicationException;
36 import javax.ws.rs.core.Context;
37 import javax.ws.rs.core.MultivaluedMap;
38 import javax.ws.rs.core.Response;
39 import javax.ws.rs.core.UriBuilder;
40 import javax.ws.rs.core.UriInfo;
41 import org.collectionspace.services.authorization.storage.AuthorizationDelegate;
43 import org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl;
44 //import org.collectionspace.services.common.context.RemoteServiceContextImpl;
45 import org.collectionspace.services.common.ServiceMessages;
46 import org.collectionspace.services.common.context.ServiceContext;
47 import org.collectionspace.services.common.context.RemoteServiceContextFactory;
48 import org.collectionspace.services.common.context.ServiceContextFactory;
49 import org.collectionspace.services.common.document.BadRequestException;
50 import org.collectionspace.services.common.document.DocumentFilter;
51 import org.collectionspace.services.common.document.DocumentNotFoundException;
52 import org.collectionspace.services.common.document.DocumentHandler;
53 import org.collectionspace.services.common.security.UnauthorizedException;
54 import org.collectionspace.services.common.storage.StorageClient;
55 import org.collectionspace.services.common.storage.jpa.JpaStorageClientImpl;
56 import org.jboss.resteasy.util.HttpResponseCodes;
57 import org.slf4j.Logger;
58 import org.slf4j.LoggerFactory;
61 * The Class PermissionResource.
63 @Path("/authorization/permissions")
64 @Consumes("application/xml")
65 @Produces("application/xml")
66 public class PermissionResource
67 extends AbstractCollectionSpaceResourceImpl<Permission, Permission> {
69 /** The service name. */
70 final private String serviceName = "authorization/permissions";
72 final Logger logger = LoggerFactory.getLogger(PermissionResource.class);
73 /** The storage client. */
74 final StorageClient storageClient = new JpaStorageClientImpl();
77 * @see org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl#getVersionString()
80 protected String getVersionString() {
81 /** The last change revision. */
82 final String lastChangeRevision = "$LastChangedRevision: 1165 $";
83 return lastChangeRevision;
87 * @see org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl#getServiceName()
90 public String getServiceName() {
95 * @see org.collectionspace.services.common.CollectionSpaceResource#getCommonPartClass()
98 public Class<Permission> getCommonPartClass() {
99 return Permission.class;
103 * @see org.collectionspace.services.common.CollectionSpaceResource#getServiceContextFactory()
106 public ServiceContextFactory<Permission, Permission> getServiceContextFactory() {
107 return RemoteServiceContextFactory.get();
111 * @see org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl#getStorageClient(org.collectionspace.services.common.context.ServiceContext)
114 public StorageClient getStorageClient(ServiceContext ctx) {
115 //FIXME use ctx to identify storage client
116 return storageClient;
120 // public DocumentHandler createDocumentHandler(ServiceContext ctx) throws Exception {
121 // DocumentHandler docHandler = ctx.getDocumentHandler();
122 // docHandler.setCommonPart(ctx.getInput());
123 // return docHandler;
126 * Creates the permission.
128 * @param input the input
130 * @return the response
133 public Response createPermission(Permission input) {
135 ServiceContext<Permission, Permission> ctx = createServiceContext(input, Permission.class);
136 DocumentHandler handler = createDocumentHandler(ctx);
137 String csid = getStorageClient(ctx).create(ctx, handler);
138 UriBuilder path = UriBuilder.fromResource(PermissionResource.class);
139 path.path("" + csid);
140 Response response = Response.created(path.build()).build();
142 } catch (BadRequestException bre) {
143 Response response = Response.status(
144 Response.Status.BAD_REQUEST).entity(ServiceMessages.POST_FAILED
145 + bre.getErrorReason()).type("text/plain").build();
146 throw new WebApplicationException(response);
147 } catch (UnauthorizedException ue) {
148 Response response = Response.status(
149 Response.Status.UNAUTHORIZED).entity(ServiceMessages.POST_FAILED
150 + ue.getErrorReason()).type("text/plain").build();
151 throw new WebApplicationException(response);
152 } catch (Exception e) {
153 if (logger.isDebugEnabled()) {
154 logger.debug("Caught exception in createPermission", e);
156 logger.error(ServiceMessages.UNKNOWN_ERROR_MSG, e);
157 Response response = Response.status(
158 Response.Status.INTERNAL_SERVER_ERROR).entity(
159 ServiceMessages.POST_FAILED
160 + ServiceMessages.UNKNOWN_ERROR_MSG).type("text/plain").build();
161 throw new WebApplicationException(response);
166 * Gets the permission.
168 * @param csid the csid
170 * @return the permission
174 public Permission getPermission(
175 @PathParam("csid") String csid) {
176 if (logger.isDebugEnabled()) {
177 logger.debug("getPermission with csid=" + csid);
179 if (csid == null || "".equals(csid)) {
180 logger.error("getPermission: missing csid!");
181 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
182 ServiceMessages.GET_FAILED + "permission "
183 + ServiceMessages.MISSING_INVALID_CSID + csid).type(
184 "text/plain").build();
185 throw new WebApplicationException(response);
187 Permission result = null;
189 ServiceContext<Permission, Permission> ctx = createServiceContext((Permission) null, Permission.class);
190 DocumentHandler handler = createDocumentHandler(ctx);
191 getStorageClient(ctx).get(ctx, csid, handler);
192 result = (Permission) ctx.getOutput();
193 } catch (UnauthorizedException ue) {
194 Response response = Response.status(
195 Response.Status.UNAUTHORIZED).entity(ServiceMessages.GET_FAILED
196 + ue.getErrorReason()).type("text/plain").build();
197 throw new WebApplicationException(response);
198 } catch (DocumentNotFoundException dnfe) {
199 if (logger.isDebugEnabled()) {
200 logger.debug("getPermission", dnfe);
202 Response response = Response.status(Response.Status.NOT_FOUND).entity(
203 ServiceMessages.GET_FAILED + "permission csid=" + csid).type(
204 "text/plain").build();
205 throw new WebApplicationException(response);
206 } catch (Exception e) {
207 if (logger.isDebugEnabled()) {
208 logger.debug("getPermission", e);
210 logger.error(ServiceMessages.UNKNOWN_ERROR_MSG, e);
211 Response response = Response.status(
212 Response.Status.INTERNAL_SERVER_ERROR).entity(
213 ServiceMessages.GET_FAILED
214 + ServiceMessages.UNKNOWN_ERROR_MSG).type("text/plain").build();
215 throw new WebApplicationException(response);
218 if (result == null) {
219 Response response = Response.status(Response.Status.NOT_FOUND).entity(
220 ServiceMessages.GET_FAILED + " permission csid=" + csid + ": was not found.").type(
221 "text/plain").build();
222 throw new WebApplicationException(response);
228 * Gets the permission list.
232 * @return the permission list
235 @Produces("application/xml")
236 public PermissionsList getPermissionList(
237 @Context UriInfo ui) {
238 PermissionsList permissionList = new PermissionsList();
240 ServiceContext<Permission, Permission> ctx = createServiceContext((Permission) null, Permission.class);
241 DocumentHandler handler = createDocumentHandler(ctx);
242 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
243 DocumentFilter myFilter = handler.createDocumentFilter();
244 myFilter.setPagination(queryParams);
245 myFilter.setQueryParams(queryParams);
246 handler.setDocumentFilter(myFilter);
247 getStorageClient(ctx).getFiltered(ctx, handler);
248 permissionList = (PermissionsList) handler.getCommonPartList();
249 } catch (UnauthorizedException ue) {
250 Response response = Response.status(
251 Response.Status.UNAUTHORIZED).entity(ServiceMessages.LIST_FAILED
252 + ue.getErrorReason()).type("text/plain").build();
253 throw new WebApplicationException(response);
255 } catch (Exception e) {
256 if (logger.isDebugEnabled()) {
257 logger.debug("Caught exception in getPermissionsList", e);
259 logger.error(ServiceMessages.UNKNOWN_ERROR_MSG, e);
260 Response response = Response.status(
261 Response.Status.INTERNAL_SERVER_ERROR).entity(
262 ServiceMessages.LIST_FAILED
263 + ServiceMessages.UNKNOWN_ERROR_MSG).type("text/plain").build();
264 throw new WebApplicationException(response);
266 return permissionList;
272 * @param csid the csid
273 * @param theUpdate the the update
275 * @return the permission
279 public Permission updatePermission(
280 @PathParam("csid") String csid,
281 Permission theUpdate) {
282 if (logger.isDebugEnabled()) {
283 logger.debug("updatePermission with csid=" + csid);
285 if (csid == null || "".equals(csid)) {
286 logger.error("updatePermission: missing csid!");
287 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
288 ServiceMessages.PUT_FAILED + "permission "
289 + ServiceMessages.MISSING_INVALID_CSID + csid).type(
290 "text/plain").build();
291 throw new WebApplicationException(response);
293 Permission result = null;
295 ServiceContext<Permission, Permission> ctx = createServiceContext(theUpdate, Permission.class);
296 DocumentHandler handler = createDocumentHandler(ctx);
297 getStorageClient(ctx).update(ctx, csid, handler);
298 result = (Permission) ctx.getOutput();
299 } catch (BadRequestException bre) {
300 Response response = Response.status(
301 Response.Status.BAD_REQUEST).entity(ServiceMessages.PUT_FAILED
302 + bre.getErrorReason()).type("text/plain").build();
303 throw new WebApplicationException(response);
304 } catch (UnauthorizedException ue) {
305 Response response = Response.status(
306 Response.Status.UNAUTHORIZED).entity(ServiceMessages.PUT_FAILED
307 + ue.getErrorReason()).type("text/plain").build();
308 throw new WebApplicationException(response);
309 } catch (DocumentNotFoundException dnfe) {
310 if (logger.isDebugEnabled()) {
311 logger.debug("caugth exception in updatePermission", dnfe);
313 Response response = Response.status(Response.Status.NOT_FOUND).entity(
314 ServiceMessages.PUT_FAILED + "permission csid=" + csid).type(
315 "text/plain").build();
316 throw new WebApplicationException(response);
317 } catch (Exception e) {
318 logger.error(ServiceMessages.UNKNOWN_ERROR_MSG, e);
319 Response response = Response.status(
320 Response.Status.INTERNAL_SERVER_ERROR).entity(
321 ServiceMessages.PUT_FAILED
322 + ServiceMessages.UNKNOWN_ERROR_MSG).type("text/plain").build();
323 throw new WebApplicationException(response);
331 * @param csid the csid
333 * @return the response
337 public Response deletePermission(@PathParam("csid") String csid) {
339 if (logger.isDebugEnabled()) {
340 logger.debug("deletePermission with csid=" + csid);
342 if (csid == null || "".equals(csid)) {
343 logger.error("deletePermission: missing csid!");
344 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
345 ServiceMessages.DELETE_FAILED + "permission "
346 + ServiceMessages.MISSING_INVALID_CSID + csid).type(
347 "text/plain").build();
348 throw new WebApplicationException(response);
351 //FIXME ideally the following two ops should be in the same tx CSPACE-658
352 //delete all relationships for this permission
353 PermissionRoleSubResource subResource =
354 new PermissionRoleSubResource(PermissionRoleSubResource.PERMISSION_PERMROLE_SERVICE);
355 subResource.deletePermissionRole(csid, SubjectType.ROLE);
356 //NOTE for delete permissions in the authz provider
357 //at the PermissionRoleSubResource/DocHandler level, there is no visibility
358 //if permission is deleted, so do it here, however,
359 //this is a very dangerous operation as it deletes the Spring ACL instead of ACE(s)
360 //the ACL might be needed for other ACEs roles...
361 AuthorizationDelegate.deletePermissions(csid);
363 ServiceContext<Permission, Permission> ctx = createServiceContext((Permission) null, Permission.class);
364 getStorageClient(ctx).delete(ctx, csid);
365 return Response.status(HttpResponseCodes.SC_OK).build();
366 } catch (UnauthorizedException ue) {
367 Response response = Response.status(
368 Response.Status.UNAUTHORIZED).entity(ServiceMessages.DELETE_FAILED
369 + ue.getErrorReason()).type("text/plain").build();
370 throw new WebApplicationException(response);
372 } catch (DocumentNotFoundException dnfe) {
373 if (logger.isDebugEnabled()) {
374 logger.debug("caught exception in deletePermission", dnfe);
376 Response response = Response.status(Response.Status.NOT_FOUND).entity(
377 ServiceMessages.DELETE_FAILED + "permission csid=" + csid).type(
378 "text/plain").build();
379 throw new WebApplicationException(response);
380 } catch (Exception e) {
381 logger.error(ServiceMessages.UNKNOWN_ERROR_MSG, e);
382 Response response = Response.status(
383 Response.Status.INTERNAL_SERVER_ERROR).entity(
384 ServiceMessages.DELETE_FAILED
385 + ServiceMessages.UNKNOWN_ERROR_MSG).type("text/plain").build();
386 throw new WebApplicationException(response);
392 @Path("{csid}/permroles")
393 public Response createPermissionRole(@QueryParam("_method") String method,
394 @PathParam("csid") String permCsid,
395 PermissionRole input) {
396 if (method != null) {
397 if ("delete".equalsIgnoreCase(method)) {
398 return deletePermissionRole(permCsid, input);
401 if (logger.isDebugEnabled()) {
402 logger.debug("createPermissionRole with permCsid=" + permCsid);
404 if (permCsid == null || "".equals(permCsid)) {
405 logger.error("createPermissionRole: missing permCsid!");
406 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
407 ServiceMessages.POST_FAILED + "permroles permission "
408 + ServiceMessages.MISSING_INVALID_CSID + permCsid).type(
409 "text/plain").build();
410 throw new WebApplicationException(response);
413 PermissionRoleSubResource subResource =
414 new PermissionRoleSubResource(PermissionRoleSubResource.PERMISSION_PERMROLE_SERVICE);
415 String permrolecsid = subResource.createPermissionRole(input, SubjectType.ROLE);
416 UriBuilder path = UriBuilder.fromResource(PermissionResource.class);
417 path.path(permCsid + "/permroles/" + permrolecsid);
418 Response response = Response.created(path.build()).build();
420 } catch (BadRequestException bre) {
421 Response response = Response.status(
422 Response.Status.BAD_REQUEST).entity("Create failed reason "
423 + bre.getErrorReason()).type("text/plain").build();
424 throw new WebApplicationException(response);
425 } catch (UnauthorizedException ue) {
426 Response response = Response.status(
427 Response.Status.UNAUTHORIZED).entity("Create failed reason "
428 + ue.getErrorReason()).type("text/plain").build();
429 throw new WebApplicationException(response);
430 } catch (Exception e) {
431 if (logger.isDebugEnabled()) {
432 logger.debug("Caught exception in createPermissionRole", e);
434 logger.error(ServiceMessages.UNKNOWN_ERROR_MSG, e);
435 Response response = Response.status(
436 Response.Status.INTERNAL_SERVER_ERROR).entity(
437 ServiceMessages.POST_FAILED
438 + ServiceMessages.UNKNOWN_ERROR_MSG).type("text/plain").build();
439 throw new WebApplicationException(response);
444 @Path("{csid}/permroles/{permrolecsid}")
445 public PermissionRole getPermissionRole(
446 @PathParam("csid") String permCsid,
447 @PathParam("permrolecsid") String permrolecsid) {
448 if (logger.isDebugEnabled()) {
449 logger.debug("getPermissionRole with permCsid=" + permCsid);
451 if (permCsid == null || "".equals(permCsid)) {
452 logger.error("getPermissionRole: missing permCsid!");
453 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
454 ServiceMessages.GET_FAILED + "permroles permission "
455 + ServiceMessages.MISSING_INVALID_CSID + permCsid).type(
456 "text/plain").build();
457 throw new WebApplicationException(response);
459 PermissionRole result = null;
461 PermissionRoleSubResource subResource =
462 new PermissionRoleSubResource(PermissionRoleSubResource.PERMISSION_PERMROLE_SERVICE);
463 //get relationships for a permission
464 result = subResource.getPermissionRole(permCsid, SubjectType.ROLE);
465 } catch (UnauthorizedException ue) {
466 Response response = Response.status(
467 Response.Status.UNAUTHORIZED).entity(ServiceMessages.GET_FAILED
468 + ue.getErrorReason()).type("text/plain").build();
469 throw new WebApplicationException(response);
470 } catch (DocumentNotFoundException dnfe) {
471 if (logger.isDebugEnabled()) {
472 logger.debug("getPermissionRole", dnfe);
474 Response response = Response.status(Response.Status.NOT_FOUND).entity(
475 ServiceMessages.GET_FAILED + "permroles permission csid=" + permCsid).type(
476 "text/plain").build();
477 throw new WebApplicationException(response);
478 } catch (Exception e) {
479 if (logger.isDebugEnabled()) {
480 logger.debug("getPermissionRole", e);
482 logger.error(ServiceMessages.UNKNOWN_ERROR_MSG, e);
483 Response response = Response.status(
484 Response.Status.INTERNAL_SERVER_ERROR).entity(
485 ServiceMessages.GET_FAILED
486 + ServiceMessages.UNKNOWN_ERROR_MSG).type("text/plain").build();
487 throw new WebApplicationException(response);
489 if (result == null) {
490 Response response = Response.status(Response.Status.NOT_FOUND).entity(
491 ServiceMessages.GET_FAILED + "permroles permisison csid=" + permCsid
492 + ": was not found.").type(
493 "text/plain").build();
494 throw new WebApplicationException(response);
499 public Response deletePermissionRole(
500 @PathParam("csid") String permCsid,
501 PermissionRole input) {
502 if (logger.isDebugEnabled()) {
503 logger.debug("deletePermissionRole with permCsid=" + permCsid);
505 if (permCsid == null || "".equals(permCsid)) {
506 logger.error("deletePermissionRole: missing permCsid!");
507 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
508 ServiceMessages.DELETE_FAILED + "permroles permission "
509 + ServiceMessages.MISSING_INVALID_CSID + permCsid).type(
510 "text/plain").build();
511 throw new WebApplicationException(response);
514 PermissionRoleSubResource subResource =
515 new PermissionRoleSubResource(PermissionRoleSubResource.PERMISSION_PERMROLE_SERVICE);
516 //delete all relationships for a permission
517 subResource.deletePermissionRole(permCsid, SubjectType.ROLE, input);
518 return Response.status(HttpResponseCodes.SC_OK).build();
519 } catch (UnauthorizedException ue) {
520 Response response = Response.status(
521 Response.Status.UNAUTHORIZED).entity(ServiceMessages.DELETE_FAILED
522 + ue.getErrorReason()).type("text/plain").build();
523 throw new WebApplicationException(response);
524 } catch (DocumentNotFoundException dnfe) {
525 if (logger.isDebugEnabled()) {
526 logger.debug("caught exception in deletePermissionRole", dnfe);
528 Response response = Response.status(Response.Status.NOT_FOUND).entity(
529 ServiceMessages.DELETE_FAILED + "permisison csid=" + permCsid).type(
530 "text/plain").build();
531 throw new WebApplicationException(response);
532 } catch (Exception e) {
533 logger.error(ServiceMessages.UNKNOWN_ERROR_MSG, e);
534 Response response = Response.status(
535 Response.Status.INTERNAL_SERVER_ERROR).entity(
536 ServiceMessages.DELETE_FAILED
537 + ServiceMessages.UNKNOWN_ERROR_MSG).type("text/plain").build();
538 throw new WebApplicationException(response);