From 36edce38f6b17f73322fa38404d6e01818a44fd2 Mon Sep 17 00:00:00 2001
From: rsanchez <rsanchez@curisit.net>
Date: Thu, 11 Dec 2014 19:08:16 +0000
Subject: [PATCH] #2140 fix - Added renew period to pack, change on DB schema, fixed pack selection in listing, upgrade angular to 1.3.6 and other minor issues

---
 securis/src/main/java/net/curisit/securis/services/ApiResource.java |  179 +++++++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 125 insertions(+), 54 deletions(-)

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 23913e0..2df1325 100644
--- a/securis/src/main/java/net/curisit/securis/services/ApiResource.java
+++ b/securis/src/main/java/net/curisit/securis/services/ApiResource.java
@@ -1,11 +1,8 @@
 package net.curisit.securis.services;
 
-import java.io.File;
 import java.io.IOException;
 import java.util.Date;
 import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
 
 import javax.inject.Inject;
 import javax.inject.Provider;
@@ -19,7 +16,6 @@
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
-import net.curisit.integrity.commons.JsonUtils;
 import net.curisit.securis.LicenseGenerator;
 import net.curisit.securis.LicenseManager;
 import net.curisit.securis.SeCurisException;
@@ -27,14 +23,22 @@
 import net.curisit.securis.beans.RequestBean;
 import net.curisit.securis.beans.SignedLicenseBean;
 import net.curisit.securis.beans.StatusBean;
+import net.curisit.securis.db.BlockedRequest;
 import net.curisit.securis.db.License;
+import net.curisit.securis.db.LicenseHistory;
+import net.curisit.securis.db.LicenseStatus;
+import net.curisit.securis.db.Pack;
+import net.curisit.securis.db.User;
 import net.curisit.securis.security.BasicSecurityContext;
 import net.curisit.securis.security.Securable;
 import net.curisit.securis.services.exception.SeCurisServiceException;
 import net.curisit.securis.services.exception.SeCurisServiceException.ErrorCodes;
+import net.curisit.securis.services.helpers.LicenseHelper;
+import net.curisit.securis.utils.JsonUtils;
+import net.curisit.securis.utils.LicUtils;
+import net.curisit.securis.utils.SignatureHelper;
 import net.curisit.securis.utils.TokenHelper;
 
-import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang.time.DateUtils;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -57,10 +61,15 @@
     TokenHelper tokenHelper;
 
     @Inject
+    private LicenseHelper licenseHelper;
+
+    @Inject
     Provider<EntityManager> emProvider;
 
     @Inject
     LicenseGenerator licenseGenerator;
+
+    private static final String CLIENT_USERNAME = "_client";
 
     public ApiResource() {
     }
@@ -116,15 +125,9 @@
             SeCurisException {
         LOG.info("Request to get license: {}", request);
 
-        Map<String, Object> metadata = getLicenseMetadata(request);
-        License licDB = getLicenseData(request);
+        SignedLicenseBean lic = createLicense(request, emProvider.get(), false);
 
-        Date expirationDate = licDB.getExpirationDate();
-        String licenseTypeCode = licDB.getPack().getLicenseType().getCode();
-        String licenseCode = licDB.getCode();
-        LicenseBean lic = licenseGenerator.generateLicense(request, metadata, expirationDate, licenseTypeCode, licenseCode);
-        SignedLicenseBean signedLic = new SignedLicenseBean(lic);
-        return Response.ok(signedLic).build();
+        return Response.ok(lic).build();
     }
 
     /**
@@ -186,14 +189,41 @@
             throw new SeCurisServiceException(ErrorCodes.LICENSE_NOT_READY_FOR_RENEW, "The license is still valid, not ready for renew");
         }
 
-        Map<String, Object> metadata = getLicenseMetadata(previousLic);
-        License licDB = getLicenseData(previousLic);
+        SignedLicenseBean lic = createLicense(previousLic, emProvider.get(), true);
 
-        Date expirationDate = licDB.getExpirationDate();
-        String licenseTypeCode = licDB.getPack().getLicenseType().getCode();
-        String licenseCode = licDB.getCode();
-        LicenseBean lic = licenseGenerator.generateLicense(previousLic, metadata, expirationDate, licenseTypeCode, licenseCode);
         return Response.ok(lic).build();
+    }
+
+    /**
+     * License validation on server side, in this case we validate that the
+     * current licenses has not been cancelled.
+     * 
+     * @param currentLic
+     * @param bsc
+     * @return
+     * @throws IOException
+     * @throws SeCurisServiceException
+     * @throws SeCurisException
+     */
+    @POST
+    @Path("/validate")
+    @Consumes(MediaType.APPLICATION_JSON)
+    // TODO: Enable this: @Securable
+    @Produces({
+        MediaType.APPLICATION_JSON
+    })
+    @Transactional
+    public Response validate(LicenseBean currentLic, @Context BasicSecurityContext bsc) throws IOException, SeCurisServiceException, SeCurisException {
+        LOG.info("Validate license: {}", currentLic);
+        EntityManager em = emProvider.get();
+        try {
+            SignatureHelper.getInstance().validateSignature(currentLic);
+        } catch (SeCurisException ex) {
+            throw new SeCurisServiceException(ErrorCodes.LICENSE_DATA_IS_NOT_VALID, "The license signature is not valid");
+        }
+        licenseHelper.assertLicenseStatusIsActive(currentLic, em);
+
+        return Response.ok(currentLic).build();
     }
 
     /**
@@ -236,49 +266,90 @@
         return createFromRequest(lic, bsc);
     }
 
-    private License getLicenseData(RequestBean req) throws SeCurisException {
-        // TODO: The dummy expiration date is temporal, this info should be read
-        // from DB
-        License lic = new License();
-        // TODO: IMPLEMENT LICENSE GENERATION
-
-        // lic.setExpirationDate(new Date(new Date().getTime() + (1000L * 3600 *
-        // 24 * 30)));
-        // lic.setCode(req.getPackCode() + "-LIC-INTERNAL");
-        // LicenseType lt = new LicenseType();
-        // lt.setCode("TYPE-" + req.getAppCode());
-        // Pack pack = new Pack();
-        // pack.setLicenseType(lt);
-        // lic.setPack(pack);
-        return lic;
-    }
-
     /**
-     * Extract the corresponding metadata for the Request license given
+     * Creates a new signed license from request data or from previous license
+     * if It's a renew
      * 
      * @param req
+     * @param em
+     * @param renew
      * @return
-     * @throws SeCurisException
+     * @throws SeCurisServiceException
      */
-    @SuppressWarnings("unchecked")
-    private Map<String, Object> getLicenseMetadata(RequestBean req) throws SeCurisException {
-        // TODO: The dummy metadata file is temporal, this info should be read
-        // from DB
-        File dummyMetadata = new File(System.getProperty("user.home") + File.separator + ".SeCuris" + File.separator + "dummy_metadata.json");
-        Map<String, Object> metadata = null;
-        try {
-            String metadataJson = IOUtils.toString(dummyMetadata.toURI());
-            metadata = (Map<String, Object>) JsonUtils.json2map(metadataJson).get(req.getLicenseTypeCode());
-            if (metadata == null) {
-                throw new SeCurisException("App code in request is unknown: " + req.getLicenseTypeCode());
+    private SignedLicenseBean createLicense(RequestBean req, EntityManager em, boolean renew) throws SeCurisServiceException {
+        LicenseBean previousLicenseBean = null;
+        License lic = null;
+        if (renew) {
+            previousLicenseBean = (LicenseBean) req;
+            lic = License.findLicenseByCode(previousLicenseBean.getLicenseCode(), em);
+            if (lic.getStatus() != LicenseStatus.ACTIVE && lic.getStatus() != LicenseStatus.PRE_ACTIVE) {
+                throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The current license has been cancelled");
             }
-            metadata = new TreeMap<>(metadata);
-        } catch (IOException e) {
-            LOG.error("Error reading dummy metadata file", e);
-            throw new SeCurisException("Error reading dummy metadata file");
+        } else {
+            lic = new License();
         }
 
-        return metadata;
+        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");
+            }
+        }
+        Pack pack = em.createNamedQuery("pack-by-code", Pack.class).setParameter("code", req.getPackCode()).getSingleResult();
+
+        if (!renew && pack.getNumAvailables() <= 0) {
+            throw new SeCurisServiceException(ErrorCodes.NO_AVAILABLE_LICENSES, "The current pack has no licenses availables");
+        }
+        SignedLicenseBean signedLicense;
+        try {
+            String licCode;
+            if (renew) {
+                licCode = previousLicenseBean.getLicenseCode();
+            } else {
+                licCode = LicUtils.getLicenseCode(pack.getCode(), licenseHelper.getNextCodeSuffix(pack.getId(), em));
+            }
+            Date expirationDate = licenseHelper.getExpirationDateFromPack(pack, !renew);
+
+            LicenseBean lb = licenseGenerator.generateLicense(req, licenseHelper.extractPackMetadata(pack.getMetadata()), expirationDate, licCode,
+                    pack.getAppName());
+            signedLicense = new SignedLicenseBean(lb);
+        } catch (SeCurisException e) {
+            throw new SeCurisServiceException(ErrorCodes.INVALID_LICENSE_REQUEST_DATA, "Error generating license: " + e.toString());
+        }
+        try {
+            lic.setRequestData(JsonUtils.toJSON(signedLicense, RequestBean.class));
+            if (BlockedRequest.isRequestBlocked(lic.getRequestData(), em)) {
+                throw new SeCurisServiceException(ErrorCodes.BLOCKED_REQUEST_DATA, "Given request data is blocked and cannot be activated");
+            }
+            lic.setLicenseData(JsonUtils.toJSON(signedLicense));
+        } catch (SeCurisException e) {
+            LOG.error("Error generating license JSON", e);
+            throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Error generating license JSON");
+        }
+
+        lic.setModificationTimestamp(new Date());
+        lic.setExpirationDate(signedLicense.getExpirationDate());
+        User user = em.find(User.class, CLIENT_USERNAME);
+        if (!renew) {
+
+            lic.setPack(pack);
+            lic.setCreatedBy(user);
+            lic.setCreationTimestamp(new Date());
+            lic.setStatus(LicenseStatus.PRE_ACTIVE);
+            lic.setCode(signedLicense.getLicenseCode());
+            lic.setCodeSuffix(LicUtils.getLicenseCodeSuffix(signedLicense.getLicenseCode()));
+            em.persist(lic);
+            em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.CREATE));
+            if (lic.getStatus() == LicenseStatus.ACTIVE) {
+                em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.PRE_ACTIVATE, "Pre-activated on creation"));
+            }
+        } else {
+            lic.setStatus(LicenseStatus.ACTIVE);
+            em.merge(lic);
+            em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.RENEW));
+        }
+
+        return signedLicense;
     }
 
 }

--
Gitblit v1.3.2