From 85e2a65874fcd41771b30ebfff93f86edd4f32b3 Mon Sep 17 00:00:00 2001
From: rsanchez <rsanchez@curisit.net>
Date: Mon, 01 Dec 2014 14:59:34 +0000
Subject: [PATCH] #396 fix - Added automated license code generation and other minor fixes
---
securis/src/main/java/net/curisit/securis/db/License.java | 14 ++++
securis/src/main/webapp/licenses.html | 18 +++---
securis/src/main/webapp/login.html | 2
securis/src/main/java/net/curisit/securis/services/LicenseResource.java | 41 +++++++++----
securis/src/main/webapp/js/licenses.js | 37 ++++++++----
securis/src/main/java/net/curisit/securis/db/Pack.java | 1
securis/src/main/java/net/curisit/securis/services/exception/SeCurisServiceException.java | 2
securis/src/main/resources/db/schema.sql | 1
securis/src/main/java/net/curisit/securis/services/PackResource.java | 56 ++++++++++++++++++
9 files changed, 136 insertions(+), 36 deletions(-)
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 de6973b..b8ce30f 100644
--- a/securis/src/main/java/net/curisit/securis/db/License.java
+++ b/securis/src/main/java/net/curisit/securis/db/License.java
@@ -55,6 +55,8 @@
@Table(name = "license")
@JsonIgnoreProperties(ignoreUnknown = true)
@NamedQueries({
+ @NamedQuery(name = "license-by-code", query = "SELECT l FROM License l where l.code = :code"),
+ @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')")
@@ -70,6 +72,10 @@
private int id;
private String code;
+
+ @Column(name = "code_suffix")
+ @JsonProperty("code_suffix")
+ private Integer codeSuffix;
@JsonIgnore
@ManyToOne
@@ -372,4 +378,12 @@
}
}
+ public Integer getCodeSuffix() {
+ return codeSuffix;
+ }
+
+ public void setCodeSuffix(Integer codeSuffix) {
+ this.codeSuffix = codeSuffix;
+ }
+
}
diff --git a/securis/src/main/java/net/curisit/securis/db/Pack.java b/securis/src/main/java/net/curisit/securis/db/Pack.java
index 8406bff..5e44cac 100644
--- a/securis/src/main/java/net/curisit/securis/db/Pack.java
+++ b/securis/src/main/java/net/curisit/securis/db/Pack.java
@@ -42,6 +42,7 @@
@JsonIgnoreProperties(ignoreUnknown = true)
@NamedQueries({
@NamedQuery(name = "list-packs", query = "SELECT pa FROM Pack pa"),//
+ @NamedQuery(name = "pack-by-code", query = "SELECT pa FROM Pack pa where pa.code = :code"),//
@NamedQuery(name = "list-packs-by-orgs", query = "SELECT pa FROM Pack pa where pa.organization.id in :list_ids")
})
public class Pack implements Serializable {
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 927122e..d3165b4 100644
--- a/securis/src/main/java/net/curisit/securis/services/LicenseResource.java
+++ b/securis/src/main/java/net/curisit/securis/services/LicenseResource.java
@@ -2,7 +2,6 @@
import java.io.File;
import java.io.IOException;
-import java.nio.file.Files;
import java.text.MessageFormat;
import java.util.Date;
import java.util.HashMap;
@@ -55,6 +54,7 @@
import net.curisit.securis.utils.Config;
import net.curisit.securis.utils.EmailManager;
import net.curisit.securis.utils.JsonUtils;
+import net.curisit.securis.utils.LicUtils;
import net.curisit.securis.utils.TokenHelper;
import org.apache.commons.io.IOUtils;
@@ -320,6 +320,23 @@
return Response.ok(lic).build();
}
+ /**
+ * 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
+ */
+ 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)
@@ -330,6 +347,14 @@
@Transactional
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");
+ }
+ if (!LicUtils.checkValidLicenseCodeCrc(lic.getCode())) {
+ throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The license code is not valid");
+ }
+
Pack pack = null;
if (lic.getPackId() != null) {
pack = em.find(Pack.class, lic.getPackId());
@@ -376,18 +401,16 @@
} else {
lic.setStatus(LicenseStatus.CREATED);
}
+ lic.setCodeSuffix(LicUtils.getLicenseCodeSuffix(lic.getCode()));
lic.setCreatedBy(createdBy);
lic.setCreationTimestamp(new Date());
lic.setModificationTimestamp(lic.getCreationTimestamp());
- LOG.info("LICENSE: {}", lic);
+
em.persist(lic);
- LOG.info("LICENSE on HISTORY create");
em.persist(licenseHelper.createLicenseHistoryAction(lic, createdBy, LicenseHistory.Actions.CREATE));
if (lic.getStatus() == LicenseStatus.ACTIVE) {
- LOG.info("LICENSE ACTIVATION on HISTORY create");
em.persist(licenseHelper.createLicenseHistoryAction(lic, createdBy, LicenseHistory.Actions.CREATE, "Activated on creation"));
}
- LOG.info("LICENSE created oK ??");
return Response.ok(lic).build();
}
@@ -599,14 +622,6 @@
throw new SeCurisServiceException(Status.UNAUTHORIZED.getStatusCode(), "Unathorized access to license data");
}
return lic;
- }
-
- public static void main(String[] args) throws IOException {
- File f = Files.createTempDirectory("securis-server").toFile();
-
- LOG.info("f: {}", f);
- f = new File(f, "config-server.lic");
- LOG.info("f: {}", f);
}
@JsonAutoDetect
diff --git a/securis/src/main/java/net/curisit/securis/services/PackResource.java b/securis/src/main/java/net/curisit/securis/services/PackResource.java
index 8a29756..a584779 100644
--- a/securis/src/main/java/net/curisit/securis/services/PackResource.java
+++ b/securis/src/main/java/net/curisit/securis/services/PackResource.java
@@ -41,6 +41,7 @@
import net.curisit.securis.services.exception.SeCurisServiceException.ErrorCodes;
import net.curisit.securis.services.helpers.LicenseHelper;
import net.curisit.securis.services.helpers.UserHelper;
+import net.curisit.securis.utils.LicUtils;
import net.curisit.securis.utils.TokenHelper;
import org.apache.logging.log4j.LogManager;
@@ -147,9 +148,13 @@
MediaType.APPLICATION_JSON
})
@Transactional
- public Response create(Pack pack, @Context BasicSecurityContext bsc) {
+ public Response create(Pack pack, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
LOG.info("Creating new pack");
EntityManager em = emProvider.get();
+
+ if (checkIfCodeExists(pack.getCode(), em)) {
+ throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The pack code is already used in an existing pack");
+ }
try {
setPackOrganization(pack, pack.getOrgId(), em);
@@ -181,6 +186,55 @@
return Response.ok(pack).build();
}
+ /**
+ * 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
+ */
+ private boolean checkIfCodeExists(String code, EntityManager em) {
+ TypedQuery<Pack> query = em.createNamedQuery("pack-by-code", Pack.class);
+ query.setParameter("code", code);
+ int packs = query.getResultList().size();
+ return packs > 0;
+ }
+
+ private int getNextCodeSuffix(int packId, EntityManager em) {
+ TypedQuery<Integer> query = em.createNamedQuery("last-code-suffix-used-in-pack", Integer.class);
+ query.setParameter("packId", packId);
+ Integer lastCodeSuffix = query.getSingleResult();
+ return lastCodeSuffix == null ? 1 : lastCodeSuffix + 1;
+ }
+
+ /**
+ *
+ * @return The next available code suffix in pack for license code
+ * @throws SeCurisServiceException
+ */
+ @GET
+ @Path("/{packId}/next_license_code")
+ @Securable
+ @Produces({
+ MediaType.TEXT_PLAIN
+ })
+ public Response getCodeSuffix(@PathParam("packId") Integer packId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
+ EntityManager em = emProvider.get();
+
+ if (packId == null) {
+ throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The pack code is mandatory");
+ }
+ Integer codeSuffix = getNextCodeSuffix(packId, em);
+ Pack pack = em.find(Pack.class, packId);
+ ;
+
+ String licCode = LicUtils.getLicenseCode(pack.getCode(), codeSuffix);
+ return Response.ok(licCode).build();
+ }
+
private void setPackLicenseType(Pack pack, Integer licTypeId, EntityManager em) throws SeCurisException {
LicenseType lt = null;
if (licTypeId != null) {
diff --git a/securis/src/main/java/net/curisit/securis/services/exception/SeCurisServiceException.java b/securis/src/main/java/net/curisit/securis/services/exception/SeCurisServiceException.java
index 9b71247..722ff47 100644
--- a/securis/src/main/java/net/curisit/securis/services/exception/SeCurisServiceException.java
+++ b/securis/src/main/java/net/curisit/securis/services/exception/SeCurisServiceException.java
@@ -40,5 +40,7 @@
public static int INVALID_REQUEST_DATA_FORMAT = 1202;
public static int BLOCKED_REQUEST_DATA = 1203;
public static int DUPLICATED_REQUEST_DATA = 1204;
+
+ public static int INVALID_DATA = 1301;
}
}
diff --git a/securis/src/main/resources/db/schema.sql b/securis/src/main/resources/db/schema.sql
index 23d01ca..8a56b9d 100644
--- a/securis/src/main/resources/db/schema.sql
+++ b/securis/src/main/resources/db/schema.sql
@@ -104,6 +104,7 @@
CREATE TABLE IF NOT EXISTS license (
id INT NOT NULL auto_increment,
code VARCHAR(100) NOT NULL ,
+ code_suffix INT NULL ,
request_data VARCHAR(1024) NULL ,
request_data_hash VARCHAR(64) NULL ,
license_data VARCHAR(1024) NULL ,
diff --git a/securis/src/main/webapp/js/licenses.js b/securis/src/main/webapp/js/licenses.js
index 5df0f34..5e24c67 100644
--- a/securis/src/main/webapp/js/licenses.js
+++ b/securis/src/main/webapp/js/licenses.js
@@ -12,7 +12,7 @@
}
var app = angular.module('securis');
- app.service('Packs', ['$L','$resource', 'toaster', function($L, $resource, toaster) {
+ app.service('Packs', ['$L','$resource', '$http', 'toaster', function($L, $resource, $http, toaster) {
var PACK_STATUS = {
CREATED: 'CR',
ACTIVE: 'AC',
@@ -117,6 +117,14 @@
var _error = _createErrorCallback(pack, $L.get('Put on hold'), _onerror);
packResource.putonhold({id: pack.id}, _success, _error);
}
+ this.nextliccode = function(packId, _onsuccess, _onerror) {
+ console.log('Get next code: ' + packId);
+ var _error = function(data, status, headers, config) {
+ console.log(headers);
+ toaster.pop('error', $L.get('Getting next code suffix'), $L.get("Error getting license code, pack ID: '{0}'. Reason: {1}", packId, $L.get(headers('X-SECURIS-ERROR-MSG'))));
+ }
+ $http.get("/securis/pack/"+packId+"/next_license_code").success(_onsuccess).error(_error);
+ }
this.cancel = function(pack, extra_data, _onsuccess, _onerror) {
console.log('Cancellation on pack: ' + pack.id);
var _success = _createSuccessCallback($L.get('Cancellation'), $L.get("Pack '{0}' {1} successfully", pack.code, $L.get("cancelled")), _onsuccess);
@@ -133,7 +141,7 @@
}]);
- app.service('Licenses', ['$L', '$resource', 'toaster', function($L, $resource, toaster) {
+ app.service('Licenses', ['$L', '$resource', 'toaster', 'Packs', function($L, $resource, toaster, Packs) {
var LIC_STATUS = {
CREATED: 'CR',
ACTIVE: 'AC',
@@ -225,7 +233,14 @@
}
var _error = function(error) {
console.log(error);
- toaster.pop('error', 'Licenses', $L.get("Error {0} license '{1}'. Reason: {2}", isNew ? $L.get("creating") : $L.get("updating"), license.code, $L.get(error.headers('X-SECURIS-ERROR-MSG'))));
+ toaster.pop('error', 'Licenses', $L.get("Error {0} license '{1}'. Reason: {2}", isNew ? $L.get("creating") : $L.get("updating"), license.code, $L.get(error.headers('X-SECURIS-ERROR-MSG'))), 5000);
+ if (error.headers('X-SECURIS-ERROR-CODE') === '1301') {
+ Packs.nextliccode(license.pack_id, function(data) {
+ console.log('New code: ' + data);
+ license.code = data;
+ toaster.pop('info', 'Licenses', $L.get("New license code, {0}, has been generated, please try again", license.code), 5000);
+ });
+ }
}
licenseResource.save(license, _success, _error);
}
@@ -622,9 +637,10 @@
'$resource',
'toaster',
'Licenses',
+ 'Packs',
'$store',
'$L',
- function($scope, $http, $resource, toaster, Licenses, $store, $L) {
+ function($scope, $http, $resource, toaster, Licenses, Packs, $store, $L) {
$scope.Licenses = Licenses;
$scope.$on('pack_changed', function(evt, message) {
$scope.licenses = Licenses.getLicensesList($scope.currentPack);
@@ -708,8 +724,12 @@
$scope.license = {
pack_id: $scope.currentPack.id
}
+ Packs.nextliccode($scope.currentPack.id, function(data) {
+ console.log('New code: ' + data);
+ $scope.license.code = data;
+ });
setTimeout(function() {
- $('#licenseForm * #code').focus();
+ $('#licenseForm * #email').focus();
}, 0);
}
@@ -816,13 +836,6 @@
$scope.cancel = function() {
$scope.showForm = false;
- }
-
- $scope.showStatus = function(lic) {
-
- }
- $scope.showStatusLong = function(license) {
-
}
} ]);
diff --git a/securis/src/main/webapp/licenses.html b/securis/src/main/webapp/licenses.html
index 425a85e..ad76d33 100644
--- a/securis/src/main/webapp/licenses.html
+++ b/securis/src/main/webapp/licenses.html
@@ -25,10 +25,10 @@
<div class="input-group-addon" style="width: 28px;">
<span class=" glyphicon glyphicon-search"></span>
</div> <input type="text" class="form-control" placeholder="Search"
- ng-model="$searchPacksText">
+ ng-model="searchPackText">
<div class="input-group-addon" style="width: 20px;">
<span class=" glyphicon glyphicon-remove"
- ng-click="$searchPacksText = '';"></span>
+ ng-click="searchPackText = '';"></span>
</div>
</span>
</div>
@@ -64,7 +64,7 @@
</div>
<div class="form-group">
- <label class="col-md-3 control-label" for="code" i18n>Validity (from - to)</label>
+ <label class="col-md-3 control-label" for="init_valid_date" i18n>Validity (from - to)</label>
<div class="col-md-4">
<input type="date" id="init_valid_date" name="init_valid_date" placeholder=""
class="form-control" ng-model="pack.init_valid_date"
@@ -282,7 +282,7 @@
</tr>
</thead>
<tbody>
- <tr ng-repeat="p in packs | filter:searchText"
+ <tr ng-repeat="p in packs | filter:searchPackText"
ng-dblclick="editPack(p)"
ng-class="{success: currentPack.id === p.id}"
ng-click="selectPack(p)">
@@ -351,10 +351,10 @@
<div class="input-group-addon" style="width: 28px;">
<span class=" glyphicon glyphicon-search"></span>
</div> <input type="text" class="form-control" placeholder="Search"
- ng-model="$searchLicensesText">
+ ng-model="searchLicenseText">
<div class="input-group-addon" style="width: 20px;">
<span class=" glyphicon glyphicon-remove"
- ng-click="$searchLicensesText = '';"></span>
+ ng-click="searchLicenseText = '';"></span>
</div>
</span>
</div>
@@ -389,7 +389,7 @@
<label class="col-md-3 control-label" for="code" i18n>Code</label>
<div class="col-md-8">
<input type="string" id="code" name="code" placeholder=""
- class="form-control" ng-model="license.code"
+ class="form-control" ng-model="license.code" readonly
ng-required="mandatory.code" ng-maxlength="{{maxlength.code}}" />
<div class="alert inline-alert alert-warning"
ng-show="licenseForm.code.$invalid">
@@ -404,7 +404,7 @@
<div class="form-group" ng-if="!isNew">
<label class="col-md-3 control-label" i18n>Status</label>
<div class="col-md-8">
- <p class="form-control-static" ng-bind="showStatusLong(license)"></p>
+ <p class="form-control-static" ng-bind="license.status_name"></p>
</div>
</div>
@@ -625,7 +625,7 @@
<td ng-bind="ellipsis(lic.full_name, 20)"
title="{{lic.full_name}}"></td>
<td ng-bind="ellipsis(lic.email, 30)" title="{{lic.email}}"></td>
- <td ng-bind="showStatus(lic.status)"></td>
+ <td ng-bind="Licenses.getStatusName(lic.status)"></td>
<td>
<div class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown"> <span
diff --git a/securis/src/main/webapp/login.html b/securis/src/main/webapp/login.html
index 4b9ef09..04f6fea 100644
--- a/securis/src/main/webapp/login.html
+++ b/securis/src/main/webapp/login.html
@@ -22,7 +22,7 @@
<div class="jumbotron">
<div class="container">
<h2 i18n >SeCuris</h2>
- <p i18n >Server License for CurisTEC products.</p>
+ <p i18n >Licenses Server for CurisTEC products.</p>
</div>
</div>
--
Gitblit v1.3.2