package fi.otavanopisto.muikku.plugins.announcer.rest; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.List; 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.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import fi.otavanopisto.muikku.model.users.UserEntity; import fi.otavanopisto.muikku.model.users.UserGroupEntity; import fi.otavanopisto.muikku.model.workspace.WorkspaceEntity; import fi.otavanopisto.muikku.plugin.PluginRESTService; import fi.otavanopisto.muikku.plugins.announcer.AnnouncementController; import fi.otavanopisto.muikku.plugins.announcer.AnnouncerPermissions; import fi.otavanopisto.muikku.plugins.announcer.dao.AnnouncementEnvironmentRestriction; import fi.otavanopisto.muikku.plugins.announcer.dao.AnnouncementTimeFrame; import fi.otavanopisto.muikku.plugins.announcer.model.Announcement; import fi.otavanopisto.muikku.plugins.announcer.model.AnnouncementAttachment; import fi.otavanopisto.muikku.plugins.announcer.model.AnnouncementUserGroup; import fi.otavanopisto.muikku.plugins.announcer.workspace.model.AnnouncementWorkspace; import fi.otavanopisto.muikku.plugins.workspace.rest.model.WorkspaceBasicInfo; import fi.otavanopisto.muikku.plugins.workspace.rest.model.WorkspaceRESTModelController; import fi.otavanopisto.muikku.schooldata.WorkspaceEntityController; import fi.otavanopisto.muikku.session.SessionController; import fi.otavanopisto.muikku.session.local.LocalSession; import fi.otavanopisto.muikku.users.UserGroupEntityController; import fi.otavanopisto.security.rest.RESTPermit; import fi.otavanopisto.security.rest.RESTPermit.Handling; @RequestScoped @Stateful @Path("/announcer") @Produces("application/json") public class AnnouncerRESTService extends PluginRESTService { private static final long serialVersionUID = 1L; @Inject private Logger logger; @Inject private AnnouncementController announcementController; @Inject @LocalSession private SessionController sessionController; @Inject private UserGroupEntityController userGroupEntityController; @Inject private WorkspaceEntityController workspaceEntityController; @Inject private WorkspaceRESTModelController workspaceRESTModelController; private Date currentDate() { Calendar cal = Calendar.getInstance(); cal.setTime(new Date()); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); return cal.getTime(); } @POST @Path("/announcements") @RESTPermit(handling = Handling.INLINE) public Response createAnnouncement(AnnouncementRESTModel restModel) { UserEntity userEntity = sessionController.getLoggedUserEntity(); List<Long> workspaceEntityIds = restModel.getWorkspaceEntityIds(); if (workspaceEntityIds == null) { workspaceEntityIds = Collections.emptyList(); } List<Long> userGroupEntityIds = restModel.getUserGroupEntityIds(); if (userGroupEntityIds == null) { userGroupEntityIds = Collections.emptyList(); } if (workspaceEntityIds.isEmpty() && !sessionController.hasEnvironmentPermission(AnnouncerPermissions.CREATE_ANNOUNCEMENT)) { return Response.status(Status.FORBIDDEN).entity("You don't have the permission to create environment announcements").build(); } for (Long workspaceEntityId : workspaceEntityIds) { WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId); if (workspaceEntity == null) { return Response.status(Status.BAD_REQUEST).entity("Invalid workspaceEntityId").build(); } if (!sessionController.hasWorkspacePermission(AnnouncerPermissions.CREATE_WORKSPACE_ANNOUNCEMENT, workspaceEntity)) { return Response.status(Status.FORBIDDEN).entity("You don't have the permission to create workspace announcement").build(); } } Announcement announcement = announcementController.createAnnouncement( userEntity, restModel.getCaption(), restModel.getContent(), restModel.getStartDate(), restModel.getEndDate(), restModel.getPubliclyVisible()); for (Long userGroupEntityId : userGroupEntityIds) { UserGroupEntity userGroupEntity = userGroupEntityController.findUserGroupEntityById(userGroupEntityId); if (userGroupEntity == null) { return Response.status(Status.BAD_REQUEST).entity("Invalid userGroupEntityId").build(); } announcementController.addAnnouncementTargetGroup(announcement, userGroupEntity); } for (Long workspaceEntityId : workspaceEntityIds) { WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId); if (workspaceEntity == null) { return Response.status(Status.BAD_REQUEST).entity("Invalid workspaceEntityId").build(); } announcementController.addAnnouncementWorkspace(announcement, workspaceEntity); } return Response.noContent().build(); } @PUT @Path("/announcements/{ID}") @RESTPermit(handling = Handling.INLINE) public Response updateAnnouncement(@PathParam("ID") Long announcementId, AnnouncementRESTModel restModel) { UserEntity userEntity = sessionController.getLoggedUserEntity(); if (announcementId == null) { return Response.status(Status.BAD_REQUEST).build(); } Announcement oldAnnouncement = announcementController.findById(announcementId); if (oldAnnouncement == null) { return Response.status(Status.NOT_FOUND).build(); } // Check that the user has permission to update the old announcement if (!canEdit(oldAnnouncement, userEntity)) return Response.status(Status.FORBIDDEN).entity("You don't have the permission to update this announcement.").build(); List<Long> workspaceEntityIds = restModel.getWorkspaceEntityIds(); if (workspaceEntityIds == null) { workspaceEntityIds = Collections.emptyList(); } List<Long> userGroupEntityIds = restModel.getUserGroupEntityIds(); if (userGroupEntityIds == null) { userGroupEntityIds = Collections.emptyList(); } if (workspaceEntityIds.isEmpty() && !sessionController.hasEnvironmentPermission(AnnouncerPermissions.UPDATE_ANNOUNCEMENT)) { return Response.status(Status.FORBIDDEN).entity("You don't have the permission to update environment announcements").build(); } for (Long workspaceEntityId : workspaceEntityIds) { WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId); if (workspaceEntity == null) { return Response.status(Status.BAD_REQUEST).entity("Invalid workspaceEntityId").build(); } if (!sessionController.hasWorkspacePermission(AnnouncerPermissions.UPDATE_WORKSPACE_ANNOUNCEMENT, workspaceEntity)) { return Response.status(Status.FORBIDDEN).entity("You don't have the permission to update workspace announcement").build(); } } Announcement newAnnouncement = announcementController.updateAnnouncement( oldAnnouncement, restModel.getCaption(), restModel.getContent(), restModel.getStartDate(), restModel.getEndDate(), restModel.getPubliclyVisible()); announcementController.clearAnnouncementTargetGroups(newAnnouncement); for (Long userGroupEntityId : userGroupEntityIds) { UserGroupEntity userGroupEntity = userGroupEntityController.findUserGroupEntityById(userGroupEntityId); if (userGroupEntity == null) { return Response.status(Status.BAD_REQUEST).entity("Invalid userGroupEntityId").build(); } announcementController.addAnnouncementTargetGroup(newAnnouncement, userGroupEntity); } announcementController.clearAnnouncementWorkspaces(newAnnouncement); for (Long workspaceEntityId : workspaceEntityIds) { WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId); if (workspaceEntity == null) { return Response.status(Status.BAD_REQUEST).entity("Invalid workspaceEntityId").build(); } announcementController.addAnnouncementWorkspace(newAnnouncement, workspaceEntity); } List<AnnouncementUserGroup> announcementUserGroups = announcementController.listAnnouncementUserGroups(newAnnouncement); List<AnnouncementWorkspace> announcementWorkspaces = announcementController.listAnnouncementWorkspaces(newAnnouncement); return Response .ok(createRESTModel(newAnnouncement, announcementUserGroups, announcementWorkspaces)) .build(); } @GET @Path("/announcements") @RESTPermit(handling=Handling.INLINE) public Response listAnnouncements( @QueryParam("hideEnvironmentAnnouncements") @DefaultValue("false") boolean hideEnvironmentAnnouncements, @QueryParam("hideWorkspaceAnnouncements") @DefaultValue("false") boolean hideWorkspaceAnnouncements, @QueryParam("hideGroupAnnouncements") @DefaultValue("false") boolean hideGroupAnnouncements, @QueryParam("workspaceEntityId") Long workspaceEntityId, @QueryParam("onlyMine") @DefaultValue("false") boolean onlyMine, @QueryParam("onlyEditable") @DefaultValue("false") boolean onlyEditable, @QueryParam("onlyArchived") @DefaultValue("false") boolean onlyArchived, @QueryParam("timeFrame") @DefaultValue("CURRENT") AnnouncementTimeFrame timeFrame ) { UserEntity currentUserEntity = sessionController.getLoggedUserEntity(); List<Announcement> announcements = null; AnnouncementEnvironmentRestriction environment = hideEnvironmentAnnouncements ? AnnouncementEnvironmentRestriction.NONE : sessionController.hasEnvironmentPermission(AnnouncerPermissions.LIST_ENVIRONMENT_GROUP_ANNOUNCEMENTS) ? AnnouncementEnvironmentRestriction.PUBLICANDGROUP : AnnouncementEnvironmentRestriction.PUBLIC; if (workspaceEntityId == null) { boolean includeGroups = !hideGroupAnnouncements; boolean includeWorkspaces = !hideWorkspaceAnnouncements; announcements = announcementController.listAnnouncements( includeGroups, includeWorkspaces, environment, timeFrame, currentUserEntity, onlyMine, onlyArchived); } else { WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId); if (workspaceEntity == null) { return Response.status(Status.BAD_REQUEST).entity("Workspace entity with given ID not found").build(); } if (!sessionController.hasWorkspacePermission(AnnouncerPermissions.LIST_WORKSPACE_ANNOUNCEMENTS, workspaceEntity)) { return Response.status(Status.FORBIDDEN).entity("You don't have the permission to list workspace announcements").build(); } List<WorkspaceEntity> workspaceEntities = Arrays.asList(workspaceEntity); announcements = announcementController.listWorkspaceAnnouncements( workspaceEntities, environment, timeFrame, currentUserEntity, onlyMine, onlyArchived); } List<AnnouncementRESTModel> restModels = new ArrayList<>(); for (Announcement announcement : announcements) { if (onlyEditable && !canEdit(announcement, currentUserEntity)) continue; List<AnnouncementUserGroup> announcementUserGroups = announcementController.listAnnouncementUserGroups(announcement); List<AnnouncementWorkspace> announcementWorkspaces = announcementController.listAnnouncementWorkspacesSortByUserFirst(announcement, currentUserEntity); AnnouncementRESTModel restModel = createRESTModel(announcement, announcementUserGroups, announcementWorkspaces); restModels.add(restModel); } return Response.ok(restModels).build(); } @GET @Path("/announcements/{ID}") @RESTPermit(AnnouncerPermissions.FIND_ANNOUNCEMENT) public Response findAnnouncementById(@PathParam("ID") Long announcementId) { UserEntity userEntity = sessionController.getLoggedUserEntity(); Announcement announcement = announcementController.findById(announcementId); if (announcement == null) { return Response.status(Status.NOT_FOUND).entity("Announcement not found").build(); } List<AnnouncementUserGroup> announcementUserGroups = announcementController.listAnnouncementUserGroups(announcement); List<AnnouncementWorkspace> announcementWorkspaces = announcementController.listAnnouncementWorkspacesSortByUserFirst(announcement, userEntity); return Response.ok(createRESTModel(announcement, announcementUserGroups, announcementWorkspaces)).build(); } private AnnouncementRESTModel createRESTModel(Announcement announcement, List<AnnouncementUserGroup> announcementUserGroups, List<AnnouncementWorkspace> announcementWorkspaces) { AnnouncementRESTModel restModel = new AnnouncementRESTModel(); restModel.setPublisherUserEntityId(announcement.getPublisherUserEntityId()); restModel.setCaption(announcement.getCaption()); restModel.setContent(announcement.getContent()); restModel.setCreated(announcement.getCreated()); restModel.setStartDate(announcement.getStartDate()); restModel.setEndDate(announcement.getEndDate()); restModel.setId(announcement.getId()); restModel.setPubliclyVisible(announcement.getPubliclyVisible()); List<Long> userGroupEntityIds = new ArrayList<>(); for (AnnouncementUserGroup announcementUserGroup : announcementUserGroups) { userGroupEntityIds.add(announcementUserGroup.getUserGroupEntityId()); } restModel.setUserGroupEntityIds(userGroupEntityIds); List<Long> workspaceEntityIds = new ArrayList<>(); List<WorkspaceBasicInfo> workspaceBasicInfos = new ArrayList<>(); for (AnnouncementWorkspace announcementWorkspace : announcementWorkspaces) { workspaceEntityIds.add(announcementWorkspace.getWorkspaceEntityId()); WorkspaceBasicInfo workspaceBasicInfo = workspaceRESTModelController.workspaceBasicInfo(announcementWorkspace.getWorkspaceEntityId()); if (workspaceBasicInfo != null) workspaceBasicInfos.add(workspaceBasicInfo); else logger.warning(String.format("Logged user couldn't find workspace basic info for workspace")); } restModel.setWorkspaceEntityIds(workspaceEntityIds); restModel.setWorkspaces(workspaceBasicInfos); Date date = currentDate(); if (date.before(announcement.getStartDate())) { restModel.setTemporalStatus(AnnouncementTemporalStatus.UPCOMING); } else if (date.after(announcement.getEndDate())) { restModel.setTemporalStatus(AnnouncementTemporalStatus.ENDED); } else { restModel.setTemporalStatus(AnnouncementTemporalStatus.ACTIVE); } return restModel; } private boolean canEdit(Announcement announcement, List<AnnouncementWorkspace> announcementWorkspaces, UserEntity userEntity) { // You can edit your own announcements if (announcement.getPublisherUserEntityId() == userEntity.getId()) return true; if (CollectionUtils.isEmpty(announcementWorkspaces)) { // Environment announcement return sessionController.hasEnvironmentPermission(AnnouncerPermissions.UPDATE_ANNOUNCEMENT); } else { // Workspace(s)-tied announcement, needs to have permission to update in all workspaces. for (AnnouncementWorkspace announcementWorkspace : announcementWorkspaces) { WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(announcementWorkspace.getWorkspaceEntityId()); if (!sessionController.hasWorkspacePermission(AnnouncerPermissions.UPDATE_WORKSPACE_ANNOUNCEMENT, workspaceEntity)) { return false; } } return true; } } private boolean canEdit(Announcement announcement, UserEntity userEntity) { List<AnnouncementWorkspace> announcementWorkspaces = announcementController.listAnnouncementWorkspaces(announcement); return canEdit(announcement, announcementWorkspaces, userEntity); } @DELETE @Path("/announcements/{ID}") @RESTPermit(handling = Handling.INLINE) public Response deleteAnnouncement(@PathParam("ID") Long announcementId) { Announcement announcement = announcementController.findById(announcementId); if (announcement == null) { return Response.status(Status.NOT_FOUND).build(); } List<AnnouncementWorkspace> announcementWorkspaces = announcementController.listAnnouncementWorkspaces(announcement); if (announcementWorkspaces.isEmpty() && !sessionController.hasEnvironmentPermission(AnnouncerPermissions.DELETE_ANNOUNCEMENT)) { return Response.status(Status.FORBIDDEN).entity("You don't have the permission to update environment announcements").build(); } for (AnnouncementWorkspace announcementWorkspace : announcementWorkspaces) { WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(announcementWorkspace.getWorkspaceEntityId()); if (workspaceEntity == null) { return Response.status(Status.BAD_REQUEST).entity("Invalid workspaceEntityId").build(); } if (!sessionController.hasWorkspacePermission(AnnouncerPermissions.DELETE_WORKSPACE_ANNOUNCEMENT, workspaceEntity)) { return Response.status(Status.FORBIDDEN).entity("You don't have the permission to update workspace announcement").build(); } } announcementController.archive(announcement); return Response.noContent().build(); } @GET @Path("/attachment/{ATTACHMENTNAME}") @RESTPermit(handling = Handling.UNSECURED) public Response getMessageAttachment(@PathParam ("ATTACHMENTNAME") String attachmentName, @Context Request request) { if (StringUtils.isBlank(attachmentName)) { return Response.status(Response.Status.BAD_REQUEST).build(); } AnnouncementAttachment announcementAttachment = announcementController.findAttachmentByName(attachmentName); if (announcementAttachment == null) { return Response.status(Response.Status.NOT_FOUND).build(); } EntityTag tag = new EntityTag(announcementAttachment.getName()); ResponseBuilder builder = request.evaluatePreconditions(tag); if (builder != null) { return builder.build(); } CacheControl cacheControl = new CacheControl(); cacheControl.setMustRevalidate(true); return Response.ok(announcementAttachment.getContent()) .cacheControl(cacheControl) .tag(tag) .type(announcementAttachment.getContentType()) .build(); } }