package fi.otavanopisto.muikku.plugins.forum.rest;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.Stateful;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
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 org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Entities.EscapeMode;
import org.jsoup.safety.Whitelist;
import fi.otavanopisto.muikku.model.users.UserEntity;
import fi.otavanopisto.muikku.model.workspace.WorkspaceEntity;
import fi.otavanopisto.muikku.plugin.PluginRESTService;
import fi.otavanopisto.muikku.plugins.forum.ForumController;
import fi.otavanopisto.muikku.plugins.forum.ForumResourcePermissionCollection;
import fi.otavanopisto.muikku.plugins.forum.model.ForumArea;
import fi.otavanopisto.muikku.plugins.forum.model.ForumMessage;
import fi.otavanopisto.muikku.plugins.forum.model.ForumThread;
import fi.otavanopisto.muikku.plugins.forum.model.ForumThreadReply;
import fi.otavanopisto.muikku.plugins.forum.model.WorkspaceForumArea;
import fi.otavanopisto.muikku.schooldata.SchoolDataIdentifier;
import fi.otavanopisto.muikku.schooldata.WorkspaceEntityController;
import fi.otavanopisto.muikku.security.MuikkuPermissions;
import fi.otavanopisto.muikku.session.SessionController;
import fi.otavanopisto.muikku.users.UserEntityController;
import fi.otavanopisto.security.rest.RESTPermit;
import fi.otavanopisto.security.rest.RESTPermit.Handling;
@RequestScoped
@Stateful
@Produces("application/json")
@Path("/workspace")
public class WorkspaceForumRESTService extends PluginRESTService {
private static final long serialVersionUID = 5295688968589424274L;
@Inject
private Logger logger;
@Inject
private ForumController forumController;
@Inject
private SessionController sessionController;
@Inject
private WorkspaceEntityController workspaceEntityController;
@Inject
private UserEntityController userEntityController;
@GET
@Path ("/workspaces/{WORKSPACEENTITYID}/forumAreas")
@RESTPermit(handling = Handling.INLINE)
public Response listWorkspaceForumAreas(@PathParam ("WORKSPACEENTITYID") Long workspaceEntityId) {
WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId);
if (workspaceEntity == null) {
return Response.status(Status.NOT_FOUND).entity(String.format("Workspace entity %d not found", workspaceEntityId)).build();
}
if (!sessionController.hasWorkspacePermission(ForumResourcePermissionCollection.FORUM_LIST_WORKSPACE_FORUM, workspaceEntity)) {
return Response.status(Status.FORBIDDEN)
.build();
}
List<WorkspaceForumArea> workspaceForumAreas = forumController.listWorkspaceForumAreas(workspaceEntity);
List<WorkspaceForumAreaRESTModel> result = new ArrayList<WorkspaceForumAreaRESTModel>();
for (WorkspaceForumArea forum : workspaceForumAreas) {
Long numThreads = forumController.getThreadCount(forum);
result.add(new WorkspaceForumAreaRESTModel(forum.getId(), forum.getWorkspace(), forum.getName(),
forum.getDescription(), forum.getGroup() != null ? forum.getGroup().getId() : null, numThreads));
}
return Response.ok(
result
).build();
}
@GET
@Path ("/workspaces/{WORKSPACEENTITYID}/forumAreas/{AREAID}")
@RESTPermit(handling = Handling.INLINE)
public Response findWorkspaceArea(@Context Request request, @PathParam ("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam ("AREAID") Long areaId) {
ForumArea forumArea = forumController.getForumArea(areaId);
WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId);
if (workspaceEntity == null) {
return Response.status(Status.NOT_FOUND).entity(String.format("Workspace entity %d not found", workspaceEntityId)).build();
}
if (forumArea != null) {
if (!(forumArea instanceof WorkspaceForumArea)) {
logger.severe(String.format("Trying to access forum %d via incorrect REST endpoint", forumArea.getId()));
return Response.status(Status.NOT_FOUND).build();
}
if (!workspaceEntity.getId().equals(((WorkspaceForumArea) forumArea).getWorkspace())) {
return Response.status(Status.NOT_FOUND).entity(String.format("WorkspaceForumArea %d does not belong to workspace entity %d", forumArea.getId(), workspaceEntity.getId())).build();
}
if (sessionController.hasWorkspacePermission(ForumResourcePermissionCollection.FORUM_ACCESSWORKSPACEFORUMS, workspaceEntity)) {
Long numThreads = forumController.getThreadCount(forumArea);
EntityTag tag = new EntityTag(DigestUtils.md5Hex(String.valueOf(forumArea.getVersion()) + String.valueOf(numThreads)));
ResponseBuilder builder = request.evaluatePreconditions(tag);
if (builder != null) {
return builder.build();
}
CacheControl cacheControl = new CacheControl();
cacheControl.setMustRevalidate(true);
ForumAreaRESTModel result = new ForumAreaRESTModel(forumArea.getId(), forumArea.getName(), forumArea.getDescription(),
forumArea.getGroup() != null ? forumArea.getGroup().getId() : null, numThreads);
return Response
.ok(result)
.cacheControl(cacheControl)
.tag(tag)
.build();
} else {
return Response.status(Status.FORBIDDEN).build();
}
} else {
return Response.status(Status.NOT_FOUND).build();
}
}
@PUT
@Path ("/workspaces/{WORKSPACEENTITYID}/forumAreas/{AREAID}")
@RESTPermit(handling = Handling.INLINE)
public Response updateArea(@PathParam ("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam ("AREAID") Long areaId, ForumAreaRESTModel restModel) {
WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId);
if (workspaceEntity == null) {
return Response.status(Status.NOT_FOUND).entity(String.format("Workspace entity %d not found", workspaceEntityId)).build();
}
ForumArea forumArea = forumController.getForumArea(areaId);
if (forumArea != null) {
if (!(forumArea instanceof WorkspaceForumArea)) {
logger.severe(String.format("Trying to access forum %d via incorrect REST endpoint", forumArea.getId()));
return Response.status(Status.NOT_FOUND).build();
}
if (!workspaceEntity.getId().equals(((WorkspaceForumArea) forumArea).getWorkspace())) {
return Response.status(Status.NOT_FOUND).entity(String.format("WorkspaceForumArea %d does not belong to workspace entity %d", forumArea.getId(), workspaceEntity.getId())).build();
}
if (sessionController.hasWorkspacePermission(ForumResourcePermissionCollection.FORUM_UPDATEWORKSPACEFORUM, workspaceEntity)) {
forumController.updateForumAreaName(forumArea, restModel.getName());
forumController.updateForumAreaDescription(forumArea, restModel.getDescription());
return Response.noContent().build();
} else {
return Response.status(Status.FORBIDDEN).build();
}
} else {
return Response.status(Status.NOT_FOUND).build();
}
}
@DELETE
@Path ("/workspaces/{WORKSPACEENTITYID}/forumAreas/{AREAID}")
@RESTPermit(handling = Handling.INLINE)
public Response archiveWorkspaceForumArea(@PathParam ("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam ("AREAID") Long areaId) {
WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId);
if (workspaceEntity == null) {
return Response.status(Status.NOT_FOUND).entity(String.format("Workspace entity %d not found", workspaceEntityId)).build();
}
ForumArea forumArea = forumController.getForumArea(areaId);
if (!(forumArea instanceof WorkspaceForumArea)) {
logger.severe(String.format("Trying to access forum %d via incorrect REST endpoint", forumArea.getId()));
return Response.status(Status.NOT_FOUND).build();
}
if (!workspaceEntity.getId().equals(((WorkspaceForumArea) forumArea).getWorkspace())) {
return Response.status(Status.NOT_FOUND).entity(String.format("WorkspaceForumArea %d does not belong to workspace entity %d", forumArea.getId(), workspaceEntity.getId())).build();
}
if (sessionController.hasPermission(MuikkuPermissions.OWNER, forumArea) || sessionController.hasWorkspacePermission(ForumResourcePermissionCollection.FORUM_DELETEWORKSPACEFORUM, workspaceEntity)) {
forumController.archiveArea(forumArea);
} else {
return Response.status(Status.FORBIDDEN).build();
}
return Response.noContent().build();
}
@POST
@Path ("/workspaces/{WORKSPACEENTITYID}/forumAreas")
@RESTPermit(handling = Handling.INLINE)
public Response createWorkspaceForumArea(@PathParam ("WORKSPACEENTITYID") Long workspaceEntityId, @QueryParam ("sourceWorkspaceEntityId") Long sourceWorkspaceEntityId, ForumAreaRESTModel newForum) {
if (sourceWorkspaceEntityId == null) {
// Create workspace forum area
WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId);
if (workspaceEntity == null) {
return Response.status(Status.NOT_FOUND).build();
}
if (!sessionController.hasPermission(ForumResourcePermissionCollection.FORUM_CREATEWORKSPACEFORUM, workspaceEntity)) {
return Response.status(Status.FORBIDDEN).build();
}
if (StringUtils.isBlank(newForum.getName())) {
return Response.status(Status.BAD_REQUEST).entity("Name is required").build();
}
WorkspaceForumArea workspaceForumArea = forumController.createWorkspaceForumArea(workspaceEntity, newForum.getName(), newForum.getDescription(), newForum.getGroupId());
Long numThreads = forumController.getThreadCount(workspaceForumArea);
WorkspaceForumAreaRESTModel result = new WorkspaceForumAreaRESTModel(
workspaceForumArea.getId(), workspaceForumArea.getWorkspace(), workspaceForumArea.getName(), workspaceForumArea.getDescription(),
workspaceForumArea.getGroup() != null ? workspaceForumArea.getGroup().getId() : null, numThreads);
return Response.ok(result).build();
}
else {
// Copy workspace areas from source
// Access
if (!sessionController.hasEnvironmentPermission(MuikkuPermissions.COPY_WORKSPACE)) {
return Response.status(Status.FORBIDDEN).build();
}
// Source
WorkspaceEntity sourceWorkspace = workspaceEntityController.findWorkspaceEntityById(sourceWorkspaceEntityId);
if (sourceWorkspace == null) {
return Response.status(Status.BAD_REQUEST).entity("null source workspace").build();
}
// Target
WorkspaceEntity targetWorkspace = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId);
if (targetWorkspace == null) {
return Response.status(Status.BAD_REQUEST).entity("null target workspace").build();
}
// Copy
forumController.copyWorkspaceForumAreas(sourceWorkspace, targetWorkspace);
// Done
return Response.noContent().build();
}
}
@GET
@Path ("/workspaces/{WORKSPACEENTITYID}/forumAreas/{AREAID}/threads")
@RESTPermit(handling = Handling.INLINE)
public Response listThreads(@PathParam ("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam ("AREAID") Long areaId, @QueryParam("firstResult") @DefaultValue ("0") Integer firstResult,
@QueryParam("maxResults") @DefaultValue ("10") Integer maxResults) {
WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId);
if (workspaceEntity == null) {
return Response.status(Status.NOT_FOUND).entity(String.format("Workspace entity %d not found", workspaceEntityId)).build();
}
ForumArea forumArea = forumController.getForumArea(areaId);
if (forumArea == null) {
return Response.status(Status.NOT_FOUND).entity("Forum area not found").build();
}
if (!(forumArea instanceof WorkspaceForumArea)) {
logger.severe(String.format("Trying to access forum %d via incorrect REST endpoint", forumArea.getId()));
return Response.status(Status.NOT_FOUND).build();
}
if (!workspaceEntity.getId().equals(((WorkspaceForumArea) forumArea).getWorkspace())) {
return Response.status(Status.NOT_FOUND).entity(String.format("WorkspaceForumArea %d does not belong to workspace entity %d", forumArea.getId(), workspaceEntity.getId())).build();
}
if (sessionController.hasWorkspacePermission(ForumResourcePermissionCollection.FORUM_READ_WORKSPACE_MESSAGES, workspaceEntity)) {
List<ForumThread> threads = forumController.listForumThreads(forumArea, firstResult, maxResults);
List<ForumThreadRESTModel> result = new ArrayList<ForumThreadRESTModel>();
for (ForumThread thread : threads) {
long numReplies = forumController.getThreadReplyCount(thread);
result.add(new ForumThreadRESTModel(thread.getId(), thread.getTitle(), thread.getMessage(), thread.getCreator(), thread.getCreated(), thread.getForumArea().getId(), thread.getSticky(), thread.getLocked(), thread.getUpdated(), numReplies, thread.getLastModified()));
}
return Response.ok(
result
).build();
} else {
return Response.status(Status.FORBIDDEN).build();
}
}
@GET
@Path ("/workspaces/{WORKSPACEENTITYID}/forumAreas/{AREAID}/threads/{THREADID}")
@RESTPermit(handling = Handling.INLINE)
public Response findThread(@PathParam ("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam ("AREAID") Long areaId, @PathParam ("THREADID") Long threadId) {
WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId);
if (workspaceEntity == null) {
return Response.status(Status.NOT_FOUND).entity(String.format("Workspace entity %d not found", workspaceEntityId)).build();
}
ForumThread thread = forumController.getForumThread(threadId);
if (thread == null) {
return Response.status(Status.NOT_FOUND).entity("Forum thread not found").build();
}
ForumArea forumArea = thread.getForumArea();
if (!(forumArea instanceof WorkspaceForumArea)) {
logger.severe(String.format("Trying to access forum %d via incorrect REST endpoint", forumArea.getId()));
return Response.status(Status.NOT_FOUND).build();
}
if (!workspaceEntity.getId().equals(((WorkspaceForumArea) forumArea).getWorkspace())) {
return Response.status(Status.NOT_FOUND).entity(String.format("WorkspaceForumArea %d does not belong to workspace entity %d", forumArea.getId(), workspaceEntity.getId())).build();
}
if (sessionController.hasWorkspacePermission(ForumResourcePermissionCollection.FORUM_READ_WORKSPACE_MESSAGES, workspaceEntity)) {
long numReplies = forumController.getThreadReplyCount(thread);
ForumThreadRESTModel result = new ForumThreadRESTModel(thread.getId(), thread.getTitle(), thread.getMessage(), thread.getCreator(), thread.getCreated(), thread.getForumArea().getId(), thread.getSticky(), thread.getLocked(), thread.getUpdated(), numReplies, thread.getLastModified());
return Response.ok(
result
).build();
} else {
return Response.status(Status.FORBIDDEN).build();
}
}
@PUT
@Path ("/workspaces/{WORKSPACEENTITYID}/forumAreas/{AREAID}/threads/{THREADID}")
@RESTPermit(handling = Handling.INLINE)
public Response updateThread(@PathParam ("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam ("AREAID") Long areaId, @PathParam ("THREADID") Long threadId, ForumThreadRESTModel updThread) {
WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId);
if (workspaceEntity == null) {
return Response.status(Status.NOT_FOUND).entity(String.format("Workspace entity %d not found", workspaceEntityId)).build();
}
ForumThread forumThread = forumController.getForumThread(threadId);
if (forumThread == null) {
return Response.status(Status.NOT_FOUND).entity("Forum thread not found").build();
}
ForumArea forumArea = forumController.getForumArea(areaId);
if (forumArea == null) {
return Response.status(Status.NOT_FOUND).entity("Forum area not found").build();
}
if (!(forumArea instanceof WorkspaceForumArea)) {
logger.severe(String.format("Trying to access forum %d via incorrect REST endpoint", forumArea.getId()));
return Response.status(Status.NOT_FOUND).build();
}
if (!workspaceEntity.getId().equals(((WorkspaceForumArea) forumArea).getWorkspace())) {
return Response.status(Status.NOT_FOUND).entity(String.format("WorkspaceForumArea %d does not belong to workspace entity %d", forumArea.getId(), workspaceEntity.getId())).build();
}
if (!forumArea.getId().equals(forumThread.getForumArea().getId())) {
return Response.status(Status.NOT_FOUND).entity("Forum thread not found from the specified area").build();
}
if (!forumThread.getId().equals(threadId)) {
return Response.status(Status.BAD_REQUEST).build();
}
if (sessionController.hasPermission(MuikkuPermissions.OWNER, forumThread) || sessionController.hasWorkspacePermission(ForumResourcePermissionCollection.FORUM_EDIT_WORKSPACE_MESSAGES, workspaceEntity)) {
if (!forumThread.getSticky().equals(updThread.getSticky()) || !forumThread.getLocked().equals(updThread.getLocked())) {
if (!sessionController.hasWorkspacePermission(ForumResourcePermissionCollection.FORUM_LOCK_OR_STICKIFY_WORKSPACE_MESSAGES, workspaceEntity))
return Response.status(Status.BAD_REQUEST).build();
}
forumController.updateForumThread(forumThread,
updThread.getTitle(),
updThread.getMessage(),
updThread.getSticky(),
updThread.getLocked());
long numReplies = forumController.getThreadReplyCount(forumThread);
ForumThreadRESTModel result = new ForumThreadRESTModel(forumThread.getId(), forumThread.getTitle(),
forumThread.getMessage(), forumThread.getCreator(), forumThread.getCreated(), forumThread.getForumArea().getId(),
forumThread.getSticky(), forumThread.getLocked(), forumThread.getUpdated(), numReplies, forumThread.getLastModified());
return Response.ok(
result
).build();
} else {
return Response.status(Status.FORBIDDEN).build();
}
}
@DELETE
@Path ("/workspaces/{WORKSPACEENTITYID}/forumAreas/{AREAID}/threads/{THREADID}")
@RESTPermit(handling = Handling.INLINE)
public Response archiveThread(@PathParam ("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam ("AREAID") Long areaId, @PathParam ("THREADID") Long threadId) {
WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId);
if (workspaceEntity == null) {
return Response.status(Status.NOT_FOUND).entity(String.format("Workspace entity %d not found", workspaceEntityId)).build();
}
ForumThread thread = forumController.getForumThread(threadId);
if (thread == null) {
return Response.status(Status.NOT_FOUND).entity(String.format("Forum thread (%d) not found", threadId)).build();
}
ForumArea forumArea = thread.getForumArea();
if (!(forumArea instanceof WorkspaceForumArea)) {
logger.severe(String.format("Trying to access forum %d via incorrect REST endpoint", forumArea.getId()));
return Response.status(Status.NOT_FOUND).build();
}
if (!workspaceEntity.getId().equals(((WorkspaceForumArea) forumArea).getWorkspace())) {
return Response.status(Status.NOT_FOUND).entity(String.format("WorkspaceForumArea %d does not belong to workspace entity %d", forumArea.getId(), workspaceEntity.getId())).build();
}
if (sessionController.hasWorkspacePermission(ForumResourcePermissionCollection.FORUM_DELETE_WORKSPACE_MESSAGES, workspaceEntity)) {
forumController.archiveThread(thread);
return Response.noContent().build();
} else {
return Response.status(Status.FORBIDDEN).build();
}
}
@POST
@Path ("/workspaces/{WORKSPACEENTITYID}/forumAreas/{AREAID}/threads")
@RESTPermit(handling = Handling.INLINE)
public Response createThread(@PathParam ("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam ("AREAID") Long areaId, ForumThreadRESTModel newThread) {
WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId);
if (workspaceEntity == null) {
return Response.status(Status.NOT_FOUND).entity(String.format("Workspace entity %d not found", workspaceEntityId)).build();
}
ForumArea forumArea = forumController.getForumArea(areaId);
if (forumArea == null) {
return Response.status(Status.NOT_FOUND).entity("Forum area not found").build();
}
if (!(forumArea instanceof WorkspaceForumArea)) {
logger.severe(String.format("Trying to access forum %d via incorrect REST endpoint", forumArea.getId()));
return Response.status(Status.NOT_FOUND).build();
}
if (!workspaceEntity.getId().equals(((WorkspaceForumArea) forumArea).getWorkspace())) {
return Response.status(Status.NOT_FOUND).entity(String.format("WorkspaceForumArea %d does not belong to workspace entity %d", forumArea.getId(), workspaceEntity.getId())).build();
}
if (sessionController.hasWorkspacePermission(ForumResourcePermissionCollection.FORUM_WRITE_WORKSPACE_MESSAGES, workspaceEntity)) {
if (Boolean.TRUE.equals(newThread.getSticky()) || Boolean.TRUE.equals(newThread.getLocked())) {
if (!sessionController.hasWorkspacePermission(ForumResourcePermissionCollection.FORUM_LOCK_OR_STICKIFY_WORKSPACE_MESSAGES, workspaceEntity))
return Response.status(Status.BAD_REQUEST).build();
}
Document message = Jsoup.parse(Jsoup.clean(newThread.getMessage(), Whitelist.relaxed().addAttributes("a", "target")));
message.outputSettings().escapeMode(EscapeMode.xhtml);
message.select("a[target]").attr("rel", "noopener noreferer");
ForumThread thread = forumController.createForumThread(
forumArea,
newThread.getTitle(),
message.body().toString(),
newThread.getSticky(),
newThread.getLocked());
ForumThreadRESTModel result = new ForumThreadRESTModel(thread.getId(), thread.getTitle(), thread.getMessage(), thread.getCreator(), thread.getCreated(), thread.getForumArea().getId(), thread.getSticky(), thread.getLocked(), thread.getUpdated(), 1l, thread.getLastModified());
return Response.ok(
result
).build();
} else {
return Response.status(Status.FORBIDDEN).build();
}
}
@GET
@Path ("/workspaces/{WORKSPACEID}/forumLatest")
@RESTPermit(handling = Handling.INLINE)
public Response listLatestThreadsFromWorkspace(
@PathParam ("WORKSPACEID") Long workspaceEntityId,
@QueryParam("firstResult") @DefaultValue ("0") Integer firstResult,
@QueryParam("maxResults") @DefaultValue ("10") Integer maxResults) {
if (!sessionController.isLoggedIn()) {
return Response.status(Status.UNAUTHORIZED).build();
}
WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId);
if (workspaceEntity == null) {
return Response.status(Status.NOT_FOUND).entity(String.format("Workspace entity %d not found", workspaceEntityId)).build();
}
if (!sessionController.hasWorkspacePermission(ForumResourcePermissionCollection.FORUM_READ_WORKSPACE_MESSAGES, workspaceEntity)) {
return Response.status(Status.FORBIDDEN).build();
}
List<ForumThread> threads = forumController.listLatestForumThreadsFromWorkspace(workspaceEntity, firstResult, maxResults);
List<ForumThreadRESTModel> result = new ArrayList<ForumThreadRESTModel>();
for (ForumThread thread : threads) {
long numReplies = forumController.getThreadReplyCount(thread);
result.add(new ForumThreadRESTModel(thread.getId(), thread.getTitle(), thread.getMessage(), thread.getCreator(), thread.getCreated(), thread.getForumArea().getId(), thread.getSticky(), thread.getLocked(), thread.getUpdated(), numReplies, thread.getLastModified()));
}
return Response.ok(
result
).build();
}
@GET
@Path ("/workspaces/{WORKSPACEENTITYID}/forumAreas/{AREAID}/threads/{THREADID}/replies")
@RESTPermit(handling = Handling.INLINE)
public Response listReplies(@PathParam ("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam ("AREAID") Long areaId, @PathParam ("THREADID") Long threadId,
@QueryParam("firstResult") @DefaultValue ("0") Integer firstResult,
@QueryParam("maxResults") @DefaultValue ("10") Integer maxResults) {
WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId);
if (workspaceEntity == null) {
return Response.status(Status.NOT_FOUND).entity(String.format("Workspace entity %d not found", workspaceEntityId)).build();
}
try {
ForumArea forumArea = forumController.getForumArea(areaId);
if (forumArea == null) {
return Response.status(Status.NOT_FOUND).entity("Forum area not found").build();
}
ForumThread forumThread = forumController.getForumThread(threadId);
if (forumThread == null) {
return Response.status(Status.NOT_FOUND).entity("Forum thread not found").build();
}
if (!(forumArea instanceof WorkspaceForumArea)) {
logger.severe(String.format("Trying to access forum %d via incorrect REST endpoint", forumArea.getId()));
return Response.status(Status.NOT_FOUND).build();
}
if (!workspaceEntity.getId().equals(((WorkspaceForumArea) forumArea).getWorkspace())) {
return Response.status(Status.NOT_FOUND).entity(String.format("WorkspaceForumArea %d does not belong to workspace entity %d", forumArea.getId(), workspaceEntity.getId())).build();
}
if (sessionController.hasWorkspacePermission(ForumResourcePermissionCollection.FORUM_READ_WORKSPACE_MESSAGES, workspaceEntity)) {
if (!forumArea.getId().equals(forumThread.getForumArea().getId())) {
return Response.status(Status.NOT_FOUND).entity("Forum thread not found from the specified area").build();
}
List<ForumThreadReply> replies = forumController.listForumThreadReplies(forumThread, firstResult, maxResults);
return Response.ok(createRestModel(replies.toArray(new ForumThreadReply[0]))).build();
} else
return Response.status(Status.FORBIDDEN).build();
} catch (Exception e) {
logger.log(Level.SEVERE, "Listing forum thread replies failed", e);
return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
}
@GET
@Path ("/workspaces/{WORKSPACEENTITYID}/forumAreas/{AREAID}/threads/{THREADID}/replies/{REPLYID}")
@RESTPermit(handling = Handling.INLINE)
public Response findReply(@PathParam ("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam ("AREAID") Long areaId, @PathParam ("THREADID") Long threadId, @PathParam ("REPLYID") Long replyId) {
WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId);
if (workspaceEntity == null) {
return Response.status(Status.NOT_FOUND).entity(String.format("Workspace entity %d not found", workspaceEntityId)).build();
}
try {
ForumArea forumArea = forumController.getForumArea(areaId);
if (forumArea == null) {
return Response.status(Status.NOT_FOUND).entity("Forum area not found").build();
}
ForumThread forumThread = forumController.getForumThread(threadId);
if (forumThread == null) {
return Response.status(Status.NOT_FOUND).entity("Forum thread not found").build();
}
if (!forumArea.getId().equals(forumThread.getForumArea().getId())) {
return Response.status(Status.NOT_FOUND).entity("Forum thread not found from the specified area").build();
}
ForumThreadReply threadReply = forumController.getForumThreadReply(replyId);
if (threadReply == null) {
return Response.status(Status.NOT_FOUND).entity("Forum thread reply not found").build();
}
if (!threadReply.getThread().getId().equals(forumThread.getId())) {
return Response.status(Status.NOT_FOUND).entity("Forum thread reply not found from the specified thread").build();
}
if (!(forumArea instanceof WorkspaceForumArea)) {
logger.severe(String.format("Trying to access forum %d via incorrect REST endpoint", forumArea.getId()));
return Response.status(Status.NOT_FOUND).build();
}
if (!workspaceEntity.getId().equals(((WorkspaceForumArea) forumArea).getWorkspace())) {
return Response.status(Status.NOT_FOUND).entity(String.format("WorkspaceForumArea %d does not belong to workspace entity %d", forumArea.getId(), workspaceEntity.getId())).build();
}
if (sessionController.hasWorkspacePermission(ForumResourcePermissionCollection.FORUM_READ_WORKSPACE_MESSAGES, workspaceEntity)) {
return Response.ok(createRestModel(threadReply)).build();
} else {
return Response.status(Status.FORBIDDEN).build();
}
} catch (Exception e) {
logger.log(Level.SEVERE, "Finding forum thread reply failed", e);
return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
}
@PUT
@Path ("/workspaces/{WORKSPACEENTITYID}/forumAreas/{AREAID}/threads/{THREADID}/replies/{REPLYID}")
@RESTPermit(handling = Handling.INLINE)
public Response updateReply(@PathParam ("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam ("AREAID") Long areaId, @PathParam ("THREADID") Long threadId, @PathParam ("REPLYID") Long replyId, ForumThreadReplyRESTModel reply) {
WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId);
if (workspaceEntity == null) {
return Response.status(Status.NOT_FOUND).entity(String.format("Workspace entity %d not found", workspaceEntityId)).build();
}
try {
ForumArea forumArea = forumController.getForumArea(areaId);
if (forumArea == null) {
return Response.status(Status.NOT_FOUND).entity("Forum area not found").build();
}
ForumThread forumThread = forumController.getForumThread(threadId);
if (forumThread == null) {
return Response.status(Status.NOT_FOUND).entity("Forum thread not found").build();
}
if (!forumArea.getId().equals(forumThread.getForumArea().getId())) {
return Response.status(Status.NOT_FOUND).entity("Forum thread not found from the specified area").build();
}
ForumThreadReply threadReply = forumController.getForumThreadReply(replyId);
if (threadReply == null) {
return Response.status(Status.NOT_FOUND).entity("Forum thread reply not found").build();
}
if (!threadReply.getThread().getId().equals(forumThread.getId())) {
return Response.status(Status.NOT_FOUND).entity("Forum thread reply not found from the specified thread").build();
}
if (!reply.getId().equals(replyId)) {
return Response.status(Status.BAD_REQUEST).build();
}
if (!(forumArea instanceof WorkspaceForumArea)) {
logger.severe(String.format("Trying to access forum %d via incorrect REST endpoint", forumArea.getId()));
return Response.status(Status.NOT_FOUND).build();
}
if (!workspaceEntity.getId().equals(((WorkspaceForumArea) forumArea).getWorkspace())) {
return Response.status(Status.NOT_FOUND).entity(String.format("WorkspaceForumArea %d does not belong to workspace entity %d", forumArea.getId(), workspaceEntity.getId())).build();
}
if (sessionController.hasPermission(MuikkuPermissions.OWNER, threadReply) ||
sessionController.hasWorkspacePermission(ForumResourcePermissionCollection.FORUM_EDIT_WORKSPACE_MESSAGES, workspaceEntity)) {
forumController.updateForumThreadReply(threadReply, reply.getMessage());
return Response.ok(createRestModel(threadReply)).build();
} else {
return Response.status(Status.FORBIDDEN).build();
}
} catch (Exception e) {
logger.log(Level.SEVERE, "Finding forum thread reply failed", e);
return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
}
@DELETE
@Path ("/workspaces/{WORKSPACEENTITYID}/forumAreas/{AREAID}/threads/{THREADID}/replies/{REPLYID}")
@RESTPermit(handling = Handling.INLINE)
public Response archiveReply(
@PathParam ("WORKSPACEENTITYID") Long workspaceEntityId,
@PathParam ("AREAID") Long areaId,
@PathParam ("THREADID") Long threadId,
@PathParam ("REPLYID") Long replyId,
@DefaultValue ("false") @QueryParam ("permanent") Boolean permanent) {
WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId);
if (workspaceEntity == null) {
return Response.status(Status.NOT_FOUND).entity(String.format("Workspace entity %d not found", workspaceEntityId)).build();
}
ForumThreadReply reply = forumController.getForumThreadReply(replyId);
ForumArea forumArea = reply.getForumArea();
if (!(forumArea instanceof WorkspaceForumArea)) {
logger.severe(String.format("Trying to access forum %d via incorrect REST endpoint", forumArea.getId()));
return Response.status(Status.NOT_FOUND).build();
}
if (!workspaceEntity.getId().equals(((WorkspaceForumArea) forumArea).getWorkspace())) {
return Response.status(Status.NOT_FOUND).entity(String.format("WorkspaceForumArea %d does not belong to workspace entity %d", forumArea.getId(), workspaceEntity.getId())).build();
}
if (!permanent) {
if (sessionController.hasPermission(MuikkuPermissions.OWNER, reply) || sessionController.hasWorkspacePermission(ForumResourcePermissionCollection.FORUM_DELETE_WORKSPACE_MESSAGES, workspaceEntity)) {
forumController.updateReplyDeleted(reply, true);
return Response.noContent().build();
}
} else {
if (sessionController.hasWorkspacePermission(ForumResourcePermissionCollection.FORUM_DELETE_WORKSPACE_MESSAGES, workspaceEntity)) {
forumController.archiveReply(reply);
return Response.noContent().build();
}
}
return Response.status(Status.FORBIDDEN).build();
}
@POST
@Path ("/workspaces/{WORKSPACEENTITYID}/forumAreas/{AREAID}/threads/{THREADID}/replies")
@RESTPermit(handling = Handling.INLINE)
public Response createReply(@PathParam ("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam ("AREAID") Long areaId, @PathParam ("THREADID") Long threadId, ForumThreadReplyRESTModel newReply) {
WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId);
if (workspaceEntity == null) {
return Response.status(Status.NOT_FOUND).entity(String.format("Workspace entity %d not found", workspaceEntityId)).build();
}
try {
ForumArea forumArea = forumController.getForumArea(areaId);
if (forumArea == null) {
return Response.status(Status.NOT_FOUND).entity("Forum area not found").build();
}
ForumThread forumThread = forumController.getForumThread(threadId);
if (forumThread == null) {
return Response.status(Status.NOT_FOUND).entity("Forum thread not found").build();
}
if (!forumArea.getId().equals(forumThread.getForumArea().getId())) {
return Response.status(Status.NOT_FOUND).entity("Forum thread not found from the specified area").build();
}
if (forumThread.getLocked()) {
return Response.status(Status.BAD_REQUEST).entity("Forum thread is locked").build();
}
if (!(forumArea instanceof WorkspaceForumArea)) {
logger.severe(String.format("Trying to access forum %d via incorrect REST endpoint", forumArea.getId()));
return Response.status(Status.NOT_FOUND).build();
}
if (!workspaceEntity.getId().equals(((WorkspaceForumArea) forumArea).getWorkspace())) {
return Response.status(Status.NOT_FOUND).entity(String.format("WorkspaceForumArea %d does not belong to workspace entity %d", forumArea.getId(), workspaceEntity.getId())).build();
}
if (sessionController.hasWorkspacePermission(ForumResourcePermissionCollection.FORUM_WRITE_WORKSPACE_MESSAGES, workspaceEntity)) {
ForumThreadReply parentReply = null;
if (newReply.getParentReplyId() != null) {
parentReply = forumController.getForumThreadReply(newReply.getParentReplyId());
if (parentReply == null) {
return Response.status(Status.BAD_REQUEST).entity("Invalid parent reply id").build();
}
if (!Objects.equals(parentReply.getThread().getId(), threadId)) {
return Response.status(Status.BAD_REQUEST).entity("Parent reply is in wrong thread").build();
}
}
return Response.ok(createRestModel(forumController.createForumThreadReply(forumThread, newReply.getMessage(), parentReply))).build();
} else {
return Response.status(Status.FORBIDDEN).build();
}
} catch (Exception e) {
logger.log(Level.SEVERE, "Failed to create new forum thread reply", e);
return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
}
@GET
@Path ("/workspaces/{WORKSPACEENTITYID}/forumStatistics")
@RESTPermit(handling = Handling.INLINE)
public Response getWorkspaceForumStatistics(@PathParam ("WORKSPACEENTITYID") Long workspaceEntityId, @QueryParam ("userIdentifier") String userId) {
WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId);
if (workspaceEntity == null) {
return Response.status(Status.NOT_FOUND).entity(String.format("Workspace entity %d could not be found", workspaceEntityId)).build();
}
SchoolDataIdentifier userIdentifier = null;
if (StringUtils.isNotBlank(userId)) {
userIdentifier = SchoolDataIdentifier.fromId(userId);
}
if (userIdentifier == null) {
return Response.status(Status.NOT_IMPLEMENTED).entity("Listing forum statistics for all users is not implemented yet").build();
}
UserEntity userEntity = userEntityController.findUserEntityByUserIdentifier(userIdentifier);
if (userEntity == null) {
return Response.status(Status.BAD_REQUEST).entity("Invalid userIdentifier").build();
}
if (!sessionController.hasWorkspacePermission(ForumResourcePermissionCollection.FORUM_FINDWORKSPACE_USERSTATISTICS, workspaceEntity)) {
return Response.status(Status.FORBIDDEN).build();
}
Long messageCount = forumController.countUserEntityWorkspaceMessages(workspaceEntity, userEntity);
ForumMessage latestMessage = forumController.findUserEntitysLatestWorkspaceMessage(workspaceEntity, userEntity);
return Response
.ok(new WorkspaceForumUserStatisticsRESTModel(messageCount, latestMessage != null ? latestMessage.getCreated() : null))
.build();
}
private ForumThreadReplyRESTModel createRestModel(ForumThreadReply entity) {
Long parentReplyId = null;
String message = entity.getMessage();
if (entity.getParentReply() != null) {
parentReplyId = entity.getParentReply().getId();
}
if (entity.getDeleted())
message = null;
return new ForumThreadReplyRESTModel(entity.getId(), message, entity.getCreator(), entity.getCreated(),
entity.getForumArea().getId(), parentReplyId, entity.getLastModified(), entity.getChildReplyCount(),
entity.getDeleted());
}
private List<ForumThreadReplyRESTModel> createRestModel(ForumThreadReply... entries) {
List<ForumThreadReplyRESTModel> result = new ArrayList<>();
for (ForumThreadReply entry : entries) {
result.add(createRestModel(entry));
}
return result;
}
}