rsanchez
2015-09-24 94c288b4f8d353c44b64e40c0863c7fce6782293
#2756 fix - chnaged API to allow activation by code and other UI changes
14 files modified
changed files
securis/pom.xml patch | view | blame | history
securis/src/main/java/net/curisit/securis/db/Application.java patch | view | blame | history
securis/src/main/java/net/curisit/securis/db/License.java patch | view | blame | history
securis/src/main/java/net/curisit/securis/ioc/RequestsInterceptor.java patch | view | blame | history
securis/src/main/java/net/curisit/securis/services/ApiResource.java patch | view | blame | history
securis/src/main/java/net/curisit/securis/services/ApplicationResource.java patch | view | blame | history
securis/src/main/java/net/curisit/securis/services/BasicServices.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/helpers/LicenseHelper.java patch | view | blame | history
securis/src/main/java/net/curisit/securis/utils/TokenHelper.java patch | view | blame | history
securis/src/main/resources/db/schema.sql patch | view | blame | history
securis/src/main/webapp/js/catalogs.json 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/pom.xml
....@@ -3,7 +3,7 @@
33 <modelVersion>4.0.0</modelVersion>
44 <groupId>net.curisit</groupId>
55 <artifactId>securis-server</artifactId>
6
- <version>1.0.2</version>
6
+ <version>1.1.1</version>
77 <name>SeCuris</name>
88 <description>CurisTEC Server Licenses</description>
99 <dependencies>
....@@ -51,7 +51,7 @@
5151 <dependency>
5252 <groupId>net.curisit</groupId>
5353 <artifactId>securis-client</artifactId>
54
- <version>1.0.6-SNAPSHOT</version>
54
+ <version>1.1.0-SNAPSHOT</version>
5555 </dependency>
5656 <dependency>
5757 <groupId>org.apache.httpcomponents</groupId>
securis/src/main/java/net/curisit/securis/db/Application.java
....@@ -46,6 +46,7 @@
4646 @GeneratedValue
4747 private Integer id;
4848
49
+ private String code;
4950 private String name;
5051 private String description;
5152
....@@ -139,4 +140,12 @@
139140 public void setLicenseTypes(Set<LicenseType> licenseTypes) {
140141 this.licenseTypes = licenseTypes;
141142 }
143
+
144
+ public String getCode() {
145
+ return code;
146
+ }
147
+
148
+ public void setCode(String code) {
149
+ this.code = code;
150
+ }
142151 }
securis/src/main/java/net/curisit/securis/db/License.java
....@@ -54,6 +54,7 @@
5454 @JsonIgnoreProperties(ignoreUnknown = true)
5555 @NamedQueries({
5656 @NamedQuery(name = "license-by-code", query = "SELECT l FROM License l where l.code = :code"),
57
+ @NamedQuery(name = "license-by-activation-code", query = "SELECT l FROM License l where l.activationCode = :activationCode"),
5758 @NamedQuery(name = "last-code-suffix-used-in-pack", query = "SELECT max(l.codeSuffix) FROM License l where l.pack.id = :packId"),
5859 @NamedQuery(name = "list-licenses-by-pack", query = "SELECT l FROM License l where l.pack.id = :packId"),
5960 @NamedQuery(name = "list-licenses-by-req-data", query = "SELECT l FROM License l where l.reqDataHash = :hash"),
....@@ -72,6 +73,10 @@
7273 private int id;
7374
7475 private String code;
76
+
77
+ @Column(name = "activation_code")
78
+ @JsonProperty("activation_code")
79
+ private String activationCode;
7580
7681 @Column(name = "code_suffix")
7782 @JsonProperty("code_suffix")
....@@ -397,6 +402,26 @@
397402 }
398403 }
399404
405
+ /**
406
+ * Return licenses with status: REquested, ACtive, Pre-Active for a given
407
+ * request data
408
+ *
409
+ * @param requestData
410
+ * @param em
411
+ * @return
412
+ * @throws SeCurisServiceException
413
+ */
414
+ public static License findLicenseByActivationCode(String activationCode, EntityManager em) throws SeCurisServiceException {
415
+ TypedQuery<License> query = em.createNamedQuery("license-by-activation-code", License.class);
416
+ query.setParameter("activationCode", activationCode);
417
+ try {
418
+ return query.getSingleResult();
419
+ } catch (NoResultException e) {
420
+ // There is no license for request data
421
+ return null;
422
+ }
423
+ }
424
+
400425 public static License findActiveLicenseByRequestData(String requestData, EntityManager em) throws SeCurisServiceException {
401426 TypedQuery<License> query = em.createNamedQuery("list-active-licenses-by-req-data", License.class);
402427 query.setParameter("hash", BlockedRequest.generateHash(requestData));
....@@ -435,4 +460,12 @@
435460 this.codeSuffix = codeSuffix;
436461 }
437462
463
+ public String getActivationCode() {
464
+ return activationCode;
465
+ }
466
+
467
+ public void setActivationCode(String activationCode) {
468
+ this.activationCode = activationCode;
469
+ }
470
+
438471 }
securis/src/main/java/net/curisit/securis/ioc/RequestsInterceptor.java
....@@ -143,8 +143,10 @@
143143 if (user != null) {
144144 userRoles = 0;
145145 List<Integer> roles = user.getRoles();
146
- for (Integer rol : roles) {
147
- userRoles += rol;
146
+ if (roles != null) {
147
+ for (Integer rol : roles) {
148
+ userRoles += rol;
149
+ }
148150 }
149151 // We store user roles in cache only for one hour
150152 cache.set("roles_" + username, userRoles, 3600);
securis/src/main/java/net/curisit/securis/services/ApiResource.java
....@@ -68,7 +68,7 @@
6868 @Inject
6969 LicenseGenerator licenseGenerator;
7070
71
- private static final String CLIENT_USERNAME = "_client";
71
+ public static final String API_CLIENT_USERNAME = "_client";
7272
7373 public ApiResource() {
7474 }
....@@ -115,7 +115,7 @@
115115 @POST
116116 @Path("/request")
117117 @Consumes(MediaType.APPLICATION_JSON)
118
- // TODO: Enable this: @Securable
118
+ @Securable
119119 @Produces({
120120 MediaType.APPLICATION_JSON
121121 })
....@@ -123,7 +123,7 @@
123123 public Response createFromRequest(RequestBean request, @HeaderParam(LicenseManager.HEADER_LICENSE_NAME_OR_REFERENCE) String nameOrReference,
124124 @HeaderParam(LicenseManager.HEADER_LICENSE_EMAIL) String userEmail) throws IOException, SeCurisServiceException, SeCurisException {
125125 LOG.info("Request to get license: {}", request);
126
- SignedLicenseBean lic = createLicense(request, em, false, nameOrReference, userEmail);
126
+ SignedLicenseBean lic = createLicense(request, em, nameOrReference, userEmail);
127127
128128 return Response.ok(lic).build();
129129 }
....@@ -151,6 +151,8 @@
151151 @HeaderParam(LicenseManager.HEADER_LICENSE_NAME_OR_REFERENCE) String nameOrReference,
152152 @HeaderParam(LicenseManager.HEADER_LICENSE_EMAIL) String userEmail) throws IOException, SeCurisServiceException, SeCurisException {
153153 RequestBean req = new RequestBean();
154
+ req.setAppCode(mpfdi.getFormDataPart("appCode", String.class, null));
155
+ req.setActivationCode(mpfdi.getFormDataPart("activationCode", String.class, null));
154156 req.setPackCode(mpfdi.getFormDataPart("packCode", String.class, null));
155157 req.setLicenseTypeCode(mpfdi.getFormDataPart("licenseTypeCode", String.class, null));
156158 req.setCustomerCode(mpfdi.getFormDataPart("customerCode", String.class, null));
....@@ -175,7 +177,7 @@
175177 @POST
176178 @Path("/renew")
177179 @Consumes(MediaType.APPLICATION_JSON)
178
- // TODO: Enable this: @Securable
180
+ @Securable
179181 @Produces({
180182 MediaType.APPLICATION_JSON
181183 })
....@@ -214,7 +216,7 @@
214216 @POST
215217 @Path("/validate")
216218 @Consumes(MediaType.APPLICATION_JSON)
217
- // TODO: Enable this: @Securable
219
+ @Securable
218220 @Produces({
219221 MediaType.APPLICATION_JSON
220222 })
....@@ -226,7 +228,6 @@
226228 throw new SeCurisServiceException(ErrorCodes.LICENSE_IS_EXPIRED, "The license is expired");
227229 }
228230
229
- // EntityManager em = emProvider.get();
230231 try {
231232 SignatureHelper.getInstance().validateSignature(currentLic);
232233 } catch (SeCurisException ex) {
....@@ -261,6 +262,8 @@
261262 SeCurisServiceException, SeCurisException {
262263 LicenseBean lic = new LicenseBean();
263264
265
+ lic.setAppCode(mpfdi.getFormDataPart("appCode", String.class, null));
266
+ lic.setActivationCode(mpfdi.getFormDataPart("activationName", String.class, null));
264267 lic.setAppName(mpfdi.getFormDataPart("appName", String.class, null));
265268 lic.setArch(mpfdi.getFormDataPart("arch", String.class, null));
266269 lic.setCrcLogo(mpfdi.getFormDataPart("crcLogo", String.class, null));
....@@ -279,7 +282,7 @@
279282 }
280283
281284 private SignedLicenseBean renewLicense(RequestBean req, EntityManager em) throws SeCurisServiceException {
282
- return createLicense(req, em, true, null, null);
285
+ return renewLicense(req, em);
283286 }
284287
285288 /**
....@@ -292,16 +295,38 @@
292295 * @return
293296 * @throws SeCurisServiceException
294297 */
295
- private SignedLicenseBean createLicense(RequestBean req, EntityManager em, boolean renew, String nameOrReference, String email)
296
- throws SeCurisServiceException {
297
- LicenseBean previousLicenseBean = null;
298
+ private SignedLicenseBean createLicense(RequestBean req, EntityManager em, String nameOrReference, String email) throws SeCurisServiceException {
298299 License lic = null;
299
- if (renew) {
300
- previousLicenseBean = (LicenseBean) req;
301
- lic = License.findLicenseByCode(previousLicenseBean.getLicenseCode(), em);
302
- if (lic.getStatus() != LicenseStatus.ACTIVE && lic.getStatus() != LicenseStatus.PRE_ACTIVE) {
303
- throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The current license has been cancelled");
300
+
301
+ if (req.getActivationCode() != null) {
302
+ lic = License.findLicenseByActivationCode(req.getActivationCode(), em);
303
+ if (lic == null) {
304
+ throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The given activation code is invalid: " + req.getActivationCode());
304305 }
306
+ if (lic.getStatus() == LicenseStatus.ACTIVE) {
307
+ RequestBean initialRequest;
308
+ try {
309
+ initialRequest = JsonUtils.json2object(lic.getRequestData(), RequestBean.class);
310
+ if (!req.match(initialRequest)) {
311
+ throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "There is already an active license for given activation code: "
312
+ + req.getActivationCode());
313
+ } else {
314
+ return JsonUtils.json2object(lic.getLicenseData(), SignedLicenseBean.class);
315
+ }
316
+ } catch (SeCurisException e) {
317
+ LOG.error("Error getting existing license", e);
318
+ throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Original request is wrong");
319
+ }
320
+ } else {
321
+ if (req.getAppCode() != null && !req.getAppCode().equals(lic.getPack().getLicenseType().getApplication().getCode())) {
322
+ LOG.error("Activation code {} belongs to app: {} but was sent by: {}", req.getActivationCode(), lic.getPack().getLicenseType()
323
+ .getApplication().getCode(), req.getAppCode());
324
+ throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The given activation code belongs to a different application: "
325
+ + req.getActivationCode());
326
+ }
327
+ }
328
+ // We validate if the HW is the same, otherwise an error is
329
+ // thrown
305330 } else {
306331 try {
307332 lic = License.findValidLicenseByRequestData(JsonUtils.toJSON(req), em);
....@@ -321,40 +346,126 @@
321346 lic = new License();
322347 }
323348 }
349
+
324350 Pack pack;
325
- try {
326
- pack = em.createNamedQuery("pack-by-code", Pack.class).setParameter("code", req.getPackCode()).getSingleResult();
327
- } catch (NoResultException e) {
328
- throw new SeCurisServiceException(ErrorCodes.NOT_FOUND, "No pack found for code: " + req.getPackCode());
329
- }
351
+ if (lic.getActivationCode() == null) {
352
+ try {
353
+ pack = em.createNamedQuery("pack-by-code", Pack.class).setParameter("code", req.getPackCode()).getSingleResult();
354
+ } catch (NoResultException e) {
355
+ throw new SeCurisServiceException(ErrorCodes.NOT_FOUND, "No pack found for code: " + req.getPackCode());
356
+ }
330357
331
- if (!renew && pack.getNumAvailables() <= 0) {
332
- throw new SeCurisServiceException(ErrorCodes.NO_AVAILABLE_LICENSES, "The current pack has no licenses availables");
333
- }
334
- if (!renew && lic.getStatus() == LicenseStatus.REQUESTED && !pack.isLicensePreactivation()) {
335
- throw new SeCurisServiceException(ErrorCodes.NO_AVAILABLE_LICENSES, "Current pack doesn't allow license preactivation");
336
- }
358
+ if (pack.getNumAvailables() <= 0) {
359
+ throw new SeCurisServiceException(ErrorCodes.NO_AVAILABLE_LICENSES, "The current pack has no licenses availables");
360
+ }
361
+ if (lic.getStatus() == LicenseStatus.REQUESTED && !pack.isLicensePreactivation()) {
362
+ throw new SeCurisServiceException(ErrorCodes.NO_AVAILABLE_LICENSES, "Current pack doesn't allow license preactivation");
363
+ }
337364
338
- if (!req.getCustomerCode().equals(pack.getOrganization().getCode())) {
339
- throw new SeCurisServiceException(ErrorCodes.INVALID_LICENSE_REQUEST_DATA, "Customer code is not valid: " + req.getCustomerCode());
340
- }
365
+ if (!req.getCustomerCode().equals(pack.getOrganization().getCode())) {
366
+ throw new SeCurisServiceException(ErrorCodes.INVALID_LICENSE_REQUEST_DATA, "Customer code is not valid: " + req.getCustomerCode());
367
+ }
341368
342
- if (!req.getLicenseTypeCode().equals(pack.getLicenseTypeCode())) {
343
- throw new SeCurisServiceException(ErrorCodes.INVALID_LICENSE_REQUEST_DATA, "License type code is not valid: " + req.getLicenseTypeCode());
369
+ if (!req.getLicenseTypeCode().equals(pack.getLicenseTypeCode())) {
370
+ throw new SeCurisServiceException(ErrorCodes.INVALID_LICENSE_REQUEST_DATA, "License type code is not valid: "
371
+ + req.getLicenseTypeCode());
372
+ }
373
+ } else {
374
+ pack = lic.getPack();
344375 }
345
-
346376 SignedLicenseBean signedLicense;
347377 try {
348378 String licCode;
349
- if (renew || lic.getStatus() == LicenseStatus.REQUESTED) {
350
- licCode = lic.getCode();
351
- } else {
379
+ if (lic.getCode() == null) {
352380 licCode = LicUtils.getLicenseCode(pack.getCode(), licenseHelper.getNextCodeSuffix(pack.getId(), em));
381
+ } else {
382
+ licCode = lic.getCode();
353383 }
354
- Date expirationDate = licenseHelper.getExpirationDateFromPack(pack, !renew);
384
+ Date expirationDate = licenseHelper.getExpirationDateFromPack(pack, lic.getActivationCode() == null);
355385
356386 LicenseBean lb = licenseGenerator.generateLicense(req, licenseHelper.extractPackMetadata(pack.getMetadata()), expirationDate, licCode,
357387 pack.getAppName());
388
+ signedLicense = new SignedLicenseBean(lb);
389
+ } catch (SeCurisException e) {
390
+ throw new SeCurisServiceException(ErrorCodes.INVALID_LICENSE_REQUEST_DATA, "Error generating license: " + e.toString());
391
+ }
392
+ try {
393
+ lic.setRequestData(JsonUtils.toJSON(req));
394
+ if (BlockedRequest.isRequestBlocked(lic.getRequestData(), em)) {
395
+ throw new SeCurisServiceException(ErrorCodes.BLOCKED_REQUEST_DATA, "Given request data is blocked and cannot be activated");
396
+ }
397
+ lic.setLicenseData(JsonUtils.toJSON(signedLicense));
398
+ } catch (SeCurisException e) {
399
+ LOG.error("Error generating license JSON", e);
400
+ throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Error generating license JSON");
401
+ }
402
+
403
+ lic.setModificationTimestamp(new Date());
404
+ lic.setExpirationDate(signedLicense.getExpirationDate());
405
+ User user = em.find(User.class, API_CLIENT_USERNAME);
406
+ if (lic.getStatus() != LicenseStatus.REQUESTED) {
407
+ lic.setPack(pack);
408
+ lic.setCreatedBy(user);
409
+ lic.setCreationTimestamp(new Date());
410
+ if (lic.getActivationCode() != null) {
411
+ lic.setStatus(LicenseStatus.ACTIVE);
412
+ } else {
413
+ lic.setStatus(pack.isLicensePreactivation() ? LicenseStatus.PRE_ACTIVE : LicenseStatus.REQUESTED);
414
+ }
415
+ lic.setCode(signedLicense.getLicenseCode());
416
+ lic.setCodeSuffix(LicUtils.getLicenseCodeSuffix(signedLicense.getLicenseCode()));
417
+ if (lic.getEmail() == null || "".equals(lic.getEmail())) {
418
+ lic.setEmail(email);
419
+ }
420
+ if (lic.getFullName() == null || "".equals(lic.getFullName())) {
421
+ lic.setFullName(nameOrReference);
422
+ }
423
+ em.persist(lic);
424
+ em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.CREATE));
425
+ if (lic.getActivationCode() != null) {
426
+ em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.ACTIVATE, "Activated by code on creation"));
427
+ } else {
428
+ if (pack.isLicensePreactivation()) {
429
+ em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.PRE_ACTIVATE, "Pre-activated on creation"));
430
+ } else {
431
+ LOG.warn("License ({}) created, but the pack doesn't allow preactivation", lic.getCode());
432
+ throw new SeCurisServiceException(ErrorCodes.NO_AVAILABLE_LICENSES, "Current pack doesn't allow license preactivation");
433
+ }
434
+ }
435
+ } else {
436
+ lic.setStatus(LicenseStatus.PRE_ACTIVE);
437
+ em.merge(lic);
438
+ em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.PRE_ACTIVATE, "Pre-activated after request"));
439
+ }
440
+
441
+ return signedLicense;
442
+ }
443
+
444
+ /**
445
+ * Creates a new signed license from request data or from previous license
446
+ * if It's a renew
447
+ *
448
+ * @param req
449
+ * @param em
450
+ * @param renew
451
+ * @return
452
+ * @throws SeCurisServiceException
453
+ */
454
+ private SignedLicenseBean renewLicense(LicenseBean previousLicenseBean, EntityManager em) throws SeCurisServiceException {
455
+
456
+ License lic = License.findLicenseByCode(previousLicenseBean.getLicenseCode(), em);
457
+ if (lic.getStatus() != LicenseStatus.ACTIVE && lic.getStatus() != LicenseStatus.PRE_ACTIVE) {
458
+ throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The current license has been cancelled");
459
+ }
460
+
461
+ Pack pack = lic.getPack();
462
+ SignedLicenseBean signedLicense;
463
+ try {
464
+ String licCode = lic.getCode();
465
+ Date expirationDate = licenseHelper.getExpirationDateFromPack(pack, false);
466
+
467
+ LicenseBean lb = licenseGenerator.generateLicense(previousLicenseBean, licenseHelper.extractPackMetadata(pack.getMetadata()),
468
+ expirationDate, licCode, pack.getAppName());
358469 signedLicense = new SignedLicenseBean(lb);
359470 } catch (SeCurisException e) {
360471 throw new SeCurisServiceException(ErrorCodes.INVALID_LICENSE_REQUEST_DATA, "Error generating license: " + e.toString());
....@@ -372,37 +483,11 @@
372483
373484 lic.setModificationTimestamp(new Date());
374485 lic.setExpirationDate(signedLicense.getExpirationDate());
375
- User user = em.find(User.class, CLIENT_USERNAME);
376
- if (!renew && lic.getStatus() != LicenseStatus.REQUESTED) {
377
- lic.setPack(pack);
378
- lic.setCreatedBy(user);
379
- lic.setCreationTimestamp(new Date());
380
- if (pack.isLicensePreactivation()) {
381
- lic.setStatus(LicenseStatus.PRE_ACTIVE);
382
- } else {
383
- lic.setStatus(LicenseStatus.REQUESTED);
384
- }
385
- lic.setCode(signedLicense.getLicenseCode());
386
- lic.setCodeSuffix(LicUtils.getLicenseCodeSuffix(signedLicense.getLicenseCode()));
387
- lic.setEmail(email);
388
- lic.setFullName(nameOrReference);
389
- em.persist(lic);
390
- em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.CREATE));
391
- if (pack.isLicensePreactivation()) {
392
- em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.PRE_ACTIVATE, "Pre-activated on creation"));
393
- } else {
394
- LOG.warn("License ({}) created, but the pack doesn't allow preactivation", lic.getCode());
395
- throw new SeCurisServiceException(ErrorCodes.NO_AVAILABLE_LICENSES, "Current pack doesn't allow license preactivation");
396
- }
397
- } else {
398
- lic.setStatus(renew ? LicenseStatus.ACTIVE : LicenseStatus.PRE_ACTIVE);
399
- em.merge(lic);
400
- if (renew) {
401
- em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.RENEW));
402
- } else {
403
- em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.PRE_ACTIVATE, "Pre-activated after request"));
404
- }
405
- }
486
+ User user = em.find(User.class, API_CLIENT_USERNAME);
487
+
488
+ lic.setStatus(LicenseStatus.ACTIVE);
489
+ em.merge(lic);
490
+ em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.RENEW));
406491
407492 return signedLicense;
408493 }
securis/src/main/java/net/curisit/securis/services/ApplicationResource.java
....@@ -161,6 +161,7 @@
161161 return Response.status(Status.NOT_FOUND).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "Application not found with ID: " + appid)
162162 .build();
163163 }
164
+ currentapp.setCode(app.getCode());
164165 currentapp.setName(app.getName());
165166 currentapp.setLicenseFilename(app.getLicenseFilename());
166167 currentapp.setDescription(app.getDescription());
securis/src/main/java/net/curisit/securis/services/BasicServices.java
....@@ -73,14 +73,8 @@
7373 MediaType.APPLICATION_JSON
7474 })
7575 public Response login(@FormParam("username") String user, @FormParam("password") String password, @Context HttpServletRequest request) {
76
- LOG.info("index session: " + request.getSession());
77
- LOG.info("user: {}, pass: {}", user, password);
7876 LOG.info("is user in role: {} == {} ? ", "advance", request.isUserInRole("advance"));
7977
80
- if ("no".equals(password)) {
81
- // TODO: Code to text exception handling
82
- return Response.status(Status.UNAUTHORIZED).build();
83
- }
8478 String tokenAuth = tokenHelper.generateToken(user);
8579 return Response.ok(Utils.createMap("success", true, "token", tokenAuth)).build();
8680 }
securis/src/main/java/net/curisit/securis/services/LicenseResource.java
....@@ -209,7 +209,7 @@
209209
210210 License existingLicense = License.findActiveLicenseByRequestData(lic.getRequestData(), em);
211211 if (existingLicense != null && existingLicense.getStatus() == LicenseStatus.ACTIVE) {
212
- throw new SeCurisServiceException(ErrorCodes.NO_AVAILABLE_LICENSES, "The pack has not available licenses");
212
+ throw new SeCurisServiceException(ErrorCodes.NO_AVAILABLE_LICENSES, "An active license already exists for the given request data");
213213 }
214214
215215 lic.setStatus(LicenseStatus.ACTIVE);
....@@ -347,9 +347,19 @@
347347 if (checkIfCodeExists(lic.getCode(), em)) {
348348 throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The license code is already used in an existing license");
349349 }
350
+ if (lic.getActivationCode() == null) {
351
+ throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The activation code is mandatory");
352
+ }
353
+ License existingLic = License.findLicenseByActivationCode(lic.getActivationCode(), em);
354
+ if (existingLic != null) {
355
+ throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The activation code is already used in: " + existingLic.getCode());
356
+ }
350357 if (!LicUtils.checkValidLicenseCodeCrc(lic.getCode())) {
351358 throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The license code is not valid");
352359 }
360
+ if (!Utils.isValidEmail(lic.getEmail())) {
361
+ throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The user email should be a valid email");
362
+ }
353363
354364 Pack pack = null;
355365 if (lic.getPackId() != null) {
securis/src/main/java/net/curisit/securis/services/helpers/LicenseHelper.java
....@@ -125,6 +125,9 @@
125125 if (isPreActivation) {
126126 validPeriod = pack.getPreactivationValidPeriod() * MS_PER_DAY;
127127 } else {
128
+ if (pack.getRenewValidPeriod() <= 0) {
129
+ return pack.getEndValidDate();
130
+ }
128131 validPeriod = pack.getRenewValidPeriod() * MS_PER_DAY;
129132 }
130133 Date expirationDate = new Date(new Date().getTime() + validPeriod);
securis/src/main/java/net/curisit/securis/utils/TokenHelper.java
....@@ -11,6 +11,7 @@
1111 import javax.inject.Inject;
1212
1313 import net.curisit.integrity.commons.Utils;
14
+import net.curisit.securis.services.ApiResource;
1415
1516 import org.apache.commons.lang3.StringUtils;
1617 import org.apache.logging.log4j.LogManager;
....@@ -42,8 +43,12 @@
4243 * @return
4344 */
4445 public String generateToken(String user) {
46
+
47
+ return generateToken(user, new Date());
48
+ }
49
+
50
+ public String generateToken(String user, Date date) {
4551 try {
46
- Date date = new Date();
4752 String secret = generateSecret(user, date);
4853 StringBuffer sb = new StringBuffer();
4954 sb.append(secret);
....@@ -58,7 +63,6 @@
5863 LOG.error("Error generating SHA-256 hash", e);
5964 }
6065 return null;
61
-
6266 }
6367
6468 private String generateSecret(String user, Date date) throws UnsupportedEncodingException, NoSuchAlgorithmException {
....@@ -90,9 +94,11 @@
9094 String secret = parts[0];
9195 String user = parts[1];
9296 Date date = Utils.toDateFromIso(parts[2]);
93
- if (new Date().after(new Date(date.getTime() + VALID_TOKEN_PERIOD * 60 * 60 * 1000))) {
94
- return false;
95
- }
97
+ if (date.getTime() > 0 || !user.equals(ApiResource.API_CLIENT_USERNAME)) {
98
+ if (new Date().after(new Date(date.getTime() + VALID_TOKEN_PERIOD * 60 * 60 * 1000))) {
99
+ return false;
100
+ }
101
+ } // else: It's a securis-client API call
96102 String newSecret = generateSecret(user, date);
97103 return newSecret.equals(secret);
98104 } catch (IOException e) {
....@@ -136,4 +142,10 @@
136142 return null;
137143 }
138144
145
+ public static void main(String[] args) {
146
+ // client token:
147
+ // OTk3ODRiMzY5NzQ5MWI5NmYyZGQyODRiYjY2ZTU2YzdmMTZjYzM3YTY3N2ExM2M3ODI2MjU5ZTMzOTIyYjUzNSBfY2xpZW50IDE5NzAtMDEtMDFUMDA6NTk6NTkuOTk5KzAxMDA=
148
+ // OTk3ODRiMzY5NzQ5MWI5NmYyZGQyODRiYjY2ZTU2YzdmMTZjYzM3YTY3N2ExM2M3ODI2MjU5ZTMzOTIyYjUzNSBfY2xpZW50IDE5NzAtMDEtMDFUMDA6NTk6NTkuOTk5KzAxMDA=
149
+ System.out.print("client token: " + new TokenHelper().generateToken("_client", new Date(-1)));
150
+ }
139151 }
securis/src/main/resources/db/schema.sql
....@@ -23,6 +23,7 @@
2323 drop table IF EXISTS application;
2424 CREATE TABLE IF NOT EXISTS application (
2525 id INT NOT NULL auto_increment,
26
+ code VARCHAR(4) NOT NULL ,
2627 name VARCHAR(45) NOT NULL ,
2728 license_filename VARCHAR(100) NOT NULL ,
2829 description VARCHAR(500) NULL ,
....@@ -105,6 +106,7 @@
105106 CREATE TABLE IF NOT EXISTS license (
106107 id INT NOT NULL auto_increment,
107108 code VARCHAR(100) NOT NULL ,
109
+ activation_code VARCHAR(100) NULL ,
108110 code_suffix INT NULL ,
109111 request_data VARCHAR(1024) NULL ,
110112 request_data_hash VARCHAR(64) NULL ,
securis/src/main/webapp/js/catalogs.json
....@@ -10,6 +10,12 @@
1010 "autogenerate" : true,
1111 "readOnly" : true
1212 }, {
13
+ "name" : "code",
14
+ "display" : "Code",
15
+ "type" : "string",
16
+ "maxlength" : 4,
17
+ "mandatory" : true
18
+ }, {
1319 "name" : "name",
1420 "display" : "Name",
1521 "type" : "string",
securis/src/main/webapp/js/licenses.js
....@@ -724,7 +724,10 @@
724724 email: true
725725 }
726726 $scope.maxlength = {
727
+ activation_code: 36,
727728 code: 50,
729
+ full_name: 100,
730
+ email: 100,
728731 request_data: 500,
729732 comments: 1024
730733 }
....@@ -787,7 +790,8 @@
787790 $scope.isNew = true;
788791 $scope.showForm = true;
789792 $scope.license = {
790
- pack_id: $scope.currentPack.id
793
+ pack_id: $scope.currentPack.id,
794
+ activation_code: $scope.createUUID()
791795 }
792796 Packs.nextliccode($scope.currentPack.id, function(data) {
793797 console.log('New code: ' + data);
....@@ -797,12 +801,26 @@
797801 $('#licenseForm * #email').focus();
798802 }, 0);
799803 }
804
+ $scope.createUUID = function () {
805
+ // http://www.ietf.org/rfc/rfc4122.txt
806
+ var s = new Array(36);
807
+ var hexDigits = "0123456789abcdef";
808
+ for (var i = 0; i < 36; i++) {
809
+ s[i] = hexDigits.substr(Math.random() * 0x10 | 0, 1);
810
+ }
811
+ s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
812
+ s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
813
+ s[8] = s[13] = s[18] = s[23] = "-";
800814
815
+ var uuid = s.join("");
816
+ return uuid;
817
+ }
801818 $scope.editLicense = function(selectedlicense) {
802819 $scope.isNew = false;
803820 $scope.showForm = true;
804821 $scope.license = selectedlicense;
805822 $scope.license.status_name = Licenses.getStatusName($scope.license.status);
823
+ $scope.license.activation_code = $scope.license.activation_code || $scope.createUUID();
806824
807825 setTimeout(function() {
808826 $('#licenseForm * #code').focus();
securis/src/main/webapp/licenses.html
....@@ -56,7 +56,7 @@
5656 ng-show="packForm.code.$invalid">
5757 <span class="glyphicon glyphicon-warning-sign"></span> <span
5858 ng-show="packForm.code.$error.maxlength"
59
- ng-bind="maxlengthErrorMsg('Code', maxlength.code)"></span> <span
59
+ ng-bind="maxLengthErrorMsg('Code', maxlength.code)"></span> <span
6060 ng-show="packForm.code.$error.required"
6161 ng-bind="mandatoryFieldErrorMsg('Code')"></span>
6262 </div>
....@@ -103,7 +103,7 @@
103103 ng-show="packForm.num_licenses.$invalid">
104104 <span class="glyphicon glyphicon-warning-sign"></span> <span
105105 ng-show="packForm.num_licenses.$error.maxlength"
106
- ng-bind="maxlengthErrorMsg('Num. Licenses', maxlength.num_licenses)"></span>
106
+ ng-bind="maxLengthErrorMsg('Num. Licenses', maxlength.num_licenses)"></span>
107107 <span ng-show="packForm.num_licenses.$error.required"
108108 ng-bind="mandatoryFieldErrorMsg('Num. Licenses')"></span>
109109 </div>
....@@ -190,7 +190,7 @@
190190 i18n>Period for renew (days)</label>
191191 <div class="col-md-8">
192192 <input type="number" id="renew_valid_period" name="renew_valid_period"
193
- min="1" class="form-control" ng-model="pack.renew_valid_period"
193
+ min="0" class="form-control" ng-model="pack.renew_valid_period"
194194 ng-required="true" />
195195 <div class="alert inline-alert alert-warning"
196196 ng-show="packForm.renew_valid_period.$invalid">
....@@ -215,7 +215,7 @@
215215 ng-show="packForm.comments.$invalid">
216216 <span class="glyphicon glyphicon-warning-sign"></span> <span
217217 ng-show="packForm.comments.$error.maxlength"
218
- ng-bind="maxlengthErrorMsg('Comments', maxlength.comments)"></span>
218
+ ng-bind="maxLengthErrorMsg('Comments', maxlength.comments)"></span>
219219 <span ng-show="packForm.comments.$error.required"
220220 ng-bind="mandatoryFieldErrorMsg('comments')"></span>
221221 </div>
....@@ -415,9 +415,25 @@
415415 ng-show="licenseForm.code.$invalid">
416416 <span class="glyphicon glyphicon-warning-sign"></span> <span
417417 ng-show="licenseForm.code.$error.maxlength"
418
- ng-bind="maxlengthErrorMsg('Code', maxlength.code)"></span> <span
418
+ ng-bind="maxLengthErrorMsg('Code', maxlength.code)"></span> <span
419419 ng-show="licenseForm.code.$error.required"
420420 ng-bind="mandatoryFieldErrorMsg('Code')"></span>
421
+ </div>
422
+ </div>
423
+ </div>
424
+ <div class="form-group">
425
+ <label class="col-md-3 control-label" for="activation_code" i18n>Activation code</label>
426
+ <div class="col-md-8">
427
+ <input type="string" id="activation_code" name="activation_code" placeholder=""
428
+ class="form-control" ng-model="license.activation_code" readonly
429
+ ng-required="mandatory.activation_code" ng-maxlength="{{maxlength.activation_code}}" />
430
+ <div class="alert inline-alert alert-warning"
431
+ ng-show="licenseForm.activation_code.$invalid">
432
+ <span class="glyphicon glyphicon-warning-sign"></span> <span
433
+ ng-show="licenseForm.activation_code.$error.maxlength"
434
+ ng-bind="maxLengthErrorMsg('Activation code', maxlength.activation_code)"></span> <span
435
+ ng-show="licenseForm.activation_code.$error.required"
436
+ ng-bind="mandatoryFieldErrorMsg('Activation code')"></span>
421437 </div>
422438 </div>
423439 </div>
....@@ -442,12 +458,12 @@
442458 <div class="col-md-8">
443459 <input type="string" id="full_name" name="full_name"
444460 placeholder="" class="form-control" ng-model="license.full_name"
445
- ng-required="mandatory.full_name" />
461
+ ng-required="mandatory.full_name" ng-maxlength="{{maxlength.full_name}}" />
446462 <div class="alert inline-alert alert-warning"
447463 ng-show="licenseForm.full_name.$invalid">
448464 <span class="glyphicon glyphicon-warning-sign"></span> <span
449465 ng-show="licenseForm.full_name.$error.maxlength"
450
- ng-bind="maxlengthErrorMsg('User full name', maxlength.full_name)"></span>
466
+ ng-bind="maxLengthErrorMsg('User full name', maxlength.full_name)"></span>
451467 <span ng-show="licenseForm.full_name.$error.required"
452468 ng-bind="mandatoryFieldErrorMsg('User full name')"></span>
453469 </div>
....@@ -460,14 +476,14 @@
460476 <div class="col-md-8">
461477 <input type="email" id="email" name="email" placeholder=""
462478 class="form-control" ng-model="license.email"
463
- ng-required="mandatory.email" />
479
+ ng-required="mandatory.email" ng-maxlength="{{maxlength.email}}" />
464480 <div class="alert inline-alert alert-warning"
465481 ng-show="licenseForm.email.$invalid">
466482 <span class="glyphicon glyphicon-warning-sign"></span> <span
467483 ng-show="licenseForm.email.$error.email"
468484 ng-bind="'Please, write a valid email address'"></span> <span
469485 ng-show="licenseForm.email.$error.maxlength"
470
- ng-bind="maxlengthErrorMsg('User email', maxlength.email)"></span>
486
+ ng-bind="maxLengthErrorMsg('User email', maxlength.email)"></span>
471487 <span ng-show="licenseForm.email.$error.required"
472488 ng-bind="mandatoryFieldErrorMsg('User email')"></span>
473489 </div>
....@@ -490,7 +506,7 @@
490506 <span class="glyphicon glyphicon-warning-sign">
491507 <span
492508 ng-show="licenseForm.request_data.$error.maxlength"
493
- ng-bind="maxlengthErrorMsg('Request data', maxlength.request_data)"></span>
509
+ ng-bind="maxLengthErrorMsg('Request data', maxlength.request_data)"></span>
494510 <span ng-show="licenseForm.request_data.$error.required"
495511 ng-bind="mandatoryFieldErrorMsg('Request data')"></span>
496512 </span>
....@@ -514,7 +530,7 @@
514530 ng-show="licenseForm.comments.$invalid">
515531 <span class="glyphicon glyphicon-warning-sign"></span> <span
516532 ng-show="licenseForm.comments.$error.maxlength"
517
- ng-bind="maxlengthErrorMsg('Comments', maxlength.comments)"></span>
533
+ ng-bind="maxLengthErrorMsg('Comments', maxlength.comments)"></span>
518534 <span ng-show="licenseForm.comments.$error.required"
519535 ng-bind="mandatoryFieldErrorMsg('comments')"></span>
520536 </div>