rsanchez
2017-04-03 347803bd8d8349baa0577156896a1ec924a69e6d
#3535 fix - Marked obsolete metadata field on licenses
1 files added
11 files modified
changed files
securis/src/main/java/net/curisit/securis/db/License.java patch | view | blame | history
securis/src/main/java/net/curisit/securis/db/Pack.java patch | view | blame | history
securis/src/main/java/net/curisit/securis/services/ApiResource.java patch | view | blame | history
securis/src/main/java/net/curisit/securis/services/PackResource.java patch | view | blame | history
securis/src/main/java/net/curisit/securis/services/helpers/MetadataHelper.java patch | view | blame | history
securis/src/main/resources/db/schema.sql patch | view | blame | history
securis/src/main/webapp/sql_update.sql patch | view | blame | history
securis/src/main/webapp/src/app/forms/license.form.component.ts patch | view | blame | history
securis/src/main/webapp/src/app/forms/pack.form.component.ts patch | view | blame | history
securis/src/main/webapp/src/app/listing/license.list.component.html patch | view | blame | history
securis/src/main/webapp/src/app/listing/license.list.component.ts patch | view | blame | history
securis/src/main/webapp/src/app/resources/licenses.ts patch | view | blame | history
securis/src/main/java/net/curisit/securis/db/License.java
....@@ -22,13 +22,6 @@
2222 import javax.persistence.Table;
2323 import javax.persistence.TypedQuery;
2424
25
-import net.curisit.integrity.commons.Utils;
26
-import net.curisit.securis.db.common.CreationTimestampEntity;
27
-import net.curisit.securis.db.common.ModificationTimestampEntity;
28
-import net.curisit.securis.db.listeners.CreationTimestampListener;
29
-import net.curisit.securis.db.listeners.ModificationTimestampListener;
30
-import net.curisit.securis.services.exception.SeCurisServiceException;
31
-
3225 import org.apache.logging.log4j.LogManager;
3326 import org.apache.logging.log4j.Logger;
3427 import org.hibernate.annotations.Type;
....@@ -40,6 +33,13 @@
4033 import com.fasterxml.jackson.annotation.JsonInclude.Include;
4134 import com.fasterxml.jackson.annotation.JsonProperty;
4235
36
+import net.curisit.integrity.commons.Utils;
37
+import net.curisit.securis.db.common.CreationTimestampEntity;
38
+import net.curisit.securis.db.common.ModificationTimestampEntity;
39
+import net.curisit.securis.db.listeners.CreationTimestampListener;
40
+import net.curisit.securis.db.listeners.ModificationTimestampListener;
41
+import net.curisit.securis.services.exception.SeCurisServiceException;
42
+
4343 /**
4444 * Entity implementation class for Entity: license
4545 *
....@@ -47,425 +47,432 @@
4747 @JsonAutoDetect
4848 @JsonInclude(Include.NON_NULL)
4949 @Entity
50
-@EntityListeners({
51
- CreationTimestampListener.class, ModificationTimestampListener.class
52
-})
50
+@EntityListeners({ CreationTimestampListener.class, ModificationTimestampListener.class })
5351 @Table(name = "license")
5452 @JsonIgnoreProperties(ignoreUnknown = true)
55
-@NamedQueries({
56
- @NamedQuery(name = "license-by-code", query = "SELECT l FROM License l where l.code = :code"),
57
- @NamedQuery(name = "license-by-activation-code", query = "SELECT l FROM License l where l.activationCode = :activationCode"),
58
- @NamedQuery(name = "last-code-suffix-used-in-pack", query = "SELECT max(l.codeSuffix) FROM License l where l.pack.id = :packId"),
59
- @NamedQuery(name = "list-licenses-by-pack", query = "SELECT l FROM License l where l.pack.id = :packId"),
60
- @NamedQuery(name = "list-licenses-by-req-data", query = "SELECT l FROM License l where l.reqDataHash = :hash"),
61
- @NamedQuery(name = "list-active-licenses-by-req-data", query = "SELECT l FROM License l where l.reqDataHash = :hash and l.status in ('AC', 'PA')"),
62
- @NamedQuery(name = "list-valid-licenses-by-req-data", query = "SELECT l FROM License l where l.reqDataHash = :hash and l.status in ('RE', 'AC', 'PA')")
53
+@NamedQueries({ @NamedQuery(name = "license-by-code", query = "SELECT l FROM License l where l.code = :code"),
54
+ @NamedQuery(name = "license-by-activation-code", query = "SELECT l FROM License l where l.activationCode = :activationCode"),
55
+ @NamedQuery(name = "last-code-suffix-used-in-pack", query = "SELECT max(l.codeSuffix) FROM License l where l.pack.id = :packId"),
56
+ @NamedQuery(name = "list-licenses-by-pack", query = "SELECT l FROM License l where l.pack.id = :packId"),
57
+ @NamedQuery(name = "list-licenses-by-req-data", query = "SELECT l FROM License l where l.reqDataHash = :hash"),
58
+ @NamedQuery(name = "list-active-licenses-by-req-data", query = "SELECT l FROM License l where l.reqDataHash = :hash and l.status in ('AC', 'PA')"),
59
+ @NamedQuery(name = "list-valid-licenses-by-req-data", query = "SELECT l FROM License l where l.reqDataHash = :hash and l.status in ('RE', 'AC', 'PA')")
6360
6461 })
6562 public class License implements CreationTimestampEntity, ModificationTimestampEntity, Serializable {
6663
67
- private static final long serialVersionUID = 2700310404904877227L;
64
+ private static final long serialVersionUID = 2700310404904877227L;
6865
69
- private static final Logger LOG = LogManager.getLogger(License.class);
66
+ private static final Logger LOG = LogManager.getLogger(License.class);
7067
71
- @Id
72
- @GeneratedValue
73
- private Integer id;
68
+ @Id
69
+ @GeneratedValue
70
+ private Integer id;
7471
75
- private String code;
72
+ private String code;
7673
77
- @Column(name = "activation_code")
78
- @JsonProperty("activation_code")
79
- private String activationCode;
74
+ @Column(name = "metadata_obsolete")
75
+ @JsonProperty("metadata_obsolete")
76
+ private Boolean metadataObsolete;
8077
81
- @Column(name = "code_suffix")
82
- @JsonProperty("code_suffix")
83
- private Integer codeSuffix;
78
+ @Column(name = "activation_code")
79
+ @JsonProperty("activation_code")
80
+ private String activationCode;
8481
85
- @JsonIgnore
86
- @ManyToOne
87
- @JoinColumn(name = "pack_id")
88
- private Pack pack;
82
+ @Column(name = "code_suffix")
83
+ @JsonProperty("code_suffix")
84
+ private Integer codeSuffix;
8985
90
- @JsonIgnore
91
- @ManyToOne
92
- @JoinColumn(name = "created_by")
93
- private User createdBy;
86
+ @JsonIgnore
87
+ @ManyToOne
88
+ @JoinColumn(name = "pack_id")
89
+ private Pack pack;
9490
95
- @JsonIgnore
96
- @ManyToOne
97
- @JoinColumn(name = "cancelled_by")
98
- private User cancelledBy;
91
+ @JsonIgnore
92
+ @ManyToOne
93
+ @JoinColumn(name = "created_by")
94
+ private User createdBy;
9995
100
- @Type(type = "net.curisit.securis.db.common.LicenseStatusType")
101
- private LicenseStatus status;
96
+ @JsonIgnore
97
+ @ManyToOne
98
+ @JoinColumn(name = "cancelled_by")
99
+ private User cancelledBy;
102100
103
- @Column(name = "full_name")
104
- @JsonProperty("full_name")
105
- private String fullName;
101
+ @Type(type = "net.curisit.securis.db.common.LicenseStatusType")
102
+ private LicenseStatus status;
106103
107
- private String email;
104
+ @Column(name = "full_name")
105
+ @JsonProperty("full_name")
106
+ private String fullName;
108107
109
- @Column(name = "request_data")
110
- @JsonProperty("request_data")
111
- private String requestData;
108
+ private String email;
112109
113
- /**
114
- * request data hash is automatically set when we use
115
- * {@link License#setRequestData(String)} method
116
- */
117
- @Column(name = "request_data_hash")
118
- @JsonIgnore
119
- private String reqDataHash;
110
+ @Column(name = "request_data")
111
+ @JsonProperty("request_data")
112
+ private String requestData;
120113
121
- @Column(name = "license_data")
122
- @JsonProperty("license_data")
123
- @JsonIgnore
124
- // The license data is sent to user as a separate file, It doesn't need to
125
- // be included as License attribute on browser
126
- private String licenseData;
114
+ /**
115
+ * request data hash is automatically set when we use
116
+ * {@link License#setRequestData(String)} method
117
+ */
118
+ @Column(name = "request_data_hash")
119
+ @JsonIgnore
120
+ private String reqDataHash;
127121
128
- @Column(name = "creation_timestamp")
129
- @JsonProperty("creation_timestamp")
130
- private Date creationTimestamp;
122
+ @Column(name = "license_data")
123
+ @JsonProperty("license_data")
124
+ @JsonIgnore
125
+ // The license data is sent to user as a separate file, It doesn't need to
126
+ // be included as License attribute on browser
127
+ private String licenseData;
131128
132
- @Column(name = "modification_timestamp")
133
- @JsonProperty("modification_timestamp")
134
- private Date modificationTimestamp;
129
+ @Column(name = "creation_timestamp")
130
+ @JsonProperty("creation_timestamp")
131
+ private Date creationTimestamp;
135132
136
- @Column(name = "last_access_timestamp")
137
- @JsonProperty("last_access_timestamp")
138
- private Date lastAccessTimestamp;
133
+ @Column(name = "modification_timestamp")
134
+ @JsonProperty("modification_timestamp")
135
+ private Date modificationTimestamp;
139136
140
- @Column(name = "expiration_date")
141
- @JsonProperty("expiration_date")
142
- private Date expirationDate;
137
+ @Column(name = "last_access_timestamp")
138
+ @JsonProperty("last_access_timestamp")
139
+ private Date lastAccessTimestamp;
143140
144
- private String comments;
141
+ @Column(name = "expiration_date")
142
+ @JsonProperty("expiration_date")
143
+ private Date expirationDate;
145144
146
- @OneToMany(fetch = FetchType.LAZY, mappedBy = "license")
147
- @JsonIgnore
148
- private List<LicenseHistory> history;
145
+ private String comments;
149146
150
- public Integer getId() {
151
- return id;
152
- }
147
+ @OneToMany(fetch = FetchType.LAZY, mappedBy = "license")
148
+ @JsonIgnore
149
+ private List<LicenseHistory> history;
153150
154
- public String getCode() {
155
- return code;
156
- }
151
+ public Integer getId() {
152
+ return id;
153
+ }
157154
158
- public void setCode(String code) {
159
- this.code = code;
160
- }
155
+ public String getCode() {
156
+ return code;
157
+ }
161158
162
- @Override
163
- public Date getCreationTimestamp() {
164
- return creationTimestamp;
165
- }
159
+ public void setCode(String code) {
160
+ this.code = code;
161
+ }
166162
167
- @Override
168
- public void setCreationTimestamp(Date creationTimestamp) {
169
- this.creationTimestamp = creationTimestamp;
170
- }
163
+ @Override
164
+ public Date getCreationTimestamp() {
165
+ return creationTimestamp;
166
+ }
171167
172
- public User getCreatedBy() {
173
- return createdBy;
174
- }
168
+ @Override
169
+ public void setCreationTimestamp(Date creationTimestamp) {
170
+ this.creationTimestamp = creationTimestamp;
171
+ }
175172
176
- public void setCreatedBy(User createdBy) {
177
- this.createdBy = createdBy;
178
- }
173
+ public User getCreatedBy() {
174
+ return createdBy;
175
+ }
179176
180
- public Pack getPack() {
181
- return pack;
182
- }
177
+ public void setCreatedBy(User createdBy) {
178
+ this.createdBy = createdBy;
179
+ }
183180
184
- public void setPack(Pack pack) {
185
- this.pack = pack;
186
- }
181
+ public Pack getPack() {
182
+ return pack;
183
+ }
187184
188
- @JsonProperty("created_by_id")
189
- public String getCreatedById() {
190
- return createdBy == null ? null : createdBy.getUsername();
191
- }
185
+ public void setPack(Pack pack) {
186
+ this.pack = pack;
187
+ }
192188
193
- @JsonProperty("created_by_id")
194
- public void setCreatedById(String username) {
195
- if (username == null) {
196
- createdBy = null;
197
- } else {
198
- createdBy = new User();
199
- createdBy.setUsername(username);
200
- }
201
- }
189
+ @JsonProperty("created_by_id")
190
+ public String getCreatedById() {
191
+ return createdBy == null ? null : createdBy.getUsername();
192
+ }
202193
203
- @JsonProperty("cancelled_by_id")
204
- public String getCancelledById() {
205
- return cancelledBy == null ? null : cancelledBy.getUsername();
206
- }
194
+ @JsonProperty("created_by_id")
195
+ public void setCreatedById(String username) {
196
+ if (username == null) {
197
+ createdBy = null;
198
+ } else {
199
+ createdBy = new User();
200
+ createdBy.setUsername(username);
201
+ }
202
+ }
207203
208
- @JsonProperty("cancelled_by_id")
209
- public void setCancelledById(String username) {
210
- if (username == null) {
211
- cancelledBy = null;
212
- } else {
213
- cancelledBy = new User();
214
- cancelledBy.setUsername(username);
215
- }
216
- }
204
+ @JsonProperty("cancelled_by_id")
205
+ public String getCancelledById() {
206
+ return cancelledBy == null ? null : cancelledBy.getUsername();
207
+ }
217208
218
- @JsonProperty("pack_code")
219
- public String getPackCode() {
220
- return pack == null ? null : pack.getCode();
221
- }
209
+ @JsonProperty("cancelled_by_id")
210
+ public void setCancelledById(String username) {
211
+ if (username == null) {
212
+ cancelledBy = null;
213
+ } else {
214
+ cancelledBy = new User();
215
+ cancelledBy.setUsername(username);
216
+ }
217
+ }
222218
223
- @JsonProperty("pack_id")
224
- public Integer getPackId() {
225
- return pack == null ? null : pack.getId();
226
- }
219
+ @JsonProperty("pack_code")
220
+ public String getPackCode() {
221
+ return pack == null ? null : pack.getCode();
222
+ }
227223
228
- @JsonProperty("pack_id")
229
- public void setPackId(Integer idPack) {
230
- if (idPack == null) {
231
- pack = null;
232
- } else {
233
- pack = new Pack();
234
- pack.setId(idPack);
235
- }
236
- }
224
+ @JsonProperty("pack_id")
225
+ public Integer getPackId() {
226
+ return pack == null ? null : pack.getId();
227
+ }
237228
238
- public LicenseStatus getStatus() {
239
- return status;
240
- }
229
+ @JsonProperty("pack_id")
230
+ public void setPackId(Integer idPack) {
231
+ if (idPack == null) {
232
+ pack = null;
233
+ } else {
234
+ pack = new Pack();
235
+ pack.setId(idPack);
236
+ }
237
+ }
241238
242
- public void setStatus(LicenseStatus status) {
243
- this.status = status;
244
- }
239
+ public LicenseStatus getStatus() {
240
+ return status;
241
+ }
245242
246
- @Override
247
- public Date getModificationTimestamp() {
248
- return modificationTimestamp;
249
- }
243
+ public void setStatus(LicenseStatus status) {
244
+ this.status = status;
245
+ }
250246
251
- @Override
252
- public void setModificationTimestamp(Date modificationTimestamp) {
253
- this.modificationTimestamp = modificationTimestamp;
254
- }
247
+ @Override
248
+ public Date getModificationTimestamp() {
249
+ return modificationTimestamp;
250
+ }
255251
256
- public String getFullName() {
257
- return fullName;
258
- }
252
+ @Override
253
+ public void setModificationTimestamp(Date modificationTimestamp) {
254
+ this.modificationTimestamp = modificationTimestamp;
255
+ }
259256
260
- public void setFullName(String fullName) {
261
- this.fullName = fullName;
262
- }
257
+ public String getFullName() {
258
+ return fullName;
259
+ }
263260
264
- public String getEmail() {
265
- return email;
266
- }
261
+ public void setFullName(String fullName) {
262
+ this.fullName = fullName;
263
+ }
267264
268
- public void setEmail(String email) {
269
- this.email = email;
270
- }
265
+ public String getEmail() {
266
+ return email;
267
+ }
271268
272
- public void setId(Integer id) {
273
- this.id = id;
274
- }
269
+ public void setEmail(String email) {
270
+ this.email = email;
271
+ }
272
+
273
+ public void setId(Integer id) {
274
+ this.id = id;
275
+ }
276
+
277
+ public User getCancelledBy() {
278
+ return cancelledBy;
279
+ }
280
+
281
+ public void setCancelledBy(User cancelledBy) {
282
+ this.cancelledBy = cancelledBy;
283
+ }
275284
276
- public User getCancelledBy() {
277
- return cancelledBy;
278
- }
285
+ public Date getLastAccessTimestamp() {
286
+ return lastAccessTimestamp;
287
+ }
279288
280
- public void setCancelledBy(User cancelledBy) {
281
- this.cancelledBy = cancelledBy;
282
- }
289
+ public void setLastAccessTimestamp(Date lastAccessTimestamp) {
290
+ this.lastAccessTimestamp = lastAccessTimestamp;
291
+ }
283292
284
- public Date getLastAccessTimestamp() {
285
- return lastAccessTimestamp;
286
- }
293
+ public String getRequestData() {
294
+ return requestData;
295
+ }
287296
288
- public void setLastAccessTimestamp(Date lastAccessTimestamp) {
289
- this.lastAccessTimestamp = lastAccessTimestamp;
290
- }
297
+ public void setRequestData(String requestData) {
298
+ this.requestData = requestData;
299
+ this.reqDataHash = BlockedRequest.generateHash(this.requestData);
300
+ }
291301
292
- public String getRequestData() {
293
- return requestData;
294
- }
302
+ public String getLicenseData() {
303
+ return licenseData;
304
+ }
295305
296
- public void setRequestData(String requestData) {
297
- this.requestData = requestData;
298
- this.reqDataHash = BlockedRequest.generateHash(this.requestData);
299
- }
306
+ public void setLicenseData(String licenseData) {
307
+ this.licenseData = licenseData;
308
+ }
300309
301
- public String getLicenseData() {
302
- return licenseData;
303
- }
310
+ public String getComments() {
311
+ return comments;
312
+ }
304313
305
- public void setLicenseData(String licenseData) {
306
- this.licenseData = licenseData;
307
- }
314
+ public void setComments(String comments) {
315
+ this.comments = comments;
316
+ }
308317
309
- public String getComments() {
310
- return comments;
311
- }
318
+ public List<LicenseHistory> getHistory() {
319
+ return history;
320
+ }
312321
313
- public void setComments(String comments) {
314
- this.comments = comments;
315
- }
322
+ public void setHistory(List<LicenseHistory> history) {
323
+ this.history = history;
324
+ }
316325
317
- public List<LicenseHistory> getHistory() {
318
- return history;
319
- }
326
+ public Date getExpirationDate() {
327
+ return expirationDate;
328
+ }
320329
321
- public void setHistory(List<LicenseHistory> history) {
322
- this.history = history;
323
- }
330
+ public void setExpirationDate(Date expirationDate) {
331
+ this.expirationDate = expirationDate;
332
+ }
324333
325
- public Date getExpirationDate() {
326
- return expirationDate;
327
- }
334
+ public String getReqDataHash() {
335
+ return reqDataHash;
336
+ }
328337
329
- public void setExpirationDate(Date expirationDate) {
330
- this.expirationDate = expirationDate;
331
- }
338
+ public static class Action {
339
+ public static final int CREATE = 1;
340
+ public static final int REQUEST = 2;
341
+ public static final int ACTIVATION = 3;
342
+ public static final int SEND = 4;
343
+ public static final int DOWNLOAD = 5;
344
+ public static final int CANCEL = 6;
345
+ public static final int DELETE = 7;
346
+ public static final int BLOCK = 8;
347
+ public static final int UNBLOCK = 9;
348
+ }
332349
333
- public String getReqDataHash() {
334
- return reqDataHash;
335
- }
350
+ public static class Status {
336351
337
- public static class Action {
338
- public static final int CREATE = 1;
339
- public static final int REQUEST = 2;
340
- public static final int ACTIVATION = 3;
341
- public static final int SEND = 4;
342
- public static final int DOWNLOAD = 5;
343
- public static final int CANCEL = 6;
344
- public static final int DELETE = 7;
345
- public static final int BLOCK = 8;
346
- public static final int UNBLOCK = 9;
347
- }
352
+ private static final Map<Integer, List<LicenseStatus>> transitions = Utils.createMap( //
353
+ Action.REQUEST, Arrays.asList(LicenseStatus.CREATED, LicenseStatus.REQUESTED), //
354
+ Action.ACTIVATION, Arrays.asList(LicenseStatus.CREATED, LicenseStatus.REQUESTED, LicenseStatus.PRE_ACTIVE, LicenseStatus.EXPIRED), //
355
+ Action.SEND, Arrays.asList(LicenseStatus.ACTIVE, LicenseStatus.PRE_ACTIVE), //
356
+ Action.DOWNLOAD, Arrays.asList(LicenseStatus.ACTIVE, LicenseStatus.PRE_ACTIVE), //
357
+ Action.CANCEL, Arrays.asList(LicenseStatus.ACTIVE, LicenseStatus.PRE_ACTIVE, LicenseStatus.REQUESTED, LicenseStatus.EXPIRED), //
358
+ Action.DELETE, Arrays.asList(LicenseStatus.CANCELLED, LicenseStatus.CREATED, LicenseStatus.BLOCKED), //
359
+ Action.UNBLOCK, Arrays.asList(LicenseStatus.BLOCKED), //
360
+ Action.BLOCK, Arrays.asList(LicenseStatus.CANCELLED) //
361
+ );
348362
349
- public static class Status {
363
+ /**
364
+ * It checks if a given action is valid for the License, passing the
365
+ * action and the current license status
366
+ *
367
+ * @param oldStatus
368
+ * @param newStatus
369
+ * @return
370
+ */
371
+ public static boolean isActionValid(Integer action, LicenseStatus currentStatus) {
372
+ List<LicenseStatus> validStatuses = transitions.get(action);
373
+ LOG.info("Action {} is valid ? => {} current: {} OK? {}", action, validStatuses, currentStatus, validStatuses.contains(currentStatus));
374
+ return validStatuses != null && validStatuses.contains(currentStatus);
375
+ }
376
+ }
350377
351
- private static final Map<Integer, List<LicenseStatus>> transitions = Utils.createMap( //
352
- Action.REQUEST, Arrays.asList(LicenseStatus.CREATED, LicenseStatus.REQUESTED), //
353
- Action.ACTIVATION, Arrays.asList(LicenseStatus.CREATED, LicenseStatus.REQUESTED, LicenseStatus.PRE_ACTIVE, LicenseStatus.EXPIRED), //
354
- Action.SEND, Arrays.asList(LicenseStatus.ACTIVE, LicenseStatus.PRE_ACTIVE), //
355
- Action.DOWNLOAD, Arrays.asList(LicenseStatus.ACTIVE, LicenseStatus.PRE_ACTIVE), //
356
- Action.CANCEL, Arrays.asList(LicenseStatus.ACTIVE, LicenseStatus.PRE_ACTIVE, LicenseStatus.REQUESTED, LicenseStatus.EXPIRED), //
357
- Action.DELETE, Arrays.asList(LicenseStatus.CANCELLED, LicenseStatus.CREATED, LicenseStatus.BLOCKED), //
358
- Action.UNBLOCK, Arrays.asList(LicenseStatus.BLOCKED), //
359
- Action.BLOCK, Arrays.asList(LicenseStatus.CANCELLED) //
360
- );
378
+ /**
379
+ * Return licenses with status: REquested, ACtive, Pre-Active for a given
380
+ * request data
381
+ *
382
+ * @param requestData
383
+ * @param em
384
+ * @return
385
+ * @throws SeCurisServiceException
386
+ */
387
+ public static License findValidLicenseByRequestData(String requestData, EntityManager em) throws SeCurisServiceException {
388
+ TypedQuery<License> query = em.createNamedQuery("list-valid-licenses-by-req-data", License.class);
389
+ query.setParameter("hash", BlockedRequest.generateHash(requestData));
390
+ try {
391
+ List<License> list = query.getResultList();
392
+ if (list.size() == 0) {
393
+ return null;
394
+ }
395
+ if (list.size() > 1) {
396
+ LOG.error("There are more than 1 active or requested license for request data: {}\nHash: {}", requestData, BlockedRequest.generateHash(requestData));
397
+ }
398
+ return list.get(0);
399
+ } catch (NoResultException e) {
400
+ // There is no license for request data
401
+ return null;
402
+ }
403
+ }
361404
362
- /**
363
- * It checks if a given action is valid for the License, passing the
364
- * action and the current license status
365
- *
366
- * @param oldStatus
367
- * @param newStatus
368
- * @return
369
- */
370
- public static boolean isActionValid(Integer action, LicenseStatus currentStatus) {
371
- List<LicenseStatus> validStatuses = transitions.get(action);
372
- LOG.info("Action {} is valid ? => {} current: {} OK? {}", action, validStatuses, currentStatus, validStatuses.contains(currentStatus));
373
- return validStatuses != null && validStatuses.contains(currentStatus);
374
- }
375
- }
405
+ /**
406
+ * Return licenses with status: REquested, ACtive, Pre-Active for a given
407
+ * request data
408
+ *
409
+ * @param requestData
410
+ * @param em
411
+ * @return
412
+ * @throws SeCurisServiceException
413
+ */
414
+ public static License findLicenseByActivationCode(String activationCode, EntityManager em) throws SeCurisServiceException {
415
+ TypedQuery<License> query = em.createNamedQuery("license-by-activation-code", License.class);
416
+ query.setParameter("activationCode", activationCode);
417
+ try {
418
+ return query.getSingleResult();
419
+ } catch (NoResultException e) {
420
+ // There is no license for request data
421
+ return null;
422
+ }
423
+ }
376424
377
- /**
378
- * Return licenses with status: REquested, ACtive, Pre-Active for a given
379
- * request data
380
- *
381
- * @param requestData
382
- * @param em
383
- * @return
384
- * @throws SeCurisServiceException
385
- */
386
- public static License findValidLicenseByRequestData(String requestData, EntityManager em) throws SeCurisServiceException {
387
- TypedQuery<License> query = em.createNamedQuery("list-valid-licenses-by-req-data", License.class);
388
- query.setParameter("hash", BlockedRequest.generateHash(requestData));
389
- try {
390
- List<License> list = query.getResultList();
391
- if (list.size() == 0) {
392
- return null;
393
- }
394
- if (list.size() > 1) {
395
- LOG.error("There are more than 1 active or requested license for request data: {}\nHash: {}", requestData,
396
- BlockedRequest.generateHash(requestData));
397
- }
398
- return list.get(0);
399
- } catch (NoResultException e) {
400
- // There is no license for request data
401
- return null;
402
- }
403
- }
425
+ public static License findActiveLicenseByRequestData(String requestData, EntityManager em) throws SeCurisServiceException {
426
+ TypedQuery<License> query = em.createNamedQuery("list-active-licenses-by-req-data", License.class);
427
+ query.setParameter("hash", BlockedRequest.generateHash(requestData));
428
+ try {
429
+ List<License> list = query.getResultList();
430
+ if (list.size() == 0) {
431
+ return null;
432
+ }
433
+ if (list.size() > 1) {
434
+ LOG.error("There are more than 1 active license for request data: {}\nHash: {}", requestData, BlockedRequest.generateHash(requestData));
435
+ }
436
+ return list.get(0);
437
+ } catch (NoResultException e) {
438
+ // There is no license for request data
439
+ return null;
440
+ }
441
+ }
404442
405
- /**
406
- * Return licenses with status: REquested, ACtive, Pre-Active for a given
407
- * request data
408
- *
409
- * @param requestData
410
- * @param em
411
- * @return
412
- * @throws SeCurisServiceException
413
- */
414
- public static License findLicenseByActivationCode(String activationCode, EntityManager em) throws SeCurisServiceException {
415
- TypedQuery<License> query = em.createNamedQuery("license-by-activation-code", License.class);
416
- query.setParameter("activationCode", activationCode);
417
- try {
418
- return query.getSingleResult();
419
- } catch (NoResultException e) {
420
- // There is no license for request data
421
- return null;
422
- }
423
- }
443
+ public static License findLicenseByCode(String code, EntityManager em) throws SeCurisServiceException {
444
+ TypedQuery<License> query = em.createNamedQuery("license-by-code", License.class);
445
+ query.setParameter("code", code);
446
+ try {
447
+ return query.getSingleResult();
448
+ } catch (NoResultException e) {
449
+ // There is no license for request data
450
+ return null;
451
+ }
452
+ }
424453
425
- public static License findActiveLicenseByRequestData(String requestData, EntityManager em) throws SeCurisServiceException {
426
- TypedQuery<License> query = em.createNamedQuery("list-active-licenses-by-req-data", License.class);
427
- query.setParameter("hash", BlockedRequest.generateHash(requestData));
428
- try {
429
- List<License> list = query.getResultList();
430
- if (list.size() == 0) {
431
- return null;
432
- }
433
- if (list.size() > 1) {
434
- LOG.error("There are more than 1 active license for request data: {}\nHash: {}", requestData,
435
- BlockedRequest.generateHash(requestData));
436
- }
437
- return list.get(0);
438
- } catch (NoResultException e) {
439
- // There is no license for request data
440
- return null;
441
- }
442
- }
454
+ public Integer getCodeSuffix() {
455
+ return codeSuffix;
456
+ }
443457
444
- public static License findLicenseByCode(String code, EntityManager em) throws SeCurisServiceException {
445
- TypedQuery<License> query = em.createNamedQuery("license-by-code", License.class);
446
- query.setParameter("code", code);
447
- try {
448
- return query.getSingleResult();
449
- } catch (NoResultException e) {
450
- // There is no license for request data
451
- return null;
452
- }
453
- }
458
+ public void setCodeSuffix(Integer codeSuffix) {
459
+ this.codeSuffix = codeSuffix;
460
+ }
454461
455
- public Integer getCodeSuffix() {
456
- return codeSuffix;
457
- }
462
+ public String getActivationCode() {
463
+ return activationCode;
464
+ }
458465
459
- public void setCodeSuffix(Integer codeSuffix) {
460
- this.codeSuffix = codeSuffix;
461
- }
466
+ public void setActivationCode(String activationCode) {
467
+ this.activationCode = activationCode;
468
+ }
462469
463
- public String getActivationCode() {
464
- return activationCode;
465
- }
470
+ public boolean isMetadataObsolete() {
471
+ return metadataObsolete != null && metadataObsolete;
472
+ }
466473
467
- public void setActivationCode(String activationCode) {
468
- this.activationCode = activationCode;
469
- }
474
+ public void setMetadataObsolete(Boolean obsolete) {
475
+ this.metadataObsolete = obsolete;
476
+ }
470477
471478 }
securis/src/main/java/net/curisit/securis/db/Pack.java
....@@ -56,6 +56,8 @@
5656
5757 private String comments;
5858
59
+ private Boolean frozen;
60
+
5961 @Column(name = "creation_timestamp")
6062 @JsonProperty("creation_timestamp")
6163 private Date creationTimestamp;
....@@ -365,6 +367,14 @@
365367 return String.format("Pack: ID: %d, code: %s", id, code);
366368 }
367369
370
+ public boolean isFrozen() {
371
+ return frozen != null && frozen;
372
+ }
373
+
374
+ public void setFrozen(Boolean frozen) {
375
+ this.frozen = frozen;
376
+ }
377
+
368378 public static class Action {
369379 public static final int CREATE = 1;
370380 public static final int ACTIVATION = 2;
securis/src/main/java/net/curisit/securis/services/ApiResource.java
....@@ -268,10 +268,6 @@
268268 return renewFromPreviousLicense(lic, bsc);
269269 }
270270
271
- private SignedLicenseBean renewLicense(RequestBean req, EntityManager em) throws SeCurisServiceException {
272
- return renewLicense(req, em);
273
- }
274
-
275271 /**
276272 * Creates a new signed license from request data or from previous license
277273 * if It's a renew
securis/src/main/java/net/curisit/securis/services/PackResource.java
....@@ -44,6 +44,7 @@
4444 import net.curisit.securis.services.exception.SeCurisServiceException;
4545 import net.curisit.securis.services.exception.SeCurisServiceException.ErrorCodes;
4646 import net.curisit.securis.services.helpers.LicenseHelper;
47
+import net.curisit.securis.services.helpers.MetadataHelper;
4748 import net.curisit.securis.utils.LicUtils;
4849 import net.curisit.securis.utils.TokenHelper;
4950
....@@ -60,6 +61,9 @@
6061
6162 @Inject
6263 TokenHelper tokenHelper;
64
+
65
+ @Inject
66
+ MetadataHelper metadataHelper;
6367
6468 @Context
6569 EntityManager em;
....@@ -273,27 +277,34 @@
273277 currentPack.setEndValidDate(pack.getEndValidDate());
274278
275279 Set<PackMetadata> newMD = pack.getMetadata();
276
- Set<String> newMdKeys = getMdKeys(newMD);
277
- for (PackMetadata currentMd : currentPack.getMetadata()) {
278
- if (!newMdKeys.contains(currentMd.getKey())) {
279
- em.remove(currentMd);
280
- }
281
- }
282
-
283
- if (newMD != null) {
284
- Set<String> oldMdKeys = getMdKeys(newMD);
285
- for (PackMetadata md : newMD) {
286
- if (oldMdKeys.contains(md.getKey())) {
287
- em.merge(md);
288
- } else {
289
- md.setPack(currentPack);
290
- em.persist(md);
280
+ boolean metadataChanges = !metadataHelper.match(newMD, currentPack.getMetadata());
281
+ if (metadataChanges) {
282
+ Set<String> newMdKeys = getMdKeys(newMD);
283
+ for (PackMetadata currentMd : currentPack.getMetadata()) {
284
+ if (!newMdKeys.contains(currentMd.getKey())) {
285
+ em.remove(currentMd);
291286 }
292287 }
288
+
289
+ if (newMD != null) {
290
+ Set<String> oldMdKeys = getMdKeys(newMD);
291
+ for (PackMetadata md : newMD) {
292
+ if (oldMdKeys.contains(md.getKey())) {
293
+ em.merge(md);
294
+ } else {
295
+ md.setPack(currentPack);
296
+ em.persist(md);
297
+ }
298
+ }
299
+ }
300
+ currentPack.setMetadata(newMD);
293301 }
294
- currentPack.setMetadata(newMD);
295302 em.merge(currentPack);
296303
304
+ if (metadataChanges) {
305
+ metadataHelper.markObsoleteMetadata(em, currentPack);
306
+ }
307
+
297308 return Response.ok(currentPack).build();
298309 }
299310
securis/src/main/java/net/curisit/securis/services/helpers/MetadataHelper.java
....@@ -16,6 +16,8 @@
1616
1717 import net.curisit.securis.db.Application;
1818 import net.curisit.securis.db.ApplicationMetadata;
19
+import net.curisit.securis.db.License;
20
+import net.curisit.securis.db.LicenseStatus;
1921 import net.curisit.securis.db.LicenseType;
2022 import net.curisit.securis.db.LicenseTypeMetadata;
2123 import net.curisit.securis.db.Pack;
....@@ -108,13 +110,11 @@
108110 public void propagateMetadata(EntityManager em, Application app) {
109111 Set<ApplicationMetadata> appMd = app.getApplicationMetadata();
110112 Set<String> keys = appMd.parallelStream().map(md -> md.getKey()).collect(Collectors.toSet());
111
- log.info("App metadata keys: {}", keys);
112113 for (LicenseType lt : app.getLicenseTypes()) {
113114 log.info("Lic type to update: {}", lt.getCode());
114115 this.mergeMetadata(em, appMd, lt.getMetadata(), keys);
115116 Set<LicenseTypeMetadata> newMdList = createNewMetadata(appMd, lt.getMetadata(), lt);
116117 for (LicenseTypeMetadata newMetadata : newMdList) {
117
- log.info("MD key to add to lt: {}", newMetadata.getKey());
118118 em.persist(newMetadata);
119119 }
120120 em.detach(lt);
....@@ -142,14 +142,29 @@
142142 List<Pack> packs = packsQuery.getResultList();
143143 log.info("Packs to update the metadata: {}", packs.size());
144144 for (Pack pack : packs) {
145
+ if (pack.isFrozen()) {
146
+ log.warn("Metadata in LicenseType {} has changed but the Pack {} is frozen and won't be updated.", lt.getCode(), pack.getCode());
147
+ continue;
148
+ }
145149 this.mergeMetadata(em, ltMd, pack.getMetadata(), keys);
146150 Set<PackMetadata> newMdList = createNewMetadata(ltMd, pack.getMetadata(), pack);
147151 for (PackMetadata newMetadata : newMdList) {
148
- log.info("MD key to add to pack: {}", newMetadata.getKey());
149152 em.persist(newMetadata);
150153 }
154
+ markObsoleteMetadata(em, pack);
151155 em.detach(pack);
152156 }
153157 }
154158
159
+ public void markObsoleteMetadata(EntityManager em, Pack pack) {
160
+ TypedQuery<License> existingPackLicenses = em.createNamedQuery("list-licenses-by-pack", License.class);
161
+ existingPackLicenses.setParameter("packId", pack.getId());
162
+ for (License lic : existingPackLicenses.getResultList()) {
163
+ log.info("License from pack: {}, status: {}", lic.getCode(), lic.getStatus());
164
+ if (lic.getStatus() == LicenseStatus.ACTIVE || lic.getStatus() == LicenseStatus.PRE_ACTIVE || lic.getStatus() == LicenseStatus.CANCELLED) {
165
+ lic.setMetadataObsolete(true);
166
+ em.merge(lic);
167
+ }
168
+ }
169
+ }
155170 }
securis/src/main/resources/db/schema.sql
....@@ -90,6 +90,7 @@
9090 renew_valid_period INT NOT NULL DEFAULT 30,
9191 created_by varchar(45) NULL ,
9292 creation_timestamp TIMESTAMP NOT NULL default now(),
93
+ frozen BOOLEAN NOT NULL default false,
9394 PRIMARY KEY (id));
9495
9596 drop table IF EXISTS pack_metadata;
....@@ -122,6 +123,7 @@
122123 cancelled_by varchar(45) NULL ,
123124 created_by varchar(45) NULL ,
124125 status VARCHAR(2) NOT NULL default 'CR',
126
+ metadata_obsolete BOOLEAN NOT NULL default false,
125127 PRIMARY KEY (id),
126128 index(request_data_hash, pack_id));
127129
securis/src/main/webapp/sql_update.sql
....@@ -0,0 +1,2 @@
1
+alter table pack add column frozen BOOLEAN NOT NULL default false;
2
+alter table license add column metadata_obsolete BOOLEAN NOT NULL default false;
securis/src/main/webapp/src/app/forms/license.form.component.ts
....@@ -56,7 +56,7 @@
5656 return this.licenses[action](this.data.id).subscribe(
5757 (actionResponse : any) => {
5858 this.toaster.success(this.$L.get('Action "{}" executed successfully', action));
59
- this.reload();
59
+ this.init();
6060 },
6161 (err : any) => this.toaster.error(this.$L.get('Action "{}" failed', action))
6262 );
securis/src/main/webapp/src/app/forms/pack.form.component.ts
....@@ -69,7 +69,7 @@
6969 return this.packs[action](this.data.id).subscribe(
7070 (actionResponse : any) => {
7171 this.toaster.success(this.$L.get('Action "{}" executed successfully', action));
72
- this.reload();
72
+ this.init();
7373 },
7474 (err : any) => this.toaster.error(this.$L.get('Action "{}" failed', action))
7575 );
securis/src/main/webapp/src/app/listing/license.list.component.html
....@@ -50,6 +50,9 @@
5050 <a md-button color="primary" [href]="'mailto:' + value + '?subject=SeCuris'">{{value}}</a>
5151 </div>
5252 </template>
53
+ <template tdDataTableTemplate="metadata_obsolete" let-row="row" let-value="value">
54
+ <md-icon *ngIf="value" color="warn" [mdTooltip]="$L.get('License metadata is obsolete')">warning</md-icon>
55
+ </template>
5356 <template tdDataTableTemplate="expiration_date" let-row="row">
5457 <div layout="row">
5558 <span [class.expired]="isLicenseExpired(row)" >{{row.expiration_date | date: 'mediumDate'}}</span>
securis/src/main/webapp/src/app/listing/license.list.component.ts
....@@ -19,7 +19,7 @@
1919 created_by_id: '_client',
2020 creation_timestamp: 1447848747000,
2121 email: 'ccalvo@curisit.net',
22
- expiration_date: 1450440747000,
22
+ expiration_date: 1450440747000,
2323 full_name: 'César SA',
2424 id: 110,
2525 licenseData: '{"appCode":"CISA","appName":"CurisIntegrity SA","licenseCode":"CISA02-494-1","activationCode":"19fa8d30-29cb-4b59-81b5-3837af8204b6","expirationDate":1450440746790,"arch":"x86_64","osName":"Mac OS X","macAddresses":["60-03-08-95-AE-D0","B6-2B-33-E9-64-2D"],"crcLogo":"10f6379e0e1c00ebc403160307e3c5d0aba0727c9cae0bf1ac7cd19d84fdc80f","metadata":{"maxWellLifeLines":"50","simulationModes":"A1,A2,N1,QL"},"signature":"Tejun4bNbknxOyEmPaO/fGfGhv4URhVON/7bESxbODFWMJYKQqOPHrDiSUMlf6RbfWSVg2Dry8bY1WX881QGjTkBaHeDJKCy1EaJBwJ2nv9TYSMOiRj0eqMNYWE9/oLpvufHylAkPUpZwXVkSzTxmN+RvWa2Xt4Fu7xN+4PDHV4t7PSq7QwsFlD9ArgYC6Vx+zuL9WZANBtJ2gU/gKOE0CU0KjsB49RGQSFS/G27+H/YuDkCiQq7PC7VdVwYONQ2HO91fyPvInIrzDC5+sWHcUAqSCop//8klMy03hWl6VvAlaSP7kNM3KadyqXIJ3tx4Jwm1W+gBb3tngHzVCpYmw=="}',
....@@ -37,6 +37,7 @@
3737 pack: any = null;
3838 columns: ITdDataTableColumn[] = [
3939 { name: 'code', label: 'Code', tooltip: 'License code' },
40
+ { name: 'metadata_obsolete', label: 'Obsolete', tooltip: 'Metadata obsolete' },
4041 { name: 'full_name', label: 'User name' },
4142 { name: 'email', label: 'User email' },
4243 { name: 'expiration_date', label: 'Expiration date' },
securis/src/main/webapp/src/app/resources/licenses.ts
....@@ -3,7 +3,9 @@
33 import { Injectable } from '@angular/core';
44 import { Http, RequestOptions, ResponseContentType, Response } from '@angular/http';
55 import { SeCurisResourceServices } from './base';
6
-import * as saveAsFile from "file-saver";
6
+import "file-saver";
7
+
8
+declare var saveAs: FileSaver;
79
810 export const LIC_STATUS = {
911 CREATED: 'CR',
....@@ -109,7 +111,7 @@
109111 return this.http.get(url).map((response : Response) => {
110112 let filename = JSON.parse(response.headers.get('Content-Disposition').match(/".*"$/g)[0]);
111113 let content = JSON.stringify(response.json(), null, 2);
112
- saveAsFile( new Blob([ content ], { type : 'application/octet-stream' }), filename);
114
+ saveAs( new Blob([ content ], { type : 'application/octet-stream' }), filename);
113115 return Observable.of(true);
114116 }).catch(err => super.processErrorResponse(err));
115117 }