rsanchez
2014-12-02 1493d0f7be4ccf14631ba3e0b31cf63ca7fcf32c
#396 fix - Many issues fixed: Block/Unblock commands, Upload request
data, Send second email, ...
6 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/LicenseStatus.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/utils/EmailManager.java 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/java/net/curisit/securis/db/License.java
....@@ -115,6 +115,9 @@
115115
116116 @Column(name = "license_data")
117117 @JsonProperty("license_data")
118
+ @JsonIgnore
119
+ // The license data is sent to user as a separate file, It doesn't need to
120
+ // be included as License attribute on browser
118121 private String licenseData;
119122
120123 @Column(name = "creation_timestamp")
....@@ -136,6 +139,7 @@
136139 private String comments;
137140
138141 @OneToMany(fetch = FetchType.LAZY, mappedBy = "license")
142
+ @JsonIgnore
139143 private List<LicenseHistory> history;
140144
141145 public int getId() {
....@@ -334,17 +338,19 @@
334338 public static final int CANCEL = 6;
335339 public static final int DELETE = 7;
336340 public static final int BLOCK = 8;
341
+ public static final int UNBLOCK = 9;
337342 }
338343
339344 public static class Status {
340345
341346 private static final Map<Integer, List<LicenseStatus>> transitions = Utils.createMap( //
342347 Action.REQUEST, Arrays.asList(LicenseStatus.CREATED, LicenseStatus.REQUESTED), //
343
- Action.ACTIVATION, Arrays.asList(LicenseStatus.REQUESTED, LicenseStatus.PRE_ACTIVE, LicenseStatus.EXPIRED), //
348
+ Action.ACTIVATION, Arrays.asList(LicenseStatus.CREATED, LicenseStatus.REQUESTED, LicenseStatus.PRE_ACTIVE, LicenseStatus.EXPIRED), //
344349 Action.SEND, Arrays.asList(LicenseStatus.ACTIVE, LicenseStatus.PRE_ACTIVE), //
345350 Action.DOWNLOAD, Arrays.asList(LicenseStatus.ACTIVE, LicenseStatus.PRE_ACTIVE), //
346351 Action.CANCEL, Arrays.asList(LicenseStatus.ACTIVE, LicenseStatus.PRE_ACTIVE, LicenseStatus.REQUESTED, LicenseStatus.EXPIRED), //
347
- Action.DELETE, Arrays.asList(LicenseStatus.CANCELLED, LicenseStatus.CREATED), //
352
+ Action.DELETE, Arrays.asList(LicenseStatus.CANCELLED, LicenseStatus.CREATED, LicenseStatus.BLOCKED), //
353
+ Action.UNBLOCK, Arrays.asList(LicenseStatus.BLOCKED), //
348354 Action.BLOCK, Arrays.asList(LicenseStatus.CANCELLED) //
349355 );
350356
securis/src/main/java/net/curisit/securis/db/LicenseStatus.java
....@@ -12,7 +12,7 @@
1212 * @author rob
1313 */
1414 public enum LicenseStatus implements CodedEnum {
15
- CREATED("CR"), REQUESTED("RE"), ACTIVE("AC"), PRE_ACTIVE("PA"), EXPIRED("EX"), CANCELLED("CA");
15
+ CREATED("CR"), REQUESTED("RE"), ACTIVE("AC"), PRE_ACTIVE("PA"), EXPIRED("EX"), CANCELLED("CA"), BLOCKED("BL");
1616
1717 private final String code;
1818
securis/src/main/java/net/curisit/securis/services/LicenseResource.java
....@@ -55,7 +55,6 @@
5555 import net.curisit.securis.utils.EmailManager;
5656 import net.curisit.securis.utils.JsonUtils;
5757 import net.curisit.securis.utils.LicUtils;
58
-import net.curisit.securis.utils.TokenHelper;
5958
6059 import org.apache.commons.io.IOUtils;
6160 import org.apache.commons.lang3.ObjectUtils;
....@@ -77,9 +76,6 @@
7776 public class LicenseResource {
7877
7978 private static final Logger LOG = LogManager.getLogger(LicenseResource.class);
80
-
81
- @Inject
82
- private TokenHelper tokenHelper;
8379
8480 @Inject
8581 private EmailManager emailManager;
....@@ -206,6 +202,11 @@
206202 throw new SeCurisServiceException(Status.FORBIDDEN.getStatusCode(), "License with id " + licId
207203 + " can not be activated from the current license status");
208204 }
205
+
206
+ if (lic.getPack().getNumAvailables() == 0) {
207
+ throw new SeCurisServiceException(Status.FORBIDDEN.getStatusCode(), "The pack has not available licenses");
208
+ }
209
+
209210 validateRequestData(lic.getPack(), lic.getRequestData());
210211
211212 License existingLicense = License.findLicenseByRequestData(lic.getRequestData(), em);
....@@ -250,11 +251,11 @@
250251 Application app = lic.getPack().getLicenseType().getApplication();
251252 File licFile = null;
252253 if (lic.getLicenseData() == null) {
253
- throw new SeCurisServiceException(Status.NOT_FOUND.getStatusCode(), "There is no license file available");
254
+ throw new SeCurisServiceException(ErrorCodes.NOT_FOUND, "There is no license file available");
254255 }
255256
256257 if (lic.getFullName() == null) {
257
- throw new SeCurisServiceException(Status.NOT_FOUND.getStatusCode(), "Please add an user name in license data to send it the license file");
258
+ throw new SeCurisServiceException(ErrorCodes.NOT_FOUND, "Please add an user name in license data to send it the license file");
258259 }
259260
260261 User user = userHelper.getUser(bsc.getUserPrincipal().getName(), em);
....@@ -276,7 +277,7 @@
276277 }
277278
278279 // lic.setModificationTimestamp(new Date());
279
- em.merge(lic);
280
+ // em.merge(lic);
280281 em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.SEND, "Email sent to: " + lic.getEmail()));
281282 return Response.ok(lic).build();
282283 }
....@@ -384,19 +385,23 @@
384385 .header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "There is already an active license for current request data")
385386 .type(MediaType.APPLICATION_JSON).entity(existingLicense).build();
386387 }
387
- SignedLicenseBean signedLicense = generateLicense(lic, em);
388
- // If user provide a request data the license status is passed
389
- // directly to ACTIVE
390
- lic.setStatus(LicenseStatus.ACTIVE);
391
- try {
392
- lic.setRequestData(JsonUtils.toJSON((RequestBean) signedLicense));
393
- if (BlockedRequest.isRequestBlocked(lic.getRequestData(), em)) {
394
- throw new SeCurisServiceException(ErrorCodes.BLOCKED_REQUEST_DATA, "Given request data is blocked and cannot be activated");
388
+
389
+ if (pack.getNumAvailables() > 0) {
390
+
391
+ SignedLicenseBean signedLicense = generateLicense(lic, em);
392
+ // If user provide a request data the license status is passed
393
+ // directly to ACTIVE
394
+ lic.setStatus(LicenseStatus.ACTIVE);
395
+ try {
396
+ lic.setRequestData(JsonUtils.toJSON(signedLicense, RequestBean.class));
397
+ if (BlockedRequest.isRequestBlocked(lic.getRequestData(), em)) {
398
+ throw new SeCurisServiceException(ErrorCodes.BLOCKED_REQUEST_DATA, "Given request data is blocked and cannot be activated");
399
+ }
400
+ lic.setLicenseData(JsonUtils.toJSON(signedLicense));
401
+ } catch (SeCurisException e) {
402
+ LOG.error("Error generating license JSON", e);
403
+ throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Error generating license JSON");
395404 }
396
- lic.setLicenseData(JsonUtils.toJSON(signedLicense));
397
- } catch (SeCurisException e) {
398
- LOG.error("Error generating license JSON", e);
399
- throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Error generating license JSON");
400405 }
401406 } else {
402407 lic.setStatus(LicenseStatus.CREATED);
....@@ -493,14 +498,15 @@
493498 if (lic.getRequestData() != null) {
494499 SignedLicenseBean signedLicense = generateLicense(lic, em);
495500 try {
496
- // Next line is necessary to normalize the String that
501
+ // Next 2 lines are necessary to normalize the String that
497502 // contains
498503 // the request.
499
- lic.setRequestData(JsonUtils.toJSON((RequestBean) signedLicense));
500
- if (BlockedRequest.isRequestBlocked(lic.getRequestData(), em)) {
504
+ currentLicense.setRequestData(JsonUtils.toJSON(signedLicense, RequestBean.class));
505
+ LOG.info("JSON generated for request: \n{}", currentLicense.getRequestData());
506
+ if (BlockedRequest.isRequestBlocked(currentLicense.getRequestData(), em)) {
501507 throw new SeCurisServiceException(ErrorCodes.BLOCKED_REQUEST_DATA, "Given request data is blocked and cannot be used again");
502508 }
503
- lic.setLicenseData(JsonUtils.toJSON(signedLicense));
509
+ currentLicense.setLicenseData(JsonUtils.toJSON(signedLicense));
504510 } catch (SeCurisException e) {
505511 LOG.error("Error generaing license JSON", e);
506512 throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Error generaing license JSON");
....@@ -534,18 +540,15 @@
534540 LOG.error("License {} can not be deleted with status {}", lic.getCode(), lic.getStatus());
535541 throw new SeCurisServiceException(ErrorCodes.WRONG_STATUS, "License can not be deleted in current status: " + lic.getStatus().name());
536542 }
537
- if (lic.getStatus() == LicenseStatus.CANCELLED) {
543
+ if (lic.getStatus() == LicenseStatus.BLOCKED) {
538544 // If license is removed and it's blocked then the blocked request
539545 // should be removed, that is,
540546 // the license deletion will unblock the request data
541
- TypedQuery<License> query = em.createNamedQuery("list-licenses-by-req-data", License.class);
542
- query.setParameter("hash", lic.getReqDataHash());
543
- List<License> list = query.getResultList();
544
- if (list == null || list.size() == 0) {
545
- BlockedRequest br = em.find(BlockedRequest.class, lic.getReqDataHash());
546
- if (br != null) {
547
- em.remove(br);
548
- }
547
+ BlockedRequest blockedReq = em.find(BlockedRequest.class, lic.getReqDataHash());
548
+ if (blockedReq != null) {
549
+ // This if is to avoid some race condition or if the request has
550
+ // been already removed manually
551
+ em.remove(blockedReq);
549552 }
550553 }
551554
....@@ -578,6 +581,9 @@
578581 blockedReq.setRequestData(lic.getRequestData());
579582
580583 em.persist(blockedReq);
584
+ lic.setStatus(LicenseStatus.BLOCKED);
585
+ lic.setModificationTimestamp(new Date());
586
+ em.merge(lic);
581587
582588 em.persist(licenseHelper.createLicenseHistoryAction(lic, userHelper.getUser(bsc, em), LicenseHistory.Actions.BLOCK));
583589 return Response.ok(Utils.createMap("success", true, "id", licId)).build();
....@@ -598,6 +604,10 @@
598604 if (BlockedRequest.isRequestBlocked(lic.getRequestData(), em)) {
599605 BlockedRequest blockedReq = em.find(BlockedRequest.class, lic.getReqDataHash());
600606 em.remove(blockedReq);
607
+
608
+ lic.setStatus(LicenseStatus.CANCELLED);
609
+ lic.setModificationTimestamp(new Date());
610
+ em.merge(lic);
601611 em.persist(licenseHelper.createLicenseHistoryAction(lic, userHelper.getUser(bsc, em), LicenseHistory.Actions.UNBLOCK));
602612 } else {
603613 LOG.info("Request data for license {} is NOT blocked", licId);
securis/src/main/java/net/curisit/securis/utils/EmailManager.java
....@@ -17,12 +17,15 @@
1717 import javax.inject.Singleton;
1818
1919 import net.curisit.securis.SeCurisException;
20
+import net.curisit.securis.services.exception.SeCurisServiceException;
21
+import net.curisit.securis.services.exception.SeCurisServiceException.ErrorCodes;
2022
2123 import org.apache.commons.io.IOUtils;
2224 import org.apache.http.HttpResponse;
2325 import org.apache.http.auth.AuthScope;
2426 import org.apache.http.auth.UsernamePasswordCredentials;
2527 import org.apache.http.client.CredentialsProvider;
28
+import org.apache.http.client.HttpClient;
2629 import org.apache.http.client.methods.HttpPost;
2730 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
2831 import org.apache.http.entity.ContentType;
....@@ -30,7 +33,6 @@
3033 import org.apache.http.entity.mime.MultipartEntityBuilder;
3134 import org.apache.http.entity.mime.content.FileBody;
3235 import org.apache.http.impl.client.BasicCredentialsProvider;
33
-import org.apache.http.impl.client.CloseableHttpClient;
3436 import org.apache.http.impl.client.HttpClientBuilder;
3537 import org.apache.http.ssl.SSLContextBuilder;
3638 import org.apache.http.ssl.TrustStrategy;
....@@ -49,7 +51,7 @@
4951 private static final Logger LOG = LogManager.getLogger(EmailManager.class);
5052
5153 private final String serverUrl;
52
- private final CloseableHttpClient httpClient;
54
+ private final HttpClientBuilder httpClientBuilder;
5355
5456 /**
5557 *
....@@ -61,11 +63,11 @@
6163 throw new SeCurisException("Please, add '" + Config.KEYS.MAILGUN_DOMAIN + "' parameter to config file");
6264 }
6365 serverUrl = String.format("https://api.mailgun.net/v2/%s/messages", domain);
64
- httpClient = createHttpClient();
66
+ httpClientBuilder = createHttpClient();
6567
6668 }
6769
68
- private CloseableHttpClient createHttpClient() throws SeCurisException {
70
+ private HttpClientBuilder createHttpClient() throws SeCurisException {
6971 SSLContextBuilder builder = new SSLContextBuilder();
7072 SSLConnectionSocketFactory sslsf = null;
7173 try {
....@@ -84,7 +86,7 @@
8486 UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("api", Config.get(Config.KEYS.MAILGUN_API_KEY));
8587 provider.setCredentials(AuthScope.ANY, credentials);
8688
87
- return HttpClientBuilder.create().setDefaultCredentialsProvider(provider).setSSLSocketFactory(sslsf).build();
89
+ return HttpClientBuilder.create().setDefaultCredentialsProvider(provider).setSSLSocketFactory(sslsf);
8890 }
8991
9092 /**
....@@ -98,7 +100,7 @@
98100 * @throws SeCurisException
99101 * @throws UnsupportedEncodingException
100102 */
101
- public void sendEmail(String subject, String body, String to, String cc, File file) throws SeCurisException, UnsupportedEncodingException {
103
+ public void sendEmail(String subject, String body, String to, String cc, File file) throws SeCurisServiceException, UnsupportedEncodingException {
102104 HttpPost postRequest = new HttpPost(serverUrl);
103105
104106 MultipartEntityBuilder builder = MultipartEntityBuilder.create();
....@@ -120,6 +122,7 @@
120122
121123 postRequest.setEntity(builder.build());
122124 HttpResponse response;
125
+ HttpClient httpClient = httpClientBuilder.build();
123126 try {
124127 response = httpClient.execute(postRequest);
125128
....@@ -130,11 +133,11 @@
130133
131134 LOG.debug("Response mail read OK: {}", responseBean);
132135 } else {
133
- throw new SeCurisException("Error sending email, response estatus: " + response.getStatusLine());
136
+ throw new SeCurisServiceException(ErrorCodes.UNEXPECTED_ERROR, "Error sending email, response estatus: " + response.getStatusLine());
134137 }
135138 } catch (IOException e) {
136139 LOG.error("Error sending email", e);
137
- throw new SeCurisException("Error sending email");
140
+ throw new SeCurisServiceException(ErrorCodes.UNEXPECTED_ERROR, "Error sending email");
138141 }
139142 }
140143
....@@ -160,8 +163,8 @@
160163 EmailManager.this.sendEmail(subject, body, to, cc, file);
161164 callback.success();
162165 } catch (UnsupportedEncodingException e) {
163
- callback.error(new SeCurisException("Error sending email", e));
164
- } catch (SeCurisException e) {
166
+ callback.error(new SeCurisServiceException("Error sending email: " + e));
167
+ } catch (SeCurisServiceException e) {
165168 callback.error(e);
166169 }
167170
....@@ -173,7 +176,7 @@
173176 public static interface EmailCallback {
174177 public void success();
175178
176
- public void error(SeCurisException e);
179
+ public void error(SeCurisServiceException e);
177180 }
178181
179182 public static void main(String[] args) throws SeCurisException, UnsupportedEncodingException {
....@@ -190,7 +193,7 @@
190193 }
191194
192195 @Override
193
- public void error(SeCurisException e) {
196
+ public void error(SeCurisServiceException e) {
194197 LOG.error("Error: {} !!!", e);
195198 }
196199 });
securis/src/main/webapp/js/licenses.js
....@@ -148,6 +148,7 @@
148148 REQUESTED: 'RE',
149149 PREACTIVE: 'PA',
150150 EXPIRED: 'EX',
151
+ BLOCKED: 'BL',
151152 CANCELLED: 'CA'
152153 }
153154
....@@ -157,6 +158,7 @@
157158 'PA': $L.get('Pre-active'),
158159 'RE': $L.get('Requested'),
159160 'EX': $L.get('Expired'),
161
+ 'BL': $L.get('Blocked'),
160162 'CA': $L.get('Cancelled')
161163 };
162164
....@@ -165,13 +167,14 @@
165167 * we copy them for simplicity, this info won't change easily
166168 */
167169 var LIC_ACTIONS_BY_STATUS = {
170
+ add_request: [LIC_STATUS.CREATED],
168171 activate: [LIC_STATUS.CREATED, LIC_STATUS.REQUESTED, LIC_STATUS.PREACTIVE],
169172 send: [LIC_STATUS.ACTIVE, LIC_STATUS.PREACTIVE],
170173 download: [LIC_STATUS.ACTIVE, LIC_STATUS.PREACTIVE],
171174 block: [LIC_STATUS.CANCELLED],
172
- unblock: [LIC_STATUS.CANCELLED],
175
+ unblock: [LIC_STATUS.BLOCKED],
173176 cancel: [LIC_STATUS.REQUESTED, LIC_STATUS.EXPIRED, LIC_STATUS.PREACTIVE, LIC_STATUS.ACTIVE],
174
- 'delete': [LIC_STATUS.CREATED, LIC_STATUS.CANCELLED]
177
+ 'delete': [LIC_STATUS.CREATED, LIC_STATUS.CANCELLED, LIC_STATUS.BLOCKED]
175178 }
176179
177180 var licenseResource = $resource('license/:licenseId/:action', {
....@@ -217,6 +220,7 @@
217220 'AC': '#329e5a',
218221 'RE': '#2981d4',
219222 'EX': '#ea7824',
223
+ 'BL': '#ff0000',
220224 'CA': '#a21717'
221225 };
222226
....@@ -236,9 +240,11 @@
236240 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);
237241 if (error.headers('X-SECURIS-ERROR-CODE') === '1301') {
238242 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);
243
+ if (license.code !== data) {
244
+ // Only if the new code is different we can think about an erro related with License CODE
245
+ license.code = data;
246
+ toaster.pop('info', 'Licenses', $L.get("New license code, {0}, has been generated, please try again", license.code), 5000);
247
+ }
242248 });
243249 }
244250 }
....@@ -348,7 +354,8 @@
348354 scope.$apply();
349355 }
350356
351
- reader.readAsText(fileList[0]);
357
+ reader.readAsText(fileList[0]);
358
+ element.val('');
352359 } else {
353360 setter(scope.$parent, '');
354361 scope.$apply();
....@@ -383,6 +390,9 @@
383390 return txt.substring(0, len) + '...';
384391 }
385392 $scope.currentPack = $store.get('currentPack');
393
+ setTimeout(function() {
394
+ $scope.$broadcast('pack_changed', $scope.currentPack);
395
+ }, 0);
386396
387397 }]);
388398
securis/src/main/webapp/licenses.html
....@@ -445,7 +445,7 @@
445445 </div>
446446 </div>
447447 </div>
448
- <div class="form-group" ng-if="isNew || !license.request_data">
448
+ <div class="form-group" >
449449 <label class="col-md-3 control-label" for="request_data" i18n>Request
450450 data</label>
451451 <div class="col-md-7">
....@@ -455,9 +455,9 @@
455455 ng-maxlength="{{maxlength.request_data}}"></textarea>
456456 <div class="alert inline-alert alert-warning"
457457 ng-show="licenseForm.request_data.$invalid">
458
- Invalid ? {{licenseForm.request_data.$invalid}}
458
+ <!-- Invalid ? {{licenseForm.request_data.$invalid}}
459459 Error ? {{licenseForm.request_data.$error | json}}
460
- Error ? {{licenseForm.request_data.$error.maxlength}}
460
+ Error ? {{licenseForm.request_data.$error.maxlength}} -->
461461 <span class="glyphicon glyphicon-warning-sign">
462462 <span
463463 ng-show="licenseForm.request_data.$error.maxlength"
....@@ -467,7 +467,7 @@
467467 </span>
468468 </div>
469469 </div>
470
- <span class="btn btn-file btn-default btn-xs">
470
+ <span class="btn btn-file btn-default btn-xs" ng-if="isNew || Licenses.isActionAvailable('add_request', license)">
471471 <span class="glyphicon glyphicon-folder-open"></span>
472472 <input file-loader="license.request_data" type="file" />
473473 </span>
....@@ -489,14 +489,6 @@
489489 <span ng-show="licenseForm.comments.$error.required"
490490 ng-bind="mandatoryFieldErrorMsg('comments')"></span>
491491 </div>
492
- </div>
493
- </div>
494
-
495
- <div class="form-group" ng-if="!isNew && license.request_data">
496
- <label class="col-md-3 control-label" i18n>Request data</label>
497
- <div class="col-md-8">
498
- <pre class="form-control-static"
499
- ng-bind="license.request_data | json"></pre>
500492 </div>
501493 </div>
502494