package net.curisit.securis.services; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.annotation.security.RolesAllowed; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.persistence.EntityManager; import javax.persistence.PersistenceException; import javax.persistence.TypedQuery; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.FormParam; 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.QueryParam; 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 net.curisit.integrity.commons.Utils; import net.curisit.securis.DefaultExceptionHandler; import net.curisit.securis.SeCurisException; import net.curisit.securis.db.Organization; import net.curisit.securis.db.User; 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.utils.TokenHelper; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; /** * User resource * * @author roberto */ @Path("/user") @RequestScoped public class UserResource { @Inject TokenHelper tokenHelper; @Context EntityManager em; private static final Logger LOG = LogManager.getLogger(UserResource.class); public UserResource() { } /** * * @return the server version in format majorVersion.minorVersion */ @GET @Path("/") @Produces({ MediaType.APPLICATION_JSON }) @Securable @RolesAllowed(BasicSecurityContext.ROL_ADMIN) public Response index() { LOG.info("Getting users list "); // EntityManager em = emProvider.get(); em.clear(); TypedQuery q = em.createNamedQuery("list-users", User.class); List list = q.getResultList(); return Response.ok(list).build(); } /** * * @return The user */ @GET @Path("/{uid}") @Produces({ MediaType.APPLICATION_JSON }) @Securable @RolesAllowed(BasicSecurityContext.ROL_ADMIN) public Response get(@PathParam("uid") String uid, @HeaderParam(TokenHelper.TOKEN_HEADER_PÀRAM) String token) { LOG.info("Getting user data for id: {}: ", uid); if (uid == null || "".equals(uid)) { LOG.error("User ID is mandatory"); return Response.status(Status.NOT_FOUND).build(); } // EntityManager em = emProvider.get(); em.clear(); User lt = em.find(User.class, uid); if (lt == null) { LOG.error("User with id {} not found in DB", uid); return Response.status(Status.NOT_FOUND).build(); } return Response.ok(lt).build(); } @POST @Path("/") @Consumes(MediaType.APPLICATION_JSON) @Produces({ MediaType.APPLICATION_JSON }) @EnsureTransaction @Securable @RolesAllowed(BasicSecurityContext.ROL_ADMIN) public Response create(User user, @HeaderParam(TokenHelper.TOKEN_HEADER_PÀRAM) String token) { LOG.info("Creating new user"); // EntityManager em = emProvider.get(); User currentUser = em.find(User.class, user.getUsername()); if (currentUser != null) { LOG.info("User with id {} was found in DB, we'll try to modify it", user.getUsername()); return modify(user, user.getUsername(), token); } try { this.setUserOrg(user, user.getOrgsIds(), em); } catch (SeCurisException e) { return Response.status(Status.NOT_FOUND).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, e.getMessage()).build(); } if (user.getPassword() != null && !"".equals(user.getPassword())) { user.setPassword(Utils.sha256(user.getPassword())); } else { return Response.status(DefaultExceptionHandler.DEFAULT_APP_ERROR_STATUS_CODE) .header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "User password is mandatory").build(); } user.setModificationTimestamp(new Date()); user.setLastLogin(null); user.setCreationTimestamp(new Date()); em.persist(user); return Response.ok(user).build(); } private void setUserOrg(User user, Set orgsIds, EntityManager em) throws SeCurisException { Set orgs = null; if (orgsIds != null && !orgsIds.isEmpty()) { orgs = new HashSet<>(); for (Integer orgId : orgsIds) { Organization o = em.find(Organization.class, orgId); if (o == null) { LOG.error("User organization with id {} not found in DB", orgId); throw new SeCurisException("User's organization not found with ID: " + orgId); } orgs.add(o); } } user.setOrganizations(orgs); } @PUT @POST @Path("/{uid}") @EnsureTransaction @Consumes(MediaType.APPLICATION_JSON) @Produces({ MediaType.APPLICATION_JSON }) @Securable @RolesAllowed(BasicSecurityContext.ROL_ADMIN) public Response modify(User user, @PathParam("uid") String uid, @HeaderParam(TokenHelper.TOKEN_HEADER_PÀRAM) String token) { LOG.info("Modifying user with id: {}", uid); // EntityManager em = emProvider.get(); User currentUser = em.find(User.class, uid); if (currentUser == null) { LOG.info("User with id {} not found in DB, we'll try to create it", uid); return create(user, token); } try { this.setUserOrg(currentUser, user.getOrgsIds(), em); } catch (SeCurisException e) { return Response.status(Status.NOT_FOUND).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, e.getMessage()).build(); } currentUser.setFirstName(user.getFirstName()); currentUser.setLastName(user.getLastName()); currentUser.setRoles(user.getRoles()); currentUser.setLang(user.getLang()); currentUser.setModificationTimestamp(new Date()); if (user.getPassword() != null && !"".equals(user.getPassword())) { currentUser.setPassword(Utils.sha256(user.getPassword())); } else { // Password has not been modified // return // Response.status(DefaultExceptionHandler.DEFAULT_APP_ERROR_STATUS_CODE).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, // "User password is mandatory").build(); } currentUser.setLastLogin(user.getLastLogin()); em.persist(currentUser); return Response.ok(currentUser).build(); } @DELETE @Path("/{uid}") @EnsureTransaction @Produces({ MediaType.APPLICATION_JSON }) @Securable @RolesAllowed(BasicSecurityContext.ROL_ADMIN) public Response delete(@PathParam("uid") String uid, @Context HttpServletRequest request) { LOG.info("Deleting app with id: {}", uid); // EntityManager em = emProvider.get(); User app = em.find(User.class, uid); if (app == null) { LOG.error("User with id {} can not be deleted, It was not found in DB", uid); return Response.status(Status.NOT_FOUND).build(); } em.remove(app); return Response.ok(Utils.createMap("success", true, "id", uid)).build(); } @POST @Path("/login") @Produces({ MediaType.APPLICATION_JSON }) public Response login(@FormParam("username") String username, @FormParam("password") String password, @Context HttpServletRequest request) throws SeCurisServiceException { LOG.info("index session: " + request.getSession()); LOG.info("user: {}, pass: {}", username, password); LOG.info("is user in role: {} == {} ? ", "advance", request.isUserInRole("advance")); LOG.info("is user in role: {} == {} ? ", "admin", request.isUserInRole("admin")); // EntityManager em = emProvider.get(); User user = em.find(User.class, username); if (user == null) { LOG.error("Inknown username {} used in login service", username); throw new SeCurisServiceException(ErrorCodes.UNAUTHORIZED_ACCESS, "Wrong credentials"); } String securedPassword = Utils.sha256(password); if (securedPassword == null || !securedPassword.equals(user.getPassword())) { throw new SeCurisServiceException(ErrorCodes.UNAUTHORIZED_ACCESS, "Wrong credentials"); } user.setLastLogin(new Date()); em.getTransaction().begin(); try { em.persist(user); em.getTransaction().commit(); } catch (PersistenceException ex) { LOG.error("Error updating last login date for user: {}", username); LOG.error(ex); em.getTransaction().rollback(); } String tokenAuth = tokenHelper.generateToken(username); return Response.ok(Utils.createMap("success", true, "token", tokenAuth)).build(); } /** * Check if current token is valid * * @param user * @param password * @param request * @return */ @POST @Path("/check") @Produces({ MediaType.APPLICATION_JSON }) public Response check(@HeaderParam(TokenHelper.TOKEN_HEADER_PÀRAM) String token, @QueryParam("token") String token2) { if (token == null) { token = token2; } if (token == null) { return Response.status(Status.FORBIDDEN).build(); } LOG.info("Token : " + token); String user = tokenHelper.extractUserFromToken(token); LOG.info("Token user: " + user); Date date = tokenHelper.extractDateCreationFromToken(token); LOG.info("Token date: " + date); boolean valid = tokenHelper.isTokenValid(token); LOG.info("Is Token valid: " + valid); return Response.ok(Utils.createMap("valid", true, "user", user, "date", date, "token", token)).build(); } @GET @Path("/logout") @Produces({ MediaType.APPLICATION_JSON }) public Response logout(@Context HttpServletRequest request) { request.getSession().invalidate(); return Response.ok().build(); } }