securis/pom.xml
.. .. @@ -3,7 +3,7 @@ 3 3 <modelVersion>4.0.0</modelVersion> 4 4 <groupId>net.curisit</groupId> 5 5 <artifactId>securis-server</artifactId> 6 - <version>1.0.2</version>6 + <version>1.1.1</version>7 7 <name>SeCuris</name> 8 8 <description>CurisTEC Server Licenses</description> 9 9 <dependencies> .. .. @@ -51,7 +51,7 @@ 51 51 <dependency> 52 52 <groupId>net.curisit</groupId> 53 53 <artifactId>securis-client</artifactId> 54 - <version>1.0.6-SNAPSHOT</version>54 + <version>1.1.0-SNAPSHOT</version>55 55 </dependency> 56 56 <dependency> 57 57 <groupId>org.apache.httpcomponents</groupId> securis/src/main/java/net/curisit/securis/db/Application.java
.. .. @@ -46,6 +46,7 @@ 46 46 @GeneratedValue 47 47 private Integer id; 48 48 49 + private String code;49 50 private String name; 50 51 private String description; 51 52 .. .. @@ -139,4 +140,12 @@ 139 140 public void setLicenseTypes(Set<LicenseType> licenseTypes) { 140 141 this.licenseTypes = licenseTypes; 141 142 } 143 +144 + public String getCode() {145 + return code;146 + }147 +148 + public void setCode(String code) {149 + this.code = code;150 + }142 151 } securis/src/main/java/net/curisit/securis/db/License.java
.. .. @@ -54,6 +54,7 @@ 54 54 @JsonIgnoreProperties(ignoreUnknown = true) 55 55 @NamedQueries({ 56 56 @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"),57 58 @NamedQuery(name = "last-code-suffix-used-in-pack", query = "SELECT max(l.codeSuffix) FROM License l where l.pack.id = :packId"), 58 59 @NamedQuery(name = "list-licenses-by-pack", query = "SELECT l FROM License l where l.pack.id = :packId"), 59 60 @NamedQuery(name = "list-licenses-by-req-data", query = "SELECT l FROM License l where l.reqDataHash = :hash"), .. .. @@ -72,6 +73,10 @@ 72 73 private int id; 73 74 74 75 private String code; 76 +77 + @Column(name = "activation_code")78 + @JsonProperty("activation_code")79 + private String activationCode;75 80 76 81 @Column(name = "code_suffix") 77 82 @JsonProperty("code_suffix") .. .. @@ -397,6 +402,26 @@ 397 402 } 398 403 } 399 404 405 + /**406 + * Return licenses with status: REquested, ACtive, Pre-Active for a given407 + * request data408 + *409 + * @param requestData410 + * @param em411 + * @return412 + * @throws SeCurisServiceException413 + */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 data421 + return null;422 + }423 + }424 +400 425 public static License findActiveLicenseByRequestData(String requestData, EntityManager em) throws SeCurisServiceException { 401 426 TypedQuery<License> query = em.createNamedQuery("list-active-licenses-by-req-data", License.class); 402 427 query.setParameter("hash", BlockedRequest.generateHash(requestData)); .. .. @@ -435,4 +460,12 @@ 435 460 this.codeSuffix = codeSuffix; 436 461 } 437 462 463 + public String getActivationCode() {464 + return activationCode;465 + }466 +467 + public void setActivationCode(String activationCode) {468 + this.activationCode = activationCode;469 + }470 +438 471 } securis/src/main/java/net/curisit/securis/ioc/RequestsInterceptor.java
.. .. @@ -143,8 +143,10 @@ 143 143 if (user != null) { 144 144 userRoles = 0; 145 145 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 + }148 150 } 149 151 // We store user roles in cache only for one hour 150 152 cache.set("roles_" + username, userRoles, 3600); securis/src/main/java/net/curisit/securis/services/ApiResource.java
.. .. @@ -68,7 +68,7 @@ 68 68 @Inject 69 69 LicenseGenerator licenseGenerator; 70 70 71 - private static final String CLIENT_USERNAME = "_client";71 + public static final String API_CLIENT_USERNAME = "_client";72 72 73 73 public ApiResource() { 74 74 } .. .. @@ -115,7 +115,7 @@ 115 115 @POST 116 116 @Path("/request") 117 117 @Consumes(MediaType.APPLICATION_JSON) 118 - // TODO: Enable this: @Securable118 + @Securable119 119 @Produces({ 120 120 MediaType.APPLICATION_JSON 121 121 }) .. .. @@ -123,7 +123,7 @@ 123 123 public Response createFromRequest(RequestBean request, @HeaderParam(LicenseManager.HEADER_LICENSE_NAME_OR_REFERENCE) String nameOrReference, 124 124 @HeaderParam(LicenseManager.HEADER_LICENSE_EMAIL) String userEmail) throws IOException, SeCurisServiceException, SeCurisException { 125 125 LOG.info("Request to get license: {}", request); 126 - SignedLicenseBean lic = createLicense(request, em, false, nameOrReference, userEmail);126 + SignedLicenseBean lic = createLicense(request, em, nameOrReference, userEmail);127 127 128 128 return Response.ok(lic).build(); 129 129 } .. .. @@ -151,6 +151,8 @@ 151 151 @HeaderParam(LicenseManager.HEADER_LICENSE_NAME_OR_REFERENCE) String nameOrReference, 152 152 @HeaderParam(LicenseManager.HEADER_LICENSE_EMAIL) String userEmail) throws IOException, SeCurisServiceException, SeCurisException { 153 153 RequestBean req = new RequestBean(); 154 + req.setAppCode(mpfdi.getFormDataPart("appCode", String.class, null));155 + req.setActivationCode(mpfdi.getFormDataPart("activationCode", String.class, null));154 156 req.setPackCode(mpfdi.getFormDataPart("packCode", String.class, null)); 155 157 req.setLicenseTypeCode(mpfdi.getFormDataPart("licenseTypeCode", String.class, null)); 156 158 req.setCustomerCode(mpfdi.getFormDataPart("customerCode", String.class, null)); .. .. @@ -175,7 +177,7 @@ 175 177 @POST 176 178 @Path("/renew") 177 179 @Consumes(MediaType.APPLICATION_JSON) 178 - // TODO: Enable this: @Securable180 + @Securable179 181 @Produces({ 180 182 MediaType.APPLICATION_JSON 181 183 }) .. .. @@ -214,7 +216,7 @@ 214 216 @POST 215 217 @Path("/validate") 216 218 @Consumes(MediaType.APPLICATION_JSON) 217 - // TODO: Enable this: @Securable219 + @Securable218 220 @Produces({ 219 221 MediaType.APPLICATION_JSON 220 222 }) .. .. @@ -226,7 +228,6 @@ 226 228 throw new SeCurisServiceException(ErrorCodes.LICENSE_IS_EXPIRED, "The license is expired"); 227 229 } 228 230 229 - // EntityManager em = emProvider.get();230 231 try { 231 232 SignatureHelper.getInstance().validateSignature(currentLic); 232 233 } catch (SeCurisException ex) { .. .. @@ -261,6 +262,8 @@ 261 262 SeCurisServiceException, SeCurisException { 262 263 LicenseBean lic = new LicenseBean(); 263 264 265 + lic.setAppCode(mpfdi.getFormDataPart("appCode", String.class, null));266 + lic.setActivationCode(mpfdi.getFormDataPart("activationName", String.class, null));264 267 lic.setAppName(mpfdi.getFormDataPart("appName", String.class, null)); 265 268 lic.setArch(mpfdi.getFormDataPart("arch", String.class, null)); 266 269 lic.setCrcLogo(mpfdi.getFormDataPart("crcLogo", String.class, null)); .. .. @@ -279,7 +282,7 @@ 279 282 } 280 283 281 284 private SignedLicenseBean renewLicense(RequestBean req, EntityManager em) throws SeCurisServiceException { 282 - return createLicense(req, em, true, null, null);285 + return renewLicense(req, em);283 286 } 284 287 285 288 /** .. .. @@ -292,16 +295,38 @@ 292 295 * @return 293 296 * @throws SeCurisServiceException 294 297 */ 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 {298 299 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());304 305 } 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 is329 + // thrown305 330 } else { 306 331 try { 307 332 lic = License.findValidLicenseByRequestData(JsonUtils.toJSON(req), em); .. .. @@ -321,40 +346,126 @@ 321 346 lic = new License(); 322 347 } 323 348 } 349 +324 350 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 + }330 357 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 + }337 364 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 + }341 368 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();344 375 } 345 -346 376 SignedLicenseBean signedLicense; 347 377 try { 348 378 String licCode; 349 - if (renew || lic.getStatus() == LicenseStatus.REQUESTED) {350 - licCode = lic.getCode();351 - } else {379 + if (lic.getCode() == null) {352 380 licCode = LicUtils.getLicenseCode(pack.getCode(), licenseHelper.getNextCodeSuffix(pack.getId(), em)); 381 + } else {382 + licCode = lic.getCode();353 383 } 354 - Date expirationDate = licenseHelper.getExpirationDateFromPack(pack, !renew);384 + Date expirationDate = licenseHelper.getExpirationDateFromPack(pack, lic.getActivationCode() == null);355 385 356 386 LicenseBean lb = licenseGenerator.generateLicense(req, licenseHelper.extractPackMetadata(pack.getMetadata()), expirationDate, licCode, 357 387 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 license446 + * if It's a renew447 + *448 + * @param req449 + * @param em450 + * @param renew451 + * @return452 + * @throws SeCurisServiceException453 + */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());358 469 signedLicense = new SignedLicenseBean(lb); 359 470 } catch (SeCurisException e) { 360 471 throw new SeCurisServiceException(ErrorCodes.INVALID_LICENSE_REQUEST_DATA, "Error generating license: " + e.toString()); .. .. @@ -372,37 +483,11 @@ 372 483 373 484 lic.setModificationTimestamp(new Date()); 374 485 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));406 491 407 492 return signedLicense; 408 493 } securis/src/main/java/net/curisit/securis/services/ApplicationResource.java
.. .. @@ -161,6 +161,7 @@ 161 161 return Response.status(Status.NOT_FOUND).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "Application not found with ID: " + appid) 162 162 .build(); 163 163 } 164 + currentapp.setCode(app.getCode());164 165 currentapp.setName(app.getName()); 165 166 currentapp.setLicenseFilename(app.getLicenseFilename()); 166 167 currentapp.setDescription(app.getDescription()); securis/src/main/java/net/curisit/securis/services/BasicServices.java
.. .. @@ -73,14 +73,8 @@ 73 73 MediaType.APPLICATION_JSON 74 74 }) 75 75 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);78 76 LOG.info("is user in role: {} == {} ? ", "advance", request.isUserInRole("advance")); 79 77 80 - if ("no".equals(password)) {81 - // TODO: Code to text exception handling82 - return Response.status(Status.UNAUTHORIZED).build();83 - }84 78 String tokenAuth = tokenHelper.generateToken(user); 85 79 return Response.ok(Utils.createMap("success", true, "token", tokenAuth)).build(); 86 80 } securis/src/main/java/net/curisit/securis/services/LicenseResource.java
.. .. @@ -209,7 +209,7 @@ 209 209 210 210 License existingLicense = License.findActiveLicenseByRequestData(lic.getRequestData(), em); 211 211 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");213 213 } 214 214 215 215 lic.setStatus(LicenseStatus.ACTIVE); .. .. @@ -347,9 +347,19 @@ 347 347 if (checkIfCodeExists(lic.getCode(), em)) { 348 348 throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The license code is already used in an existing license"); 349 349 } 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 + }350 357 if (!LicUtils.checkValidLicenseCodeCrc(lic.getCode())) { 351 358 throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The license code is not valid"); 352 359 } 360 + if (!Utils.isValidEmail(lic.getEmail())) {361 + throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The user email should be a valid email");362 + }353 363 354 364 Pack pack = null; 355 365 if (lic.getPackId() != null) { securis/src/main/java/net/curisit/securis/services/helpers/LicenseHelper.java
.. .. @@ -125,6 +125,9 @@ 125 125 if (isPreActivation) { 126 126 validPeriod = pack.getPreactivationValidPeriod() * MS_PER_DAY; 127 127 } else { 128 + if (pack.getRenewValidPeriod() <= 0) {129 + return pack.getEndValidDate();130 + }128 131 validPeriod = pack.getRenewValidPeriod() * MS_PER_DAY; 129 132 } 130 133 Date expirationDate = new Date(new Date().getTime() + validPeriod); securis/src/main/java/net/curisit/securis/utils/TokenHelper.java
.. .. @@ -11,6 +11,7 @@ 11 11 import javax.inject.Inject; 12 12 13 13 import net.curisit.integrity.commons.Utils; 14 +import net.curisit.securis.services.ApiResource;14 15 15 16 import org.apache.commons.lang3.StringUtils; 16 17 import org.apache.logging.log4j.LogManager; .. .. @@ -42,8 +43,12 @@ 42 43 * @return 43 44 */ 44 45 public String generateToken(String user) { 46 +47 + return generateToken(user, new Date());48 + }49 +50 + public String generateToken(String user, Date date) {45 51 try { 46 - Date date = new Date();47 52 String secret = generateSecret(user, date); 48 53 StringBuffer sb = new StringBuffer(); 49 54 sb.append(secret); .. .. @@ -58,7 +63,6 @@ 58 63 LOG.error("Error generating SHA-256 hash", e); 59 64 } 60 65 return null; 61 -62 66 } 63 67 64 68 private String generateSecret(String user, Date date) throws UnsupportedEncodingException, NoSuchAlgorithmException { .. .. @@ -90,9 +94,11 @@ 90 94 String secret = parts[0]; 91 95 String user = parts[1]; 92 96 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 call96 102 String newSecret = generateSecret(user, date); 97 103 return newSecret.equals(secret); 98 104 } catch (IOException e) { .. .. @@ -136,4 +142,10 @@ 136 142 return null; 137 143 } 138 144 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 + }139 151 } securis/src/main/resources/db/schema.sql
.. .. @@ -23,6 +23,7 @@ 23 23 drop table IF EXISTS application; 24 24 CREATE TABLE IF NOT EXISTS application ( 25 25 id INT NOT NULL auto_increment, 26 + code VARCHAR(4) NOT NULL ,26 27 name VARCHAR(45) NOT NULL , 27 28 license_filename VARCHAR(100) NOT NULL , 28 29 description VARCHAR(500) NULL , .. .. @@ -105,6 +106,7 @@ 105 106 CREATE TABLE IF NOT EXISTS license ( 106 107 id INT NOT NULL auto_increment, 107 108 code VARCHAR(100) NOT NULL , 109 + activation_code VARCHAR(100) NULL ,108 110 code_suffix INT NULL , 109 111 request_data VARCHAR(1024) NULL , 110 112 request_data_hash VARCHAR(64) NULL , securis/src/main/webapp/js/catalogs.json
.. .. @@ -10,6 +10,12 @@ 10 10 "autogenerate" : true, 11 11 "readOnly" : true 12 12 }, { 13 + "name" : "code",14 + "display" : "Code",15 + "type" : "string",16 + "maxlength" : 4,17 + "mandatory" : true18 + }, {13 19 "name" : "name", 14 20 "display" : "Name", 15 21 "type" : "string", securis/src/main/webapp/js/licenses.js
.. .. @@ -724,7 +724,10 @@ 724 724 email: true 725 725 } 726 726 $scope.maxlength = { 727 + activation_code: 36,727 728 code: 50, 729 + full_name: 100,730 + email: 100,728 731 request_data: 500, 729 732 comments: 1024 730 733 } .. .. @@ -787,7 +790,8 @@ 787 790 $scope.isNew = true; 788 791 $scope.showForm = true; 789 792 $scope.license = { 790 - pack_id: $scope.currentPack.id793 + pack_id: $scope.currentPack.id,794 + activation_code: $scope.createUUID()791 795 } 792 796 Packs.nextliccode($scope.currentPack.id, function(data) { 793 797 console.log('New code: ' + data); .. .. @@ -797,12 +801,26 @@ 797 801 $('#licenseForm * #email').focus(); 798 802 }, 0); 799 803 } 804 + $scope.createUUID = function () {805 + // http://www.ietf.org/rfc/rfc4122.txt806 + 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 0010812 + s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01813 + s[8] = s[13] = s[18] = s[23] = "-";800 814 815 + var uuid = s.join("");816 + return uuid;817 + }801 818 $scope.editLicense = function(selectedlicense) { 802 819 $scope.isNew = false; 803 820 $scope.showForm = true; 804 821 $scope.license = selectedlicense; 805 822 $scope.license.status_name = Licenses.getStatusName($scope.license.status); 823 + $scope.license.activation_code = $scope.license.activation_code || $scope.createUUID();806 824 807 825 setTimeout(function() { 808 826 $('#licenseForm * #code').focus(); securis/src/main/webapp/licenses.html
.. .. @@ -56,7 +56,7 @@ 56 56 ng-show="packForm.code.$invalid"> 57 57 <span class="glyphicon glyphicon-warning-sign"></span> <span 58 58 ng-show="packForm.code.$error.maxlength" 59 - ng-bind="maxlengthErrorMsg('Code', maxlength.code)"></span> <span59 + ng-bind="maxLengthErrorMsg('Code', maxlength.code)"></span> <span60 60 ng-show="packForm.code.$error.required" 61 61 ng-bind="mandatoryFieldErrorMsg('Code')"></span> 62 62 </div> .. .. @@ -103,7 +103,7 @@ 103 103 ng-show="packForm.num_licenses.$invalid"> 104 104 <span class="glyphicon glyphicon-warning-sign"></span> <span 105 105 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>107 107 <span ng-show="packForm.num_licenses.$error.required" 108 108 ng-bind="mandatoryFieldErrorMsg('Num. Licenses')"></span> 109 109 </div> .. .. @@ -190,7 +190,7 @@ 190 190 i18n>Period for renew (days)</label> 191 191 <div class="col-md-8"> 192 192 <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"194 194 ng-required="true" /> 195 195 <div class="alert inline-alert alert-warning" 196 196 ng-show="packForm.renew_valid_period.$invalid"> .. .. @@ -215,7 +215,7 @@ 215 215 ng-show="packForm.comments.$invalid"> 216 216 <span class="glyphicon glyphicon-warning-sign"></span> <span 217 217 ng-show="packForm.comments.$error.maxlength" 218 - ng-bind="maxlengthErrorMsg('Comments', maxlength.comments)"></span>218 + ng-bind="maxLengthErrorMsg('Comments', maxlength.comments)"></span>219 219 <span ng-show="packForm.comments.$error.required" 220 220 ng-bind="mandatoryFieldErrorMsg('comments')"></span> 221 221 </div> .. .. @@ -415,9 +415,25 @@ 415 415 ng-show="licenseForm.code.$invalid"> 416 416 <span class="glyphicon glyphicon-warning-sign"></span> <span 417 417 ng-show="licenseForm.code.$error.maxlength" 418 - ng-bind="maxlengthErrorMsg('Code', maxlength.code)"></span> <span418 + ng-bind="maxLengthErrorMsg('Code', maxlength.code)"></span> <span419 419 ng-show="licenseForm.code.$error.required" 420 420 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" readonly429 + 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> <span433 + ng-show="licenseForm.activation_code.$error.maxlength"434 + ng-bind="maxLengthErrorMsg('Activation code', maxlength.activation_code)"></span> <span435 + ng-show="licenseForm.activation_code.$error.required"436 + ng-bind="mandatoryFieldErrorMsg('Activation code')"></span>421 437 </div> 422 438 </div> 423 439 </div> .. .. @@ -442,12 +458,12 @@ 442 458 <div class="col-md-8"> 443 459 <input type="string" id="full_name" name="full_name" 444 460 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}}" />446 462 <div class="alert inline-alert alert-warning" 447 463 ng-show="licenseForm.full_name.$invalid"> 448 464 <span class="glyphicon glyphicon-warning-sign"></span> <span 449 465 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>451 467 <span ng-show="licenseForm.full_name.$error.required" 452 468 ng-bind="mandatoryFieldErrorMsg('User full name')"></span> 453 469 </div> .. .. @@ -460,14 +476,14 @@ 460 476 <div class="col-md-8"> 461 477 <input type="email" id="email" name="email" placeholder="" 462 478 class="form-control" ng-model="license.email" 463 - ng-required="mandatory.email" />479 + ng-required="mandatory.email" ng-maxlength="{{maxlength.email}}" />464 480 <div class="alert inline-alert alert-warning" 465 481 ng-show="licenseForm.email.$invalid"> 466 482 <span class="glyphicon glyphicon-warning-sign"></span> <span 467 483 ng-show="licenseForm.email.$error.email" 468 484 ng-bind="'Please, write a valid email address'"></span> <span 469 485 ng-show="licenseForm.email.$error.maxlength" 470 - ng-bind="maxlengthErrorMsg('User email', maxlength.email)"></span>486 + ng-bind="maxLengthErrorMsg('User email', maxlength.email)"></span>471 487 <span ng-show="licenseForm.email.$error.required" 472 488 ng-bind="mandatoryFieldErrorMsg('User email')"></span> 473 489 </div> .. .. @@ -490,7 +506,7 @@ 490 506 <span class="glyphicon glyphicon-warning-sign"> 491 507 <span 492 508 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>494 510 <span ng-show="licenseForm.request_data.$error.required" 495 511 ng-bind="mandatoryFieldErrorMsg('Request data')"></span> 496 512 </span> .. .. @@ -514,7 +530,7 @@ 514 530 ng-show="licenseForm.comments.$invalid"> 515 531 <span class="glyphicon glyphicon-warning-sign"></span> <span 516 532 ng-show="licenseForm.comments.$error.maxlength" 517 - ng-bind="maxlengthErrorMsg('Comments', maxlength.comments)"></span>533 + ng-bind="maxLengthErrorMsg('Comments', maxlength.comments)"></span>518 534 <span ng-show="licenseForm.comments.$error.required" 519 535 ng-bind="mandatoryFieldErrorMsg('comments')"></span> 520 536 </div>