Joaquín Reñé
2025-10-07 146a0fb8b0e90f9196e569152f649baf60d6cc8f
securis/src/main/java/net/curisit/securis/services/OrganizationResource.java
....@@ -1,3 +1,6 @@
1
+/*
2
+ * Copyright @ 2013 CurisTEC, S.A.S. All Rights Reserved.
3
+ */
14 package net.curisit.securis.services;
25
36 import java.util.Date;
....@@ -39,10 +42,12 @@
3942 import net.curisit.securis.utils.TokenHelper;
4043
4144 /**
42
- * Organization resource, this service will provide methods to create, modify
43
- * and delete organizations
44
- *
45
- * @author roberto <roberto.sanchez@curisit.net>
45
+ * OrganizationResource
46
+ * <p>
47
+ * CRUD and listing of organizations. Non-admin users are scoped by their
48
+ * accessible organization ids when listing.
49
+ *
50
+ * Last reviewed by JRA on Oct 5, 2025.
4651 */
4752 @Path("/organization")
4853 @RequestScoped
....@@ -50,18 +55,18 @@
5055
5156 private static final Logger LOG = LogManager.getLogger(OrganizationResource.class);
5257
53
- @Context
54
- EntityManager em;
58
+ @Context EntityManager em;
59
+ @Context BasicSecurityContext bsc;
5560
56
- @Context
57
- BasicSecurityContext bsc;
58
-
59
- public OrganizationResource() {
60
- }
61
+ public OrganizationResource() { }
6162
6263 /**
63
- *
64
- * @return the server version in format majorVersion.minorVersion
64
+ * index
65
+ * <p>
66
+ * List organizations. For admins returns all; for non-admins filters
67
+ * by the ids in {@link BasicSecurityContext#getOrganizationsIds()}.
68
+ *
69
+ * @return 200 OK with the list.
6570 */
6671 @GET
6772 @Path("/")
....@@ -69,8 +74,6 @@
6974 @Securable
7075 public Response index() {
7176 LOG.info("Getting organizations list ");
72
-
73
- // EntityManager em = emProvider.get();
7477 em.clear();
7578 TypedQuery<Organization> q;
7679 if (bsc.isUserInRole(BasicSecurityContext.ROL_ADMIN)) {
....@@ -84,15 +87,18 @@
8487 q.setParameter("list_ids", bsc.getOrganizationsIds());
8588 }
8689 }
87
-
8890 List<Organization> list = q.getResultList();
89
-
9091 return Response.ok(list).build();
9192 }
9293
9394 /**
94
- *
95
- * @return the server version in format majorVersion.minorVersion
95
+ * get
96
+ * <p>
97
+ * Fetch an organization by id.
98
+ *
99
+ * @param orgid organization id (string form).
100
+ * @param token header token (unused).
101
+ * @return 200 OK with entity or 404 if not found.
96102 */
97103 @GET
98104 @Path("/{orgid}")
....@@ -104,8 +110,6 @@
104110 LOG.error("Organization ID is mandatory");
105111 return Response.status(Status.NOT_FOUND).build();
106112 }
107
-
108
- // EntityManager em = emProvider.get();
109113 em.clear();
110114 Organization org = em.find(Organization.class, Integer.parseInt(orgid));
111115 if (org == null) {
....@@ -115,16 +119,15 @@
115119 return Response.ok(org).build();
116120 }
117121
118
- private boolean isCyclicalRelationship(int currentId, Organization parent) {
119
- while (parent != null) {
120
- if (parent.getId() == currentId) {
121
- return true;
122
- }
123
- parent = parent.getParentOrganization();
124
- }
125
- return false;
126
- }
127
-
122
+ /**
123
+ * create
124
+ * <p>
125
+ * Create a new organization, setting optional parent and user members.
126
+ * Requires ADMIN.
127
+ *
128
+ * @param org payload with code/name/etc., optional parentOrgId and usersIds.
129
+ * @return 200 OK with created organization or 404 when parent/user not found.
130
+ */
128131 @POST
129132 @Path("/")
130133 @Consumes(MediaType.APPLICATION_JSON)
....@@ -134,7 +137,6 @@
134137 @RolesAllowed(BasicSecurityContext.ROL_ADMIN)
135138 public Response create(Organization org) {
136139 LOG.info("Creating new organization");
137
- // EntityManager em = emProvider.get();
138140
139141 try {
140142 this.setParentOrg(org, org.getParentOrgId(), em);
....@@ -162,36 +164,17 @@
162164 return Response.ok(org).build();
163165 }
164166
165
- private void setParentOrg(Organization org, Integer parentOrgId, EntityManager em) throws SeCurisException {
166
- Organization parentOrg = null;
167
- if (parentOrgId != null) {
168
- parentOrg = em.find(Organization.class, parentOrgId);
169
- if (parentOrg == null) {
170
- LOG.error("Organization parent with id {} not found in DB", org.getParentOrgId());
171
- throw new SecurityException("Organization's parent not found with ID: " + org.getParentOrgId());
172
- }
173
- }
174
-
175
- org.setParentOrganization(parentOrg);
176
- }
177
-
178
- private void setOrgUsers(Organization org, Set<String> usersIds, EntityManager em) throws SeCurisException {
179
- Set<User> users = null;
180
- if (usersIds != null && !usersIds.isEmpty()) {
181
- users = new HashSet<>();
182
- for (String username : usersIds) {
183
- User user = em.find(User.class, username);
184
- if (user == null) {
185
- LOG.error("Organization user with id '{}' not found in DB", username);
186
- throw new SecurityException("Organization's user not found with ID: " + username);
187
- }
188
- users.add(user);
189
- }
190
- }
191
-
192
- org.setUsers(users);
193
- }
194
-
167
+ /**
168
+ * modify
169
+ * <p>
170
+ * Update an organization. Validates no cyclic parent relationship,
171
+ * updates parent and user set. Requires ADMIN.
172
+ *
173
+ * @param org new values (including optional parent/usersIds).
174
+ * @param orgid target id.
175
+ * @param token (unused) header token.
176
+ * @return 200 OK with updated organization, or specific error status.
177
+ */
195178 @PUT
196179 @POST
197180 @Path("/{orgid}")
....@@ -202,7 +185,6 @@
202185 @RolesAllowed(BasicSecurityContext.ROL_ADMIN)
203186 public Response modify(Organization org, @PathParam("orgid") String orgid, @HeaderParam(TokenHelper.TOKEN_HEADER_PÀRAM) String token) {
204187 LOG.info("Modifying organization with id: {}", orgid);
205
- // EntityManager em = emProvider.get();
206188 Organization currentOrg = em.find(Organization.class, Integer.parseInt(orgid));
207189 if (currentOrg == null) {
208190 LOG.error("Organization with id {} not found in DB", orgid);
....@@ -233,15 +215,23 @@
233215 return Response.ok(currentOrg).build();
234216 }
235217
218
+ /**
219
+ * delete
220
+ * <p>
221
+ * Delete an organization if it has no children. Requires ADMIN.
222
+ *
223
+ * @param orgid target id.
224
+ * @param req request (unused).
225
+ * @return 200 OK with success map, or 404/403 on constraints.
226
+ */
236227 @DELETE
237228 @Path("/{orgid}")
238229 @EnsureTransaction
239230 @Produces({ MediaType.APPLICATION_JSON })
240231 @Securable(roles = Rol.ADMIN)
241232 @RolesAllowed(BasicSecurityContext.ROL_ADMIN)
242
- public Response delete(@PathParam("orgid") String orgid, @Context HttpServletRequest request) {
233
+ public Response delete(@PathParam("orgid") String orgid, @Context HttpServletRequest req) {
243234 LOG.info("Deleting organization with id: {}", orgid);
244
- // EntityManager em = emProvider.get();
245235 Organization org = em.find(Organization.class, Integer.parseInt(orgid));
246236 if (org == null) {
247237 LOG.error("Organization with id {} can not be deleted, It was not found in DB", orgid);
....@@ -256,4 +246,70 @@
256246 return Response.ok(Utils.createMap("success", true, "id", orgid)).build();
257247 }
258248
249
+ // ---------------------------------------------------------------------
250
+ // Helpers
251
+ // ---------------------------------------------------------------------
252
+
253
+ /**
254
+ * isCyclicalRelationship<p>
255
+ * Detects cycles by walking up the parent chain.
256
+ *
257
+ * @param currentId
258
+ * @param parent
259
+ * @return isCyclicalRelationship
260
+ */
261
+ private boolean isCyclicalRelationship(int currentId, Organization parent) {
262
+ while (parent != null) {
263
+ if (parent.getId() == currentId) return true;
264
+ parent = parent.getParentOrganization();
265
+ }
266
+ return false;
267
+ }
268
+
269
+ /**
270
+ * setParentOrg<p>
271
+ * Resolve and set parent organization (nullable).
272
+ *
273
+ * @param org
274
+ * @param parentOrgId
275
+ * @param entitymanager
276
+ * @throws SeCurisException
277
+ */
278
+ private void setParentOrg(Organization org, Integer parentOrgId, EntityManager em) throws SeCurisException {
279
+ Organization parentOrg = null;
280
+ if (parentOrgId != null) {
281
+ parentOrg = em.find(Organization.class, parentOrgId);
282
+ if (parentOrg == null) {
283
+ LOG.error("Organization parent with id {} not found in DB", org.getParentOrgId());
284
+ throw new SecurityException("Organization's parent not found with ID: " + org.getParentOrgId());
285
+ }
286
+ }
287
+ org.setParentOrganization(parentOrg);
288
+ }
289
+
290
+ /**
291
+ * setOrgUsers<p>
292
+ * Replace organization users from the provided usernames set.
293
+ *
294
+ * @param org
295
+ * @param usersIds
296
+ * @param entityManager
297
+ * @throws SeCurisException
298
+ */
299
+ private void setOrgUsers(Organization org, Set<String> usersIds, EntityManager em) throws SeCurisException {
300
+ Set<User> users = null;
301
+ if (usersIds != null && !usersIds.isEmpty()) {
302
+ users = new HashSet<>();
303
+ for (String username : usersIds) {
304
+ User user = em.find(User.class, username);
305
+ if (user == null) {
306
+ LOG.error("Organization user with id '{}' not found in DB", username);
307
+ throw new SecurityException("Organization's user not found with ID: " + username);
308
+ }
309
+ users.add(user);
310
+ }
311
+ }
312
+ org.setUsers(users);
313
+ }
259314 }
315
+