package net.curisit.securis.services; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import javax.annotation.security.RolesAllowed; import javax.inject.Inject; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; 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.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import net.curisit.integrity.commons.Utils; import net.curisit.securis.DefaultExceptionHandler; import net.curisit.securis.db.Application; import net.curisit.securis.db.ApplicationMetadata; import net.curisit.securis.ioc.EnsureTransaction; import net.curisit.securis.security.BasicSecurityContext; import net.curisit.securis.security.Securable; import net.curisit.securis.services.exception.SeCurisServiceException; import net.curisit.securis.services.exception.SeCurisServiceException.ErrorCodes; import net.curisit.securis.services.helpers.MetadataHelper; import net.curisit.securis.utils.TokenHelper; /** * Application resource, this service will provide methods to create, modify and * delete applications * * @author roberto */ @Path("/application") public class ApplicationResource { @Inject TokenHelper tokenHelper; @Inject MetadataHelper metadataHelper; @Context EntityManager em; private static final Logger LOG = LogManager.getLogger(ApplicationResource.class); public ApplicationResource() { } /** * * @return the server version in format majorVersion.minorVersion */ @GET @Path("/") @Produces({ MediaType.APPLICATION_JSON }) @Securable public Response index() { LOG.info("Getting applications list "); // EntityManager em = emProvider.get(); em.clear(); TypedQuery q = em.createNamedQuery("list-applications", Application.class); List list = q.getResultList(); return Response.ok(list).build(); } /** * * @return the server version in format majorVersion.minorVersion * @throws SeCurisServiceException */ @GET @Path("/{appid}") @Produces({ MediaType.APPLICATION_JSON }) @Securable public Response get(@PathParam("appid") String appid) throws SeCurisServiceException { LOG.info("Getting application data for id: {}: ", appid); if (appid == null || "".equals(appid)) { LOG.error("Application ID is mandatory"); return Response.status(Status.NOT_FOUND).build(); } em.clear(); Application app = null; try { LOG.info("READY to GET app: {}", appid); app = em.find(Application.class, Integer.parseInt(appid)); } catch (Exception e) { LOG.info("ERROR GETTING app: {}", e); } if (app == null) { LOG.error("Application with id {} not found in DB", appid); throw new SeCurisServiceException(ErrorCodes.NOT_FOUND, "Application not found with ID: " + appid); } return Response.ok(app).build(); } @POST @Path("/") @Consumes(MediaType.APPLICATION_JSON) @Produces({ MediaType.APPLICATION_JSON }) @EnsureTransaction @Securable @RolesAllowed(BasicSecurityContext.ROL_ADMIN) public Response create(Application app, @HeaderParam(TokenHelper.TOKEN_HEADER_PÀRAM) String token) { LOG.info("Creating new application"); // EntityManager em = emProvider.get(); app.setCreationTimestamp(new Date()); em.persist(app); if (app.getApplicationMetadata() != null) { for (ApplicationMetadata md : app.getApplicationMetadata()) { md.setApplication(app); md.setCreationTimestamp(new Date()); em.persist(md); } } LOG.info("Creating application ({}) with date: {}", app.getId(), app.getCreationTimestamp()); return Response.ok(app).build(); } @PUT @POST @Path("/{appid}") @EnsureTransaction @Consumes(MediaType.APPLICATION_JSON) @Produces({ MediaType.APPLICATION_JSON }) @Securable @RolesAllowed(BasicSecurityContext.ROL_ADMIN) public Response modify(Application app, @PathParam("appid") String appid, @HeaderParam(TokenHelper.TOKEN_HEADER_PÀRAM) String token) { LOG.info("Modifying application with id: {}", appid); // EntityManager em = emProvider.get(); Application currentapp = em.find(Application.class, Integer.parseInt(appid)); if (currentapp == null) { LOG.error("Application with id {} not found in DB", appid); return Response.status(Status.NOT_FOUND).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "Application not found with ID: " + appid).build(); } currentapp.setCode(app.getCode()); currentapp.setName(app.getName()); currentapp.setLicenseFilename(app.getLicenseFilename()); currentapp.setDescription(app.getDescription()); Set newMD = app.getApplicationMetadata(); Set oldMD = currentapp.getApplicationMetadata(); boolean metadataChanges = !metadataHelper.match(newMD, oldMD); if (metadataChanges) { Map directOldMD = getMapMD(oldMD); Map directNewMD = getMapMD(newMD); for (ApplicationMetadata currentMd : oldMD) { if (newMD == null || !directNewMD.containsKey(currentMd.getKey())) { em.remove(currentMd); } } if (newMD != null) { for (ApplicationMetadata md : newMD) { if (directOldMD.containsKey(md.getKey())) { em.merge(md); } else { md.setApplication(currentapp); if (md.getCreationTimestamp() == null) { md.setCreationTimestamp(app.getCreationTimestamp()); } em.persist(md); } } } currentapp.setApplicationMetadata(app.getApplicationMetadata()); } em.merge(currentapp); if (metadataChanges) { metadataHelper.propagateMetadata(em, currentapp); } return Response.ok(currentapp).build(); } private Map getMapMD(Set amd) { Map map = new HashMap(); if (amd != null) { for (ApplicationMetadata applicationMetadata : amd) { map.put(applicationMetadata.getKey(), applicationMetadata); } } return map; } @DELETE @Path("/{appid}") @EnsureTransaction @Produces({ MediaType.APPLICATION_JSON }) @Securable @RolesAllowed(BasicSecurityContext.ROL_ADMIN) public Response delete(@PathParam("appid") String appid, @Context HttpServletRequest request) { LOG.info("Deleting app with id: {}", appid); // EntityManager em = emProvider.get(); Application app = em.find(Application.class, Integer.parseInt(appid)); if (app == null) { LOG.error("Application with id {} can not be deleted, It was not found in DB", appid); return Response.status(Status.NOT_FOUND).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "Application not found with ID: " + appid).build(); } /* * if (app.getLicenseTypes() != null && * !app.getLicenseTypes().isEmpty()) { throw new * SeCurisServiceException(ErrorCodes.NOT_FOUND, * "Application can not be deleted becasue has assigned one or more License types, ID: " * + appid); } */ em.remove(app); return Response.ok(Utils.createMap("success", true, "id", appid)).build(); } }