From cbfe9207ad7c9bba96b39c550d250d12097fd06f Mon Sep 17 00:00:00 2001
From: Roberto Sánchez <roberto.sanchez@curisit.net>
Date: Thu, 23 Jan 2014 19:21:10 +0000
Subject: [PATCH] #395 feature - Implemented license section at 75%
---
securis/src/main/java/net/curisit/securis/db/License.java | 39 ++++
securis/src/main/resources/static/licenses.html | 196 ++++++++++++++++++++-
securis/src/main/java/net/curisit/securis/services/LicenseResource.java | 137 ++++++++++----
securis/src/main/resources/static/js/licenses.js | 128 +++++++++++++
securis/src/main/resources/static/js/main.js | 31 +-
securis/src/main/java/net/curisit/securis/services/PackResource.java | 8
securis/src/main/resources/static/css/securis.css | 1
7 files changed, 463 insertions(+), 77 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 010b933..f683161 100644
--- a/securis/src/main/java/net/curisit/securis/db/License.java
+++ b/securis/src/main/java/net/curisit/securis/db/License.java
@@ -15,6 +15,7 @@
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonIgnore;
+import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.annotate.JsonSerialize;
@@ -26,8 +27,9 @@
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
@Entity
@Table(name = "license")
+@JsonIgnoreProperties(ignoreUnknown = true)
@NamedQueries(
- { @NamedQuery(name = "list-licenses", query = "SELECT l FROM License l") })
+ { @NamedQuery(name = "list-licenses-by-pack", query = "SELECT l FROM License l where l.pack.id = :packId") })
public class License implements Serializable {
private static final long serialVersionUID = 1L;
@@ -56,9 +58,18 @@
private int status;
@Column(name = "full_name")
+ @JsonProperty("full_name")
private String fullName;
private String email;
+
+ @Column(name = "request_data")
+ @JsonProperty("request_data")
+ private String requestData;
+
+ @Column(name = "license_data")
+ @JsonProperty("license_data")
+ private String licenseData;
@Column(name = "creation_timestamp")
private Date creationTimestamp;
@@ -77,6 +88,8 @@
@Column(name = "last_access_timestamp")
private Date lastAccessTimestamp;
+
+ private String comments;
public int getId() {
return id;
@@ -240,6 +253,30 @@
this.lastAccessTimestamp = lastAccessTimestamp;
}
+ public String getRequestData() {
+ return requestData;
+ }
+
+ public void setRequestData(String requestData) {
+ this.requestData = requestData;
+ }
+
+ public String getLicenseData() {
+ return licenseData;
+ }
+
+ public void setLicenseData(String licenseData) {
+ this.licenseData = licenseData;
+ }
+
+ public String getComments() {
+ return comments;
+ }
+
+ public void setComments(String comments) {
+ this.comments = comments;
+ }
+
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/services/LicenseResource.java b/securis/src/main/java/net/curisit/securis/services/LicenseResource.java
index 0722d55..005ef97 100644
--- a/securis/src/main/java/net/curisit/securis/services/LicenseResource.java
+++ b/securis/src/main/java/net/curisit/securis/services/LicenseResource.java
@@ -7,16 +7,15 @@
import javax.inject.Provider;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
-import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
-import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@@ -28,6 +27,8 @@
import net.curisit.securis.db.License;
import net.curisit.securis.db.Pack;
import net.curisit.securis.db.User;
+import net.curisit.securis.security.BasicSecurityContext;
+import net.curisit.securis.security.Securable;
import net.curisit.securis.utils.TokenHelper;
import org.slf4j.Logger;
@@ -40,7 +41,7 @@
*
* @author roberto <roberto.sanchez@curisit.net>
*/
-@Path("/organization")
+@Path("/license")
public class LicenseResource {
private static final Logger log = LoggerFactory.getLogger(LicenseResource.class);
@@ -60,14 +61,25 @@
*/
@GET
@Path("/")
+ @Securable
@Produces(
{ MediaType.APPLICATION_JSON })
- public Response index() {
+ public Response index(@QueryParam("packId") Integer packId, @Context BasicSecurityContext bsc) {
log.info("Getting licenses list ");
EntityManager em = emProvider.get();
- TypedQuery<License> q = em.createNamedQuery("list-licenses-by-pack", License.class);
+ if (!bsc.isUserInRole(BasicSecurityContext.ROL_ADMIN)) {
+ Pack pack = em.find(Pack.class, packId);
+ if (pack == null)
+ return Response.ok().build();
+ if (!bsc.getOrganizationsIds().contains(pack.getOrganization().getId())) {
+ log.error("Pack with id {} not accesible by user {}", pack, bsc.getUserPrincipal());
+ return Response.status(Status.UNAUTHORIZED).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "Unathorized access to pack licenses").build();
+ }
+ }
+ TypedQuery<License> q = em.createNamedQuery("list-licenses-by-pack", License.class);
+ q.setParameter("packId", packId);
List<License> list = q.getResultList();
return Response.ok(list).build();
@@ -79,9 +91,10 @@
*/
@GET
@Path("/{licId}")
+ @Securable
@Produces(
{ MediaType.APPLICATION_JSON })
- public Response get(@PathParam("licId") String licId, @HeaderParam(TokenHelper.TOKEN_HEADER_PÀRAM) String token) {
+ public Response get(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) {
log.info("Getting organization data for id: {}: ", licId);
if (licId == null || licId.equals("")) {
log.error("License ID is mandatory");
@@ -89,21 +102,28 @@
}
EntityManager em = emProvider.get();
- License lt = em.find(License.class, Integer.parseInt(licId));
- if (lt == null) {
+ 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).build();
+ return Response.status(Status.NOT_FOUND).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "License not found for ID: " + licId).build();
}
- return Response.ok(lt).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();
+ }
+ }
+ return Response.ok(lic).build();
}
@POST
@Path("/")
@Consumes(MediaType.APPLICATION_JSON)
+ @Securable
@Produces(
{ MediaType.APPLICATION_JSON })
@Transactional
- public Response create(License lic, @HeaderParam(TokenHelper.TOKEN_HEADER_PÀRAM) String token) {
+ public Response create(License lic, @Context BasicSecurityContext bsc) {
log.info("Creating new organization");
EntityManager em = emProvider.get();
Pack pack = null;
@@ -112,6 +132,13 @@
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 created by user {}", pack.getId(), bsc.getUserPrincipal());
+ return Response.status(Status.UNAUTHORIZED).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "Unathorized action on pack license").build();
+ }
+ }
}
}
@@ -124,16 +151,11 @@
return Response.status(Status.NOT_FOUND).header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "License's created by user not found with ID: " + createdByUsername).build();
}
- try {
- User canceledBy = getUser(lic.getCanceledById(), em);
- lic.setCanceledBy(canceledBy);
- } 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();
- }
-
+ // ODO: Manage status if request data is set
+ lic.setCanceledBy(null);
+ lic.setStatus(License.Status.CREATED);
lic.setCreationTimestamp(new Date());
+ lic.setModificationTimestamp(lic.getCreationTimestamp());
em.persist(lic);
return Response.ok(lic).build();
@@ -153,22 +175,30 @@
@PUT
@POST
@Path("/{licId}")
+ @Securable
@Transactional
@Consumes(MediaType.APPLICATION_JSON)
@Produces(
{ MediaType.APPLICATION_JSON })
- public Response modify(License lic, @PathParam("licId") String licId, @HeaderParam(TokenHelper.TOKEN_HEADER_PÀRAM) String token) {
+ public Response modify(License lic, @PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) {
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();
- }
- }
+ // 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);
@@ -186,30 +216,59 @@
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());
+ currentLicense.setRequestData(lic.getRequestData());
+ currentLicense.setModificationTimestamp(new Date());
+ em.persist(currentLicense);
- lic.setCreatedBy(createdBy);
- lic.setCanceledBy(canceledBy);
- lic.setPack(pack);
- em.persist(lic);
-
- return Response.ok(lic).build();
+ return Response.ok(currentLicense).build();
}
@DELETE
@Path("/{licId}")
@Transactional
+ @Securable
@Produces(
{ MediaType.APPLICATION_JSON })
- public Response delete(@PathParam("licId") String licId, @Context HttpServletRequest request) {
+ public Response delete(@PathParam("licId") String licId, @Context BasicSecurityContext bsc) {
log.info("Deleting license with id: {}", licId);
EntityManager em = emProvider.get();
- License org = em.find(License.class, Integer.parseInt(licId));
- if (org == null) {
+ 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();
}
- em.remove(org);
+ 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();
+ }
+ }
+
+ if (lic.getStatus() != License.Status.CANCELED || lic.getStatus() != License.Status.CREATED) {
+ 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();
+ }
+
+ em.remove(lic);
return Response.ok(Utils.createMap("success", true, "id", licId)).build();
}
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 76adfa1..f22649e 100644
--- a/securis/src/main/java/net/curisit/securis/services/PackResource.java
+++ b/securis/src/main/java/net/curisit/securis/services/PackResource.java
@@ -101,7 +101,7 @@
@Securable
@Produces(
{ MediaType.APPLICATION_JSON })
- public Response get(@PathParam("packId") String packId, @Context BasicSecurityContext bsc) {
+ public Response get(@PathParam("packId") Integer packId, @Context BasicSecurityContext bsc) {
log.info("Getting pack data for id: {}: ", packId);
if (packId == null || packId.equals("")) {
log.error("Pack ID is mandatory");
@@ -109,7 +109,7 @@
}
EntityManager em = emProvider.get();
- Pack pack = em.find(Pack.class, Integer.parseInt(packId));
+ Pack pack = em.find(Pack.class, packId);
if (pack == null) {
log.error("Pack with id {} not found in DB", packId);
return Response.status(Status.NOT_FOUND).build();
@@ -171,10 +171,10 @@
@Consumes(MediaType.APPLICATION_JSON)
@Produces(
{ MediaType.APPLICATION_JSON })
- public Response modify(Pack pack, @PathParam("packId") String packId) {
+ public Response modify(Pack pack, @PathParam("packId") Integer packId) {
log.info("Modifying pack with id: {}", packId);
EntityManager em = emProvider.get();
- Pack currentPack = em.find(Pack.class, Integer.parseInt(packId));
+ Pack currentPack = em.find(Pack.class, packId);
Organization org = null;
if (pack.getOrgId() != null) {
diff --git a/securis/src/main/resources/static/css/securis.css b/securis/src/main/resources/static/css/securis.css
index 046cea7..8410ab5 100644
--- a/securis/src/main/resources/static/css/securis.css
+++ b/securis/src/main/resources/static/css/securis.css
@@ -15,6 +15,7 @@
}
}
+
a {
cursor: default !important;
}
diff --git a/securis/src/main/resources/static/js/licenses.js b/securis/src/main/resources/static/js/licenses.js
index 50afef0..67bf7b4 100644
--- a/securis/src/main/resources/static/js/licenses.js
+++ b/securis/src/main/resources/static/js/licenses.js
@@ -60,7 +60,7 @@
if (!txt || txt.length <= len) return txt;
return txt.substring(0, len) + '...';
}
- $scope.currentPackId = $store.get('currentPackId');
+ $scope.currentPack = $store.get('currentPack');
}]);
@@ -153,11 +153,131 @@
$scope.showForm = false;
}
- $scope.selectPack = function(packId) {
- $scope.$parent.currentPackId = packId;
- $store.put('currentPackId', packId);
+ $scope.selectPack = function(pack) {
+ $scope.$parent.currentPack = pack;
+ $store.put('currentPack', pack);
+ $scope.$parent.$broadcast('pack_changed', pack);
}
} ]);
+ app.controller('LicensesCtrl', [
+ '$scope',
+ '$http',
+ '$resource',
+ 'toaster',
+ '$store',
+ '$L',
+ function($scope, $http, $resource, toaster, $store, $L) {
+ $scope.$on('pack_changed', function(evt, message) {
+ $scope.licenses = licenseResource.query({packId: $scope.currentPack.id});
+ console.log('on pack_changed');
+ if ($scope.showForm) {
+ if ($scope.isNew) {
+ $scope.license.pack_id = $scope.currentPack.id
+ } else {
+ $scope.showForm = false;
+ }
+ }
+ })
+
+ var licenseResource = $resource('/license/:licenseId', {
+ licenseId : '@id'
+ });
+ $scope.mandatory = {
+ code: true
+ }
+ $scope.maxlength = {
+ code: 50,
+ comments: 1024
+ }
+ $scope.refs = {};
+
+ // Used to create the form with the appropriate data
+ $scope.isNew = undefined;
+
+ // Selected license from listing
+ // license is the edited license, in creation contains the data for the new license
+ $scope.license = null;
+ if ($scope.currentPack)
+ $scope.licenses = licenseResource.query({packId: $scope.currentPack.id});
+
+ $scope.save = function() {
+ var _success = function() {
+ if (!$scope.isNew) $scope.showForm = false;
+ $scope.licenses = licenseResource.query({packId: $scope.currentPack.id});
+ }
+ licenseResource.save($scope.license, _success)
+ }
+
+ $scope.newLicense = function() {
+ if (!$scope.currentPack) {
+ BootstrapDialog.show({
+ title: $L.get('New license'),
+ type: BootstrapDialog.TYPE_WARNING,
+ message: $L.get('Please, select a pack before to create a new license'),
+ buttons: [{
+ label: 'OK',
+ action: function(dialog) {
+ dialog.close();
+ }
+ }]
+ });
+ return;
+ }
+
+ $scope.isNew = true;
+ $scope.showForm = true;
+ $scope.license = {
+ pack_id: $scope.currentPack.id
+ }
+ setTimeout(function() {
+ $('#licenseForm * #code').focus();
+ }, 0);
+ }
+
+ $scope.editLicense = function(selectedlicense) {
+ $scope.isNew = false;
+ $scope.showForm = true;
+ $scope.license = selectedlicense;
+ setTimeout(function() {
+ $('#licenseForm * #code').focus();
+ }, 0);
+ }
+
+ $scope.deletelicense = function(selectedlicense) {
+ $scope.showForm = false;
+ BootstrapDialog.confirm($L.get("The license '{0}' will be deleted, are you sure?", selectedlicense.code), function(result){
+ if(result) {
+ var promise = licenseResource.remove({}, {id: selectedlicense.id}).$promise;
+ promise.then(function(data) {
+ $scope.selectlicense(null);
+ $scope.licenses = licenseResource.query({packId: $scope.currentPack.id});
+ toaster.pop('success', Catalogs.getName(), $L.get("License '{0}' deleted successfully", selectedlicense.code));
+ },function(error) {
+ console.log(error);
+ toaster.pop('error', Catalogs.getName(), $L.get("Error deleting license, reason: {0}. Details: {1}", $L.get(HTTP_ERRORS[error.status]), error.headers('X-SECURIS-ERROR')), 10000);
+ });
+ }
+ });
+ $scope.isNew = false;
+ }
+
+
+ $scope.cancel = function() {
+ $scope.showForm = false;
+ }
+
+ $scope.showStatus = function(lic) {
+
+ }
+ $scope.showStatusComplete = function(license) {
+
+ }
+ $scope.isActionVisible = function(actionMask, lic) {
+
+ }
+
+ } ]);
+
})();
diff --git a/securis/src/main/resources/static/js/main.js b/securis/src/main/resources/static/js/main.js
index 957e197..0bf562d 100644
--- a/securis/src/main/resources/static/js/main.js
+++ b/securis/src/main/resources/static/js/main.js
@@ -21,26 +21,27 @@
}
});
- m.factory('securisHttpInterceptor', function($q, $location, $store) {
+ m.factory('securisHttpInterceptor', function($q, $location, $store, toaster) {
var isUnauthorizedAccess = function(rejection) {
- console.log('rejection -----------------------');
- console.log(rejection);
return rejection.status === 401 /* Unauthorized */;
}
return {
'request': function(config) {
- var la = $store.get('last_access');
- var now = new Date().getTime();
- if (la !== null) {
- if (now > (la + 1800000)) { // Session timeout is 1/2 hour
- $store.clear();
- $location.path('/login');
- BootstrapDialog.alert('Session has expired');
- } else {
- console.log('Last access recent');
- }
- }
- $store.set('last_access', now);
+ var token = $store.get('token');
+ if (token) {
+ var la = $store.get('last_access');
+ var now = new Date().getTime();
+ if (la !== null) {
+ if (now > (la + 1800000)) { // Session timeout is 1/2 hour
+ $store.clear();
+ $location.path('/login');
+ toaster.pop('warning', 'Session has expired', null, 4000);
+ } else {
+ console.log('Last access recent');
+ }
+ }
+ $store.set('last_access', now);
+ }
return config || $q.when(config);
},
'responseError': function(rejection) {
diff --git a/securis/src/main/resources/static/licenses.html b/securis/src/main/resources/static/licenses.html
index 63b5b2a..79de58e 100644
--- a/securis/src/main/resources/static/licenses.html
+++ b/securis/src/main/resources/static/licenses.html
@@ -145,7 +145,7 @@
</tr>
</thead>
<tbody>
- <tr ng-repeat="p in packs | filter:searchText" ng-dblclick="editPack(p)" ng-class="{success: currentPackId === p.id}" ng-click="selectPack(p.id)">
+ <tr ng-repeat="p in packs | filter:searchText" ng-dblclick="editPack(p)" ng-class="{success: currentPack.id === p.id}" ng-click="selectPack(p)">
<td style="white-space: nowrap;" ng-bind="p.code"></td>
<td ng-bind="ellipsis(p.organization_name, 20)" title="{{pack.organization_name}}" ></td>
<td ng-bind="p.application_name"></td>
@@ -164,8 +164,8 @@
</div>
- <div id="licenses_section" class="col-md-6" >
- <nav class="navbar navbar-default navbar-static-top" ng-disabled="currentPackId === null">
+ <div id="licenses_section" class="col-md-6" ng-controller="LicensesCtrl">
+ <nav class="navbar navbar-default navbar-static-top" ng-disabled="!currentPack">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header success">
<a class="navbar-brand" i18n>Licenses</a>
@@ -175,9 +175,9 @@
<div class="collapse navbar-collapse"
id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
- <li><a i18n ng-click="editNewLicense()"><span class="glyphicon glyphicon-plus"></span>
+ <li><a i18n ng-click="newLicense()"><span class="glyphicon glyphicon-plus"></span>
New</a></li>
- <li><a i18n ng-click="cancelEditionLicense()"> <span
+ <li><a i18n ng-click="cancel()"> <span
class="glyphicon glyphicon-ban-circle"></span> Cancel
</a></li>
</ul>
@@ -191,12 +191,179 @@
</div>
</nav>
- <div ng-if="currentPackId === null" class="well well-lg">
+ <div ng-if="!currentPack" class="well well-lg">
<h4 i18n>No pack selected</h4>
<p i18n>Please, select a pack to manage its licenses</p>
</div>
- <div class="panel panel-default" ng-if="currentPackId !== null">
+ <div ng-if="currentPack" class="panel panel-default animate-show ng-hide" ng-show="showForm">
+ <form role="form" class="form-horizontal " name="licenseForm" id="licenseForm" ng-submit="save()" >
+ <div class="form-group" ng-if="!isNew">
+ <label class="col-md-3 control-label" >ID</label>
+ <div class="col-md-8">
+ <p class="form-control-static" ng-bind="license.id"></p>
+ </div>
+ </div>
+ <div class="form-group" >
+ <label class="col-md-3 control-label" for="pack_id" i18n>Pack</label>
+ <div class="col-md-8">
+ <p class="form-control-static" ng-bind="currentPack.code"></p>
+ <input type="hidden" id="pack_id" name="pack_id" ng-model="license.pack_id" />
+ </div>
+ </div>
+ <div class="form-group" >
+ <label class="col-md-3 control-label" for="code" i18n>Code</label>
+ <div class="col-md-8">
+ <input type="string" id="code" name="code" placeholder="" class="form-control" ng-model="license.code" ng-required="mandatory.code" ng-maxlength="{{maxlength.code}}" />
+ <div class="alert inline-alert alert-warning" ng-show="licenseForm.code.$invalid">
+ <span class="glyphicon glyphicon-warning-sign"></span>
+ <span ng-show="licenseForm.code.$error.maxlength" ng-bind="maxlengthErrorMsg('Code', maxlength.code)"></span>
+ <span ng-show="licenseForm.code.$error.required" ng-bind="mandatoryFieldErrorMsg('Code')"></span>
+ </div>
+ </div>
+ </div>
+ <div class="form-group" ng-if="!isNew">
+ <label class="col-md-3 control-label" i18n>Status</label>
+ <div class="col-md-8">
+ <p class="form-control-static" ng-bind="showStatusComplete(license)"></p>
+ </div>
+ </div>
+
+ <div class="form-group" >
+ <label class="col-md-3 control-label" for="full_name" i18n>User full name</label>
+ <div class="col-md-8">
+ <input type="string" id="full_name" name="full_name" placeholder="" class="form-control" ng-model="license.full_name" ng-required="mandatory.full_name" />
+ <div class="alert inline-alert alert-warning" ng-show="licenseForm.full_name.$invalid">
+ <span class="glyphicon glyphicon-warning-sign"></span>
+ <span ng-show="licenseForm.full_name.$error.maxlength" ng-bind="maxlengthErrorMsg('User full name', maxlength.full_name)"></span>
+ <span ng-show="licenseForm.full_name.$error.required" ng-bind="mandatoryFieldErrorMsg('User full name')"></span>
+ </div>
+ </div>
+ </div>
+
+ <div class="form-group" >
+ <label class="col-md-3 control-label" for="email" i18n>User email</label>
+ <div class="col-md-8">
+ <input type="email" id="email" name="email" placeholder="" class="form-control" ng-model="license.email" ng-required="mandatory.email" />
+ <div class="alert inline-alert alert-warning" ng-show="licenseForm.email.$invalid">
+ <span class="glyphicon glyphicon-warning-sign"></span>
+ <span ng-show="licenseForm.email.$error.email" ng-bind="'Please, write a valid email address'"></span>
+ <span ng-show="licenseForm.email.$error.maxlength" ng-bind="maxlengthErrorMsg('User email', maxlength.email)"></span>
+ <span ng-show="licenseForm.email.$error.required" ng-bind="mandatoryFieldErrorMsg('User email')"></span>
+ </div>
+ </div>
+ </div>
+
+ <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">
+ <textarea type="string" id="request_data" name="request_data" placeholder=""
+ class="form-control" ng-model="license.request_data" rows="2" ng-required="mandatory.request_data" ng-maxlength="{{maxlength.request_data}}"></textarea>
+ <div class="alert inline-alert alert-warning" ng-show="licenseForm.request_data.$invalid">
+ <span class="glyphicon glyphicon-warning-sign"></span>
+ <span ng-show="licenseForm.request_data.$error.maxlength" ng-bind="maxlengthErrorMsg('Request data', maxlength.request_data)"></span>
+ <span ng-show="licenseForm.request_data.$error.required" ng-bind="mandatoryFieldErrorMsg('Request data')"></span>
+ </div>
+ </div>
+ </div>
+
+ <div class="form-group" >
+ <label class="col-md-3 control-label" for="comments" i18n>Comments</label>
+ <div class="col-md-8">
+ <textarea type="string" id="comments" name="comments" placeholder=""
+ class="form-control" ng-model="license.comments" rows="2" ng-required="mandatory.comments" ng-maxlength="{{maxlength.comments}}"></textarea>
+ <div class="alert inline-alert alert-warning" ng-show="licenseForm.comments.$invalid">
+ <span class="glyphicon glyphicon-warning-sign"></span>
+ <span ng-show="licenseForm.comments.$error.maxlength" ng-bind="maxlengthErrorMsg('Comments', maxlength.comments)"></span>
+ <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>
+
+ <div class="form-group" ng-if="!isNew && license.license_data">
+ <label class="col-md-3 control-label" i18n >License file</label>
+ <div class="col-md-8">
+ <p class="form-control-static" ng-bind="license.license_data"></p>
+ <button id="downloadLicense" class="btn btn-xs btn-link" ng-click="downloadLicense(license)">
+ <span i18n class="glyphicon glyphicon-download"></span>
+ </button>
+ </div>
+ </div>
+
+ <div class="form-group" ng-if="!isNew">
+ <label class="col-md-3 control-label" i18n>Created by</label>
+ <div class="col-md-8">
+ <p class="form-control-static" ng-bind="license.created_by_name"></p>
+ </div>
+ </div>
+
+ <div class="form-group" ng-if="!isNew && license.canceled_by_name">
+ <label class="col-md-3 control-label" >Canceled by</label>
+ <div class="col-md-8">
+ <p class="form-control-static" ng-bind="license.canceled_by_name"></p>
+ </div>
+ </div>
+
+ <div class="form-group" ng-if="!isNew">
+ <label class="col-md-3 control-label" i18n>Creation date</label>
+ <div class="col-md-8">
+ <p class="form-control-static" ng-bind="license.creationTimestamp | date:'medium'"></p>
+ </div>
+ </div>
+
+ <div class="form-group" ng-if="!isNew">
+ <label class="col-md-3 control-label" i18n >Modification date</label>
+ <div class="col-md-8">
+ <p class="form-control-static" ng-bind="license.modificationTimestamp | date:'medium'"></p>
+ </div>
+ </div>
+
+ <div class="form-group" ng-if="!isNew && license.activationTimestamp">
+ <label class="col-md-3 control-label" i18n >Activation date</label>
+ <div class="col-md-8">
+ <p class="form-control-static" ng-bind="license.activationTimestamp | date:'medium'"></p>
+ </div>
+ </div>
+
+ <div class="form-group" ng-if="!isNew && license.sendTimestamp">
+ <label class="col-md-3 control-label" i18n >Send date</label>
+ <div class="col-md-8">
+ <p class="form-control-static" ng-bind="license.sendTimestamp | date:'medium'"></p>
+ </div>
+ </div>
+
+ <div class="form-group" ng-if="!isNew && license.cancelationTimestamp">
+ <label class="col-md-3 control-label" i18n >Cancelation date</label>
+ <div class="col-md-8">
+ <p class="form-control-static" ng-bind="license.cancelationTimestamp | date:'medium'"></p>
+ </div>
+ </div>
+
+ <div class="form-group" ng-if="!isNew && license.lastAccessTimestamp">
+ <label class="col-md-3 control-label" i18n>Last access date</label>
+ <div class="col-md-8">
+ <p class="form-control-static" ng-bind="license.lastAccessTimestamp | date:'medium'"></p>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <div class="col-md-offset-3 col-md-10" id="saveContainer">
+ <button id="save" type="submit" class="btn btn-primary" >
+ <span i18n class="glyphicon glyphicon-floppy-disk"></span> Save
+ </button>
+ </div>
+ </div>
+ </form>
+ </div>
+
+ <div class="panel panel-default" ng-if="currentPack">
<div class="panel-heading">
<span i18n>Licenses for pack: </span>{{currentPack.code}}
<span style="color: lightgreen;" class="badge pull-right" ng-bind="currentPack.lic_available || 0"></span>
@@ -217,19 +384,20 @@
<tbody>
<tr ng-repeat="lic in licenses | filter:searchLicenseText" ng-dblclick="editLicense(lic)" >
<td style="white-space: nowrap;" ng-bind="lic.code"></td>
- <td ng-bind="ellipsis(lic.user_fullname, 20)" title="{{lic.user_fullname}}" ></td>
- <td ng-bind="ellipsis(lic.user_email, 30)" title="{{lic.user_email}}" ></td>
- <td ng-bind="lic.status"></td>
+ <td ng-bind="ellipsis(lic.full_name, 20)" title="{{lic.full_name}}" ></td>
+ <td ng-bind="ellipsis(lic.email, 30)" title="{{lic.email}}" ></td>
+ <td ng-bind="showStatus(lic.status)"></td>
<td>
<div class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" >
<span class="glyphicon glyphicon-align-justify"></span> <span class="caret"></span>
</a>
<ul class="dropdown-menu">
- <li><a ng-click="editLicense(lic)"><span class="glyphicon glyphicon-pencil"></span> <span i18n>Edit</span></a></li>
- <li><a ng-click="activateLicense(lic)"><span class="glyphicon glyphicon-check"></span> <span i18n>Activate</span></a></li>
- <li><a ng-click="sendEmail(lic)"><span class="glyphicon glyphicon-send"></span> <span i18n>Send email</span></a></li>
- <li><a ng-click="editLicense(lic)"><span class="glyphicon glyphicon-remove"></span> <span i18n>Remove</span></a></li>
+ <li ng-if="isActionVisible(1, lic)"><a ng-click="downloadLicense(lic)"><span class="glyphicon glyphicon-download"></span> <span i18n>Download</span></a></li>
+ <li ng-if="isActionVisible(2, lic)"><a ng-click="editLicense(lic)"><span class="glyphicon glyphicon-pencil"></span> <span i18n>Edit</span></a></li>
+ <li ng-if="isActionVisible(4, lic)"><a ng-click="activateLicense(lic)"><span class="glyphicon glyphicon-check"></span> <span i18n>Activate</span></a></li>
+ <li ng-if="isActionVisible(8, lic)"><a ng-click="sendEmail(lic)"><span class="glyphicon glyphicon-send"></span> <span i18n>Send email</span></a></li>
+ <li ng-if="isActionVisible(16, lic)"><a ng-click="deleteLicense(lic)"><span class="glyphicon glyphicon-remove"></span> <span i18n>Remove</span></a></li>
</ul>
</div>
</td>
--
Gitblit v1.3.2