From 146a0fb8b0e90f9196e569152f649baf60d6cc8f Mon Sep 17 00:00:00 2001
From: Joaquín Reñé <jrene@curisit.net>
Date: Tue, 07 Oct 2025 14:52:57 +0000
Subject: [PATCH] #4410 - Comments on classes
---
securis/src/main/java/net/curisit/securis/services/LicenseResource.java | 549 ++++++++++++++++++++++++++++++++----------------------
1 files changed, 328 insertions(+), 221 deletions(-)
diff --git a/securis/src/main/java/net/curisit/securis/services/LicenseResource.java b/securis/src/main/java/net/curisit/securis/services/LicenseResource.java
index ed337ce..0885630 100644
--- a/securis/src/main/java/net/curisit/securis/services/LicenseResource.java
+++ b/securis/src/main/java/net/curisit/securis/services/LicenseResource.java
@@ -1,3 +1,6 @@
+/*
+ * Copyright @ 2013 CurisTEC, S.A.S. All Rights Reserved.
+ */
package net.curisit.securis.services;
import java.io.File;
@@ -63,34 +66,45 @@
import net.curisit.securis.utils.LicUtils;
/**
- * License resource, this service will provide methods to create, modify and
- * delete licenses
- *
- * @author roberto <roberto.sanchez@curisit.net>
+ * LicenseResource
+ * <p>
+ * REST resource in charge of managing licenses: list, fetch, create, activate,
+ * email delivery, cancel, block/unblock, modify and delete. It relies on
+ * {@link BasicSecurityContext} to scope access (organizations/apps) and
+ * on {@link EnsureTransaction} for mutating endpoints that need a TX.
+ * <p>
+ * Key rules:
+ * <ul>
+ * <li>Non-admin users must belong to the license's organization.</li>
+ * <li>License creation validates code CRC, activation code and email.</li>
+ * <li>Request payload must match Pack constraints (org/type/pack codes).</li>
+ * <li>History is recorded for key actions (CREATE/ACTIVATE/DOWNLOAD/etc.).</li>
+ * </ul>
+ *
+ * @author roberto
+ * Last reviewed by JRA on Oct 5, 2025.
*/
@Path("/license")
public class LicenseResource {
private static final Logger LOG = LogManager.getLogger(LicenseResource.class);
- @Inject
- private EmailManager emailManager;
+ @Inject private EmailManager emailManager;
+ @Inject private UserHelper userHelper;
+ @Inject private LicenseHelper licenseHelper;
+ @Inject private LicenseGenerator licenseGenerator;
- @Inject
- private UserHelper userHelper;
-
- @Inject
- private LicenseHelper licenseHelper;
-
- @Context
- EntityManager em;
-
- @Inject
- private LicenseGenerator licenseGenerator;
+ @Context EntityManager em;
/**
- *
- * @return the server version in format majorVersion.minorVersion
+ * index
+ * <p>
+ * List all licenses for a given pack. If the caller is not admin,
+ * verifies the pack belongs to an accessible organization.
+ *
+ * @param packId Pack identifier to filter licenses (required).
+ * @param bsc Security context to evaluate roles and scoping.
+ * @return 200 OK with a list (possibly empty), or 401 if unauthorized.
*/
@GET
@Path("/")
@@ -98,31 +112,33 @@
@Produces({ MediaType.APPLICATION_JSON })
public Response index(@QueryParam("packId") Integer packId, @Context BasicSecurityContext bsc) {
LOG.info("Getting licenses list ");
-
- // EntityManager em = emProvider.get();
em.clear();
if (!bsc.isUserInRole(BasicSecurityContext.ROL_ADMIN)) {
Pack pack = em.find(Pack.class, packId);
- if (pack == null) {
- return Response.ok().build();
- }
+ if (pack == null) return Response.ok().build();
if (!bsc.getOrganizationsIds().contains(pack.getOrganization().getId())) {
LOG.error("Pack with id {} not accesible by user {}", pack, bsc.getUserPrincipal());
- return Response.status(Status.UNAUTHORIZED).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "Unathorized access to pack licenses").build();
+ return Response.status(Status.UNAUTHORIZED)
+ .header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "Unathorized access to pack licenses")
+ .build();
}
}
TypedQuery<License> q = em.createNamedQuery("list-licenses-by-pack", License.class);
q.setParameter("packId", packId);
List<License> list = q.getResultList();
-
return Response.ok(list).build();
}
/**
- *
- * @return the server version in format majorVersion.minorVersion
- * @throws SeCurisServiceException
+ * get
+ * <p>
+ * Fetch a single license by id, enforcing access scope for non-admin users.
+ *
+ * @param licId License id (required).
+ * @param bsc Security context.
+ * @return 200 OK with the license.
+ * @throws SeCurisServiceException 404 if not found, 401 if out of scope.
*/
@GET
@Path("/{licId}")
@@ -130,17 +146,22 @@
@Produces({ MediaType.APPLICATION_JSON })
public Response get(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
LOG.info("Getting organization data for id: {}: ", licId);
-
- // EntityManager em = emProvider.get();
em.clear();
License lic = getCurrentLicense(licId, bsc, em);
return Response.ok(lic).build();
}
/**
- *
- * @return The license file, only of license is active
- * @throws SeCurisServiceException
+ * download
+ * <p>
+ * Download the license file. Only allowed when the license is ACTIVE
+ * and license data exists. Adds a DOWNLOAD entry in history.
+ *
+ * @param licId License id.
+ * @param bsc Security context.
+ * @return 200 OK with the binary as application/octet-stream and a
+ * Content-Disposition header; otherwise specific error codes.
+ * @throws SeCurisServiceException if state or data is invalid.
*/
@GET
@Path("/{licId}/download")
@@ -149,7 +170,6 @@
@EnsureTransaction
public Response download(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
- // EntityManager em = emProvider.get();
License lic = getCurrentLicense(licId, bsc, em);
if (lic.getLicenseData() == null) {
@@ -166,12 +186,16 @@
}
/**
- * Activate the given license
- *
- * @param licId
- * @param bsc
- * @return
- * @throws SeCurisServiceException
+ * activate
+ * <p>
+ * Set license to ACTIVE provided status transition is valid, pack has
+ * available units and request data passes validation/uniqueness.
+ * Adds an ACTIVATE entry in history.
+ *
+ * @param licId License id.
+ * @param bsc Security context.
+ * @return 200 OK with updated license.
+ * @throws SeCurisServiceException if invalid transition, no availability or invalid request data.
*/
@PUT
@POST
@@ -182,7 +206,6 @@
@Produces({ MediaType.APPLICATION_JSON })
public Response activate(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
- // EntityManager em = emProvider.get();
License lic = getCurrentLicense(licId, bsc, em);
if (!License.Status.isActionValid(License.Action.ACTIVATION, lic.getStatus())) {
@@ -211,12 +234,18 @@
}
/**
- * Send license file by email to the organization
- *
- * @param licId
- * @param bsc
- * @return
- * @throws SeCurisServiceException
+ * send
+ * <p>
+ * Email the license file to the license owner. Builds a temporary file
+ * using the application license filename and cleans it afterwards.
+ * Adds a SEND entry in history.
+ *
+ * @param licId License id.
+ * @param addCC whether to CC the current operator.
+ * @param bsc Security context.
+ * @return 200 OK with the license (no state change).
+ * @throws SeCurisServiceException when no license file exists or user full name is missing.
+ * @throws SeCurisException if JSON/signature process fails.
*/
@SuppressWarnings("deprecation")
@PUT
@@ -229,7 +258,6 @@
public Response send(@PathParam("licId") Integer licId, @DefaultValue("false") @FormParam("add_cc") Boolean addCC, @Context BasicSecurityContext bsc)
throws SeCurisServiceException, SeCurisException {
- // EntityManager em = emProvider.get();
License lic = getCurrentLicense(licId, bsc, em);
Application app = lic.getPack().getLicenseType().getApplication();
File licFile = null;
@@ -259,19 +287,21 @@
}
}
- // lic.setModificationTimestamp(new Date());
- // em.merge(lic);
em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.SEND, "Email sent to: " + lic.getEmail()));
return Response.ok(lic).build();
}
/**
- * Cancel given license
- *
- * @param licId
- * @param bsc
- * @return
- * @throws SeCurisServiceException
+ * cancel
+ * <p>
+ * Cancel a license (requires valid state transition and a non-null reason).
+ * Delegates to {@link LicenseHelper#cancelLicense}.
+ *
+ * @param licId License id.
+ * @param actionData DTO carrying the cancellation reason.
+ * @param bsc Security context.
+ * @return 200 OK with updated license.
+ * @throws SeCurisServiceException when state is invalid or reason is missing.
*/
@PUT
@POST
@@ -282,7 +312,6 @@
@Produces({ MediaType.APPLICATION_JSON })
public Response cancel(@PathParam("licId") Integer licId, CancellationLicenseActionBean actionData, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
- // EntityManager em = emProvider.get();
License lic = getCurrentLicense(licId, bsc, em);
if (!License.Status.isActionValid(License.Action.CANCEL, lic.getStatus())) {
@@ -300,22 +329,24 @@
}
/**
- * Check if there is some pack with the same code
- *
- * @param code
- * Pack code
- * @param em
- * DB session object
- * @return <code>true</code> if code is already used, <code>false</code>
- * otherwise
+ * create
+ * <p>
+ * Create a license. Validates:
+ * <ul>
+ * <li>Unique license code and valid CRC.</li>
+ * <li>Activation code presence and uniqueness.</li>
+ * <li>Valid user email.</li>
+ * <li>Pack existence, ACTIVE status and scope authorization.</li>
+ * <li>Request data consistency and unblock status (if provided).</li>
+ * </ul>
+ * If request data is provided and the Pack has availability, the license is
+ * generated and set to ACTIVE immediately.
+ *
+ * @param lic License payload.
+ * @param bsc Security context.
+ * @return 200 OK with created license.
+ * @throws SeCurisServiceException on validation failures.
*/
- private boolean checkIfCodeExists(String code, EntityManager em) {
- TypedQuery<License> query = em.createNamedQuery("license-by-code", License.class);
- query.setParameter("code", code);
- int lics = query.getResultList().size();
- return lics > 0;
- }
-
@POST
@Path("/")
@Consumes(MediaType.APPLICATION_JSON)
@@ -323,8 +354,6 @@
@Produces({ MediaType.APPLICATION_JSON })
@EnsureTransaction
public Response create(License lic, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
- // EntityManager em = emProvider.get();
-
if (checkIfCodeExists(lic.getCode(), em)) {
throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The license code is already used in an existing license");
}
@@ -370,10 +399,8 @@
}
if (pack.getNumAvailables() > 0) {
-
SignedLicenseBean signedLicense = generateLicense(lic, em);
- // If user provide a request data the license status is passed
- // directly to ACTIVE
+ // Move directly to ACTIVE when request data is provided
lic.setStatus(LicenseStatus.ACTIVE);
try {
lic.setRequestData(JsonUtils.toJSON(signedLicense, RequestBean.class));
@@ -404,6 +431,203 @@
return Response.ok(lic).build();
}
+ /**
+ * modify
+ * <p>
+ * Update license basic fields (comments, fullName, email) and, when
+ * status is CREATED and request payload changes, re-normalize/validate and
+ * regenerate the signed license data. Adds a MODIFY history entry.
+ *
+ * @param lic New values.
+ * @param licId License id.
+ * @param bsc Security context.
+ * @return 200 OK with updated license.
+ * @throws SeCurisServiceException if validation fails.
+ */
+ @SuppressWarnings("deprecation")
+ @PUT
+ @POST
+ @Path("/{licId}")
+ @Securable(roles = Rol.ADMIN | Rol.ADVANCE)
+ @EnsureTransaction
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces({ MediaType.APPLICATION_JSON })
+ public Response modify(License lic, @PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
+ LOG.info("Modifying license with id: {}", licId);
+
+ License currentLicense = getCurrentLicense(licId, bsc, em);
+ currentLicense.setComments(lic.getComments());
+ currentLicense.setFullName(lic.getFullName());
+ currentLicense.setEmail(lic.getEmail());
+ if (currentLicense.getActivationCode() == null) {
+ currentLicense.setActivationCode(lic.getActivationCode());
+ }
+
+ if (currentLicense.getStatus() == LicenseStatus.CREATED && !ObjectUtils.equals(currentLicense.getReqDataHash(), lic.getReqDataHash())) {
+ if (lic.getRequestData() != null) {
+ SignedLicenseBean signedLicense = generateLicense(lic, em);
+ try {
+ // Normalize the request JSON and update signed license JSON
+ currentLicense.setRequestData(JsonUtils.toJSON(signedLicense, RequestBean.class));
+ LOG.info("JSON generated for request: \n{}", currentLicense.getRequestData());
+ if (BlockedRequest.isRequestBlocked(currentLicense.getRequestData(), em)) {
+ throw new SeCurisServiceException(ErrorCodes.BLOCKED_REQUEST_DATA, "Given request data is blocked and cannot be used again");
+ }
+ currentLicense.setLicenseData(JsonUtils.toJSON(signedLicense));
+ } catch (SeCurisException e) {
+ LOG.error("Error generaing license JSON", e);
+ throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Error generaing license JSON");
+ }
+ } else {
+ currentLicense.setRequestData(null);
+ }
+ }
+
+ currentLicense.setModificationTimestamp(new Date());
+ em.persist(currentLicense);
+ em.persist(licenseHelper.createLicenseHistoryAction(lic, userHelper.getUser(bsc, em), LicenseHistory.Actions.MODIFY));
+
+ return Response.ok(currentLicense).build();
+ }
+
+ /**
+ * delete
+ * <p>
+ * Delete the license when the current status allows it. If the license
+ * was BLOCKED, removes the BlockedRequest entry to unblock the request.
+ *
+ * @param licId License id.
+ * @param bsc Security context.
+ * @return 200 OK with a success payload.
+ * @throws SeCurisServiceException if status does not allow deletion.
+ */
+ @DELETE
+ @Path("/{licId}")
+ @EnsureTransaction
+ @Securable(roles = Rol.ADMIN | Rol.ADVANCE)
+ @Produces({ MediaType.APPLICATION_JSON })
+ public Response delete(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
+ LOG.info("Deleting license with id: {}", licId);
+ License lic = getCurrentLicense(licId, bsc, em);
+
+ if (!License.Status.isActionValid(License.Action.DELETE, lic.getStatus())) {
+ LOG.error("License {} can not be deleted with status {}", lic.getCode(), lic.getStatus());
+ throw new SeCurisServiceException(ErrorCodes.WRONG_STATUS, "License can not be deleted in current status: " + lic.getStatus().name());
+ }
+ if (lic.getStatus() == LicenseStatus.BLOCKED) {
+ BlockedRequest blockedReq = em.find(BlockedRequest.class, lic.getReqDataHash());
+ if (blockedReq != null) {
+ em.remove(blockedReq);
+ }
+ }
+
+ em.remove(lic);
+ return Response.ok(Utils.createMap("success", true, "id", licId)).build();
+ }
+
+ /**
+ * block
+ * <p>
+ * Block the license request data (allowed only from CANCELLED state).
+ * Persists a {@link BlockedRequest} and transitions the license to BLOCKED.
+ *
+ * @param licId License id.
+ * @param bsc Security context.
+ * @return 200 OK with a success payload.
+ * @throws SeCurisServiceException if state is not CANCELLED or already blocked.
+ */
+ @POST
+ @Path("/{licId}/block")
+ @EnsureTransaction
+ @Securable(roles = Rol.ADMIN | Rol.ADVANCE)
+ @Produces({ MediaType.APPLICATION_JSON })
+ public Response block(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
+ LOG.info("Blocking license with id: {}", licId);
+ License lic = getCurrentLicense(licId, bsc, em);
+
+ if (!License.Status.isActionValid(License.Action.BLOCK, lic.getStatus())) {
+ LOG.error("License can only be blocked in CANCELLED status, current: {}", lic.getStatus().name());
+ throw new SeCurisServiceException(ErrorCodes.WRONG_STATUS, "License can only be blocked in CANCELLED status");
+ }
+ if (BlockedRequest.isRequestBlocked(lic.getRequestData(), em)) {
+ throw new SeCurisServiceException(ErrorCodes.BLOCKED_REQUEST_DATA, "Given request data is already blocked");
+ }
+ BlockedRequest blockedReq = new BlockedRequest();
+ blockedReq.setCreationTimestamp(new Date());
+ blockedReq.setBlockedBy(userHelper.getUser(bsc, em));
+ blockedReq.setRequestData(lic.getRequestData());
+
+ em.persist(blockedReq);
+ lic.setStatus(LicenseStatus.BLOCKED);
+ lic.setModificationTimestamp(new Date());
+ em.merge(lic);
+
+ em.persist(licenseHelper.createLicenseHistoryAction(lic, userHelper.getUser(bsc, em), LicenseHistory.Actions.BLOCK));
+ return Response.ok(Utils.createMap("success", true, "id", licId)).build();
+ }
+
+ /**
+ * unblock
+ * <p>
+ * Remove the block for the license request data (if present) and move
+ * license back to CANCELLED. Adds an UNBLOCK history entry.
+ *
+ * @param licId License id.
+ * @param bsc Security context.
+ * @return 200 OK with a success payload.
+ * @throws SeCurisServiceException never if not blocked (returns success anyway).
+ */
+ @POST
+ @Path("/{licId}/unblock")
+ @EnsureTransaction
+ @Securable(roles = Rol.ADMIN | Rol.ADVANCE)
+ @Produces({ MediaType.APPLICATION_JSON })
+ public Response unblock(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
+ LOG.info("Unblocking license with id: {}", licId);
+ License lic = getCurrentLicense(licId, bsc, em);
+
+ if (BlockedRequest.isRequestBlocked(lic.getRequestData(), em)) {
+ BlockedRequest blockedReq = em.find(BlockedRequest.class, lic.getReqDataHash());
+ em.remove(blockedReq);
+
+ lic.setStatus(LicenseStatus.CANCELLED);
+ lic.setModificationTimestamp(new Date());
+ em.merge(lic);
+ em.persist(licenseHelper.createLicenseHistoryAction(lic, userHelper.getUser(bsc, em), LicenseHistory.Actions.UNBLOCK));
+ } else {
+ LOG.info("Request data for license {} is NOT blocked", licId);
+ }
+
+ return Response.ok(Utils.createMap("success", true, "id", licId)).build();
+ }
+
+ // ---------------------------------------------------------------------
+ // Helpers
+ // ---------------------------------------------------------------------
+
+ /**
+ * checkIfCodeExists<p>
+ * Check if there is an existing license with the same code.
+ *
+ * @param code
+ * @param entityManager
+ */
+ private boolean checkIfCodeExists(String code, EntityManager em) {
+ TypedQuery<License> query = em.createNamedQuery("license-by-code", License.class);
+ query.setParameter("code", code);
+ int lics = query.getResultList().size();
+ return lics > 0;
+ }
+
+ /**
+ * generateLicense<p>
+ * Generate a signed license from request data and pack metadata/expiration.
+ *
+ * @param license License with requestData and packId populated.
+ * @param em Entity manager.
+ * @return Signed license bean.
+ * @throws SeCurisServiceException if validation/generation fails.
+ */
private SignedLicenseBean generateLicense(License license, EntityManager em) throws SeCurisServiceException {
SignedLicenseBean sl = null;
Pack pack = em.find(Pack.class, license.getPackId());
@@ -419,12 +643,14 @@
}
/**
- * We check if the given request data is valid for the current Pack and has
- * a valid format
- *
- * @param pack
- * @param requestData
- * @throws SeCurisServiceException
+ * validateRequestData<p>
+ * Validate that requestData matches the Pack and is well-formed.
+ *
+ * @param pack Target pack (org/type constraints).
+ * @param requestData Raw JSON string with the license request.
+ * @param activationCode Activation code from the license payload.
+ * @return Parsed {@link RequestBean}.
+ * @throws SeCurisServiceException on format mismatch or wrong codes.
*/
private RequestBean validateRequestData(Pack pack, String requestData, String activationCode) throws SeCurisServiceException {
if (requestData == null) {
@@ -456,143 +682,16 @@
return rb;
}
- @SuppressWarnings("deprecation")
- @PUT
- @POST
- @Path("/{licId}")
- @Securable(roles = Rol.ADMIN | Rol.ADVANCE)
- @EnsureTransaction
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces({ MediaType.APPLICATION_JSON })
- public Response modify(License lic, @PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
- LOG.info("Modifying license with id: {}", licId);
-
- // EntityManager em = emProvider.get();
-
- License currentLicense = getCurrentLicense(licId, bsc, em);
- currentLicense.setComments(lic.getComments());
- currentLicense.setFullName(lic.getFullName());
- currentLicense.setEmail(lic.getEmail());
- if (currentLicense.getActivationCode() == null) {
- currentLicense.setActivationCode(lic.getActivationCode());
- }
-
- if (currentLicense.getStatus() == LicenseStatus.CREATED && !ObjectUtils.equals(currentLicense.getReqDataHash(), lic.getReqDataHash())) {
- if (lic.getRequestData() != null) {
- SignedLicenseBean signedLicense = generateLicense(lic, em);
- try {
- // Next 2 lines are necessary to normalize the String that
- // contains
- // the request.
- currentLicense.setRequestData(JsonUtils.toJSON(signedLicense, RequestBean.class));
- LOG.info("JSON generated for request: \n{}", currentLicense.getRequestData());
- if (BlockedRequest.isRequestBlocked(currentLicense.getRequestData(), em)) {
- throw new SeCurisServiceException(ErrorCodes.BLOCKED_REQUEST_DATA, "Given request data is blocked and cannot be used again");
- }
- currentLicense.setLicenseData(JsonUtils.toJSON(signedLicense));
- } catch (SeCurisException e) {
- LOG.error("Error generaing license JSON", e);
- throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Error generaing license JSON");
- }
- } else {
- // This set method could pass a null value
- currentLicense.setRequestData(null);
- }
- }
-
- currentLicense.setModificationTimestamp(new Date());
- em.persist(currentLicense);
- em.persist(licenseHelper.createLicenseHistoryAction(lic, userHelper.getUser(bsc, em), LicenseHistory.Actions.MODIFY));
-
- return Response.ok(currentLicense).build();
- }
-
- @DELETE
- @Path("/{licId}")
- @EnsureTransaction
- @Securable(roles = Rol.ADMIN | Rol.ADVANCE)
- @Produces({ MediaType.APPLICATION_JSON })
- public Response delete(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
- LOG.info("Deleting license with id: {}", licId);
- // EntityManager em = emProvider.get();
- License lic = getCurrentLicense(licId, bsc, em);
-
- if (!License.Status.isActionValid(License.Action.DELETE, lic.getStatus())) {
- LOG.error("License {} can not be deleted with status {}", lic.getCode(), lic.getStatus());
- throw new SeCurisServiceException(ErrorCodes.WRONG_STATUS, "License can not be deleted in current status: " + lic.getStatus().name());
- }
- if (lic.getStatus() == LicenseStatus.BLOCKED) {
- // If license is removed and it's blocked then the blocked request
- // should be removed, that is,
- // the license deletion will unblock the request data
- BlockedRequest blockedReq = em.find(BlockedRequest.class, lic.getReqDataHash());
- if (blockedReq != null) {
- // This if is to avoid some race condition or if the request has
- // been already removed manually
- em.remove(blockedReq);
- }
- }
-
- em.remove(lic);
- return Response.ok(Utils.createMap("success", true, "id", licId)).build();
- }
-
- @POST
- @Path("/{licId}/block")
- @EnsureTransaction
- @Securable(roles = Rol.ADMIN | Rol.ADVANCE)
- @Produces({ MediaType.APPLICATION_JSON })
- public Response block(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
- LOG.info("Blocking license with id: {}", licId);
- // EntityManager em = emProvider.get();
- License lic = getCurrentLicense(licId, bsc, em);
-
- if (!License.Status.isActionValid(License.Action.BLOCK, lic.getStatus())) {
- LOG.error("License can only be blocked in CANCELLED status, current: {}", lic.getStatus().name());
- throw new SeCurisServiceException(ErrorCodes.WRONG_STATUS, "License can only be blocked in CANCELLED status");
- }
- if (BlockedRequest.isRequestBlocked(lic.getRequestData(), em)) {
- throw new SeCurisServiceException(ErrorCodes.BLOCKED_REQUEST_DATA, "Given request data is already blocked");
- }
- BlockedRequest blockedReq = new BlockedRequest();
- blockedReq.setCreationTimestamp(new Date());
- blockedReq.setBlockedBy(userHelper.getUser(bsc, em));
- blockedReq.setRequestData(lic.getRequestData());
-
- em.persist(blockedReq);
- lic.setStatus(LicenseStatus.BLOCKED);
- lic.setModificationTimestamp(new Date());
- em.merge(lic);
-
- em.persist(licenseHelper.createLicenseHistoryAction(lic, userHelper.getUser(bsc, em), LicenseHistory.Actions.BLOCK));
- return Response.ok(Utils.createMap("success", true, "id", licId)).build();
- }
-
- @POST
- @Path("/{licId}/unblock")
- @EnsureTransaction
- @Securable(roles = Rol.ADMIN | Rol.ADVANCE)
- @Produces({ MediaType.APPLICATION_JSON })
- public Response unblock(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
- LOG.info("Unblocking license with id: {}", licId);
- // EntityManager em = emProvider.get();
- License lic = getCurrentLicense(licId, bsc, em);
-
- if (BlockedRequest.isRequestBlocked(lic.getRequestData(), em)) {
- BlockedRequest blockedReq = em.find(BlockedRequest.class, lic.getReqDataHash());
- em.remove(blockedReq);
-
- lic.setStatus(LicenseStatus.CANCELLED);
- lic.setModificationTimestamp(new Date());
- em.merge(lic);
- em.persist(licenseHelper.createLicenseHistoryAction(lic, userHelper.getUser(bsc, em), LicenseHistory.Actions.UNBLOCK));
- } else {
- LOG.info("Request data for license {} is NOT blocked", licId);
- }
-
- return Response.ok(Utils.createMap("success", true, "id", licId)).build();
- }
-
+ /**
+ * getCurrentLicense<p>
+ * Load a license and verify scope for non-admin users.
+ *
+ * @param licId License id.
+ * @param bsc Security context.
+ * @param em Entity manager.
+ * @return License entity.
+ * @throws SeCurisServiceException if id is missing, not found or unauthorized.
+ */
private License getCurrentLicense(Integer licId, BasicSecurityContext bsc, EntityManager em) throws SeCurisServiceException {
if (licId == null || "".equals(Integer.toString(licId))) {
LOG.error("License ID is mandatory");
@@ -611,6 +710,13 @@
return lic;
}
+ // ---------------------------------------------------------------------
+ // DTOs
+ // ---------------------------------------------------------------------
+
+ /**
+ * DTO used to carry a cancellation reason for the cancel endpoint.
+ */
@JsonAutoDetect
@JsonIgnoreProperties(ignoreUnknown = true)
static class CancellationLicenseActionBean {
@@ -618,3 +724,4 @@
private String reason;
}
}
+
--
Gitblit v1.3.2