From c3d9abdd3cd55a12d6509ade288648c2408baeb5 Mon Sep 17 00:00:00 2001
From: Roberto Sánchez <roberto.sanchez@curisit.net>
Date: Mon, 27 Jan 2014 11:18:59 +0000
Subject: [PATCH] #395 feature - Added expiration date to license and automatic preactivation flag

---
 securis/src/main/java/net/curisit/securis/db/License.java                                 |   11 +
 securis/src/main/java/net/curisit/securis/DefaultExceptionHandler.java                    |    7 +
 securis/src/main/resources/static/licenses.html                                           |    7 +
 securis/src/main/java/net/curisit/securis/services/LicenseResource.java                   |  271 ++++++++++++++++++--------------------------
 securis/src/main/resources/static/js/licenses.js                                          |    3 
 securis/src/main/java/net/curisit/securis/db/Pack.java                                    |   12 ++
 securis/src/main/java/net/curisit/securis/services/exception/SeCurisServiceException.java |   23 +++
 securis/src/main/resources/db/schema.sql                                                  |    2 
 securis/src/main/java/net/curisit/securis/services/PackResource.java                      |    1 
 9 files changed, 175 insertions(+), 162 deletions(-)

diff --git a/securis/src/main/java/net/curisit/securis/DefaultExceptionHandler.java b/securis/src/main/java/net/curisit/securis/DefaultExceptionHandler.java
index e966ff2..e8fc260 100644
--- a/securis/src/main/java/net/curisit/securis/DefaultExceptionHandler.java
+++ b/securis/src/main/java/net/curisit/securis/DefaultExceptionHandler.java
@@ -10,6 +10,8 @@
 import javax.ws.rs.ext.ExceptionMapper;
 import javax.ws.rs.ext.Provider;
 
+import net.curisit.securis.services.exception.SeCurisServiceException;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -37,6 +39,11 @@
 			return Response.status(Status.UNAUTHORIZED).header(ERROR_MESSAGE_HEADER, "Unathorized access to the application").type(MediaType.APPLICATION_JSON).build();
 		}
 
+		if (e instanceof SeCurisServiceException) {
+			log.warn("SeCurisServiceException accessing to {}, user: {}", request.getPathInfo(), bsc.getUserPrincipal());
+			return Response.status(Status.fromStatusCode(((SeCurisServiceException) e).getStatus())).header(ERROR_MESSAGE_HEADER, e.getMessage()).type(MediaType.APPLICATION_JSON).build();
+		}
+
 		log.error("Unexpected error accesing to '{}' by user: {}", request.getPathInfo(), bsc.getUserPrincipal());
 		log.error("Request sent from {}, with User-Agent: {}", request.getRemoteHost(), request.getHeader("User-Agent"));
 		log.error("Request url: " + request.getRequestURL(), e);
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 3bd60b0..5fc6ba7 100644
--- a/securis/src/main/java/net/curisit/securis/db/License.java
+++ b/securis/src/main/java/net/curisit/securis/db/License.java
@@ -83,6 +83,9 @@
 	@Column(name = "last_access_timestamp")
 	private Date lastAccessTimestamp;
 
+	@Column(name = "expiration_date")
+	private Date expirationDate;
+
 	private String comments;
 
 	@OneToMany(fetch = FetchType.LAZY, mappedBy = "license")
@@ -258,6 +261,14 @@
 		this.history = history;
 	}
 
+	public Date getExpirationDate() {
+		return expirationDate;
+	}
+
+	public void setExpirationDate(Date expirationDate) {
+		this.expirationDate = expirationDate;
+	}
+
 	public static class Status {
 		public static final int CREATED = 0;
 		public static final int SENT = 1;
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 608b7ed..7812fbc 100644
--- a/securis/src/main/java/net/curisit/securis/db/Pack.java
+++ b/securis/src/main/java/net/curisit/securis/db/Pack.java
@@ -73,6 +73,10 @@
 	@JsonProperty("num_licenses")
 	private int numLicenses;
 
+	@Column(name = "license_preactivation")
+	@JsonProperty("license_preactivation")
+	private boolean licensePreactivation;
+
 	public int getId() {
 		return id;
 	}
@@ -240,4 +244,12 @@
 		this.comments = comments;
 	}
 
+	public boolean isLicensePreactivation() {
+		return licensePreactivation;
+	}
+
+	public void setLicensePreactivation(boolean licensePreactivation) {
+		this.licensePreactivation = licensePreactivation;
+	}
+
 }
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 3e3898d..1580497 100644
--- a/securis/src/main/java/net/curisit/securis/services/LicenseResource.java
+++ b/securis/src/main/java/net/curisit/securis/services/LicenseResource.java
@@ -22,9 +22,7 @@
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 
-import net.curisit.integrity.commons.JsonUtils;
 import net.curisit.integrity.commons.Utils;
-import net.curisit.integrity.exception.CurisException;
 import net.curisit.securis.DefaultExceptionHandler;
 import net.curisit.securis.db.License;
 import net.curisit.securis.db.LicenseHistory;
@@ -32,6 +30,7 @@
 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.utils.TokenHelper;
 
 import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
@@ -92,69 +91,43 @@
 	/**
 	 * 
 	 * @return the server version in format majorVersion.minorVersion
+	 * @throws SeCurisServiceException
 	 */
 	@GET
 	@Path("/{licId}")
 	@Securable
 	@Produces(
 		{ MediaType.APPLICATION_JSON })
-	public Response get(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) {
+	public Response get(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
 		log.info("Getting organization data for id: {}: ", licId);
-		if (licId == null || licId.equals("")) {
-			log.error("License ID is mandatory");
-			return Response.status(Status.NOT_FOUND).build();
-		}
 
 		EntityManager em = emProvider.get();
-		License lic = em.find(License.class, licId);
-		if (lic == null) {
-			log.error("License with id {} not found in DB", licId);
-			return Response.status(Status.NOT_FOUND).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "License not found for ID: " + licId).build();
-		}
-		if (!bsc.isUserInRole(BasicSecurityContext.ROL_ADMIN)) {
-			if (!bsc.getOrganizationsIds().contains(lic.getPack().getOrganization().getId())) {
-				log.error("License with id {} is not accesible by user {}", licId, bsc.getUserPrincipal());
-				return Response.status(Status.UNAUTHORIZED).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "Unathorized access to license data").build();
-			}
-		}
+		License lic = getCurrentLicense(licId, bsc, em);
 		return Response.ok(lic).build();
 	}
 
 	/**
 	 * 
 	 * @return The license file, only of license is active
+	 * @throws SeCurisServiceException
 	 */
 	@GET
 	@Path("/{licId}/download")
 	@Securable
 	@Produces(
 		{ MediaType.APPLICATION_OCTET_STREAM })
-	public Response download(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) {
-		log.info("Getting license data for id: {}: ", licId);
-		if (licId == null || licId.equals("")) {
-			log.error("License ID is mandatory");
-			return Response.status(Status.NOT_FOUND).build();
-		}
+	public Response download(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
 
 		EntityManager em = emProvider.get();
-		License lic = em.find(License.class, licId);
-		if (lic == null) {
-			log.error("License with id {} not found in DB", licId);
-			return Response.status(Status.NOT_FOUND).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "License not found for ID: " + licId).build();
-		}
-		if (!bsc.isUserInRole(BasicSecurityContext.ROL_ADMIN)) {
-			if (!bsc.getOrganizationsIds().contains(lic.getPack().getOrganization().getId())) {
-				log.error("License with id {} is not accesible by user {}", licId, bsc.getUserPrincipal());
-				return Response.status(Status.UNAUTHORIZED).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "Unathorized access to license data").build();
-			}
-		}
+		License lic = getCurrentLicense(licId, bsc, em);
+
 		if (lic.getLicenseData() == null) {
 			log.error("License with id {} has not license file generated", licId, bsc.getUserPrincipal());
-			return Response.status(Status.FORBIDDEN).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "License has not contain data to generate license file").build();
+			throw new SeCurisServiceException(Status.FORBIDDEN.getStatusCode(), "License has not contain data to generate license file");
 		}
 		if (lic.getStatus() != License.Status.ACTIVE) {
 			log.error("License with id {} is not active, so It can not downloaded", licId, bsc.getUserPrincipal());
-			return Response.status(Status.FORBIDDEN).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "License is not active, so It can not be downloaded").build();
+			throw new SeCurisServiceException(Status.FORBIDDEN.getStatusCode(), "License is not active, so It can not be downloaded");
 		}
 		return Response.ok(lic.getLicenseData()).build();
 	}
@@ -167,42 +140,60 @@
 	@Consumes(MediaType.APPLICATION_JSON)
 	@Produces(
 		{ MediaType.APPLICATION_JSON })
-	public Response activate(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) {
-		log.info("Getting license data for id: {}: ", licId);
-		if (licId == null || licId.equals("")) {
-			log.error("License ID is mandatory");
-			return Response.status(Status.NOT_FOUND).build();
-		}
+	public Response activate(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
 
 		EntityManager em = emProvider.get();
-		License lic = em.find(License.class, licId);
-		if (lic == null) {
-			log.error("License with id {} not found in DB", licId);
-			return Response.status(Status.NOT_FOUND).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "License not found for ID: " + licId).build();
-		}
-		if (!bsc.isUserInRole(BasicSecurityContext.ROL_ADMIN)) {
-			if (!bsc.getOrganizationsIds().contains(lic.getPack().getOrganization().getId())) {
-				log.error("License with id {} is not accesible by user {}", licId, bsc.getUserPrincipal());
-				return Response.status(Status.UNAUTHORIZED).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "Unathorized access to license data").build();
-			}
-		}
+		License lic = getCurrentLicense(licId, bsc, em);
 
-		User user = null;
-		try {
-			user = getUser(bsc.getUserPrincipal().getName(), em);
-		} catch (CurisException ex) {
-			return Response.status(Status.NOT_FOUND).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "Current user not found in DB: " + bsc.getUserPrincipal()).build();
-		}
+		User user = getUser(bsc.getUserPrincipal().getName(), em);
 
 		lic.setStatus(License.Status.ACTIVE);
 		lic.setModificationTimestamp(new Date());
 		em.persist(lic);
-		LicenseHistory lh = new LicenseHistory();
-		lh.setLicense(lic);
-		lh.setUser(user);
-		lh.setTimestamp(new Date());
-		lh.setAction(LicenseHistory.Actions.ACTIVATE);
-		em.persist(lh);
+		em.persist(createLicenseHistoryAction(lic, user, LicenseHistory.Actions.ACTIVATE));
+		return Response.ok(lic).build();
+	}
+
+	@PUT
+	@POST
+	@Path("/{licId}/send")
+	@Securable
+	@Transactional
+	@Consumes(MediaType.APPLICATION_JSON)
+	@Produces(
+		{ MediaType.APPLICATION_JSON })
+	public Response send(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
+
+		EntityManager em = emProvider.get();
+		License lic = getCurrentLicense(licId, bsc, em);
+
+		User user = getUser(bsc.getUserPrincipal().getName(), em);
+		// TODO: Send mail with lic file
+		lic.setModificationTimestamp(new Date());
+		em.persist(lic);
+		em.persist(createLicenseHistoryAction(lic, user, LicenseHistory.Actions.SEND, "Email sent to: " + lic.getEmail()));
+		return Response.ok(lic).build();
+	}
+
+	@PUT
+	@POST
+	@Path("/{licId}/cancel")
+	@Securable
+	@Transactional
+	@Consumes(MediaType.APPLICATION_JSON)
+	@Produces(
+		{ MediaType.APPLICATION_JSON })
+	public Response cancel(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
+
+		EntityManager em = emProvider.get();
+		License lic = getCurrentLicense(licId, bsc, em);
+
+		User user = getUser(bsc.getUserPrincipal().getName(), em);
+
+		lic.setStatus(License.Status.CANCELED);
+		lic.setModificationTimestamp(new Date());
+		em.persist(lic);
+		em.persist(createLicenseHistoryAction(lic, user, LicenseHistory.Actions.CANCEL));
 		return Response.ok(lic).build();
 	}
 
@@ -213,7 +204,7 @@
 	@Produces(
 		{ MediaType.APPLICATION_JSON })
 	@Transactional
-	public Response create(License lic, @Context BasicSecurityContext bsc) {
+	public Response create(License lic, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
 		log.info("Creating new license from create()");
 		EntityManager em = emProvider.get();
 		Pack pack = null;
@@ -232,14 +223,7 @@
 			}
 		}
 
-		User createdBy = null;
-		try {
-			createdBy = getUser(bsc.getUserPrincipal().getName(), em);
-		} catch (CurisException ex) {
-			String createdByUsername = lic.getCreatedById();
-			log.error("License created by user with id {} not found in DB", createdByUsername);
-			return Response.status(Status.NOT_FOUND).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "License's created by user not found with ID: " + createdByUsername).build();
-		}
+		User createdBy = getUser(bsc.getUserPrincipal().getName(), em);
 
 		// ODO: Manage status if request data is set
 		lic.setCreatedBy(createdBy);
@@ -247,12 +231,7 @@
 		lic.setCreationTimestamp(new Date());
 		lic.setModificationTimestamp(lic.getCreationTimestamp());
 		em.persist(lic);
-		LicenseHistory lh = new LicenseHistory();
-		lh.setLicense(lic);
-		lh.setUser(createdBy);
-		lh.setTimestamp(new Date());
-		lh.setAction(LicenseHistory.Actions.CREATE);
-		em.persist(lh);
+		em.persist(createLicenseHistoryAction(lic, createdBy, LicenseHistory.Actions.CREATE));
 
 		return Response.ok(lic).build();
 	}
@@ -264,7 +243,7 @@
 	@Produces(
 		{ MediaType.APPLICATION_JSON })
 	@Transactional
-	public Response createWithFile(MultipartFormDataInput mpfdi, @Context BasicSecurityContext bsc) throws IOException {
+	public Response createWithFile(MultipartFormDataInput mpfdi, @Context BasicSecurityContext bsc) throws IOException, SeCurisServiceException {
 		License lic = new License();
 		lic.setCode(mpfdi.getFormDataPart("code", String.class, null));
 		lic.setRequestData(mpfdi.getFormDataPart("request_data", String.class, null));
@@ -272,25 +251,8 @@
 		lic.setFullName(mpfdi.getFormDataPart("full_name", String.class, null));
 		lic.setEmail(mpfdi.getFormDataPart("email", String.class, null));
 		lic.setComments(mpfdi.getFormDataPart("comments", String.class, null));
-		try {
-			log.info("File content: {}", lic.getRequestData());
-			log.info("License read from multipart: {}", JsonUtils.toJSON(lic));
-		} catch (CurisException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		}
-		return create(lic, bsc);
-	}
 
-	private User getUser(String username, EntityManager em) throws CurisException {
-		User user = null;
-		if (username != null) {
-			user = em.find(User.class, username);
-			if (user == null) {
-				throw new CurisException("User not found");
-			}
-		}
-		return user;
+		return create(lic, bsc);
 	}
 
 	@PUT
@@ -301,57 +263,13 @@
 	@Consumes(MediaType.APPLICATION_JSON)
 	@Produces(
 		{ MediaType.APPLICATION_JSON })
-	public Response modify(License lic, @PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) {
+	public Response modify(License lic, @PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
 		log.info("Modifying organization with id: {}", licId);
+
 		EntityManager em = emProvider.get();
 
-		// Pack pack = null;
-		// if (lic.getPackId() != null) {
-		// pack = em.find(Pack.class, lic.getPackId());
-		// if (pack == null) {
-		// log.error("License pack with id {} not found in DB", lic.getPackId());
-		// return Response.status(Status.NOT_FOUND).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "License's pack not found with ID: " + lic.getPackId()).build();
-		// } else {
-		// if (!bsc.isUserInRole(BasicSecurityContext.ROL_ADMIN)) {
-		// if (!bsc.getOrganizationsIds().contains(pack.getOrganization().getId())) {
-		// log.error("License for pack with id {} can not be modified by user {}", pack.getId(), bsc.getUserPrincipal());
-		// return Response.status(Status.UNAUTHORIZED).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "Unathorized action on pack license").build();
-		// }
-		// }
-		// }
-		// }
-		User createdBy = null;
-		try {
-			createdBy = getUser(lic.getCreatedById(), em);
-		} catch (CurisException ex) {
-			String createdByUsername = lic.getCreatedById();
-			log.error("License created by user with id {} not found in DB", createdByUsername);
-			return Response.status(Status.NOT_FOUND).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "License's created by user not found with ID: " + createdByUsername).build();
-		}
+		License currentLicense = getCurrentLicense(licId, bsc, em);
 
-		User canceledBy = null;
-		try {
-			canceledBy = getUser(lic.getCanceledById(), em);
-		} catch (CurisException ex) {
-			String canceledByUsername = lic.getCreatedById();
-			log.error("License canceled by user with id {} not found in DB", canceledByUsername);
-			return Response.status(Status.NOT_FOUND).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "License's canceled by user not found with ID: " + canceledByUsername).build();
-		}
-		License currentLicense = em.find(License.class, lic.getId());
-		if (currentLicense == null) {
-			log.error("License with id {} not found in DB", licId);
-			return Response.status(Status.NOT_FOUND).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "License not found for ID: " + licId).build();
-		}
-		if (!bsc.isUserInRole(BasicSecurityContext.ROL_ADMIN)) {
-			if (!bsc.getOrganizationsIds().contains(lic.getPack().getOrganization().getId())) {
-				log.error("License with id {} is not accesible by user {}", licId, bsc.getUserPrincipal());
-				return Response.status(Status.UNAUTHORIZED).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "Unathorized access to license data").build();
-			}
-		}
-		// TODO: set status based in current one and dates ? use custom actions ?
-		currentLicense.setCreatedBy(createdBy);
-		currentLicense.setCanceledBy(canceledBy);
-		// currentLicense.setPack(pack);
 		currentLicense.setCode(lic.getCode());
 		currentLicense.setFullName(lic.getFullName());
 		currentLicense.setEmail(lic.getEmail());
@@ -368,21 +286,10 @@
 	@Securable
 	@Produces(
 		{ MediaType.APPLICATION_JSON })
-	public Response delete(@PathParam("licId") String licId, @Context BasicSecurityContext bsc) {
+	public Response delete(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException {
 		log.info("Deleting license with id: {}", licId);
 		EntityManager em = emProvider.get();
-		License lic = em.find(License.class, Integer.parseInt(licId));
-		if (lic == null) {
-			log.error("License with id {} can not be deleted, It was not found in DB", licId);
-			return Response.status(Status.NOT_FOUND).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "License was not found, ID: " + licId).build();
-		}
-
-		if (!bsc.isUserInRole(BasicSecurityContext.ROL_ADMIN)) {
-			if (!bsc.getOrganizationsIds().contains(lic.getPack().getOrganization().getId())) {
-				log.error("License with id {} is not accesible by user {}", licId, bsc.getUserPrincipal());
-				return Response.status(Status.UNAUTHORIZED).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "Unathorized access to license data").build();
-			}
-		}
+		License lic = getCurrentLicense(licId, bsc, em);
 
 		if (lic.getStatus() != License.Status.CANCELED || lic.getStatus() != License.Status.CREATED) {
 			log.error("License {} can not be deleted with status {}", lic.getCode(), lic.getStatus());
@@ -393,4 +300,48 @@
 		return Response.ok(Utils.createMap("success", true, "id", licId)).build();
 	}
 
+	private License getCurrentLicense(Integer licId, BasicSecurityContext bsc, EntityManager em) throws SeCurisServiceException {
+		if (licId == null || licId.equals("")) {
+			log.error("License ID is mandatory");
+			throw new SeCurisServiceException(Status.NOT_FOUND.getStatusCode(), "Missing license ID");
+		}
+
+		License lic = em.find(License.class, licId);
+		if (lic == null) {
+			log.error("License with id {} not found in DB", licId);
+			throw new SeCurisServiceException(Status.NOT_FOUND.getStatusCode(), "License not found for ID: " + licId);
+		}
+		if (!bsc.isUserInRole(BasicSecurityContext.ROL_ADMIN)) {
+			if (!bsc.getOrganizationsIds().contains(lic.getPack().getOrganization().getId())) {
+				log.error("License with id {} is not accesible by user {}", licId, bsc.getUserPrincipal());
+				throw new SeCurisServiceException(Status.UNAUTHORIZED.getStatusCode(), "Unathorized access to license data");
+			}
+		}
+		return lic;
+	}
+
+	private User getUser(String username, EntityManager em) throws SeCurisServiceException {
+		User user = null;
+		if (username != null) {
+			user = em.find(User.class, username);
+			if (user == null) {
+				throw new SeCurisServiceException(Status.NOT_FOUND.getStatusCode(), "User not found with username: " + username);
+			}
+		}
+		return user;
+	}
+
+	private LicenseHistory createLicenseHistoryAction(License lic, User user, String action, String comments) {
+		LicenseHistory lh = new LicenseHistory();
+		lh.setLicense(lic);
+		lh.setUser(user);
+		lh.setTimestamp(new Date());
+		lh.setAction(action);
+		lh.setComments(comments);
+		return lh;
+	}
+
+	private LicenseHistory createLicenseHistoryAction(License lic, User user, String action) {
+		return createLicenseHistoryAction(lic, user, action, null);
+	}
 }
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 f22649e..7356ae9 100644
--- a/securis/src/main/java/net/curisit/securis/services/PackResource.java
+++ b/securis/src/main/java/net/curisit/securis/services/PackResource.java
@@ -192,6 +192,7 @@
 				return Response.status(Status.NOT_FOUND).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "Pack license type not found with ID: " + pack.getLicTypeId()).build();
 			}
 		}
+		currentPack.setLicensePreactivation(pack.isLicensePreactivation());
 		currentPack.setLicenseType(lt);
 		currentPack.setOrganization(org);
 		currentPack.setCode(pack.getCode());
diff --git a/securis/src/main/java/net/curisit/securis/services/exception/SeCurisServiceException.java b/securis/src/main/java/net/curisit/securis/services/exception/SeCurisServiceException.java
new file mode 100644
index 0000000..06f59fd
--- /dev/null
+++ b/securis/src/main/java/net/curisit/securis/services/exception/SeCurisServiceException.java
@@ -0,0 +1,23 @@
+package net.curisit.securis.services.exception;
+
+import net.curisit.integrity.exception.CurisException;
+
+public class SeCurisServiceException extends CurisException {
+
+	private int status = 0;
+
+	public SeCurisServiceException(int status, String msg) {
+		super(msg);
+		this.status = status;
+	}
+
+	public int getStatus() {
+		return status;
+	}
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+
+}
diff --git a/securis/src/main/resources/db/schema.sql b/securis/src/main/resources/db/schema.sql
index 4860b61..96fcb49 100644
--- a/securis/src/main/resources/db/schema.sql
+++ b/securis/src/main/resources/db/schema.sql
@@ -61,6 +61,7 @@
   comments VARCHAR(1024) NULL ,
   license_type_id INT NOT NULL,  
   organization_id INT NOT NULL,  
+  license_preactivation BOOLEAN NOT NULL DEFAULT true,  
   created_by varchar(45) NULL ,  
   creation_timestamp DATETIME NOT NULL ,  
   PRIMARY KEY (id));
@@ -78,6 +79,7 @@
   creation_timestamp DATETIME NOT NULL ,  
   modification_timestamp DATETIME NULL ,  
   last_access_timestamp DATETIME NULL ,  
+  expiration_date DATETIME NULL ,  
   canceled_by varchar(45) NULL ,  
   created_by varchar(45) NULL ,  
   status INT NOT NULL default 0,  
diff --git a/securis/src/main/resources/static/js/licenses.js b/securis/src/main/resources/static/js/licenses.js
index fb5dd85..1fe1bdb 100644
--- a/securis/src/main/resources/static/js/licenses.js
+++ b/securis/src/main/resources/static/js/licenses.js
@@ -118,7 +118,8 @@
 					$scope.isNew = true;
 					$scope.showForm = true;
 					$scope.pack = {
-					        num_licenses: 1,
+                            license_preactivation: true,
+                            num_licenses: 1,
                             license_type_id: !$scope.refs.license_type_id || !$scope.refs.license_type_id.length ? null : $scope.refs.license_type_id[0].id,
                             organization_id: !$scope.refs.organization_id || !$scope.refs.organization_id.length ? null : $scope.refs.organization_id[0].id
 					}
diff --git a/securis/src/main/resources/static/licenses.html b/securis/src/main/resources/static/licenses.html
index 6003901..50e97c6 100644
--- a/securis/src/main/resources/static/licenses.html
+++ b/securis/src/main/resources/static/licenses.html
@@ -89,6 +89,12 @@
 							</div>
 							</div>
 						</div>
+						<div class="form-group" >
+							<label class="col-md-3 control-label" for="license_preactivation" i18n>License preactivation</label>
+							<div class="col-md-8">
+									<input type="checkbox" class="form-control" ng-model="pack.license_preactivation" />
+							</div>
+						</div>
 
 
 						<div class="form-group" >
@@ -253,7 +259,6 @@
 							</div>
 							</div>
 						</div>
-{{request_data}}
 						<div class="form-group" ng-if="isNew || !license.request_data" >
 							<label class="col-md-3 control-label" for="request_data" i18n>Request data</label>
 							<div class="col-md-8">

--
Gitblit v1.3.2