From 1493d0f7be4ccf14631ba3e0b31cf63ca7fcf32c Mon Sep 17 00:00:00 2001
From: rsanchez <rsanchez@curisit.net>
Date: Tue, 02 Dec 2014 17:57:50 +0000
Subject: [PATCH] #396 fix - Many issues fixed: Block/Unblock commands, Upload request data, Send second email, ...
---
securis/src/main/java/net/curisit/securis/db/License.java | 10 ++
securis/src/main/webapp/licenses.html | 16 +----
securis/src/main/java/net/curisit/securis/db/LicenseStatus.java | 2
securis/src/main/java/net/curisit/securis/services/LicenseResource.java | 74 ++++++++++++++----------
securis/src/main/webapp/js/licenses.js | 22 +++++--
securis/src/main/java/net/curisit/securis/utils/EmailManager.java | 27 +++++----
6 files changed, 86 insertions(+), 65 deletions(-)
diff --git a/securis/src/main/java/net/curisit/securis/db/License.java b/securis/src/main/java/net/curisit/securis/db/License.java
index b8ce30f..ab7064c 100644
--- a/securis/src/main/java/net/curisit/securis/db/License.java
+++ b/securis/src/main/java/net/curisit/securis/db/License.java
@@ -115,6 +115,9 @@
@Column(name = "license_data")
@JsonProperty("license_data")
+ @JsonIgnore
+ // The license data is sent to user as a separate file, It doesn't need to
+ // be included as License attribute on browser
private String licenseData;
@Column(name = "creation_timestamp")
@@ -136,6 +139,7 @@
private String comments;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "license")
+ @JsonIgnore
private List<LicenseHistory> history;
public int getId() {
@@ -334,17 +338,19 @@
public static final int CANCEL = 6;
public static final int DELETE = 7;
public static final int BLOCK = 8;
+ public static final int UNBLOCK = 9;
}
public static class Status {
private static final Map<Integer, List<LicenseStatus>> transitions = Utils.createMap( //
Action.REQUEST, Arrays.asList(LicenseStatus.CREATED, LicenseStatus.REQUESTED), //
- Action.ACTIVATION, Arrays.asList(LicenseStatus.REQUESTED, LicenseStatus.PRE_ACTIVE, LicenseStatus.EXPIRED), //
+ Action.ACTIVATION, Arrays.asList(LicenseStatus.CREATED, LicenseStatus.REQUESTED, LicenseStatus.PRE_ACTIVE, LicenseStatus.EXPIRED), //
Action.SEND, Arrays.asList(LicenseStatus.ACTIVE, LicenseStatus.PRE_ACTIVE), //
Action.DOWNLOAD, Arrays.asList(LicenseStatus.ACTIVE, LicenseStatus.PRE_ACTIVE), //
Action.CANCEL, Arrays.asList(LicenseStatus.ACTIVE, LicenseStatus.PRE_ACTIVE, LicenseStatus.REQUESTED, LicenseStatus.EXPIRED), //
- Action.DELETE, Arrays.asList(LicenseStatus.CANCELLED, LicenseStatus.CREATED), //
+ Action.DELETE, Arrays.asList(LicenseStatus.CANCELLED, LicenseStatus.CREATED, LicenseStatus.BLOCKED), //
+ Action.UNBLOCK, Arrays.asList(LicenseStatus.BLOCKED), //
Action.BLOCK, Arrays.asList(LicenseStatus.CANCELLED) //
);
diff --git a/securis/src/main/java/net/curisit/securis/db/LicenseStatus.java b/securis/src/main/java/net/curisit/securis/db/LicenseStatus.java
index 0127145..df94ccb 100644
--- a/securis/src/main/java/net/curisit/securis/db/LicenseStatus.java
+++ b/securis/src/main/java/net/curisit/securis/db/LicenseStatus.java
@@ -12,7 +12,7 @@
* @author rob
*/
public enum LicenseStatus implements CodedEnum {
- CREATED("CR"), REQUESTED("RE"), ACTIVE("AC"), PRE_ACTIVE("PA"), EXPIRED("EX"), CANCELLED("CA");
+ CREATED("CR"), REQUESTED("RE"), ACTIVE("AC"), PRE_ACTIVE("PA"), EXPIRED("EX"), CANCELLED("CA"), BLOCKED("BL");
private final String code;
diff --git a/securis/src/main/java/net/curisit/securis/services/LicenseResource.java b/securis/src/main/java/net/curisit/securis/services/LicenseResource.java
index d3165b4..f829f34 100644
--- a/securis/src/main/java/net/curisit/securis/services/LicenseResource.java
+++ b/securis/src/main/java/net/curisit/securis/services/LicenseResource.java
@@ -55,7 +55,6 @@
import net.curisit.securis.utils.EmailManager;
import net.curisit.securis.utils.JsonUtils;
import net.curisit.securis.utils.LicUtils;
-import net.curisit.securis.utils.TokenHelper;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ObjectUtils;
@@ -77,9 +76,6 @@
public class LicenseResource {
private static final Logger LOG = LogManager.getLogger(LicenseResource.class);
-
- @Inject
- private TokenHelper tokenHelper;
@Inject
private EmailManager emailManager;
@@ -206,6 +202,11 @@
throw new SeCurisServiceException(Status.FORBIDDEN.getStatusCode(), "License with id " + licId
+ " can not be activated from the current license status");
}
+
+ if (lic.getPack().getNumAvailables() == 0) {
+ throw new SeCurisServiceException(Status.FORBIDDEN.getStatusCode(), "The pack has not available licenses");
+ }
+
validateRequestData(lic.getPack(), lic.getRequestData());
License existingLicense = License.findLicenseByRequestData(lic.getRequestData(), em);
@@ -250,11 +251,11 @@
Application app = lic.getPack().getLicenseType().getApplication();
File licFile = null;
if (lic.getLicenseData() == null) {
- throw new SeCurisServiceException(Status.NOT_FOUND.getStatusCode(), "There is no license file available");
+ throw new SeCurisServiceException(ErrorCodes.NOT_FOUND, "There is no license file available");
}
if (lic.getFullName() == null) {
- throw new SeCurisServiceException(Status.NOT_FOUND.getStatusCode(), "Please add an user name in license data to send it the license file");
+ throw new SeCurisServiceException(ErrorCodes.NOT_FOUND, "Please add an user name in license data to send it the license file");
}
User user = userHelper.getUser(bsc.getUserPrincipal().getName(), em);
@@ -276,7 +277,7 @@
}
// lic.setModificationTimestamp(new Date());
- em.merge(lic);
+ // em.merge(lic);
em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.SEND, "Email sent to: " + lic.getEmail()));
return Response.ok(lic).build();
}
@@ -384,19 +385,23 @@
.header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "There is already an active license for current request data")
.type(MediaType.APPLICATION_JSON).entity(existingLicense).build();
}
- SignedLicenseBean signedLicense = generateLicense(lic, em);
- // If user provide a request data the license status is passed
- // directly to ACTIVE
- lic.setStatus(LicenseStatus.ACTIVE);
- try {
- lic.setRequestData(JsonUtils.toJSON((RequestBean) signedLicense));
- if (BlockedRequest.isRequestBlocked(lic.getRequestData(), em)) {
- throw new SeCurisServiceException(ErrorCodes.BLOCKED_REQUEST_DATA, "Given request data is blocked and cannot be activated");
+
+ if (pack.getNumAvailables() > 0) {
+
+ SignedLicenseBean signedLicense = generateLicense(lic, em);
+ // If user provide a request data the license status is passed
+ // directly to ACTIVE
+ lic.setStatus(LicenseStatus.ACTIVE);
+ try {
+ lic.setRequestData(JsonUtils.toJSON(signedLicense, RequestBean.class));
+ if (BlockedRequest.isRequestBlocked(lic.getRequestData(), em)) {
+ throw new SeCurisServiceException(ErrorCodes.BLOCKED_REQUEST_DATA, "Given request data is blocked and cannot be activated");
+ }
+ lic.setLicenseData(JsonUtils.toJSON(signedLicense));
+ } catch (SeCurisException e) {
+ LOG.error("Error generating license JSON", e);
+ throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Error generating license JSON");
}
- lic.setLicenseData(JsonUtils.toJSON(signedLicense));
- } catch (SeCurisException e) {
- LOG.error("Error generating license JSON", e);
- throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Error generating license JSON");
}
} else {
lic.setStatus(LicenseStatus.CREATED);
@@ -493,14 +498,15 @@
if (lic.getRequestData() != null) {
SignedLicenseBean signedLicense = generateLicense(lic, em);
try {
- // Next line is necessary to normalize the String that
+ // Next 2 lines are necessary to normalize the String that
// contains
// the request.
- lic.setRequestData(JsonUtils.toJSON((RequestBean) signedLicense));
- if (BlockedRequest.isRequestBlocked(lic.getRequestData(), em)) {
+ currentLicense.setRequestData(JsonUtils.toJSON(signedLicense, RequestBean.class));
+ LOG.info("JSON generated for request: \n{}", currentLicense.getRequestData());
+ if (BlockedRequest.isRequestBlocked(currentLicense.getRequestData(), em)) {
throw new SeCurisServiceException(ErrorCodes.BLOCKED_REQUEST_DATA, "Given request data is blocked and cannot be used again");
}
- lic.setLicenseData(JsonUtils.toJSON(signedLicense));
+ currentLicense.setLicenseData(JsonUtils.toJSON(signedLicense));
} catch (SeCurisException e) {
LOG.error("Error generaing license JSON", e);
throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Error generaing license JSON");
@@ -534,18 +540,15 @@
LOG.error("License {} can not be deleted with status {}", lic.getCode(), lic.getStatus());
throw new SeCurisServiceException(ErrorCodes.WRONG_STATUS, "License can not be deleted in current status: " + lic.getStatus().name());
}
- if (lic.getStatus() == LicenseStatus.CANCELLED) {
+ if (lic.getStatus() == LicenseStatus.BLOCKED) {
// If license is removed and it's blocked then the blocked request
// should be removed, that is,
// the license deletion will unblock the request data
- TypedQuery<License> query = em.createNamedQuery("list-licenses-by-req-data", License.class);
- query.setParameter("hash", lic.getReqDataHash());
- List<License> list = query.getResultList();
- if (list == null || list.size() == 0) {
- BlockedRequest br = em.find(BlockedRequest.class, lic.getReqDataHash());
- if (br != null) {
- em.remove(br);
- }
+ BlockedRequest blockedReq = em.find(BlockedRequest.class, lic.getReqDataHash());
+ if (blockedReq != null) {
+ // This if is to avoid some race condition or if the request has
+ // been already removed manually
+ em.remove(blockedReq);
}
}
@@ -578,6 +581,9 @@
blockedReq.setRequestData(lic.getRequestData());
em.persist(blockedReq);
+ lic.setStatus(LicenseStatus.BLOCKED);
+ lic.setModificationTimestamp(new Date());
+ em.merge(lic);
em.persist(licenseHelper.createLicenseHistoryAction(lic, userHelper.getUser(bsc, em), LicenseHistory.Actions.BLOCK));
return Response.ok(Utils.createMap("success", true, "id", licId)).build();
@@ -598,6 +604,10 @@
if (BlockedRequest.isRequestBlocked(lic.getRequestData(), em)) {
BlockedRequest blockedReq = em.find(BlockedRequest.class, lic.getReqDataHash());
em.remove(blockedReq);
+
+ lic.setStatus(LicenseStatus.CANCELLED);
+ lic.setModificationTimestamp(new Date());
+ em.merge(lic);
em.persist(licenseHelper.createLicenseHistoryAction(lic, userHelper.getUser(bsc, em), LicenseHistory.Actions.UNBLOCK));
} else {
LOG.info("Request data for license {} is NOT blocked", licId);
diff --git a/securis/src/main/java/net/curisit/securis/utils/EmailManager.java b/securis/src/main/java/net/curisit/securis/utils/EmailManager.java
index e6b686a..faf2389 100644
--- a/securis/src/main/java/net/curisit/securis/utils/EmailManager.java
+++ b/securis/src/main/java/net/curisit/securis/utils/EmailManager.java
@@ -17,12 +17,15 @@
import javax.inject.Singleton;
import net.curisit.securis.SeCurisException;
+import net.curisit.securis.services.exception.SeCurisServiceException;
+import net.curisit.securis.services.exception.SeCurisServiceException.ErrorCodes;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
@@ -30,7 +33,6 @@
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.BasicCredentialsProvider;
-import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
@@ -49,7 +51,7 @@
private static final Logger LOG = LogManager.getLogger(EmailManager.class);
private final String serverUrl;
- private final CloseableHttpClient httpClient;
+ private final HttpClientBuilder httpClientBuilder;
/**
*
@@ -61,11 +63,11 @@
throw new SeCurisException("Please, add '" + Config.KEYS.MAILGUN_DOMAIN + "' parameter to config file");
}
serverUrl = String.format("https://api.mailgun.net/v2/%s/messages", domain);
- httpClient = createHttpClient();
+ httpClientBuilder = createHttpClient();
}
- private CloseableHttpClient createHttpClient() throws SeCurisException {
+ private HttpClientBuilder createHttpClient() throws SeCurisException {
SSLContextBuilder builder = new SSLContextBuilder();
SSLConnectionSocketFactory sslsf = null;
try {
@@ -84,7 +86,7 @@
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("api", Config.get(Config.KEYS.MAILGUN_API_KEY));
provider.setCredentials(AuthScope.ANY, credentials);
- return HttpClientBuilder.create().setDefaultCredentialsProvider(provider).setSSLSocketFactory(sslsf).build();
+ return HttpClientBuilder.create().setDefaultCredentialsProvider(provider).setSSLSocketFactory(sslsf);
}
/**
@@ -98,7 +100,7 @@
* @throws SeCurisException
* @throws UnsupportedEncodingException
*/
- public void sendEmail(String subject, String body, String to, String cc, File file) throws SeCurisException, UnsupportedEncodingException {
+ public void sendEmail(String subject, String body, String to, String cc, File file) throws SeCurisServiceException, UnsupportedEncodingException {
HttpPost postRequest = new HttpPost(serverUrl);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
@@ -120,6 +122,7 @@
postRequest.setEntity(builder.build());
HttpResponse response;
+ HttpClient httpClient = httpClientBuilder.build();
try {
response = httpClient.execute(postRequest);
@@ -130,11 +133,11 @@
LOG.debug("Response mail read OK: {}", responseBean);
} else {
- throw new SeCurisException("Error sending email, response estatus: " + response.getStatusLine());
+ throw new SeCurisServiceException(ErrorCodes.UNEXPECTED_ERROR, "Error sending email, response estatus: " + response.getStatusLine());
}
} catch (IOException e) {
LOG.error("Error sending email", e);
- throw new SeCurisException("Error sending email");
+ throw new SeCurisServiceException(ErrorCodes.UNEXPECTED_ERROR, "Error sending email");
}
}
@@ -160,8 +163,8 @@
EmailManager.this.sendEmail(subject, body, to, cc, file);
callback.success();
} catch (UnsupportedEncodingException e) {
- callback.error(new SeCurisException("Error sending email", e));
- } catch (SeCurisException e) {
+ callback.error(new SeCurisServiceException("Error sending email: " + e));
+ } catch (SeCurisServiceException e) {
callback.error(e);
}
@@ -173,7 +176,7 @@
public static interface EmailCallback {
public void success();
- public void error(SeCurisException e);
+ public void error(SeCurisServiceException e);
}
public static void main(String[] args) throws SeCurisException, UnsupportedEncodingException {
@@ -190,7 +193,7 @@
}
@Override
- public void error(SeCurisException e) {
+ public void error(SeCurisServiceException e) {
LOG.error("Error: {} !!!", e);
}
});
diff --git a/securis/src/main/webapp/js/licenses.js b/securis/src/main/webapp/js/licenses.js
index 5e24c67..4d52d25 100644
--- a/securis/src/main/webapp/js/licenses.js
+++ b/securis/src/main/webapp/js/licenses.js
@@ -148,6 +148,7 @@
REQUESTED: 'RE',
PREACTIVE: 'PA',
EXPIRED: 'EX',
+ BLOCKED: 'BL',
CANCELLED: 'CA'
}
@@ -157,6 +158,7 @@
'PA': $L.get('Pre-active'),
'RE': $L.get('Requested'),
'EX': $L.get('Expired'),
+ 'BL': $L.get('Blocked'),
'CA': $L.get('Cancelled')
};
@@ -165,13 +167,14 @@
* we copy them for simplicity, this info won't change easily
*/
var LIC_ACTIONS_BY_STATUS = {
+ add_request: [LIC_STATUS.CREATED],
activate: [LIC_STATUS.CREATED, LIC_STATUS.REQUESTED, LIC_STATUS.PREACTIVE],
send: [LIC_STATUS.ACTIVE, LIC_STATUS.PREACTIVE],
download: [LIC_STATUS.ACTIVE, LIC_STATUS.PREACTIVE],
block: [LIC_STATUS.CANCELLED],
- unblock: [LIC_STATUS.CANCELLED],
+ unblock: [LIC_STATUS.BLOCKED],
cancel: [LIC_STATUS.REQUESTED, LIC_STATUS.EXPIRED, LIC_STATUS.PREACTIVE, LIC_STATUS.ACTIVE],
- 'delete': [LIC_STATUS.CREATED, LIC_STATUS.CANCELLED]
+ 'delete': [LIC_STATUS.CREATED, LIC_STATUS.CANCELLED, LIC_STATUS.BLOCKED]
}
var licenseResource = $resource('license/:licenseId/:action', {
@@ -217,6 +220,7 @@
'AC': '#329e5a',
'RE': '#2981d4',
'EX': '#ea7824',
+ 'BL': '#ff0000',
'CA': '#a21717'
};
@@ -236,9 +240,11 @@
toaster.pop('error', 'Licenses', $L.get("Error {0} license '{1}'. Reason: {2}", isNew ? $L.get("creating") : $L.get("updating"), license.code, $L.get(error.headers('X-SECURIS-ERROR-MSG'))), 5000);
if (error.headers('X-SECURIS-ERROR-CODE') === '1301') {
Packs.nextliccode(license.pack_id, function(data) {
- console.log('New code: ' + data);
- license.code = data;
- toaster.pop('info', 'Licenses', $L.get("New license code, {0}, has been generated, please try again", license.code), 5000);
+ if (license.code !== data) {
+ // Only if the new code is different we can think about an erro related with License CODE
+ license.code = data;
+ toaster.pop('info', 'Licenses', $L.get("New license code, {0}, has been generated, please try again", license.code), 5000);
+ }
});
}
}
@@ -348,7 +354,8 @@
scope.$apply();
}
- reader.readAsText(fileList[0]);
+ reader.readAsText(fileList[0]);
+ element.val('');
} else {
setter(scope.$parent, '');
scope.$apply();
@@ -383,6 +390,9 @@
return txt.substring(0, len) + '...';
}
$scope.currentPack = $store.get('currentPack');
+ setTimeout(function() {
+ $scope.$broadcast('pack_changed', $scope.currentPack);
+ }, 0);
}]);
diff --git a/securis/src/main/webapp/licenses.html b/securis/src/main/webapp/licenses.html
index ad76d33..f641478 100644
--- a/securis/src/main/webapp/licenses.html
+++ b/securis/src/main/webapp/licenses.html
@@ -445,7 +445,7 @@
</div>
</div>
</div>
- <div class="form-group" ng-if="isNew || !license.request_data">
+ <div class="form-group" >
<label class="col-md-3 control-label" for="request_data" i18n>Request
data</label>
<div class="col-md-7">
@@ -455,9 +455,9 @@
ng-maxlength="{{maxlength.request_data}}"></textarea>
<div class="alert inline-alert alert-warning"
ng-show="licenseForm.request_data.$invalid">
- Invalid ? {{licenseForm.request_data.$invalid}}
+ <!-- Invalid ? {{licenseForm.request_data.$invalid}}
Error ? {{licenseForm.request_data.$error | json}}
- Error ? {{licenseForm.request_data.$error.maxlength}}
+ Error ? {{licenseForm.request_data.$error.maxlength}} -->
<span class="glyphicon glyphicon-warning-sign">
<span
ng-show="licenseForm.request_data.$error.maxlength"
@@ -467,7 +467,7 @@
</span>
</div>
</div>
- <span class="btn btn-file btn-default btn-xs">
+ <span class="btn btn-file btn-default btn-xs" ng-if="isNew || Licenses.isActionAvailable('add_request', license)">
<span class="glyphicon glyphicon-folder-open"></span>
<input file-loader="license.request_data" type="file" />
</span>
@@ -489,14 +489,6 @@
<span ng-show="licenseForm.comments.$error.required"
ng-bind="mandatoryFieldErrorMsg('comments')"></span>
</div>
- </div>
- </div>
-
- <div class="form-group" ng-if="!isNew && license.request_data">
- <label class="col-md-3 control-label" i18n>Request data</label>
- <div class="col-md-8">
- <pre class="form-control-static"
- ng-bind="license.request_data | json"></pre>
</div>
</div>
--
Gitblit v1.3.2