rsanchez
2014-12-01 85e2a65874fcd41771b30ebfff93f86edd4f32b3
#396 fix - Added automated license code generation and other minor fixes
9 files modified
changed files
securis/src/main/java/net/curisit/securis/db/License.java patch | view | blame | history
securis/src/main/java/net/curisit/securis/db/Pack.java patch | view | blame | history
securis/src/main/java/net/curisit/securis/services/LicenseResource.java patch | view | blame | history
securis/src/main/java/net/curisit/securis/services/PackResource.java patch | view | blame | history
securis/src/main/java/net/curisit/securis/services/exception/SeCurisServiceException.java patch | view | blame | history
securis/src/main/resources/db/schema.sql patch | view | blame | history
securis/src/main/webapp/js/licenses.js patch | view | blame | history
securis/src/main/webapp/licenses.html patch | view | blame | history
securis/src/main/webapp/login.html patch | view | blame | history
securis/src/main/java/net/curisit/securis/db/License.java
....@@ -55,6 +55,8 @@
5555 @Table(name = "license")
5656 @JsonIgnoreProperties(ignoreUnknown = true)
5757 @NamedQueries({
58
+ @NamedQuery(name = "license-by-code", query = "SELECT l FROM License l where l.code = :code"),
59
+ @NamedQuery(name = "last-code-suffix-used-in-pack", query = "SELECT max(l.codeSuffix) FROM License l where l.pack.id = :packId"),
5860 @NamedQuery(name = "list-licenses-by-pack", query = "SELECT l FROM License l where l.pack.id = :packId"),
5961 @NamedQuery(name = "list-licenses-by-req-data", query = "SELECT l FROM License l where l.reqDataHash = :hash"),
6062 @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 @@
7072 private int id;
7173
7274 private String code;
75
+
76
+ @Column(name = "code_suffix")
77
+ @JsonProperty("code_suffix")
78
+ private Integer codeSuffix;
7379
7480 @JsonIgnore
7581 @ManyToOne
....@@ -372,4 +378,12 @@
372378 }
373379 }
374380
381
+ public Integer getCodeSuffix() {
382
+ return codeSuffix;
383
+ }
384
+
385
+ public void setCodeSuffix(Integer codeSuffix) {
386
+ this.codeSuffix = codeSuffix;
387
+ }
388
+
375389 }
securis/src/main/java/net/curisit/securis/db/Pack.java
....@@ -42,6 +42,7 @@
4242 @JsonIgnoreProperties(ignoreUnknown = true)
4343 @NamedQueries({
4444 @NamedQuery(name = "list-packs", query = "SELECT pa FROM Pack pa"),//
45
+ @NamedQuery(name = "pack-by-code", query = "SELECT pa FROM Pack pa where pa.code = :code"),//
4546 @NamedQuery(name = "list-packs-by-orgs", query = "SELECT pa FROM Pack pa where pa.organization.id in :list_ids")
4647 })
4748 public class Pack implements Serializable {
securis/src/main/java/net/curisit/securis/services/LicenseResource.java
....@@ -2,7 +2,6 @@
22
33 import java.io.File;
44 import java.io.IOException;
5
-import java.nio.file.Files;
65 import java.text.MessageFormat;
76 import java.util.Date;
87 import java.util.HashMap;
....@@ -55,6 +54,7 @@
5554 import net.curisit.securis.utils.Config;
5655 import net.curisit.securis.utils.EmailManager;
5756 import net.curisit.securis.utils.JsonUtils;
57
+import net.curisit.securis.utils.LicUtils;
5858 import net.curisit.securis.utils.TokenHelper;
5959
6060 import org.apache.commons.io.IOUtils;
....@@ -320,6 +320,23 @@
320320 return Response.ok(lic).build();
321321 }
322322
323
+ /**
324
+ * Check if there is some pack with the same code
325
+ *
326
+ * @param code
327
+ * Pack code
328
+ * @param em
329
+ * DB session object
330
+ * @return <code>true</code> if code is already used, <code>false</code>
331
+ * otherwise
332
+ */
333
+ private boolean checkIfCodeExists(String code, EntityManager em) {
334
+ TypedQuery<License> query = em.createNamedQuery("license-by-code", License.class);
335
+ query.setParameter("code", code);
336
+ int lics = query.getResultList().size();
337
+ return lics > 0;
338
+ }
339
+
323340 @POST
324341 @Path("/")
325342 @Consumes(MediaType.APPLICATION_JSON)
....@@ -330,6 +347,14 @@
330347 @Transactional
331348 public Response create(License lic, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
332349 EntityManager em = emProvider.get();
350
+
351
+ if (checkIfCodeExists(lic.getCode(), em)) {
352
+ throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The license code is already used in an existing license");
353
+ }
354
+ if (!LicUtils.checkValidLicenseCodeCrc(lic.getCode())) {
355
+ throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The license code is not valid");
356
+ }
357
+
333358 Pack pack = null;
334359 if (lic.getPackId() != null) {
335360 pack = em.find(Pack.class, lic.getPackId());
....@@ -376,18 +401,16 @@
376401 } else {
377402 lic.setStatus(LicenseStatus.CREATED);
378403 }
404
+ lic.setCodeSuffix(LicUtils.getLicenseCodeSuffix(lic.getCode()));
379405 lic.setCreatedBy(createdBy);
380406 lic.setCreationTimestamp(new Date());
381407 lic.setModificationTimestamp(lic.getCreationTimestamp());
382
- LOG.info("LICENSE: {}", lic);
408
+
383409 em.persist(lic);
384
- LOG.info("LICENSE on HISTORY create");
385410 em.persist(licenseHelper.createLicenseHistoryAction(lic, createdBy, LicenseHistory.Actions.CREATE));
386411 if (lic.getStatus() == LicenseStatus.ACTIVE) {
387
- LOG.info("LICENSE ACTIVATION on HISTORY create");
388412 em.persist(licenseHelper.createLicenseHistoryAction(lic, createdBy, LicenseHistory.Actions.CREATE, "Activated on creation"));
389413 }
390
- LOG.info("LICENSE created oK ??");
391414
392415 return Response.ok(lic).build();
393416 }
....@@ -599,14 +622,6 @@
599622 throw new SeCurisServiceException(Status.UNAUTHORIZED.getStatusCode(), "Unathorized access to license data");
600623 }
601624 return lic;
602
- }
603
-
604
- public static void main(String[] args) throws IOException {
605
- File f = Files.createTempDirectory("securis-server").toFile();
606
-
607
- LOG.info("f: {}", f);
608
- f = new File(f, "config-server.lic");
609
- LOG.info("f: {}", f);
610625 }
611626
612627 @JsonAutoDetect
securis/src/main/java/net/curisit/securis/services/PackResource.java
....@@ -41,6 +41,7 @@
4141 import net.curisit.securis.services.exception.SeCurisServiceException.ErrorCodes;
4242 import net.curisit.securis.services.helpers.LicenseHelper;
4343 import net.curisit.securis.services.helpers.UserHelper;
44
+import net.curisit.securis.utils.LicUtils;
4445 import net.curisit.securis.utils.TokenHelper;
4546
4647 import org.apache.logging.log4j.LogManager;
....@@ -147,9 +148,13 @@
147148 MediaType.APPLICATION_JSON
148149 })
149150 @Transactional
150
- public Response create(Pack pack, @Context BasicSecurityContext bsc) {
151
+ public Response create(Pack pack, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
151152 LOG.info("Creating new pack");
152153 EntityManager em = emProvider.get();
154
+
155
+ if (checkIfCodeExists(pack.getCode(), em)) {
156
+ throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The pack code is already used in an existing pack");
157
+ }
153158
154159 try {
155160 setPackOrganization(pack, pack.getOrgId(), em);
....@@ -181,6 +186,55 @@
181186 return Response.ok(pack).build();
182187 }
183188
189
+ /**
190
+ * Check if there is some pack with the same code
191
+ *
192
+ * @param code
193
+ * Pack code
194
+ * @param em
195
+ * DB session object
196
+ * @return <code>true</code> if code is already used, <code>false</code>
197
+ * otherwise
198
+ */
199
+ private boolean checkIfCodeExists(String code, EntityManager em) {
200
+ TypedQuery<Pack> query = em.createNamedQuery("pack-by-code", Pack.class);
201
+ query.setParameter("code", code);
202
+ int packs = query.getResultList().size();
203
+ return packs > 0;
204
+ }
205
+
206
+ private int getNextCodeSuffix(int packId, EntityManager em) {
207
+ TypedQuery<Integer> query = em.createNamedQuery("last-code-suffix-used-in-pack", Integer.class);
208
+ query.setParameter("packId", packId);
209
+ Integer lastCodeSuffix = query.getSingleResult();
210
+ return lastCodeSuffix == null ? 1 : lastCodeSuffix + 1;
211
+ }
212
+
213
+ /**
214
+ *
215
+ * @return The next available code suffix in pack for license code
216
+ * @throws SeCurisServiceException
217
+ */
218
+ @GET
219
+ @Path("/{packId}/next_license_code")
220
+ @Securable
221
+ @Produces({
222
+ MediaType.TEXT_PLAIN
223
+ })
224
+ public Response getCodeSuffix(@PathParam("packId") Integer packId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
225
+ EntityManager em = emProvider.get();
226
+
227
+ if (packId == null) {
228
+ throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The pack code is mandatory");
229
+ }
230
+ Integer codeSuffix = getNextCodeSuffix(packId, em);
231
+ Pack pack = em.find(Pack.class, packId);
232
+ ;
233
+
234
+ String licCode = LicUtils.getLicenseCode(pack.getCode(), codeSuffix);
235
+ return Response.ok(licCode).build();
236
+ }
237
+
184238 private void setPackLicenseType(Pack pack, Integer licTypeId, EntityManager em) throws SeCurisException {
185239 LicenseType lt = null;
186240 if (licTypeId != null) {
securis/src/main/java/net/curisit/securis/services/exception/SeCurisServiceException.java
....@@ -40,5 +40,7 @@
4040 public static int INVALID_REQUEST_DATA_FORMAT = 1202;
4141 public static int BLOCKED_REQUEST_DATA = 1203;
4242 public static int DUPLICATED_REQUEST_DATA = 1204;
43
+
44
+ public static int INVALID_DATA = 1301;
4345 }
4446 }
securis/src/main/resources/db/schema.sql
....@@ -104,6 +104,7 @@
104104 CREATE TABLE IF NOT EXISTS license (
105105 id INT NOT NULL auto_increment,
106106 code VARCHAR(100) NOT NULL ,
107
+ code_suffix INT NULL ,
107108 request_data VARCHAR(1024) NULL ,
108109 request_data_hash VARCHAR(64) NULL ,
109110 license_data VARCHAR(1024) NULL ,
securis/src/main/webapp/js/licenses.js
....@@ -12,7 +12,7 @@
1212 }
1313
1414 var app = angular.module('securis');
15
- app.service('Packs', ['$L','$resource', 'toaster', function($L, $resource, toaster) {
15
+ app.service('Packs', ['$L','$resource', '$http', 'toaster', function($L, $resource, $http, toaster) {
1616 var PACK_STATUS = {
1717 CREATED: 'CR',
1818 ACTIVE: 'AC',
....@@ -117,6 +117,14 @@
117117 var _error = _createErrorCallback(pack, $L.get('Put on hold'), _onerror);
118118 packResource.putonhold({id: pack.id}, _success, _error);
119119 }
120
+ this.nextliccode = function(packId, _onsuccess, _onerror) {
121
+ console.log('Get next code: ' + packId);
122
+ var _error = function(data, status, headers, config) {
123
+ console.log(headers);
124
+ 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'))));
125
+ }
126
+ $http.get("/securis/pack/"+packId+"/next_license_code").success(_onsuccess).error(_error);
127
+ }
120128 this.cancel = function(pack, extra_data, _onsuccess, _onerror) {
121129 console.log('Cancellation on pack: ' + pack.id);
122130 var _success = _createSuccessCallback($L.get('Cancellation'), $L.get("Pack '{0}' {1} successfully", pack.code, $L.get("cancelled")), _onsuccess);
....@@ -133,7 +141,7 @@
133141
134142 }]);
135143
136
- app.service('Licenses', ['$L', '$resource', 'toaster', function($L, $resource, toaster) {
144
+ app.service('Licenses', ['$L', '$resource', 'toaster', 'Packs', function($L, $resource, toaster, Packs) {
137145 var LIC_STATUS = {
138146 CREATED: 'CR',
139147 ACTIVE: 'AC',
....@@ -225,7 +233,14 @@
225233 }
226234 var _error = function(error) {
227235 console.log(error);
228
- 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'))));
236
+ 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);
237
+ if (error.headers('X-SECURIS-ERROR-CODE') === '1301') {
238
+ Packs.nextliccode(license.pack_id, function(data) {
239
+ console.log('New code: ' + data);
240
+ license.code = data;
241
+ toaster.pop('info', 'Licenses', $L.get("New license code, {0}, has been generated, please try again", license.code), 5000);
242
+ });
243
+ }
229244 }
230245 licenseResource.save(license, _success, _error);
231246 }
....@@ -622,9 +637,10 @@
622637 '$resource',
623638 'toaster',
624639 'Licenses',
640
+ 'Packs',
625641 '$store',
626642 '$L',
627
- function($scope, $http, $resource, toaster, Licenses, $store, $L) {
643
+ function($scope, $http, $resource, toaster, Licenses, Packs, $store, $L) {
628644 $scope.Licenses = Licenses;
629645 $scope.$on('pack_changed', function(evt, message) {
630646 $scope.licenses = Licenses.getLicensesList($scope.currentPack);
....@@ -708,8 +724,12 @@
708724 $scope.license = {
709725 pack_id: $scope.currentPack.id
710726 }
727
+ Packs.nextliccode($scope.currentPack.id, function(data) {
728
+ console.log('New code: ' + data);
729
+ $scope.license.code = data;
730
+ });
711731 setTimeout(function() {
712
- $('#licenseForm * #code').focus();
732
+ $('#licenseForm * #email').focus();
713733 }, 0);
714734 }
715735
....@@ -816,13 +836,6 @@
816836
817837 $scope.cancel = function() {
818838 $scope.showForm = false;
819
- }
820
-
821
- $scope.showStatus = function(lic) {
822
-
823
- }
824
- $scope.showStatusLong = function(license) {
825
-
826839 }
827840
828841 } ]);
securis/src/main/webapp/licenses.html
....@@ -25,10 +25,10 @@
2525 <div class="input-group-addon" style="width: 28px;">
2626 <span class=" glyphicon glyphicon-search"></span>
2727 </div> <input type="text" class="form-control" placeholder="Search"
28
- ng-model="$searchPacksText">
28
+ ng-model="searchPackText">
2929 <div class="input-group-addon" style="width: 20px;">
3030 <span class=" glyphicon glyphicon-remove"
31
- ng-click="$searchPacksText = '';"></span>
31
+ ng-click="searchPackText = '';"></span>
3232 </div>
3333 </span>
3434 </div>
....@@ -64,7 +64,7 @@
6464 </div>
6565
6666 <div class="form-group">
67
- <label class="col-md-3 control-label" for="code" i18n>Validity (from - to)</label>
67
+ <label class="col-md-3 control-label" for="init_valid_date" i18n>Validity (from - to)</label>
6868 <div class="col-md-4">
6969 <input type="date" id="init_valid_date" name="init_valid_date" placeholder=""
7070 class="form-control" ng-model="pack.init_valid_date"
....@@ -282,7 +282,7 @@
282282 </tr>
283283 </thead>
284284 <tbody>
285
- <tr ng-repeat="p in packs | filter:searchText"
285
+ <tr ng-repeat="p in packs | filter:searchPackText"
286286 ng-dblclick="editPack(p)"
287287 ng-class="{success: currentPack.id === p.id}"
288288 ng-click="selectPack(p)">
....@@ -351,10 +351,10 @@
351351 <div class="input-group-addon" style="width: 28px;">
352352 <span class=" glyphicon glyphicon-search"></span>
353353 </div> <input type="text" class="form-control" placeholder="Search"
354
- ng-model="$searchLicensesText">
354
+ ng-model="searchLicenseText">
355355 <div class="input-group-addon" style="width: 20px;">
356356 <span class=" glyphicon glyphicon-remove"
357
- ng-click="$searchLicensesText = '';"></span>
357
+ ng-click="searchLicenseText = '';"></span>
358358 </div>
359359 </span>
360360 </div>
....@@ -389,7 +389,7 @@
389389 <label class="col-md-3 control-label" for="code" i18n>Code</label>
390390 <div class="col-md-8">
391391 <input type="string" id="code" name="code" placeholder=""
392
- class="form-control" ng-model="license.code"
392
+ class="form-control" ng-model="license.code" readonly
393393 ng-required="mandatory.code" ng-maxlength="{{maxlength.code}}" />
394394 <div class="alert inline-alert alert-warning"
395395 ng-show="licenseForm.code.$invalid">
....@@ -404,7 +404,7 @@
404404 <div class="form-group" ng-if="!isNew">
405405 <label class="col-md-3 control-label" i18n>Status</label>
406406 <div class="col-md-8">
407
- <p class="form-control-static" ng-bind="showStatusLong(license)"></p>
407
+ <p class="form-control-static" ng-bind="license.status_name"></p>
408408 </div>
409409 </div>
410410
....@@ -625,7 +625,7 @@
625625 <td ng-bind="ellipsis(lic.full_name, 20)"
626626 title="{{lic.full_name}}"></td>
627627 <td ng-bind="ellipsis(lic.email, 30)" title="{{lic.email}}"></td>
628
- <td ng-bind="showStatus(lic.status)"></td>
628
+ <td ng-bind="Licenses.getStatusName(lic.status)"></td>
629629 <td>
630630 <div class="dropdown">
631631 <a class="dropdown-toggle" data-toggle="dropdown"> <span
securis/src/main/webapp/login.html
....@@ -22,7 +22,7 @@
2222 <div class="jumbotron">
2323 <div class="container">
2424 <h2 i18n >SeCuris</h2>
25
- <p i18n >Server License for CurisTEC products.</p>
25
+ <p i18n >Licenses Server for CurisTEC products.</p>
2626 </div>
2727 </div>
2828