#396 fix - Added automated license code generation and other minor fixes
| .. | .. |
|---|
| 55 | 55 | @Table(name = "license") |
|---|
| 56 | 56 | @JsonIgnoreProperties(ignoreUnknown = true) |
|---|
| 57 | 57 | @NamedQueries({ |
|---|
| 58 | + @NamedQuery(name = "license-by-code", query = "SELECT l FROM License l where l.code = :code"), |
|---|
| 59 | + @NamedQuery(name = "last-code-suffix-used-in-pack", query = "SELECT max(l.codeSuffix) FROM License l where l.pack.id = :packId"), |
|---|
| 58 | 60 | @NamedQuery(name = "list-licenses-by-pack", query = "SELECT l FROM License l where l.pack.id = :packId"), |
|---|
| 59 | 61 | @NamedQuery(name = "list-licenses-by-req-data", query = "SELECT l FROM License l where l.reqDataHash = :hash"), |
|---|
| 60 | 62 | @NamedQuery(name = "list-active-licenses-by-req-data", query = "SELECT l FROM License l where l.reqDataHash = :hash and l.status in ('AC', 'PA')") |
|---|
| .. | .. |
|---|
| 70 | 72 | private int id; |
|---|
| 71 | 73 | |
|---|
| 72 | 74 | private String code; |
|---|
| 75 | + |
|---|
| 76 | + @Column(name = "code_suffix") |
|---|
| 77 | + @JsonProperty("code_suffix") |
|---|
| 78 | + private Integer codeSuffix; |
|---|
| 73 | 79 | |
|---|
| 74 | 80 | @JsonIgnore |
|---|
| 75 | 81 | @ManyToOne |
|---|
| .. | .. |
|---|
| 372 | 378 | } |
|---|
| 373 | 379 | } |
|---|
| 374 | 380 | |
|---|
| 381 | + public Integer getCodeSuffix() { |
|---|
| 382 | + return codeSuffix; |
|---|
| 383 | + } |
|---|
| 384 | + |
|---|
| 385 | + public void setCodeSuffix(Integer codeSuffix) { |
|---|
| 386 | + this.codeSuffix = codeSuffix; |
|---|
| 387 | + } |
|---|
| 388 | + |
|---|
| 375 | 389 | } |
|---|
| .. | .. |
|---|
| 42 | 42 | @JsonIgnoreProperties(ignoreUnknown = true) |
|---|
| 43 | 43 | @NamedQueries({ |
|---|
| 44 | 44 | @NamedQuery(name = "list-packs", query = "SELECT pa FROM Pack pa"),// |
|---|
| 45 | + @NamedQuery(name = "pack-by-code", query = "SELECT pa FROM Pack pa where pa.code = :code"),// |
|---|
| 45 | 46 | @NamedQuery(name = "list-packs-by-orgs", query = "SELECT pa FROM Pack pa where pa.organization.id in :list_ids") |
|---|
| 46 | 47 | }) |
|---|
| 47 | 48 | public class Pack implements Serializable { |
|---|
| .. | .. |
|---|
| 2 | 2 | |
|---|
| 3 | 3 | import java.io.File; |
|---|
| 4 | 4 | import java.io.IOException; |
|---|
| 5 | | -import java.nio.file.Files; |
|---|
| 6 | 5 | import java.text.MessageFormat; |
|---|
| 7 | 6 | import java.util.Date; |
|---|
| 8 | 7 | import java.util.HashMap; |
|---|
| .. | .. |
|---|
| 55 | 54 | import net.curisit.securis.utils.Config; |
|---|
| 56 | 55 | import net.curisit.securis.utils.EmailManager; |
|---|
| 57 | 56 | import net.curisit.securis.utils.JsonUtils; |
|---|
| 57 | +import net.curisit.securis.utils.LicUtils; |
|---|
| 58 | 58 | import net.curisit.securis.utils.TokenHelper; |
|---|
| 59 | 59 | |
|---|
| 60 | 60 | import org.apache.commons.io.IOUtils; |
|---|
| .. | .. |
|---|
| 320 | 320 | return Response.ok(lic).build(); |
|---|
| 321 | 321 | } |
|---|
| 322 | 322 | |
|---|
| 323 | + /** |
|---|
| 324 | + * Check if there is some pack with the same code |
|---|
| 325 | + * |
|---|
| 326 | + * @param code |
|---|
| 327 | + * Pack code |
|---|
| 328 | + * @param em |
|---|
| 329 | + * DB session object |
|---|
| 330 | + * @return <code>true</code> if code is already used, <code>false</code> |
|---|
| 331 | + * otherwise |
|---|
| 332 | + */ |
|---|
| 333 | + private boolean checkIfCodeExists(String code, EntityManager em) { |
|---|
| 334 | + TypedQuery<License> query = em.createNamedQuery("license-by-code", License.class); |
|---|
| 335 | + query.setParameter("code", code); |
|---|
| 336 | + int lics = query.getResultList().size(); |
|---|
| 337 | + return lics > 0; |
|---|
| 338 | + } |
|---|
| 339 | + |
|---|
| 323 | 340 | @POST |
|---|
| 324 | 341 | @Path("/") |
|---|
| 325 | 342 | @Consumes(MediaType.APPLICATION_JSON) |
|---|
| .. | .. |
|---|
| 330 | 347 | @Transactional |
|---|
| 331 | 348 | public Response create(License lic, @Context BasicSecurityContext bsc) throws SeCurisServiceException { |
|---|
| 332 | 349 | EntityManager em = emProvider.get(); |
|---|
| 350 | + |
|---|
| 351 | + if (checkIfCodeExists(lic.getCode(), em)) { |
|---|
| 352 | + throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The license code is already used in an existing license"); |
|---|
| 353 | + } |
|---|
| 354 | + if (!LicUtils.checkValidLicenseCodeCrc(lic.getCode())) { |
|---|
| 355 | + throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The license code is not valid"); |
|---|
| 356 | + } |
|---|
| 357 | + |
|---|
| 333 | 358 | Pack pack = null; |
|---|
| 334 | 359 | if (lic.getPackId() != null) { |
|---|
| 335 | 360 | pack = em.find(Pack.class, lic.getPackId()); |
|---|
| .. | .. |
|---|
| 376 | 401 | } else { |
|---|
| 377 | 402 | lic.setStatus(LicenseStatus.CREATED); |
|---|
| 378 | 403 | } |
|---|
| 404 | + lic.setCodeSuffix(LicUtils.getLicenseCodeSuffix(lic.getCode())); |
|---|
| 379 | 405 | lic.setCreatedBy(createdBy); |
|---|
| 380 | 406 | lic.setCreationTimestamp(new Date()); |
|---|
| 381 | 407 | lic.setModificationTimestamp(lic.getCreationTimestamp()); |
|---|
| 382 | | - LOG.info("LICENSE: {}", lic); |
|---|
| 408 | + |
|---|
| 383 | 409 | em.persist(lic); |
|---|
| 384 | | - LOG.info("LICENSE on HISTORY create"); |
|---|
| 385 | 410 | em.persist(licenseHelper.createLicenseHistoryAction(lic, createdBy, LicenseHistory.Actions.CREATE)); |
|---|
| 386 | 411 | if (lic.getStatus() == LicenseStatus.ACTIVE) { |
|---|
| 387 | | - LOG.info("LICENSE ACTIVATION on HISTORY create"); |
|---|
| 388 | 412 | em.persist(licenseHelper.createLicenseHistoryAction(lic, createdBy, LicenseHistory.Actions.CREATE, "Activated on creation")); |
|---|
| 389 | 413 | } |
|---|
| 390 | | - LOG.info("LICENSE created oK ??"); |
|---|
| 391 | 414 | |
|---|
| 392 | 415 | return Response.ok(lic).build(); |
|---|
| 393 | 416 | } |
|---|
| .. | .. |
|---|
| 599 | 622 | throw new SeCurisServiceException(Status.UNAUTHORIZED.getStatusCode(), "Unathorized access to license data"); |
|---|
| 600 | 623 | } |
|---|
| 601 | 624 | return lic; |
|---|
| 602 | | - } |
|---|
| 603 | | - |
|---|
| 604 | | - public static void main(String[] args) throws IOException { |
|---|
| 605 | | - File f = Files.createTempDirectory("securis-server").toFile(); |
|---|
| 606 | | - |
|---|
| 607 | | - LOG.info("f: {}", f); |
|---|
| 608 | | - f = new File(f, "config-server.lic"); |
|---|
| 609 | | - LOG.info("f: {}", f); |
|---|
| 610 | 625 | } |
|---|
| 611 | 626 | |
|---|
| 612 | 627 | @JsonAutoDetect |
|---|
| .. | .. |
|---|
| 41 | 41 | import net.curisit.securis.services.exception.SeCurisServiceException.ErrorCodes; |
|---|
| 42 | 42 | import net.curisit.securis.services.helpers.LicenseHelper; |
|---|
| 43 | 43 | import net.curisit.securis.services.helpers.UserHelper; |
|---|
| 44 | +import net.curisit.securis.utils.LicUtils; |
|---|
| 44 | 45 | import net.curisit.securis.utils.TokenHelper; |
|---|
| 45 | 46 | |
|---|
| 46 | 47 | import org.apache.logging.log4j.LogManager; |
|---|
| .. | .. |
|---|
| 147 | 148 | MediaType.APPLICATION_JSON |
|---|
| 148 | 149 | }) |
|---|
| 149 | 150 | @Transactional |
|---|
| 150 | | - public Response create(Pack pack, @Context BasicSecurityContext bsc) { |
|---|
| 151 | + public Response create(Pack pack, @Context BasicSecurityContext bsc) throws SeCurisServiceException { |
|---|
| 151 | 152 | LOG.info("Creating new pack"); |
|---|
| 152 | 153 | EntityManager em = emProvider.get(); |
|---|
| 154 | + |
|---|
| 155 | + if (checkIfCodeExists(pack.getCode(), em)) { |
|---|
| 156 | + throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The pack code is already used in an existing pack"); |
|---|
| 157 | + } |
|---|
| 153 | 158 | |
|---|
| 154 | 159 | try { |
|---|
| 155 | 160 | setPackOrganization(pack, pack.getOrgId(), em); |
|---|
| .. | .. |
|---|
| 181 | 186 | return Response.ok(pack).build(); |
|---|
| 182 | 187 | } |
|---|
| 183 | 188 | |
|---|
| 189 | + /** |
|---|
| 190 | + * Check if there is some pack with the same code |
|---|
| 191 | + * |
|---|
| 192 | + * @param code |
|---|
| 193 | + * Pack code |
|---|
| 194 | + * @param em |
|---|
| 195 | + * DB session object |
|---|
| 196 | + * @return <code>true</code> if code is already used, <code>false</code> |
|---|
| 197 | + * otherwise |
|---|
| 198 | + */ |
|---|
| 199 | + private boolean checkIfCodeExists(String code, EntityManager em) { |
|---|
| 200 | + TypedQuery<Pack> query = em.createNamedQuery("pack-by-code", Pack.class); |
|---|
| 201 | + query.setParameter("code", code); |
|---|
| 202 | + int packs = query.getResultList().size(); |
|---|
| 203 | + return packs > 0; |
|---|
| 204 | + } |
|---|
| 205 | + |
|---|
| 206 | + private int getNextCodeSuffix(int packId, EntityManager em) { |
|---|
| 207 | + TypedQuery<Integer> query = em.createNamedQuery("last-code-suffix-used-in-pack", Integer.class); |
|---|
| 208 | + query.setParameter("packId", packId); |
|---|
| 209 | + Integer lastCodeSuffix = query.getSingleResult(); |
|---|
| 210 | + return lastCodeSuffix == null ? 1 : lastCodeSuffix + 1; |
|---|
| 211 | + } |
|---|
| 212 | + |
|---|
| 213 | + /** |
|---|
| 214 | + * |
|---|
| 215 | + * @return The next available code suffix in pack for license code |
|---|
| 216 | + * @throws SeCurisServiceException |
|---|
| 217 | + */ |
|---|
| 218 | + @GET |
|---|
| 219 | + @Path("/{packId}/next_license_code") |
|---|
| 220 | + @Securable |
|---|
| 221 | + @Produces({ |
|---|
| 222 | + MediaType.TEXT_PLAIN |
|---|
| 223 | + }) |
|---|
| 224 | + public Response getCodeSuffix(@PathParam("packId") Integer packId, @Context BasicSecurityContext bsc) throws SeCurisServiceException { |
|---|
| 225 | + EntityManager em = emProvider.get(); |
|---|
| 226 | + |
|---|
| 227 | + if (packId == null) { |
|---|
| 228 | + throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The pack code is mandatory"); |
|---|
| 229 | + } |
|---|
| 230 | + Integer codeSuffix = getNextCodeSuffix(packId, em); |
|---|
| 231 | + Pack pack = em.find(Pack.class, packId); |
|---|
| 232 | + ; |
|---|
| 233 | + |
|---|
| 234 | + String licCode = LicUtils.getLicenseCode(pack.getCode(), codeSuffix); |
|---|
| 235 | + return Response.ok(licCode).build(); |
|---|
| 236 | + } |
|---|
| 237 | + |
|---|
| 184 | 238 | private void setPackLicenseType(Pack pack, Integer licTypeId, EntityManager em) throws SeCurisException { |
|---|
| 185 | 239 | LicenseType lt = null; |
|---|
| 186 | 240 | if (licTypeId != null) { |
|---|
| .. | .. |
|---|
| 40 | 40 | public static int INVALID_REQUEST_DATA_FORMAT = 1202; |
|---|
| 41 | 41 | public static int BLOCKED_REQUEST_DATA = 1203; |
|---|
| 42 | 42 | public static int DUPLICATED_REQUEST_DATA = 1204; |
|---|
| 43 | + |
|---|
| 44 | + public static int INVALID_DATA = 1301; |
|---|
| 43 | 45 | } |
|---|
| 44 | 46 | } |
|---|
| .. | .. |
|---|
| 104 | 104 | CREATE TABLE IF NOT EXISTS license ( |
|---|
| 105 | 105 | id INT NOT NULL auto_increment, |
|---|
| 106 | 106 | code VARCHAR(100) NOT NULL , |
|---|
| 107 | + code_suffix INT NULL , |
|---|
| 107 | 108 | request_data VARCHAR(1024) NULL , |
|---|
| 108 | 109 | request_data_hash VARCHAR(64) NULL , |
|---|
| 109 | 110 | license_data VARCHAR(1024) NULL , |
|---|
| .. | .. |
|---|
| 12 | 12 | } |
|---|
| 13 | 13 | |
|---|
| 14 | 14 | var app = angular.module('securis'); |
|---|
| 15 | | - app.service('Packs', ['$L','$resource', 'toaster', function($L, $resource, toaster) { |
|---|
| 15 | + app.service('Packs', ['$L','$resource', '$http', 'toaster', function($L, $resource, $http, toaster) { |
|---|
| 16 | 16 | var PACK_STATUS = { |
|---|
| 17 | 17 | CREATED: 'CR', |
|---|
| 18 | 18 | ACTIVE: 'AC', |
|---|
| .. | .. |
|---|
| 117 | 117 | var _error = _createErrorCallback(pack, $L.get('Put on hold'), _onerror); |
|---|
| 118 | 118 | packResource.putonhold({id: pack.id}, _success, _error); |
|---|
| 119 | 119 | } |
|---|
| 120 | + this.nextliccode = function(packId, _onsuccess, _onerror) { |
|---|
| 121 | + console.log('Get next code: ' + packId); |
|---|
| 122 | + var _error = function(data, status, headers, config) { |
|---|
| 123 | + console.log(headers); |
|---|
| 124 | + toaster.pop('error', $L.get('Getting next code suffix'), $L.get("Error getting license code, pack ID: '{0}'. Reason: {1}", packId, $L.get(headers('X-SECURIS-ERROR-MSG')))); |
|---|
| 125 | + } |
|---|
| 126 | + $http.get("/securis/pack/"+packId+"/next_license_code").success(_onsuccess).error(_error); |
|---|
| 127 | + } |
|---|
| 120 | 128 | this.cancel = function(pack, extra_data, _onsuccess, _onerror) { |
|---|
| 121 | 129 | console.log('Cancellation on pack: ' + pack.id); |
|---|
| 122 | 130 | var _success = _createSuccessCallback($L.get('Cancellation'), $L.get("Pack '{0}' {1} successfully", pack.code, $L.get("cancelled")), _onsuccess); |
|---|
| .. | .. |
|---|
| 133 | 141 | |
|---|
| 134 | 142 | }]); |
|---|
| 135 | 143 | |
|---|
| 136 | | - app.service('Licenses', ['$L', '$resource', 'toaster', function($L, $resource, toaster) { |
|---|
| 144 | + app.service('Licenses', ['$L', '$resource', 'toaster', 'Packs', function($L, $resource, toaster, Packs) { |
|---|
| 137 | 145 | var LIC_STATUS = { |
|---|
| 138 | 146 | CREATED: 'CR', |
|---|
| 139 | 147 | ACTIVE: 'AC', |
|---|
| .. | .. |
|---|
| 225 | 233 | } |
|---|
| 226 | 234 | var _error = function(error) { |
|---|
| 227 | 235 | console.log(error); |
|---|
| 228 | | - toaster.pop('error', 'Licenses', $L.get("Error {0} license '{1}'. Reason: {2}", isNew ? $L.get("creating") : $L.get("updating"), license.code, $L.get(error.headers('X-SECURIS-ERROR-MSG')))); |
|---|
| 236 | + toaster.pop('error', 'Licenses', $L.get("Error {0} license '{1}'. Reason: {2}", isNew ? $L.get("creating") : $L.get("updating"), license.code, $L.get(error.headers('X-SECURIS-ERROR-MSG'))), 5000); |
|---|
| 237 | + if (error.headers('X-SECURIS-ERROR-CODE') === '1301') { |
|---|
| 238 | + Packs.nextliccode(license.pack_id, function(data) { |
|---|
| 239 | + console.log('New code: ' + data); |
|---|
| 240 | + license.code = data; |
|---|
| 241 | + toaster.pop('info', 'Licenses', $L.get("New license code, {0}, has been generated, please try again", license.code), 5000); |
|---|
| 242 | + }); |
|---|
| 243 | + } |
|---|
| 229 | 244 | } |
|---|
| 230 | 245 | licenseResource.save(license, _success, _error); |
|---|
| 231 | 246 | } |
|---|
| .. | .. |
|---|
| 622 | 637 | '$resource', |
|---|
| 623 | 638 | 'toaster', |
|---|
| 624 | 639 | 'Licenses', |
|---|
| 640 | + 'Packs', |
|---|
| 625 | 641 | '$store', |
|---|
| 626 | 642 | '$L', |
|---|
| 627 | | - function($scope, $http, $resource, toaster, Licenses, $store, $L) { |
|---|
| 643 | + function($scope, $http, $resource, toaster, Licenses, Packs, $store, $L) { |
|---|
| 628 | 644 | $scope.Licenses = Licenses; |
|---|
| 629 | 645 | $scope.$on('pack_changed', function(evt, message) { |
|---|
| 630 | 646 | $scope.licenses = Licenses.getLicensesList($scope.currentPack); |
|---|
| .. | .. |
|---|
| 708 | 724 | $scope.license = { |
|---|
| 709 | 725 | pack_id: $scope.currentPack.id |
|---|
| 710 | 726 | } |
|---|
| 727 | + Packs.nextliccode($scope.currentPack.id, function(data) { |
|---|
| 728 | + console.log('New code: ' + data); |
|---|
| 729 | + $scope.license.code = data; |
|---|
| 730 | + }); |
|---|
| 711 | 731 | setTimeout(function() { |
|---|
| 712 | | - $('#licenseForm * #code').focus(); |
|---|
| 732 | + $('#licenseForm * #email').focus(); |
|---|
| 713 | 733 | }, 0); |
|---|
| 714 | 734 | } |
|---|
| 715 | 735 | |
|---|
| .. | .. |
|---|
| 816 | 836 | |
|---|
| 817 | 837 | $scope.cancel = function() { |
|---|
| 818 | 838 | $scope.showForm = false; |
|---|
| 819 | | - } |
|---|
| 820 | | - |
|---|
| 821 | | - $scope.showStatus = function(lic) { |
|---|
| 822 | | - |
|---|
| 823 | | - } |
|---|
| 824 | | - $scope.showStatusLong = function(license) { |
|---|
| 825 | | - |
|---|
| 826 | 839 | } |
|---|
| 827 | 840 | |
|---|
| 828 | 841 | } ]); |
|---|
| .. | .. |
|---|
| 25 | 25 | <div class="input-group-addon" style="width: 28px;"> |
|---|
| 26 | 26 | <span class=" glyphicon glyphicon-search"></span> |
|---|
| 27 | 27 | </div> <input type="text" class="form-control" placeholder="Search" |
|---|
| 28 | | - ng-model="$searchPacksText"> |
|---|
| 28 | + ng-model="searchPackText"> |
|---|
| 29 | 29 | <div class="input-group-addon" style="width: 20px;"> |
|---|
| 30 | 30 | <span class=" glyphicon glyphicon-remove" |
|---|
| 31 | | - ng-click="$searchPacksText = '';"></span> |
|---|
| 31 | + ng-click="searchPackText = '';"></span> |
|---|
| 32 | 32 | </div> |
|---|
| 33 | 33 | </span> |
|---|
| 34 | 34 | </div> |
|---|
| .. | .. |
|---|
| 64 | 64 | </div> |
|---|
| 65 | 65 | |
|---|
| 66 | 66 | <div class="form-group"> |
|---|
| 67 | | - <label class="col-md-3 control-label" for="code" i18n>Validity (from - to)</label> |
|---|
| 67 | + <label class="col-md-3 control-label" for="init_valid_date" i18n>Validity (from - to)</label> |
|---|
| 68 | 68 | <div class="col-md-4"> |
|---|
| 69 | 69 | <input type="date" id="init_valid_date" name="init_valid_date" placeholder="" |
|---|
| 70 | 70 | class="form-control" ng-model="pack.init_valid_date" |
|---|
| .. | .. |
|---|
| 282 | 282 | </tr> |
|---|
| 283 | 283 | </thead> |
|---|
| 284 | 284 | <tbody> |
|---|
| 285 | | - <tr ng-repeat="p in packs | filter:searchText" |
|---|
| 285 | + <tr ng-repeat="p in packs | filter:searchPackText" |
|---|
| 286 | 286 | ng-dblclick="editPack(p)" |
|---|
| 287 | 287 | ng-class="{success: currentPack.id === p.id}" |
|---|
| 288 | 288 | ng-click="selectPack(p)"> |
|---|
| .. | .. |
|---|
| 351 | 351 | <div class="input-group-addon" style="width: 28px;"> |
|---|
| 352 | 352 | <span class=" glyphicon glyphicon-search"></span> |
|---|
| 353 | 353 | </div> <input type="text" class="form-control" placeholder="Search" |
|---|
| 354 | | - ng-model="$searchLicensesText"> |
|---|
| 354 | + ng-model="searchLicenseText"> |
|---|
| 355 | 355 | <div class="input-group-addon" style="width: 20px;"> |
|---|
| 356 | 356 | <span class=" glyphicon glyphicon-remove" |
|---|
| 357 | | - ng-click="$searchLicensesText = '';"></span> |
|---|
| 357 | + ng-click="searchLicenseText = '';"></span> |
|---|
| 358 | 358 | </div> |
|---|
| 359 | 359 | </span> |
|---|
| 360 | 360 | </div> |
|---|
| .. | .. |
|---|
| 389 | 389 | <label class="col-md-3 control-label" for="code" i18n>Code</label> |
|---|
| 390 | 390 | <div class="col-md-8"> |
|---|
| 391 | 391 | <input type="string" id="code" name="code" placeholder="" |
|---|
| 392 | | - class="form-control" ng-model="license.code" |
|---|
| 392 | + class="form-control" ng-model="license.code" readonly |
|---|
| 393 | 393 | ng-required="mandatory.code" ng-maxlength="{{maxlength.code}}" /> |
|---|
| 394 | 394 | <div class="alert inline-alert alert-warning" |
|---|
| 395 | 395 | ng-show="licenseForm.code.$invalid"> |
|---|
| .. | .. |
|---|
| 404 | 404 | <div class="form-group" ng-if="!isNew"> |
|---|
| 405 | 405 | <label class="col-md-3 control-label" i18n>Status</label> |
|---|
| 406 | 406 | <div class="col-md-8"> |
|---|
| 407 | | - <p class="form-control-static" ng-bind="showStatusLong(license)"></p> |
|---|
| 407 | + <p class="form-control-static" ng-bind="license.status_name"></p> |
|---|
| 408 | 408 | </div> |
|---|
| 409 | 409 | </div> |
|---|
| 410 | 410 | |
|---|
| .. | .. |
|---|
| 625 | 625 | <td ng-bind="ellipsis(lic.full_name, 20)" |
|---|
| 626 | 626 | title="{{lic.full_name}}"></td> |
|---|
| 627 | 627 | <td ng-bind="ellipsis(lic.email, 30)" title="{{lic.email}}"></td> |
|---|
| 628 | | - <td ng-bind="showStatus(lic.status)"></td> |
|---|
| 628 | + <td ng-bind="Licenses.getStatusName(lic.status)"></td> |
|---|
| 629 | 629 | <td> |
|---|
| 630 | 630 | <div class="dropdown"> |
|---|
| 631 | 631 | <a class="dropdown-toggle" data-toggle="dropdown"> <span |
|---|
| .. | .. |
|---|
| 22 | 22 | <div class="jumbotron"> |
|---|
| 23 | 23 | <div class="container"> |
|---|
| 24 | 24 | <h2 i18n >SeCuris</h2> |
|---|
| 25 | | - <p i18n >Server License for CurisTEC products.</p> |
|---|
| 25 | + <p i18n >Licenses Server for CurisTEC products.</p> |
|---|
| 26 | 26 | </div> |
|---|
| 27 | 27 | </div> |
|---|
| 28 | 28 | |
|---|