From 8200793f22c0ec9fc1ab9026406fe4d3a8cbaab7 Mon Sep 17 00:00:00 2001
From: rsanchez <rsanchez@curisit.net>
Date: Wed, 17 Dec 2014 12:30:46 +0000
Subject: [PATCH] #2205 feature - Added support for name or reference and email in license requests

---
 securis/src/main/java/net/curisit/securis/db/License.java               |   50 +++++++++++++---
 securis/pom.xml                                                         |    2 
 securis/src/main/java/net/curisit/securis/services/ApiResource.java     |   79 ++++++++++++++++++-------
 securis/src/main/java/net/curisit/securis/services/LicenseResource.java |    4 
 securis/src/main/webapp/js/licenses.js                                  |    2 
 5 files changed, 102 insertions(+), 35 deletions(-)

diff --git a/securis/pom.xml b/securis/pom.xml
index 7f9da26..49429f4 100644
--- a/securis/pom.xml
+++ b/securis/pom.xml
@@ -45,7 +45,7 @@
   	<dependency>
   		<groupId>net.curisit</groupId>
   		<artifactId>securis-client</artifactId>
-  		<version>1.0.3-SNAPSHOT</version>
+  		<version>1.0.4-SNAPSHOT</version>
   	</dependency>
   	<dependency>
   		<groupId>org.hibernate</groupId>
diff --git a/securis/src/main/java/net/curisit/securis/db/License.java b/securis/src/main/java/net/curisit/securis/db/License.java
index 5d8784c..6c0ec5b 100644
--- a/securis/src/main/java/net/curisit/securis/db/License.java
+++ b/securis/src/main/java/net/curisit/securis/db/License.java
@@ -18,7 +18,6 @@
 import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
 import javax.persistence.NoResultException;
-import javax.persistence.NonUniqueResultException;
 import javax.persistence.OneToMany;
 import javax.persistence.Table;
 import javax.persistence.TypedQuery;
@@ -29,7 +28,6 @@
 import net.curisit.securis.db.listeners.CreationTimestampListener;
 import net.curisit.securis.db.listeners.ModificationTimestampListener;
 import net.curisit.securis.services.exception.SeCurisServiceException;
-import net.curisit.securis.services.exception.SeCurisServiceException.ErrorCodes;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -59,7 +57,9 @@
         @NamedQuery(name = "last-code-suffix-used-in-pack", query = "SELECT max(l.codeSuffix) FROM License l where l.pack.id = :packId"),
         @NamedQuery(name = "list-licenses-by-pack", query = "SELECT l FROM License l where l.pack.id = :packId"),
         @NamedQuery(name = "list-licenses-by-req-data", query = "SELECT l FROM License l where l.reqDataHash = :hash"),
-        @NamedQuery(name = "list-active-licenses-by-req-data", query = "SELECT l FROM License l where l.reqDataHash = :hash and l.status in ('AC', 'PA')")
+        @NamedQuery(name = "list-active-licenses-by-req-data", query = "SELECT l FROM License l where l.reqDataHash = :hash and l.status in ('AC', 'PA')"),
+        @NamedQuery(name = "list-valid-licenses-by-req-data", query = "SELECT l FROM License l where l.reqDataHash = :hash and l.status in ('RE', 'AC', 'PA')")
+
 })
 public class License implements CreationTimestampEntity, ModificationTimestampEntity, Serializable {
 
@@ -369,15 +369,47 @@
         }
     }
 
-    public static License findLicenseByRequestData(String requestData, EntityManager em) throws SeCurisServiceException {
+    /**
+     * Return licenses with status: REquested, ACtive, Pre-Active for a given
+     * request data
+     * 
+     * @param requestData
+     * @param em
+     * @return
+     * @throws SeCurisServiceException
+     */
+    public static License findValidLicenseByRequestData(String requestData, EntityManager em) throws SeCurisServiceException {
+        TypedQuery<License> query = em.createNamedQuery("list-valid-licenses-by-req-data", License.class);
+        query.setParameter("hash", BlockedRequest.generateHash(requestData));
+        try {
+            List<License> list = query.getResultList();
+            if (list.size() == 0) {
+                return null;
+            }
+            if (list.size() > 1) {
+                LOG.error("There are more than 1 active or requested license for request data: {}\nHash: {}", requestData,
+                        BlockedRequest.generateHash(requestData));
+            }
+            return list.get(0);
+        } catch (NoResultException e) {
+            // There is no license for request data
+            return null;
+        }
+    }
+
+    public static License findActiveLicenseByRequestData(String requestData, EntityManager em) throws SeCurisServiceException {
         TypedQuery<License> query = em.createNamedQuery("list-active-licenses-by-req-data", License.class);
         query.setParameter("hash", BlockedRequest.generateHash(requestData));
         try {
-            return query.getSingleResult();
-        } catch (NonUniqueResultException e) {
-            LOG.error("There are more than 1 active license for request data: {}\nHash: {}", requestData, BlockedRequest.generateHash(requestData));
-            throw new SeCurisServiceException(ErrorCodes.DUPLICATED_REQUEST_DATA, "There are more than 1 active license for request data hash: "
-                    + BlockedRequest.generateHash(requestData));
+            List<License> list = query.getResultList();
+            if (list.size() == 0) {
+                return null;
+            }
+            if (list.size() > 1) {
+                LOG.error("There are more than 1 active license for request data: {}\nHash: {}", requestData,
+                        BlockedRequest.generateHash(requestData));
+            }
+            return list.get(0);
         } catch (NoResultException e) {
             // There is no license for request data
             return null;
diff --git a/securis/src/main/java/net/curisit/securis/services/ApiResource.java b/securis/src/main/java/net/curisit/securis/services/ApiResource.java
index d432621..032ec6f 100644
--- a/securis/src/main/java/net/curisit/securis/services/ApiResource.java
+++ b/securis/src/main/java/net/curisit/securis/services/ApiResource.java
@@ -9,6 +9,7 @@
 import javax.persistence.EntityManager;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
@@ -120,11 +121,10 @@
         MediaType.APPLICATION_JSON
     })
     @Transactional
-    public Response createFromRequest(RequestBean request, @Context BasicSecurityContext bsc) throws IOException, SeCurisServiceException,
-            SeCurisException {
+    public Response createFromRequest(RequestBean request, @HeaderParam(LicenseManager.HEADER_LICENSE_NAME_OR_REFERENCE) String nameOrReference,
+            @HeaderParam(LicenseManager.HEADER_LICENSE_EMAIL) String userEmail) throws IOException, SeCurisServiceException, SeCurisException {
         LOG.info("Request to get license: {}", request);
-
-        SignedLicenseBean lic = createLicense(request, emProvider.get(), false);
+        SignedLicenseBean lic = createLicense(request, emProvider.get(), false, nameOrReference, userEmail);
 
         return Response.ok(lic).build();
     }
@@ -148,8 +148,9 @@
     })
     @Transactional
     @SuppressWarnings("unchecked")
-    public Response createFromRequestFile(MultipartFormDataInput mpfdi, @Context BasicSecurityContext bsc) throws IOException,
-            SeCurisServiceException, SeCurisException {
+    public Response createFromRequestFile(MultipartFormDataInput mpfdi,
+            @HeaderParam(LicenseManager.HEADER_LICENSE_NAME_OR_REFERENCE) String nameOrReference,
+            @HeaderParam(LicenseManager.HEADER_LICENSE_EMAIL) String userEmail) throws IOException, SeCurisServiceException, SeCurisException {
         RequestBean req = new RequestBean();
         req.setPackCode(mpfdi.getFormDataPart("packCode", String.class, null));
         req.setLicenseTypeCode(mpfdi.getFormDataPart("licenseTypeCode", String.class, null));
@@ -159,7 +160,7 @@
         req.setMacAddresses(mpfdi.getFormDataPart("macAddresses", List.class, null));
         req.setOsName(mpfdi.getFormDataPart("osName", String.class, null));
 
-        return createFromRequest(req, bsc);
+        return createFromRequest(req, nameOrReference, userEmail);
     }
 
     /**
@@ -194,7 +195,7 @@
             throw new SeCurisServiceException(ErrorCodes.LICENSE_NOT_READY_FOR_RENEW, "Only licenses with status 'Active' can be renew");
         }
 
-        SignedLicenseBean signedLic = createLicense(previousLic, em, true);
+        SignedLicenseBean signedLic = renewLicense(previousLic, em);
 
         return Response.ok(signedLic).build();
     }
@@ -273,7 +274,11 @@
             throw new SeCurisServiceException(ErrorCodes.LICENSE_NOT_READY_FOR_RENEW, "The license is still valid, not ready for renew");
         }
 
-        return createFromRequest(lic, bsc);
+        return renewFromPreviousLicense(lic, bsc);
+    }
+
+    private SignedLicenseBean renewLicense(RequestBean req, EntityManager em) throws SeCurisServiceException {
+        return createLicense(req, em, true, null, null);
     }
 
     /**
@@ -286,7 +291,8 @@
      * @return
      * @throws SeCurisServiceException
      */
-    private SignedLicenseBean createLicense(RequestBean req, EntityManager em, boolean renew) throws SeCurisServiceException {
+    private SignedLicenseBean createLicense(RequestBean req, EntityManager em, boolean renew, String nameOrReference, String email)
+            throws SeCurisServiceException {
         LicenseBean previousLicenseBean = null;
         License lic = null;
         if (renew) {
@@ -295,14 +301,25 @@
             if (lic.getStatus() != LicenseStatus.ACTIVE && lic.getStatus() != LicenseStatus.PRE_ACTIVE) {
                 throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The current license has been cancelled");
             }
-        } else {
-            lic = new License();
         }
 
         if (!renew) {
-            License existingLicense = License.findLicenseByRequestData(lic.getRequestData(), em);
-            if (existingLicense != null) {
-                throw new SeCurisServiceException(ErrorCodes.DUPLICATED_REQUEST_DATA, "There is already an active license for current request data");
+            try {
+                lic = License.findValidLicenseByRequestData(JsonUtils.toJSON(req), em);
+            } catch (SeCurisException e1) {
+                throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Request sent is not valid");
+            }
+            if (lic != null) {
+                try {
+                    if (lic.getStatus() == LicenseStatus.ACTIVE || lic.getStatus() == LicenseStatus.PRE_ACTIVE) {
+                        return JsonUtils.json2object(lic.getLicenseData(), SignedLicenseBean.class);
+                    }
+                } catch (SeCurisException e) {
+                    throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Error trying to get the license bean from license code: "
+                            + lic.getCode());
+                }
+            } else {
+                lic = new License();
             }
         }
         Pack pack = em.createNamedQuery("pack-by-code", Pack.class).setParameter("code", req.getPackCode()).getSingleResult();
@@ -310,11 +327,15 @@
         if (!renew && pack.getNumAvailables() <= 0) {
             throw new SeCurisServiceException(ErrorCodes.NO_AVAILABLE_LICENSES, "The current pack has no licenses availables");
         }
+        if (!renew && lic.getStatus() == LicenseStatus.REQUESTED && !pack.isLicensePreactivation()) {
+            throw new SeCurisServiceException(ErrorCodes.NO_AVAILABLE_LICENSES, "Current pack doesn't allow license preactivation");
+        }
+
         SignedLicenseBean signedLicense;
         try {
             String licCode;
-            if (renew) {
-                licCode = previousLicenseBean.getLicenseCode();
+            if (renew || lic.getStatus() == LicenseStatus.REQUESTED) {
+                licCode = lic.getCode();
             } else {
                 licCode = LicUtils.getLicenseCode(pack.getCode(), licenseHelper.getNextCodeSuffix(pack.getId(), em));
             }
@@ -340,23 +361,35 @@
         lic.setModificationTimestamp(new Date());
         lic.setExpirationDate(signedLicense.getExpirationDate());
         User user = em.find(User.class, CLIENT_USERNAME);
-        if (!renew) {
-
+        if (!renew && lic.getStatus() != LicenseStatus.REQUESTED) {
             lic.setPack(pack);
             lic.setCreatedBy(user);
             lic.setCreationTimestamp(new Date());
-            lic.setStatus(LicenseStatus.PRE_ACTIVE);
+            if (pack.isLicensePreactivation()) {
+                lic.setStatus(LicenseStatus.PRE_ACTIVE);
+            } else {
+                lic.setStatus(LicenseStatus.REQUESTED);
+            }
             lic.setCode(signedLicense.getLicenseCode());
             lic.setCodeSuffix(LicUtils.getLicenseCodeSuffix(signedLicense.getLicenseCode()));
+            lic.setEmail(email);
+            lic.setFullName(nameOrReference);
             em.persist(lic);
             em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.CREATE));
-            if (lic.getStatus() == LicenseStatus.ACTIVE) {
+            if (pack.isLicensePreactivation()) {
                 em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.PRE_ACTIVATE, "Pre-activated on creation"));
+            } else {
+                LOG.warn("License ({}) created, but the pack doesn't allow preactivation", lic.getCode());
+                throw new SeCurisServiceException(ErrorCodes.NO_AVAILABLE_LICENSES, "Current pack doesn't allow license preactivation");
             }
         } else {
-            lic.setStatus(LicenseStatus.ACTIVE);
+            lic.setStatus(renew ? LicenseStatus.ACTIVE : LicenseStatus.PRE_ACTIVE);
             em.merge(lic);
-            em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.RENEW));
+            if (renew) {
+                em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.RENEW));
+            } else {
+                em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.PRE_ACTIVATE, "Pre-activated after request"));
+            }
         }
 
         return signedLicense;
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 cf10c6b..46db766 100644
--- a/securis/src/main/java/net/curisit/securis/services/LicenseResource.java
+++ b/securis/src/main/java/net/curisit/securis/services/LicenseResource.java
@@ -213,7 +213,7 @@
 
         validateRequestData(lic.getPack(), lic.getRequestData());
 
-        License existingLicense = License.findLicenseByRequestData(lic.getRequestData(), em);
+        License existingLicense = License.findActiveLicenseByRequestData(lic.getRequestData(), em);
         if (existingLicense != null && existingLicense.getStatus() == LicenseStatus.ACTIVE) {
             throw new SeCurisServiceException(ErrorCodes.NO_AVAILABLE_LICENSES, "The pack has not available licenses");
         }
@@ -379,7 +379,7 @@
         User createdBy = userHelper.getUser(bsc.getUserPrincipal().getName(), em);
 
         if (lic.getRequestData() != null) {
-            License existingLicense = License.findLicenseByRequestData(lic.getRequestData(), em);
+            License existingLicense = License.findActiveLicenseByRequestData(lic.getRequestData(), em);
             if (existingLicense != null) {
                 throw new SeCurisServiceException(ErrorCodes.DUPLICATED_REQUEST_DATA, "There is already an active license for current request data");
             }
diff --git a/securis/src/main/webapp/js/licenses.js b/securis/src/main/webapp/js/licenses.js
index facb915..8c9f17b 100644
--- a/securis/src/main/webapp/js/licenses.js
+++ b/securis/src/main/webapp/js/licenses.js
@@ -32,6 +32,7 @@
 		 * copy them for simplicity, this info won't change easily
 		 */
 		var PACK_ACTIONS_BY_STATUS = {
+				edit: [PACK_STATUS.CREATED, PACK_STATUS.EXPIRED, PACK_STATUS.ONHOLD, PACK_STATUS.ACTIVE],
 				activate: [PACK_STATUS.CREATED, PACK_STATUS.EXPIRED, PACK_STATUS.ONHOLD],
 				putonhold: [PACK_STATUS.ACTIVE],
 				cancel: [PACK_STATUS.EXPIRED, PACK_STATUS.ONHOLD, PACK_STATUS.ACTIVE],
@@ -169,6 +170,7 @@
 		 * we copy them for simplicity, this info won't change easily
 		 */
 		var LIC_ACTIONS_BY_STATUS = {
+				edit: [LIC_STATUS.REQUESTED, LIC_STATUS.EXPIRED, LIC_STATUS.PREACTIVE, LIC_STATUS.ACTIVE, LIC_STATUS.CANCELLED, LIC_STATUS.BLOCKED],
 				add_request: [LIC_STATUS.CREATED],
 				activate: [LIC_STATUS.CREATED, LIC_STATUS.REQUESTED, LIC_STATUS.PREACTIVE],
 				send: [LIC_STATUS.ACTIVE, LIC_STATUS.PREACTIVE],

--
Gitblit v1.3.2