From c4d513ca26fe80946a5d90264de5d8e13e4ea974 Mon Sep 17 00:00:00 2001
From: rsanchez <rsanchez@curisit.net>
Date: Thu, 23 Oct 2014 17:21:24 +0000
Subject: [PATCH] #2021 feature - Added pack actions in server and in frontend
---
securis/src/main/resources/META-INF/persistence.xml | 2
securis/src/main/java/net/curisit/securis/db/BlockedRequest.java | 3
securis/src/main/resources/static/js/licenses.js | 71 +++++++
securis/src/main/java/net/curisit/securis/db/Pack.java | 37 ++++
securis/src/main/java/net/curisit/securis/services/PackResource.java | 95 +++++++++
securis/src/main/java/net/curisit/securis/db/License.java | 64 ++++--
securis/src/main/java/net/curisit/securis/SeCurisServer.java | 59 +++---
securis/pom.xml | 10
securis/src/main/resources/static/licenses.html | 20 +-
securis/src/main/java/net/curisit/securis/db/Organization.java | 10
securis/src/main/java/net/curisit/securis/db/LicenseHistory.java | 1
securis/src/main/java/net/curisit/securis/services/LicenseResource.java | 115 ++++++++++--
securis/src/main/java/net/curisit/securis/ioc/SecurisModule.java | 16 -
securis/src/main/java/net/curisit/securis/utils/EmailManager.java | 2
securis/src/main/resources/db/schema.sql | 6
15 files changed, 379 insertions(+), 132 deletions(-)
diff --git a/securis/pom.xml b/securis/pom.xml
index 1f5b23b..d505b56 100644
--- a/securis/pom.xml
+++ b/securis/pom.xml
@@ -28,11 +28,6 @@
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
- <artifactId>resteasy-jackson-provider</artifactId>
- <version>3.0.9.Final</version>
- </dependency>
- <dependency>
- <groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-multipart-provider</artifactId>
<version>3.0.9.Final</version>
</dependency>
@@ -76,6 +71,11 @@
<artifactId>httpmime</artifactId>
<version>4.4-beta1</version>
</dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jackson2-provider</artifactId>
+ <version>3.0.9.Final</version>
+ </dependency>
</dependencies>
<build>
<plugins>
diff --git a/securis/src/main/java/net/curisit/securis/SeCurisServer.java b/securis/src/main/java/net/curisit/securis/SeCurisServer.java
index 8b28615..23db35f 100644
--- a/securis/src/main/java/net/curisit/securis/SeCurisServer.java
+++ b/securis/src/main/java/net/curisit/securis/SeCurisServer.java
@@ -52,7 +52,7 @@
private static final Logger CONSOLE = LogManager.getLogger("console");
private static final String PID_FILE = System.getProperty("user.home") + "/.SeCuris/securis-server.pid";
-
+
private static Server server;
private static Injector injector = null;
@@ -64,19 +64,15 @@
CONSOLE.info("Execute SeCuris server using:");
CONSOLE.info(" $ ./securis-server.sh {start|stop}");
}
-
- private void testMail() {
-
- }
-
+
public static void main(String[] args) throws Exception {
- String command;
+ String command;
if (args.length > 0) {
command = args[0].toLowerCase();
} else {
command = "start";
}
-
+
switch (command) {
case "start":
startServer();
@@ -90,7 +86,7 @@
System.exit(-1);
}
}
-
+
private static void stopServer() {
if (!new File(PID_FILE).exists()) {
CONSOLE.error("SeCuris server is NOT running or PID file is missing");
@@ -105,7 +101,7 @@
LOG.error("Error getting SeCuris server process PID from file: {}", PID_FILE);
}
}
-
+
private static void startServer() {
if (new File(PID_FILE).exists()) {
@@ -116,20 +112,22 @@
}
System.exit(-2);
}
-
+
SecurisModule securisModule = new SecurisModule();
JpaPersistModule jpaPersistModule = new JpaPersistModule("localdb");
Properties props = new Properties();
props.put("javax.persistence.jdbc.password", securisModule.getPassword());
props.put("javax.persistence.jdbc.url", securisModule.getUrl(securisModule.getAppDir()));
- //LOG.info("BD Url: {} {}", securisModule.getUrl(securisModule.getAppDir()), securisModule.getPassword());
+ // LOG.info("BD Url: {} {}",
+ // securisModule.getUrl(securisModule.getAppDir()),
+ // securisModule.getPassword());
jpaPersistModule.properties(props);
injector = Guice.createInjector(securisModule, new RequestsModule(), jpaPersistModule);
try {
startServer(injector.getInstance(Key.get(URI.class, Names.named("base-uri"))));
-
+
} catch (SeCurisException e) {
CONSOLE.error("Error launching the SeCuris server, {}", e);
}
@@ -153,14 +151,14 @@
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMaxThreads(50);
-
+
server = new Server();
-
+
ServerConnector httpConnector = new ServerConnector(server);
httpConnector.setPort(Config.getInt(Config.KEYS.SERVER_PORT, 9080));
httpConnector.setHost(Config.get(Config.KEYS.SERVER_HOSTNAME, "0.0.0.0"));
server.addConnector(httpConnector);
-
+
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
context.addEventListener(injector.getInstance(GuiceResteasyBootstrapServletContextListener.class));
@@ -191,33 +189,33 @@
contexts.setHandlers(new Handler[] {
staticResources, context
});
-
+
HttpConfiguration http_config = new HttpConfiguration();
http_config.setSecureScheme("https");
http_config.setSecurePort(Config.getInt(Config.KEYS.SERVER_SSL_PORT, 9443));
http_config.setOutputBufferSize(32768);
http_config.setSendServerVersion(true);
http_config.setSendDateHeader(false);
-
-
+
HttpConfiguration https_config = new HttpConfiguration(http_config);
https_config.addCustomizer(new SecureRequestCustomizer());
-
+
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath(Config.get(Config.KEYS.KEYSTORE_PATH));
sslContextFactory.setKeyStoreType(Config.get(Config.KEYS.KEYSTORE_TYPE, "JKS"));
sslContextFactory.setKeyStorePassword(Config.get(Config.KEYS.KEYSTORE_PASSWORD, ""));
- //sslContextFactory.setCertAlias("1");
-// sslContextFactory.setKeyManagerPassword("curist3c");
-// sslContextFactory.setTrustStorePath("/Users/rob/.ssh/keys/keystore");
-// sslContextFactory.setTrustStorePassword("curist3c");
+ // sslContextFactory.setCertAlias("1");
+ // sslContextFactory.setKeyManagerPassword("curist3c");
+ // sslContextFactory.setTrustStorePath("/Users/rob/.ssh/keys/keystore");
+ // sslContextFactory.setTrustStorePassword("curist3c");
sslContextFactory.checkKeyStore();
sslContextFactory.setNeedClientAuth(false);
-
- ServerConnector sslConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory,HttpVersion.HTTP_1_1.asString()), new HttpConnectionFactory(https_config));
+
+ ServerConnector sslConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
+ new HttpConnectionFactory(https_config));
sslConnector.setPort(Config.getInt(Config.KEYS.SERVER_SSL_PORT, 9443));
sslConnector.setHost(Config.get(Config.KEYS.SERVER_HOSTNAME, "0.0.0.0"));
- server.addConnector( sslConnector );
+ server.addConnector(sslConnector);
server.setHandler(context);
server.setStopAtShutdown(true);
@@ -233,9 +231,10 @@
}
}
-
- static class ServerStoppedListener extends AbstractLifeCycleListener {
- @Override public void lifeCycleStopped(LifeCycle event) {
+
+ static class ServerStoppedListener extends AbstractLifeCycleListener {
+ @Override
+ public void lifeCycleStopped(LifeCycle event) {
if (new File(PID_FILE).exists())
new File(PID_FILE).delete();
}
diff --git a/securis/src/main/java/net/curisit/securis/db/BlockedRequest.java b/securis/src/main/java/net/curisit/securis/db/BlockedRequest.java
index 51eac7e..b0b2826 100644
--- a/securis/src/main/java/net/curisit/securis/db/BlockedRequest.java
+++ b/securis/src/main/java/net/curisit/securis/db/BlockedRequest.java
@@ -89,8 +89,7 @@
}
public static String generateHash(String reqData) {
- String hash = reqData != null ? Utils.sha256(reqData) : null;
- return hash;
+ return (reqData != null ? Utils.sha256(reqData) : null);
}
public static boolean isRequestBlocked(String requestData, EntityManager em) {
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 e8ce296..037ccf5 100644
--- a/securis/src/main/java/net/curisit/securis/db/License.java
+++ b/securis/src/main/java/net/curisit/securis/db/License.java
@@ -16,11 +16,17 @@
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
+import javax.persistence.NonUniqueResultException;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.TypedQuery;
import net.curisit.integrity.commons.Utils;
+import net.curisit.securis.services.exception.SeCurisServiceException;
+import net.curisit.securis.services.exception.SeCurisServiceException.ErrorCodes;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -39,11 +45,13 @@
@JsonIgnoreProperties(ignoreUnknown = true)
@NamedQueries({
@NamedQuery(name = "list-licenses-by-pack", query = "SELECT l FROM License l where l.pack.id = :packId"),
+ @NamedQuery(name = "list-licenses-by-req-data", query = "SELECT l FROM License l where l.reqDataHash = :hash"),
@NamedQuery(name = "list-active-licenses-by-req-data", query = "SELECT l FROM License l where l.reqDataHash = :hash and l.status in ('AC', 'PA')")
})
public class License implements Serializable {
+ private static final long serialVersionUID = 2700310404904877227L;
- private static final long serialVersionUID = 1L;
+ private static final Logger LOG = LogManager.getLogger(License.class);
@Id
@GeneratedValue
@@ -63,8 +71,8 @@
@JsonIgnore
@ManyToOne
- @JoinColumn(name = "canceled_by")
- private User canceledBy;
+ @JoinColumn(name = "cancelled_by")
+ private User cancelledBy;
private LicenseStatus status;
@@ -78,6 +86,10 @@
@JsonProperty("request_data")
private String requestData;
+ /**
+ * request data hash is automatically set when we use
+ * {@link License#setRequestData(String)} method
+ */
@Column(name = "request_data_hash")
@JsonIgnore
private String reqDataHash;
@@ -158,18 +170,18 @@
}
}
- @JsonProperty("canceled_by_id")
- public String getCanceledById() {
- return canceledBy == null ? null : canceledBy.getUsername();
+ @JsonProperty("cancelled_by_id")
+ public String getCancelledById() {
+ return cancelledBy == null ? null : cancelledBy.getUsername();
}
- @JsonProperty("canceled_by_id")
- public void setCanceledById(String username) {
+ @JsonProperty("cancelled_by_id")
+ public void setCancelledById(String username) {
if (username == null) {
- canceledBy = null;
+ cancelledBy = null;
} else {
- canceledBy = new User();
- canceledBy.setUsername(username);
+ cancelledBy = new User();
+ cancelledBy.setUsername(username);
}
}
@@ -229,12 +241,12 @@
this.id = id;
}
- public User getCanceledBy() {
- return canceledBy;
+ public User getCancelledBy() {
+ return cancelledBy;
}
- public void setCanceledBy(User canceledBy) {
- this.canceledBy = canceledBy;
+ public void setCancelledBy(User cancelledBy) {
+ this.cancelledBy = cancelledBy;
}
public Date getLastAccessTimestamp() {
@@ -251,6 +263,7 @@
public void setRequestData(String requestData) {
this.requestData = requestData;
+ this.reqDataHash = BlockedRequest.generateHash(this.requestData);
}
public String getLicenseData() {
@@ -283,6 +296,10 @@
public void setExpirationDate(Date expirationDate) {
this.expirationDate = expirationDate;
+ }
+
+ public String getReqDataHash() {
+ return reqDataHash;
}
public static class Action {
@@ -323,17 +340,16 @@
}
}
- public License findLicenseByRequestData(String requestData, EntityManager em) {
+ public static License findLicenseByRequestData(String requestData, EntityManager em) throws SeCurisServiceException {
TypedQuery<License> query = em.createNamedQuery("list-active-licenses-by-req-data", License.class);
query.setParameter("hash", BlockedRequest.generateHash(requestData));
- return null;
+ try {
+ return query.getSingleResult();
+ } catch (NonUniqueResultException e) {
+ LOG.error("There are more than 1 active license for request data: {}\nHash: {}", requestData, BlockedRequest.generateHash(requestData));
+ throw new SeCurisServiceException(ErrorCodes.DUPLICATED_REQUEST_DATA, "There are more than 1 active license for request data hash: "
+ + BlockedRequest.generateHash(requestData));
+ }
}
- public String getReqDataHash() {
- return reqDataHash;
- }
-
- public void setReqDataHash(String reqDataHash) {
- this.reqDataHash = reqDataHash;
- }
}
diff --git a/securis/src/main/java/net/curisit/securis/db/LicenseHistory.java b/securis/src/main/java/net/curisit/securis/db/LicenseHistory.java
index 2c25dc5..3666c03 100644
--- a/securis/src/main/java/net/curisit/securis/db/LicenseHistory.java
+++ b/securis/src/main/java/net/curisit/securis/db/LicenseHistory.java
@@ -116,6 +116,7 @@
public static final String ACTIVATE = "activate";
public static final String CANCEL = "cancel";
public static final String BLOCK = "block";
+ public static final String UNBLOCK = "unblock";
public static final String DELETE = "delete";
}
}
diff --git a/securis/src/main/java/net/curisit/securis/db/Organization.java b/securis/src/main/java/net/curisit/securis/db/Organization.java
index 90e403d..56a42a9 100644
--- a/securis/src/main/java/net/curisit/securis/db/Organization.java
+++ b/securis/src/main/java/net/curisit/securis/db/Organization.java
@@ -167,10 +167,12 @@
@JsonProperty("users_ids")
public void setUsersIds(List<String> usersIds) {
users = new ArrayList<>();
- for (String userid : usersIds) {
- User u = new User();
- u.setUsername(userid);
- users.add(u);
+ if (usersIds != null) {
+ for (String userid : usersIds) {
+ User u = new User();
+ u.setUsername(userid);
+ users.add(u);
+ }
}
}
diff --git a/securis/src/main/java/net/curisit/securis/db/Pack.java b/securis/src/main/java/net/curisit/securis/db/Pack.java
index ff3a93e..65d8478 100644
--- a/securis/src/main/java/net/curisit/securis/db/Pack.java
+++ b/securis/src/main/java/net/curisit/securis/db/Pack.java
@@ -1,7 +1,10 @@
package net.curisit.securis.db;
import java.io.Serializable;
+import java.util.Arrays;
import java.util.Date;
+import java.util.List;
+import java.util.Map;
import java.util.Set;
import javax.persistence.CascadeType;
@@ -16,6 +19,8 @@
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
+
+import net.curisit.integrity.commons.Utils;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -321,4 +326,36 @@
return (id == null ? 0 : id.hashCode());
}
+
+ public static class Action {
+ public static final int CREATE = 1;
+ public static final int ACTIVATION = 2;
+ public static final int PUT_ONHOLD = 3;
+ public static final int CANCEL = 4;
+ public static final int DELETE = 5;
+ }
+
+ public static class Status {
+
+ private static final Map<Integer, List<Integer>> transitions = Utils.createMap( //
+ Action.ACTIVATION, Arrays.asList(PackStatus.CREATED, PackStatus.ON_HOLD, PackStatus.EXPIRED), //
+ Action.PUT_ONHOLD, Arrays.asList(PackStatus.ACTIVE), //
+ Action.CANCEL, Arrays.asList(PackStatus.ACTIVE, PackStatus.ON_HOLD, PackStatus.EXPIRED), //
+ Action.DELETE, Arrays.asList(PackStatus.CANCELLED, PackStatus.CREATED) //
+ );
+
+ /**
+ * It checks if a given action is valid for the License, passing the
+ * action and the current license status
+ *
+ * @param oldStatus
+ * @param newStatus
+ * @return
+ */
+ public static boolean isActionValid(Integer action, PackStatus currentStatus) {
+ List<Integer> validStatuses = transitions.get(currentStatus);
+
+ return validStatuses != null && validStatuses.contains(currentStatus);
+ }
+ }
}
diff --git a/securis/src/main/java/net/curisit/securis/ioc/SecurisModule.java b/securis/src/main/java/net/curisit/securis/ioc/SecurisModule.java
index 4e2abc6..737da7c 100644
--- a/securis/src/main/java/net/curisit/securis/ioc/SecurisModule.java
+++ b/securis/src/main/java/net/curisit/securis/ioc/SecurisModule.java
@@ -23,7 +23,7 @@
public class SecurisModule extends AbstractModule {
private static final int DEFAULT_PORT = 9997;
- private static final String PROPERTIES_FILE_NAME = "/server.properties";
+ private static final String PROPERTIES_FILE_NAME = "/securis-server.properties";
private static final Logger LOG = LogManager.getLogger(SecurisModule.class);
@@ -127,20 +127,6 @@
@Singleton
public String getHashLogo() {
return "1b42616809d4cd8ccf109e3c30d0ab25067f160b30b7354a08ddd563de0096ba";
- }
-
- @Named("license-req-file-name")
- @Provides
- @Singleton
- public String getLicenseReqFileName() {
- return "license.req";
- }
-
- @Named("license-file-name")
- @Provides
- @Singleton
- public String getLicenseFileName() {
- return "license.lic";
}
@Provides
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 93192c7..351500f 100644
--- a/securis/src/main/java/net/curisit/securis/services/LicenseResource.java
+++ b/securis/src/main/java/net/curisit/securis/services/LicenseResource.java
@@ -45,6 +45,7 @@
import net.curisit.securis.db.LicenseStatus;
import net.curisit.securis.db.Pack;
import net.curisit.securis.db.PackMetadata;
+import net.curisit.securis.db.PackStatus;
import net.curisit.securis.db.User;
import net.curisit.securis.security.BasicSecurityContext;
import net.curisit.securis.security.Securable;
@@ -56,6 +57,7 @@
import net.curisit.securis.utils.TokenHelper;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.ObjectUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -158,7 +160,7 @@
}
if (License.Status.isActionValid(License.Action.DOWNLOAD, lic.getStatus())) {
LOG.error("License with id {} is not active, so It can not downloaded", licId, bsc.getUserPrincipal());
- throw new SeCurisServiceException(Status.FORBIDDEN.getStatusCode(), "License is not active, so It can not be downloaded");
+ throw new SeCurisServiceException(ErrorCodes.WRONG_STATUS, "License is not active, so It can not be downloaded");
}
em.persist(createLicenseHistoryAction(lic, getUser(bsc, em), LicenseHistory.Actions.DOWNLOAD));
return Response
@@ -193,6 +195,15 @@
LOG.error("License with id {} can not be activated from current license status", licId);
throw new SeCurisServiceException(Status.FORBIDDEN.getStatusCode(), "License with id " + licId
+ " can not be activated from the current license status");
+ }
+ validateRequestData(lic.getPack(), lic.getRequestData());
+
+ License existingLicense = License.findLicenseByRequestData(lic.getRequestData(), em);
+ if (existingLicense != null) {
+ return Response.status(DefaultExceptionHandler.DEFAULT_APP_ERROR_STATUS_CODE)
+ .header(DefaultExceptionHandler.ERROR_CODE_MESSAGE_HEADER, ErrorCodes.DUPLICATED_REQUEST_DATA)
+ .header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "There is already an active license for current request data")
+ .type(MediaType.APPLICATION_JSON).entity(existingLicense).build();
}
lic.setStatus(LicenseStatus.ACTIVE);
@@ -291,10 +302,11 @@
}
lic.setStatus(LicenseStatus.CANCELLED);
+ lic.setCancelledById(bsc.getUserPrincipal().getName());
lic.setModificationTimestamp(new Date());
em.persist(lic);
- em.persist(createLicenseHistoryAction(lic, getUser(bsc, em), LicenseHistory.Actions.CANCEL, "Cancelation reason: " + reason));
+ em.persist(createLicenseHistoryAction(lic, getUser(bsc, em), LicenseHistory.Actions.CANCEL, "Cancellation reason: " + reason));
return Response.ok(lic).build();
}
@@ -321,11 +333,22 @@
LOG.error("License for pack with id {} can not be created by user {}", pack.getId(), bsc.getUserPrincipal());
throw new SeCurisServiceException(ErrorCodes.UNAUTHORIZED_ACCESS, "Unathorized action on pack license");
}
+ if (pack.getStatus() != PackStatus.ACTIVE) {
+ LOG.error("Current pack, {}, is not active so licenses cannot be created", pack.getId());
+ throw new SeCurisServiceException(ErrorCodes.WRONG_STATUS, "Current pack is not active so licenses cannot be created");
+ }
}
User createdBy = getUser(bsc.getUserPrincipal().getName(), em);
if (lic.getRequestData() != null) {
+ License existingLicense = License.findLicenseByRequestData(lic.getRequestData(), em);
+ if (existingLicense != null) {
+ return Response.status(DefaultExceptionHandler.DEFAULT_APP_ERROR_STATUS_CODE)
+ .header(DefaultExceptionHandler.ERROR_CODE_MESSAGE_HEADER, ErrorCodes.DUPLICATED_REQUEST_DATA)
+ .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
@@ -338,7 +361,7 @@
lic.setLicenseData(JsonUtils.toJSON(signedLicense));
} catch (SeCurisException e) {
LOG.error("Error generaing license JSON", e);
- throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Error generaing license JSON");
+ throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Error generating license JSON");
}
} else {
lic.setStatus(LicenseStatus.CREATED);
@@ -387,6 +410,9 @@
* @throws SeCurisServiceException
*/
private RequestBean validateRequestData(Pack pack, String requestData) throws SeCurisServiceException {
+ if (requestData == null) {
+ throw new SeCurisServiceException(ErrorCodes.INVALID_REQUEST_DATA, "Request data is empty");
+ }
RequestBean rb = null;
try {
rb = JsonUtils.json2object(requestData, RequestBean.class);
@@ -422,27 +448,32 @@
EntityManager em = emProvider.get();
License currentLicense = getCurrentLicense(licId, bsc, em);
-
- currentLicense.setCode(lic.getCode());
+ currentLicense.setComments(lic.getComments());
currentLicense.setFullName(lic.getFullName());
currentLicense.setEmail(lic.getEmail());
- if (lic.getRequestData() != null && currentLicense.getStatus() == LicenseStatus.CREATED) {
- SignedLicenseBean signedLicense = generateLicense(lic, em);
- lic.setStatus(LicenseStatus.ACTIVE);
- try {
- // Next line is necessary to normalize the String that contains
- // the request.
- 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 activate");
+
+ if (currentLicense.getStatus() == LicenseStatus.CREATED && !ObjectUtils.equals(currentLicense.getReqDataHash(), lic.getReqDataHash())) {
+ if (lic.getRequestData() != null) {
+ SignedLicenseBean signedLicense = generateLicense(lic, em);
+ try {
+ // Next line is necessary to normalize the String that
+ // contains
+ // the request.
+ 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 used again");
+ }
+ lic.setLicenseData(JsonUtils.toJSON(signedLicense));
+ } catch (SeCurisException e) {
+ LOG.error("Error generaing license JSON", e);
+ throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Error generaing license JSON");
}
- lic.setLicenseData(JsonUtils.toJSON(signedLicense));
- } catch (SeCurisException e) {
- LOG.error("Error generaing license JSON", e);
- throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Error generaing license JSON");
+ } else {
+ // This set method could pass a null value
+ currentLicense.setRequestData(null);
}
- currentLicense.setRequestData(lic.getRequestData());
}
+
currentLicense.setModificationTimestamp(new Date());
em.persist(currentLicense);
em.persist(createLicenseHistoryAction(lic, getUser(bsc, em), LicenseHistory.Actions.MODIFY));
@@ -462,17 +493,30 @@
EntityManager em = emProvider.get();
License lic = getCurrentLicense(licId, bsc, em);
- if (lic.getStatus() != LicenseStatus.CANCELLED || lic.getStatus() != LicenseStatus.CREATED) {
+ if (License.Status.isActionValid(License.Action.DELETE, lic.getStatus())) {
LOG.error("License {} can not be deleted with status {}", lic.getCode(), lic.getStatus());
- return Response.status(Status.FORBIDDEN)
- .header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "License can not be deleted in current status").build();
+ throw new SeCurisServiceException(ErrorCodes.WRONG_STATUS, "License can not be deleted in current status: " + lic.getStatus().name());
+ }
+ if (lic.getStatus() == LicenseStatus.CANCELLED) {
+ // 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);
+ }
+ }
}
em.remove(lic);
return Response.ok(Utils.createMap("success", true, "id", licId)).build();
}
- @DELETE
+ @POST
@Path("/{licId}/block")
@Transactional
@Securable
@@ -484,7 +528,7 @@
EntityManager em = emProvider.get();
License lic = getCurrentLicense(licId, bsc, em);
- if (lic.getStatus() != LicenseStatus.CANCELLED) {
+ if (!License.Status.isActionValid(License.Action.BLOCK, lic.getStatus())) {
LOG.error("License can only be blocked in CANCELLED status, current: {}", lic.getStatus().name());
throw new SeCurisServiceException(ErrorCodes.WRONG_STATUS, "License can only be blocked in CANCELLED status");
}
@@ -502,6 +546,29 @@
return Response.ok(Utils.createMap("success", true, "id", licId)).build();
}
+ @POST
+ @Path("/{licId}/unblock")
+ @Transactional
+ @Securable
+ @Produces({
+ MediaType.APPLICATION_JSON
+ })
+ public Response unblock(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
+ LOG.info("Unblocking license with id: {}", licId);
+ EntityManager em = emProvider.get();
+ License lic = getCurrentLicense(licId, bsc, em);
+
+ if (BlockedRequest.isRequestBlocked(lic.getRequestData(), em)) {
+ BlockedRequest blockedReq = em.find(BlockedRequest.class, lic.getReqDataHash());
+ em.remove(blockedReq);
+ em.persist(createLicenseHistoryAction(lic, getUser(bsc, em), LicenseHistory.Actions.UNBLOCK));
+ } else {
+ LOG.info("Request data for license {} is NOT blocked", licId);
+ }
+
+ return Response.ok(Utils.createMap("success", true, "id", licId)).build();
+ }
+
private License getCurrentLicense(Integer licId, BasicSecurityContext bsc, EntityManager em) throws SeCurisServiceException {
if (licId == null || "".equals(licId)) {
LOG.error("License ID is mandatory");
diff --git a/securis/src/main/java/net/curisit/securis/services/PackResource.java b/securis/src/main/java/net/curisit/securis/services/PackResource.java
index 9205945..e876cb5 100644
--- a/securis/src/main/java/net/curisit/securis/services/PackResource.java
+++ b/securis/src/main/java/net/curisit/securis/services/PackResource.java
@@ -30,9 +30,12 @@
import net.curisit.securis.db.Organization;
import net.curisit.securis.db.Pack;
import net.curisit.securis.db.PackMetadata;
+import net.curisit.securis.db.PackStatus;
import net.curisit.securis.db.User;
import net.curisit.securis.security.BasicSecurityContext;
import net.curisit.securis.security.Securable;
+import net.curisit.securis.services.exception.SeCurisServiceException;
+import net.curisit.securis.services.exception.SeCurisServiceException.ErrorCodes;
import net.curisit.securis.utils.TokenHelper;
import org.apache.logging.log4j.LogManager;
@@ -154,11 +157,12 @@
User user = em.find(User.class, bsc.getUserPrincipal().getName());
+ pack.setStatus(PackStatus.CREATED);
pack.setCreatedBy(user);
pack.setCreationTimestamp(new Date());
em.persist(pack);
- Set<PackMetadata> newMD = pack.getMetadata();
-
+ Set<PackMetadata> newMD = pack.getMetadata();
+
if (newMD != null) {
for (PackMetadata md : newMD) {
md.setPack(pack);
@@ -215,12 +219,13 @@
em.persist(currentPack);
- Set<PackMetadata> newMD = pack.getMetadata();
+ Set<PackMetadata> newMD = pack.getMetadata();
for (PackMetadata currentMd : currentPack.getMetadata()) {
- if (newMD == null || !newMD.contains(currentMd));
- em.remove(currentMd);
+ if (newMD == null || !newMD.contains(currentMd))
+ ;
+ em.remove(currentMd);
}
-
+
if (newMD != null) {
for (PackMetadata md : newMD) {
md.setPack(currentPack);
@@ -231,6 +236,84 @@
return Response.ok(pack).build();
}
+ @POST
+ @Path("/{packId}/activate")
+ @Transactional
+ @Securable
+ @RolesAllowed(BasicSecurityContext.ROL_ADMIN)
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces({
+ MediaType.APPLICATION_JSON
+ })
+ public Response activate(@PathParam("packId") Integer packId) throws SeCurisServiceException {
+ LOG.info("Activating pack with id: {}", packId);
+ EntityManager em = emProvider.get();
+
+ Pack currentPack = em.find(Pack.class, packId);
+
+ if (!Pack.Status.isActionValid(Pack.Action.ACTIVATION, currentPack.getStatus())) {
+ LOG.error("Pack with id {} cannot be activaed from status {}", packId, currentPack.getStatus().name());
+ throw new SeCurisServiceException(ErrorCodes.WRONG_STATUS, "Pack cannot be activated in status: " + currentPack.getStatus().name());
+ }
+
+ currentPack.setStatus(PackStatus.ACTIVE);
+ em.persist(currentPack);
+
+ return Response.ok(currentPack).build();
+ }
+
+ @POST
+ @Path("/{packId}/putonhold")
+ @Transactional
+ @Securable
+ @RolesAllowed(BasicSecurityContext.ROL_ADMIN)
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces({
+ MediaType.APPLICATION_JSON
+ })
+ public Response onhold(@PathParam("packId") Integer packId) throws SeCurisServiceException {
+ LOG.info("Putting On hold pack with id: {}", packId);
+ EntityManager em = emProvider.get();
+
+ Pack currentPack = em.find(Pack.class, packId);
+
+ if (!Pack.Status.isActionValid(Pack.Action.PUT_ONHOLD, currentPack.getStatus())) {
+ LOG.error("Pack with id {} cannot be put on hold from status {}", packId, currentPack.getStatus().name());
+ throw new SeCurisServiceException(ErrorCodes.WRONG_STATUS, "Pack cannot be put on hold in status: " + currentPack.getStatus().name());
+ }
+
+ currentPack.setStatus(PackStatus.ON_HOLD);
+ em.persist(currentPack);
+
+ return Response.ok(currentPack).build();
+ }
+
+ @POST
+ @Path("/{packId}/cancel")
+ @Transactional
+ @Securable
+ @RolesAllowed(BasicSecurityContext.ROL_ADMIN)
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces({
+ MediaType.APPLICATION_JSON
+ })
+ public Response cancel(@PathParam("packId") Integer packId) throws SeCurisServiceException {
+ LOG.info("Putting On hold pack with id: {}", packId);
+ EntityManager em = emProvider.get();
+
+ Pack currentPack = em.find(Pack.class, packId);
+
+ if (!Pack.Status.isActionValid(Pack.Action.CANCEL, currentPack.getStatus())) {
+ LOG.error("Pack with id {} cannot cancelled from status {}", packId, currentPack.getStatus().name());
+ throw new SeCurisServiceException(ErrorCodes.WRONG_STATUS, "Pack cannot be cancelled in status: " + currentPack.getStatus().name());
+ }
+
+ currentPack.setStatus(PackStatus.CANCELLED);
+ em.persist(currentPack);
+
+ return Response.ok(currentPack).build();
+ }
+
private void setPackOrganization(Pack currentPack, Integer orgId, EntityManager em) throws SeCurisException {
Organization org = null;
if (orgId != null) {
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 41c768e..d1d5f0e 100644
--- a/securis/src/main/java/net/curisit/securis/utils/EmailManager.java
+++ b/securis/src/main/java/net/curisit/securis/utils/EmailManager.java
@@ -55,7 +55,7 @@
*
* @throws SeCurisException
*/
- private EmailManager() throws SeCurisException {
+ public EmailManager() throws SeCurisException {
String domain = Params.get(Params.KEYS.MAILGUN_DOMAIN);
if (domain == null) {
throw new SeCurisException("Please, add '" + Params.KEYS.MAILGUN_DOMAIN + "' parameter to config file");
diff --git a/securis/src/main/resources/META-INF/persistence.xml b/securis/src/main/resources/META-INF/persistence.xml
index 2dedfc9..5b8e9ce 100644
--- a/securis/src/main/resources/META-INF/persistence.xml
+++ b/securis/src/main/resources/META-INF/persistence.xml
@@ -11,7 +11,7 @@
<properties>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
- <property name="javax.persistence.jdbc.url" value="jdbc:h2:/tmp/.CurisIntegrity/db/curissecuris" />
+<!-- <property name="javax.persistence.jdbc.url" value="jdbc:h2:~/.SeCuris/db/securis" /> -->
<property name="javax.persistence.jdbc.user" value="curis" />
<property name="javax.persistence.jdbc.password" value="53curi5" />
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
diff --git a/securis/src/main/resources/db/schema.sql b/securis/src/main/resources/db/schema.sql
index 1d4b2d9..0f448ea 100644
--- a/securis/src/main/resources/db/schema.sql
+++ b/securis/src/main/resources/db/schema.sql
@@ -8,7 +8,7 @@
drop table IF EXISTS user;
CREATE TABLE IF NOT EXISTS user (
username VARCHAR(45) NOT NULL ,
- password VARCHAR(100) NULL ,
+ password VARCHAR(256) NULL ,
roles INT NOT NULL default 0,
first_name VARCHAR(100) NULL ,
last_name VARCHAR(100) NULL ,
@@ -113,12 +113,12 @@
modification_timestamp DATETIME NULL ,
last_access_timestamp DATETIME NULL ,
expiration_date DATETIME NULL ,
- canceled_by varchar(45) NULL ,
+ cancelled_by varchar(45) NULL ,
created_by varchar(45) NULL ,
status VARCHAR(2) NOT NULL default 'CR',
PRIMARY KEY (id));
-create index if not exists lic_hash_req_idx on license(hash_request_data);
+create index if not exists lic_hash_req_idx on license(request_data_hash);
create index if not exists lic_pack_idx on license(pack_id);
drop table IF EXISTS license_history;
diff --git a/securis/src/main/resources/static/js/licenses.js b/securis/src/main/resources/static/js/licenses.js
index 09a33bd..a7d5761 100644
--- a/securis/src/main/resources/static/js/licenses.js
+++ b/securis/src/main/resources/static/js/licenses.js
@@ -101,11 +101,20 @@
'$store',
'$L',
function($scope, $http, $resource, toaster, Catalogs, $store, $L) {
- var packResource = $resource('/pack/:packId', {
- packId : '@id'
- });
+ var packResource = $resource('/pack/:packId/:action',
+ {
+ packId : '@id',
+ action : '@action'
+ },
+ {
+ activate: {
+ method: "POST",
+ params: {action: "activate"}
+ }
+ }
+ );
var PACK_STATUS = [
- {id: 'PE', label: $L.get('Pending')},
+ {id: 'CR', label: $L.get('Created')},
{id: 'AC', label: $L.get('Active')},
{id: 'OH', label: $L.get('On Hold')},
{id: 'EX', label: $L.get('Expired')},
@@ -165,13 +174,31 @@
_savePackData();
}
}
+
+ /**
+ * Execute an action over the pack, activation, onhold, cancellation
+ */
+ $scope.execute = function(action) {
+ console.log('Action: '+ action +' on pack: ' + $scope.pack.id);
+ var _success = function() {
+ if (!$scope.isNew) $scope.showForm = false;
+ $scope.packs = packResource.query();
+ toaster.pop('success', Catalogs.getName(), $L.get("Pack '{0}' {1} successfully", $scope.pack.code, $L.get("activated")));
+ }
+ var _error = function(error) {
+ console.log(error);
+ toaster.pop('error', Catalogs.getName(), $L.get("Error {0} pack '{1}'. Reason: {2}", $L.get("activating"), $scope.pack.code, $L.get(error.headers('X-SECURIS-ERROR'))));
+ }
+ packResource.activate({id: $scope.pack.id}, _success, _error);
+ }
+
$scope.newPack = function() {
$scope.isNew = true;
$scope.showForm = true;
$scope.pack = {
license_preactivation: true,
- status: 'PE',
+ status: 'CR',
num_licenses: 1,
license_type_id: null,
organization_id: null //!$scope.refs.organization_id || !$scope.refs.organization_id.length ? null : $scope.refs.organization_id[0].id
@@ -190,7 +217,13 @@
if (!(selectedPack.end_valid_date instanceof Date)) {
selectedPack.end_valid_date = new Date(selectedPack.end_valid_date);
}
+
$scope.pack = selectedPack;
+
+ //$scope.pack.organization_name = $scope.getLabelFromId('organization_id', $scope.pack.organization_id);
+ $scope.pack.license_type_name = $scope.getLabelFromId('license_type_id', $scope.pack.license_type_id);
+ $scope.pack.status_name = $scope.getLabelFromId('pack_status', $scope.pack.status);
+
setTimeout(function() {
$('#code').focus();
}, 0);
@@ -223,6 +256,16 @@
$scope.$parent.currentPack = pack;
$store.put('currentPack', pack);
$scope.$parent.$broadcast('pack_changed', pack);
+ }
+
+ $scope.getLabelFromId = function(field, myid) {
+ var label = null;
+ $scope.refs[field].forEach(function (elem) {
+ if (elem.id === myid) {
+ label = elem.label;
+ }
+ });
+ return label;
}
$scope.createMetadataRow = function() {
@@ -264,6 +307,7 @@
function($scope, $http, $resource, toaster, $store, $L) {
$scope.$on('pack_changed', function(evt, message) {
$scope.licenses = licenseResource.query({packId: $scope.currentPack.id});
+ $scope.creationAvailable = $scope.currentPack.status == 'AC';
if ($scope.showForm) {
if ($scope.isNew) {
$scope.license.pack_id = $scope.currentPack.id
@@ -296,7 +340,8 @@
}
});
$scope.mandatory = {
- code: true
+ code: true,
+ email: true
}
$scope.maxlength = {
code: 50,
@@ -356,6 +401,20 @@
});
return;
}
+ if (!$scope.creationAvailable) {
+ BootstrapDialog.show({
+ title: $L.get('Pack not active'),
+ type: BootstrapDialog.TYPE_WARNING,
+ message: $L.get('Current pack is not active, so licenses cannot be created'),
+ buttons: [{
+ label: 'OK',
+ action: function(dialog) {
+ dialog.close();
+ }
+ }]
+ });
+ return;
+ }
$scope.isNew = true;
$scope.showForm = true;
diff --git a/securis/src/main/resources/static/licenses.html b/securis/src/main/resources/static/licenses.html
index 2389f82..8f3367a 100644
--- a/securis/src/main/resources/static/licenses.html
+++ b/securis/src/main/resources/static/licenses.html
@@ -110,11 +110,7 @@
<div class="form-group" ng-if="!isNew">
<label class="col-md-3 control-label" for="status" i18n>Status</label>
<div class="col-md-8">
- <select class="form-control" id="status"
- ng-required="mandatory.status"
- ng-model="pack.status"
- ng-options="o.id as o.label for o in refs.pack_status">
- </select>
+ <p class="form-control-static" ng-bind="pack.status_name"></p>
<div class="alert inline-alert alert-warning"
ng-show="packForm.status.$invalid">
<span class="glyphicon glyphicon-warning-sign"></span> <span
@@ -128,13 +124,13 @@
<label class="col-md-3 control-label" for="license_type_id" i18n>License
type</label>
<div class="col-md-8">
- <select class="form-control" id="license_type_id"
+ <select ng-if="isNew" class="form-control" id="license_type_id"
ng-change="updateMetadata()"
ng-required="mandatory.license_type_id"
ng-model="pack.license_type_id"
ng-options="o.id as o.label for o in refs.license_type_id">
-
</select>
+ <p ng-if="!isNew" class="form-control-static" ng-bind="pack.license_type_name"></p>
<div class="alert inline-alert alert-warning"
ng-show="packForm.license_type_id.$invalid">
<span class="glyphicon glyphicon-warning-sign"></span> <span
@@ -147,10 +143,12 @@
<div class="form-group">
<label class="col-md-3 control-label" for="organization_id" i18n>Organization</label>
<div class="col-md-8">
- <select class="form-control" ng-required="field.mandatory"
+ <select ng-if="isNew" class="form-control"
ng-model="pack.organization_id"
+ ng-required="mandatory.organization_id"
ng-options="o.id as o.label for o in refs.organization_id">
</select>
+ <p ng-if="!isNew" class="form-control-static" ng-bind="pack.organization_name"></p>
<div class="alert inline-alert alert-warning"
ng-show="packForm.organization_id.$invalid">
<span class="glyphicon glyphicon-warning-sign"></span> <span
@@ -232,12 +230,12 @@
<button id="save" type="submit" class="btn btn-primary">
<span i18n class="glyphicon glyphicon-floppy-disk"></span> Save
</button>
- <button id="acc" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
+ <button ng-if="!isNew" id="acc" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span i18n class="glyphicon glyphicon-align-justify"></span> Actions
<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
- <li><a href="#">Activate</a></li>
+ <li><a href="#" ng-click="execute('activate')">Activate</a></li>
<li><a href="#">On hold</a></li>
<li class="divider"></li>
<li><a href="#">Invalidate</a></li>
@@ -545,7 +543,7 @@
<button id="save" type="submit" class="btn btn-primary">
<span i18n class="glyphicon glyphicon-floppy-disk"></span> Save
</button>
- <button id="acc" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
+ <button ng-if="!isNew" id="acc" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span i18n class="glyphicon glyphicon-align-justify"></span> Actions
<span class="caret"></span>
</button>
--
Gitblit v1.3.2