From 9430a83dde5d7c3f4535f6c3a5f9e21ac68ac8fa Mon Sep 17 00:00:00 2001
From: Joaquín Reñé <jrene@curisit.net>
Date: Thu, 16 Apr 2026 17:05:28 +0000
Subject: [PATCH] #4479 - upgrade SecurisServer to Java 21

---
 securis/src/main/java/net/curisit/securis/services/UserResource.java |   54 ++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 36 insertions(+), 18 deletions(-)

diff --git a/securis/src/main/java/net/curisit/securis/services/UserResource.java b/securis/src/main/java/net/curisit/securis/services/UserResource.java
index 7c4681a..0764f5e 100644
--- a/securis/src/main/java/net/curisit/securis/services/UserResource.java
+++ b/securis/src/main/java/net/curisit/securis/services/UserResource.java
@@ -12,7 +12,6 @@
 import jakarta.enterprise.context.RequestScoped;
 import jakarta.inject.Inject;
 import jakarta.persistence.EntityManager;
-import jakarta.persistence.PersistenceException;
 import jakarta.persistence.TypedQuery;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.ws.rs.Consumes;
@@ -57,7 +56,7 @@
  * <p>
  * Notes:
  * - Uses {@link BasicSecurityContext} authorization via @Securable and @RolesAllowed.
- * - Uses JPA {@link EntityManager} injected through @Context.
+ * - Uses JPA {@link EntityManager} injected through dependency injection.
  * - Mutating endpoints are wrapped in @EnsureTransaction to guarantee commit/rollback.
  * - Passwords are stored as SHA-256 hashes (see {@link Utils#sha256(String)}).
  *
@@ -86,7 +85,7 @@
     @Inject private CacheTTL cache;
 
     /** JPA entity manager bound to the current request context. */
-    @Context EntityManager em;
+    @Inject EntityManager em;
 
     private static final Logger LOG = LogManager.getLogger(UserResource.class);
 
@@ -330,7 +329,7 @@
         // lastLogin can be set through API (rare), otherwise managed at login
         currentUser.setLastLogin(user.getLastLogin());
 
-        em.persist(currentUser);
+        em.merge(currentUser);
         clearUserCache(currentUser.getUsername());
 
         return Response.ok(currentUser).build();
@@ -402,35 +401,54 @@
     @POST
     @Path("/login")
     @Produces({ MediaType.APPLICATION_JSON })
+    @EnsureTransaction
     public Response login(@FormParam("username") String username, @FormParam("password") String password, @Context HttpServletRequest request) throws SeCurisServiceException {
         LOG.info("index session: " + request.getSession());
+        LOG.info("login() called. session={}", request.getSession(false));
+        LOG.info("login() username='{}'", username);
 
-        User user = em.find(User.class, username);
-        if (user == null) {
-            LOG.error("Unknown username {} used in login service", username);
+        if (username == null || username.trim().isEmpty()) {
+            LOG.error("login() username is null or empty");
             throw new SeCurisServiceException(ErrorCodes.UNAUTHORIZED_ACCESS, "Wrong credentials");
         }
+        if (password == null || password.isEmpty()) {
+            LOG.error("login() password is null or empty for user '{}'", username);
+            throw new SeCurisServiceException(ErrorCodes.UNAUTHORIZED_ACCESS, "Wrong credentials");
+        }
+
+        User user = em.find(User.class, username);
+        LOG.info("login() user found? {}", user != null);
+
+        if (user == null) {
+            LOG.error("Unknown username '{}' used in login service", username);
+            throw new SeCurisServiceException(ErrorCodes.UNAUTHORIZED_ACCESS, "Wrong credentials");
+        }
+
         String securedPassword = Utils.sha256(password);
+        LOG.info("login() hashed password generated? {}", securedPassword != null);
 
         if (securedPassword == null || !securedPassword.equals(user.getPassword())) {
+            LOG.error("Wrong password for user '{}'", username);
             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();
-        }
+        em.merge(user);
 
         clearUserCache(username);
-        String userFullName = String.format("%s %s", user.getFirstName(), user.getLastName() == null ? "" : user.getLastName()).trim();
+
+        String userFullName = String.format("%s %s",
+                user.getFirstName(),
+                user.getLastName() == null ? "" : user.getLastName()).trim();
+
         String tokenAuth = tokenHelper.generateToken(username);
-        return Response.ok(Utils.createMap("success", true, "token", tokenAuth, "username", username, "full_name", userFullName)).build();
+        LOG.info("login() success for user '{}'", username);
+
+        return Response.ok(Utils.createMap(
+                "success", true,
+                "token", tokenAuth,
+                "username", username,
+                "full_name", userFullName)).build();
     }
 
     /**

--
Gitblit v1.3.2