Joaquín Reñé
yesterday 9430a83dde5d7c3f4535f6c3a5f9e21ac68ac8fa
#4479 - upgrade SecurisServer to Java 21
1 files added
7 files modified
changed files
securis/pom.xml patch | view | blame | history
securis/src/main/java/net/curisit/securis/ioc/EntityManagerProvider.java patch | view | blame | history
securis/src/main/java/net/curisit/securis/services/UserResource.java patch | view | blame | history
securis/src/main/resources/META-INF/persistence.xml patch | view | blame | history
securis/src/main/resources/version.properties patch | view | blame | history
securis/src/main/webapp/WEB-INF/web.xml patch | view | blame | history
securis/src/main/webapp/src/app/footer.component.ts patch | view | blame | history
securis/src/main/webapp/src/app/user.service.ts patch | view | blame | history
securis/pom.xml
....@@ -176,6 +176,12 @@
176176 </dependencies>
177177
178178 <build>
179
+ <resources>
180
+ <resource>
181
+ <directory>src/main/resources</directory>
182
+ <filtering>true</filtering>
183
+ </resource>
184
+ </resources>
179185 <plugins>
180186 <plugin>
181187 <groupId>org.apache.maven.plugins</groupId>
securis/src/main/java/net/curisit/securis/ioc/EntityManagerProvider.java
....@@ -3,6 +3,7 @@
33 */
44 package net.curisit.securis.ioc;
55
6
+import jakarta.annotation.PostConstruct;
67 import jakarta.enterprise.context.ApplicationScoped;
78 import jakarta.persistence.EntityManager;
89 import jakarta.persistence.EntityManagerFactory;
....@@ -27,15 +28,27 @@
2728 @ApplicationScoped
2829 public class EntityManagerProvider {
2930
30
- @SuppressWarnings("unused")
3131 private static final Logger log = LogManager.getLogger(EntityManagerProvider.class);
3232
3333 /**
3434 * entityManagerFactory<p>
3535 * Application-wide EMF built from persistence.xml PU "localdb".
3636 */
37
- private final EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("localdb");
37
+ //private final EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("localdb");
38
+ private EntityManagerFactory entityManagerFactory;
3839
40
+ @PostConstruct
41
+ public void init() {
42
+ try {
43
+ log.info("Initializing EntityManagerFactory with persistence unit 'localdb'");
44
+ entityManagerFactory = Persistence.createEntityManagerFactory("localdb");
45
+ log.info("EntityManagerFactory initialized correctly: {}", entityManagerFactory);
46
+ } catch (Exception e) {
47
+ log.error("Error creating EntityManagerFactory for persistence unit 'localdb'", e);
48
+ entityManagerFactory = null;
49
+ }
50
+ }
51
+
3952 /**
4053 * getEntityManager<p>
4154 * Create a new {@link EntityManager}.
....@@ -43,6 +56,17 @@
4356 * @return a new EntityManager; caller must close it
4457 */
4558 public EntityManager getEntityManager() {
46
- return entityManagerFactory.createEntityManager();
59
+ try {
60
+ if (entityManagerFactory == null) {
61
+ log.error("EntityManagerFactory is null");
62
+ return null;
63
+ }
64
+ EntityManager em = entityManagerFactory.createEntityManager();
65
+ log.info("Created EntityManager: {}", em);
66
+ return em;
67
+ } catch (Exception e) {
68
+ log.error("Error creating EntityManager", e);
69
+ return null;
70
+ }
4771 }
4872 }
securis/src/main/java/net/curisit/securis/services/UserResource.java
....@@ -12,7 +12,6 @@
1212 import jakarta.enterprise.context.RequestScoped;
1313 import jakarta.inject.Inject;
1414 import jakarta.persistence.EntityManager;
15
-import jakarta.persistence.PersistenceException;
1615 import jakarta.persistence.TypedQuery;
1716 import jakarta.servlet.http.HttpServletRequest;
1817 import jakarta.ws.rs.Consumes;
....@@ -57,7 +56,7 @@
5756 * <p>
5857 * Notes:
5958 * - Uses {@link BasicSecurityContext} authorization via @Securable and @RolesAllowed.
60
- * - Uses JPA {@link EntityManager} injected through @Context.
59
+ * - Uses JPA {@link EntityManager} injected through dependency injection.
6160 * - Mutating endpoints are wrapped in @EnsureTransaction to guarantee commit/rollback.
6261 * - Passwords are stored as SHA-256 hashes (see {@link Utils#sha256(String)}).
6362 *
....@@ -86,7 +85,7 @@
8685 @Inject private CacheTTL cache;
8786
8887 /** JPA entity manager bound to the current request context. */
89
- @Context EntityManager em;
88
+ @Inject EntityManager em;
9089
9190 private static final Logger LOG = LogManager.getLogger(UserResource.class);
9291
....@@ -330,7 +329,7 @@
330329 // lastLogin can be set through API (rare), otherwise managed at login
331330 currentUser.setLastLogin(user.getLastLogin());
332331
333
- em.persist(currentUser);
332
+ em.merge(currentUser);
334333 clearUserCache(currentUser.getUsername());
335334
336335 return Response.ok(currentUser).build();
....@@ -402,35 +401,54 @@
402401 @POST
403402 @Path("/login")
404403 @Produces({ MediaType.APPLICATION_JSON })
404
+ @EnsureTransaction
405405 public Response login(@FormParam("username") String username, @FormParam("password") String password, @Context HttpServletRequest request) throws SeCurisServiceException {
406406 LOG.info("index session: " + request.getSession());
407
+ LOG.info("login() called. session={}", request.getSession(false));
408
+ LOG.info("login() username='{}'", username);
407409
408
- User user = em.find(User.class, username);
409
- if (user == null) {
410
- LOG.error("Unknown username {} used in login service", username);
410
+ if (username == null || username.trim().isEmpty()) {
411
+ LOG.error("login() username is null or empty");
411412 throw new SeCurisServiceException(ErrorCodes.UNAUTHORIZED_ACCESS, "Wrong credentials");
412413 }
414
+ if (password == null || password.isEmpty()) {
415
+ LOG.error("login() password is null or empty for user '{}'", username);
416
+ throw new SeCurisServiceException(ErrorCodes.UNAUTHORIZED_ACCESS, "Wrong credentials");
417
+ }
418
+
419
+ User user = em.find(User.class, username);
420
+ LOG.info("login() user found? {}", user != null);
421
+
422
+ if (user == null) {
423
+ LOG.error("Unknown username '{}' used in login service", username);
424
+ throw new SeCurisServiceException(ErrorCodes.UNAUTHORIZED_ACCESS, "Wrong credentials");
425
+ }
426
+
413427 String securedPassword = Utils.sha256(password);
428
+ LOG.info("login() hashed password generated? {}", securedPassword != null);
414429
415430 if (securedPassword == null || !securedPassword.equals(user.getPassword())) {
431
+ LOG.error("Wrong password for user '{}'", username);
416432 throw new SeCurisServiceException(ErrorCodes.UNAUTHORIZED_ACCESS, "Wrong credentials");
417433 }
418434
419435 user.setLastLogin(new Date());
420
- em.getTransaction().begin();
421
- try {
422
- em.persist(user);
423
- em.getTransaction().commit();
424
- } catch (PersistenceException ex) {
425
- LOG.error("Error updating last login date for user: {}", username);
426
- LOG.error(ex);
427
- em.getTransaction().rollback();
428
- }
436
+ em.merge(user);
429437
430438 clearUserCache(username);
431
- String userFullName = String.format("%s %s", user.getFirstName(), user.getLastName() == null ? "" : user.getLastName()).trim();
439
+
440
+ String userFullName = String.format("%s %s",
441
+ user.getFirstName(),
442
+ user.getLastName() == null ? "" : user.getLastName()).trim();
443
+
432444 String tokenAuth = tokenHelper.generateToken(username);
433
- return Response.ok(Utils.createMap("success", true, "token", tokenAuth, "username", username, "full_name", userFullName)).build();
445
+ LOG.info("login() success for user '{}'", username);
446
+
447
+ return Response.ok(Utils.createMap(
448
+ "success", true,
449
+ "token", tokenAuth,
450
+ "username", username,
451
+ "full_name", userFullName)).build();
434452 }
435453
436454 /**
securis/src/main/resources/META-INF/persistence.xml
....@@ -1,22 +1,20 @@
11 <?xml version="1.0" encoding="UTF-8"?>
2
-<persistence version="2.0"
3
- xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
- xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
5
- <persistence-unit name="localdb" transaction-type="RESOURCE_LOCAL">
6
- <description>SeCuris LocalDB</description>
7
- <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
8
- <non-jta-data-source>java:comp/env/SeCurisDS</non-jta-data-source>
9
- <shared-cache-mode>NONE</shared-cache-mode>
10
- <properties>
11
- <property name="hibernate.cache.provider_class" value="org.hibernate.cache.internal.NoCachingRegionFactory"/>
12
- <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
13
- <!-- <property name="hibernate.connection.datasource" value="java:comp/env/jdbc/SeCurisDS" /> -->
2
+<persistence version="3.0"
3
+ xmlns="https://jakarta.ee/xml/ns/persistence"
4
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5
+ xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd">
146
15
- <property name="hibernate.cache.use_second_level_cache" value="false" />
16
- <!-- <property name="hibernate.show_sql" value="true" /> -->
17
-
18
- <property name="hibernate.format_sql" value="false"/>
19
- </properties>
7
+ <persistence-unit name="localdb" transaction-type="RESOURCE_LOCAL">
8
+ <description>SeCuris LocalDB</description>
9
+ <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
10
+ <non-jta-data-source>java:comp/env/SeCurisDS</non-jta-data-source>
11
+ <shared-cache-mode>NONE</shared-cache-mode>
2012
21
- </persistence-unit>
13
+ <properties>
14
+ <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.internal.NoCachingRegionFactory"/>
15
+ <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
16
+ <property name="hibernate.cache.use_second_level_cache" value="false"/>
17
+ <property name="hibernate.format_sql" value="false"/>
18
+ </properties>
19
+ </persistence-unit>
2220 </persistence>
securis/src/main/resources/version.properties
....@@ -0,0 +1,5 @@
1
+version=${project.version}
2
+majorVersion=3
3
+minorVersion=0
4
+incrementalVersion=2
5
+qualifier=
securis/src/main/webapp/WEB-INF/web.xml
....@@ -104,11 +104,13 @@
104104 </description>
105105 <role-name>admin</role-name>
106106 </security-role>
107
-
108
- <resource-env-ref>
109
- <resource-env-ref-name>SeCurisDS</resource-env-ref-name>
110
- <resource-env-ref-type>jakarta.sql.DataSource</resource-env-ref-type>
111
- </resource-env-ref>
107
+
108
+ <resource-ref>
109
+ <description>SeCuris DataSource</description>
110
+ <res-ref-name>SeCurisDS</res-ref-name>
111
+ <res-type>jakarta.sql.DataSource</res-type>
112
+ <res-auth>Container</res-auth>
113
+ </resource-ref>
112114
113115 <!--
114116 <resource-env-ref>
securis/src/main/webapp/src/app/footer.component.ts
....@@ -17,7 +17,7 @@
1717
1818 ngOnInit(): void {
1919 //TODO Move to service
20
- this.http.get("version", /* workaround to avoid OPTIONS method request*/ new BaseRequestOptions())
20
+ this.http.get("api/version", /* workaround to avoid OPTIONS method request*/ new BaseRequestOptions())
2121 .map((res) => <string>res.json().version)
2222 .subscribe(
2323 version => this.securisVersion = version,
securis/src/main/webapp/src/app/user.service.ts
....@@ -27,7 +27,7 @@
2727 params.append('username', username);
2828 params.append('password', password);
2929 let options = new RequestOptions({ headers: new Headers({ "Content-Type": "application/x-www-form-urlencoded" })});
30
- return this.http.post('user/login', params.toString(), options)
30
+ return this.http.post('api/user/login', params.toString(), options)
3131 .map((resp) => this.mapLogin(resp))
3232 .catch((err) => super.processErrorResponse(err));
3333 }
....@@ -47,7 +47,7 @@
4747 }
4848 var token = this.store.get("token");
4949 let option = new RequestOptions({ headers: new Headers({ 'X-SECURIS-TOKEN': token }) });
50
- return this.http.get('check', option)
50
+ return this.http.get('api/check', option)
5151 .map((resp) => this.mapCheck(resp))
5252 .catch((err) => super.processErrorResponse(err));
5353 }