org.eurekaclinical.common.resource.AbstractResource Maven / Gradle / Ivy
package org.eurekaclinical.common.resource;
/*-
* #%L
* Eureka! Clinical Common
* %%
* Copyright (C) 2016 Emory University
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.eurekaclinical.standardapis.dao.Dao;
import org.eurekaclinical.standardapis.entity.Entity;
import org.eurekaclinical.standardapis.exception.HttpStatusException;
/**
* Base class for creating Jersey root resource classes. It provides
* implementations of REST APIs for getting all objects accessed through this
* resource and for getting specific objects by its unique id. It additionally
* allows configuring the resource to grant users with the admin
* role access to all objects through these two APIs even if they are not the
* owner of the object, and even if they are not a member of a group with
* access to the object.
*
* @author Andrew Post
*
* @param the entity class
* @param the comm class
*/
public abstract class AbstractResource {
private final Dao dao;
private final boolean restricted;
/**
* Creates an instance of a resource that will use the given data access
* object for database queries.
*
* @param inDao the data access object. Cannot be null
.
*/
protected AbstractResource(Dao inDao) {
this(inDao, true);
}
/**
* Creates an instance of a resource that will use the given data access
* object for database queries. This constructor additionally permits
* authorizing admin users for read-only access to objects that they
* are not otherwise authorized to access through Eureka! Clinical's
* group and owner permissions.
*
* @param inDao the data access object. Cannot be null
.
* @param inRestricted false
to grant users with the
* admin
role read-only access to objects that they are not
* otherwise authorized to access through Eureka! Clinical's group and
* owner permissions. Setting this parameter to true
achieves
* the same behavior as the one-argument constructor, which grants all
* users access only to objects that they own or otherwise have access to
* through being a member of a group.
*/
protected AbstractResource(Dao inDao, boolean inRestricted) {
this.dao = inDao;
this.restricted = inRestricted;
}
/**
* Whether or not admin users have read-only access to all objects, even
* if they are not the object's owner, and even if they are not a member
* of a group that has access to the object.
*
* @return false
if admin users do have these extra
* privileges, false
if they do not. The default value is
* true
.
*/
public boolean isRestricted() {
return restricted;
}
/**
* Gets all objects managed by this resource. By default, only users with
* the admin
role are authorized to use this API. Setting
* the restricted
field to false
in the two-
* argument constructor will change this behavior so that non-admin users
* may also make this API call.
*
* @param req the HTTP servlet request.
* @return the list of objects managed by this resource.
*
* @throws HttpStatusException if an error occurred, for example, the user
* is not authorized to make this call.
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
public List getAll(@Context HttpServletRequest req) {
if (isRestricted() && !req.isUserInRole("admin")) {
throw new HttpStatusException(Response.Status.FORBIDDEN);
}
List results = new ArrayList<>();
for (E userEntity : this.dao.getAll()) {
results.add(toComm(userEntity, req));
}
return results;
}
/**
* Gets the object with the given unique identifier.
*
* @param inId the unique identifier. Cannot be null
.
* @param req the HTTP servlet request.
* @return the object with the given unique identifier. Guaranteed not
* null
.
*
* @throws HttpStatusException if there is no object with the given
* unique identifier, or if the user is not authorized to access the
* object.
*/
@GET
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
public C getAny(@PathParam("id") Long inId, @Context HttpServletRequest req) {
E entity = this.dao.retrieve(inId);
if (entity == null) {
throw new HttpStatusException(Response.Status.NOT_FOUND);
} else if (isAuthorizedEntity(entity, req) && (!isRestricted() || req.isUserInRole("admin"))) {
return toComm(entity, req);
} else {
throw new HttpStatusException(Response.Status.NOT_FOUND);
}
}
/**
* Converts a JPA entity to a Jersey POJO. Your implementation of this
* method should create a Jersey POJO and copy the entity's fields into the
* corresponding fields of the Jersey POJO.
*
* @param entity the entity. Cannot be null
.
* @param req the HTTP servlet request.
* @return the Jersey POJO. Guaranteed not null
.
*/
protected abstract C toComm(E entity, HttpServletRequest req);
/**
* Returns whether the requesting user is authorized to access an entity.
*
* @param entity the entity.
* @param req the HTTP servlet request.
* @return true
if the current user is authorized to access
* the entity, false
otherwise.
*/
protected abstract boolean isAuthorizedEntity(E entity, HttpServletRequest req);
}