package fi.otavanopisto.muikku.plugins.material.rest;
import javax.ejb.Stateful;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.EntityTag;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import fi.foyt.coops.CoOpsApi;
import fi.foyt.coops.CoOpsForbiddenException;
import fi.foyt.coops.CoOpsInternalErrorException;
import fi.foyt.coops.CoOpsNotFoundException;
import fi.foyt.coops.CoOpsNotImplementedException;
import fi.foyt.coops.CoOpsUsageException;
import fi.foyt.coops.model.File;
import fi.otavanopisto.muikku.plugin.PluginRESTService;
import fi.otavanopisto.muikku.plugins.material.HtmlMaterialController;
import fi.otavanopisto.muikku.plugins.material.model.HtmlMaterial;
import fi.otavanopisto.muikku.plugins.workspace.WorkspaceMaterialContainsAnswersExeption;
import fi.otavanopisto.muikku.rest.RESTPermitUnimplemented;
import fi.otavanopisto.muikku.security.MuikkuPermissions;
import fi.otavanopisto.muikku.session.SessionController;
import fi.otavanopisto.security.rest.RESTPermit;
import fi.otavanopisto.security.rest.RESTPermit.Handling;
@RequestScoped
@Path("/materials/html")
@Stateful
@Produces("application/json")
public class HtmlMaterialRESTService extends PluginRESTService {
private static final long serialVersionUID = 5678403648328971273L;
@Inject
private HtmlMaterialController htmlMaterialController;
@Inject
private CoOpsApi coOpsApi;
@Inject
private SessionController sessionController;
@POST
@Path("/")
@RESTPermit (handling = Handling.INLINE, requireLoggedIn = true)
public Response createMaterial(HtmlRestMaterial entity) {
if (!sessionController.hasEnvironmentPermission(MuikkuPermissions.MANAGE_MATERIALS)) {
return Response.status(Status.FORBIDDEN).entity("Permission denied").build();
}
if (StringUtils.isBlank(entity.getContentType())) {
return Response.status(Status.BAD_REQUEST).entity("contentType is missing").build();
}
if (StringUtils.isBlank(entity.getTitle())) {
return Response.status(Status.BAD_REQUEST).entity("title is missing").build();
}
HtmlMaterial htmlMaterial = htmlMaterialController.createHtmlMaterial(entity.getTitle(), entity.getHtml(), entity.getContentType(), 0l, entity.getLicense());
return Response.ok(createRestModel(htmlMaterial)).build();
}
@GET
@Path("/{id}")
@RESTPermitUnimplemented
public Response findMaterial(@PathParam("id") Long id, @QueryParam ("revision") Long revision, @Context Request request) {
HtmlMaterial htmlMaterial = htmlMaterialController.findHtmlMaterialById(id);
if (htmlMaterial == null) {
return Response.status(Status.NOT_FOUND).build();
} else {
EntityTag tag = new EntityTag(DigestUtils.md5Hex(String.valueOf(revision == null ? htmlMaterial.getRevisionNumber() : revision)));
ResponseBuilder builder = request.evaluatePreconditions(tag);
if (builder != null) {
return builder.build();
}
CacheControl cacheControl = new CacheControl();
cacheControl.setMustRevalidate(true);
if (revision == null) {
return Response.ok(createRestModel(htmlMaterial)).build();
} else {
File fileRevision;
try {
fileRevision = coOpsApi.fileGet(id.toString(), revision);
} catch (CoOpsNotImplementedException | CoOpsNotFoundException | CoOpsUsageException | CoOpsInternalErrorException | CoOpsForbiddenException e) {
return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
if (fileRevision == null) {
return Response.status(Status.NOT_FOUND).build();
}
return Response.ok(createRestModel(htmlMaterial, fileRevision)).build();
}
}
}
@POST
@Path("/{id}/publish/")
@RESTPermit (handling = Handling.INLINE, requireLoggedIn = true)
public Response publishMaterial(@PathParam("id") Long id, HtmlRestMaterialPublish entity) {
if (!sessionController.hasEnvironmentPermission(MuikkuPermissions.MANAGE_MATERIALS)) {
return Response.status(Status.FORBIDDEN).entity("Permission denied").build();
}
HtmlMaterial htmlMaterial = htmlMaterialController.findHtmlMaterialById(id);
if (htmlMaterial == null) {
return Response.status(Status.NOT_FOUND).build();
}
if (!htmlMaterial.getRevisionNumber().equals(entity.getFromRevision())) {
return Response.status(Status.CONFLICT)
.entity(new HtmlRestMaterialPublishError(HtmlRestMaterialPublishError.Reason.CONCURRENT_MODIFICATIONS)).build();
}
try {
File fileRevision = coOpsApi.fileGet(id.toString(), entity.getToRevision());
if (fileRevision == null) {
return Response.status(Status.NOT_FOUND).build();
}
htmlMaterialController.updateHtmlMaterialToRevision(htmlMaterial, fileRevision.getContent(), entity.getToRevision(), false, entity.getRemoveAnswers() != null ? entity.getRemoveAnswers() : false);
} catch (WorkspaceMaterialContainsAnswersExeption e) {
return Response.status(Status.CONFLICT)
.entity(new HtmlRestMaterialPublishError(HtmlRestMaterialPublishError.Reason.CONTAINS_ANSWERS)).build();
} catch (CoOpsNotImplementedException | CoOpsNotFoundException | CoOpsUsageException | CoOpsInternalErrorException | CoOpsForbiddenException e) {
return Response.status(Status.INTERNAL_SERVER_ERROR).build();
}
return Response.noContent().build();
}
@PUT
@Path("/{id}/revert/")
@RESTPermit (handling = Handling.INLINE, requireLoggedIn = true)
public Response revertMaterial(@PathParam("id") Long id, HtmlRestMaterialRevert entity) {
if (!sessionController.hasEnvironmentPermission(MuikkuPermissions.MANAGE_MATERIALS)) {
return Response.status(Status.FORBIDDEN).entity("Permission denied").build();
}
HtmlMaterial htmlMaterial = htmlMaterialController.findHtmlMaterialById(id);
if (htmlMaterial == null) {
return Response.status(Status.NOT_FOUND).build();
}
Long currentRevision = htmlMaterialController.lastHtmlMaterialRevision(htmlMaterial);
if (!currentRevision.equals(entity.getFromRevision())) {
return Response.status(Status.CONFLICT)
.entity(new HtmlRestMaterialPublishError(HtmlRestMaterialPublishError.Reason.CONCURRENT_MODIFICATIONS)).build();
}
try {
File fileRevision = coOpsApi.fileGet(id.toString(), entity.getToRevision());
if (fileRevision == null) {
return Response.status(Status.NOT_FOUND).entity("Specified revision could not be found").build();
}
htmlMaterialController.updateHtmlMaterialToRevision(htmlMaterial, fileRevision.getContent(), entity.getToRevision(), true, entity.getRemoveAnswers() != null ? entity.getRemoveAnswers() : false);
} catch (WorkspaceMaterialContainsAnswersExeption e) {
return Response.status(Status.CONFLICT)
.entity(new HtmlRestMaterialPublishError(HtmlRestMaterialPublishError.Reason.CONTAINS_ANSWERS)).build();
} catch (CoOpsNotImplementedException | CoOpsNotFoundException | CoOpsUsageException | CoOpsInternalErrorException | CoOpsForbiddenException e) {
return Response.status(Status.INTERNAL_SERVER_ERROR).build();
}
return Response.noContent().build();
}
private HtmlRestMaterial createRestModel(HtmlMaterial htmlMaterial, File fileRevision) {
return new HtmlRestMaterial(htmlMaterial.getId(),
htmlMaterial.getTitle(),
htmlMaterial.getContentType(),
fileRevision.getContent(),
fileRevision.getRevisionNumber(),
htmlMaterial.getRevisionNumber(),
htmlMaterial.getLicense(),
htmlMaterial.getViewRestrict());
}
private HtmlRestMaterial createRestModel(HtmlMaterial htmlMaterial) {
Long currentRevision = htmlMaterialController.lastHtmlMaterialRevision(htmlMaterial);
return new HtmlRestMaterial(htmlMaterial.getId(),
htmlMaterial.getTitle(),
htmlMaterial.getContentType(),
htmlMaterial.getHtml(),
currentRevision,
htmlMaterial.getRevisionNumber(),
htmlMaterial.getLicense(),
htmlMaterial.getViewRestrict());
}
}