rsanchez
2014-12-11 36edce38f6b17f73322fa38404d6e01818a44fd2
securis/src/main/java/net/curisit/securis/services/ApiResource.java
....@@ -1,11 +1,8 @@
11 package net.curisit.securis.services;
22
3
-import java.io.File;
43 import java.io.IOException;
54 import java.util.Date;
65 import java.util.List;
7
-import java.util.Map;
8
-import java.util.TreeMap;
96
107 import javax.inject.Inject;
118 import javax.inject.Provider;
....@@ -19,7 +16,6 @@
1916 import javax.ws.rs.core.MediaType;
2017 import javax.ws.rs.core.Response;
2118
22
-import net.curisit.integrity.commons.JsonUtils;
2319 import net.curisit.securis.LicenseGenerator;
2420 import net.curisit.securis.LicenseManager;
2521 import net.curisit.securis.SeCurisException;
....@@ -27,14 +23,22 @@
2723 import net.curisit.securis.beans.RequestBean;
2824 import net.curisit.securis.beans.SignedLicenseBean;
2925 import net.curisit.securis.beans.StatusBean;
26
+import net.curisit.securis.db.BlockedRequest;
3027 import net.curisit.securis.db.License;
28
+import net.curisit.securis.db.LicenseHistory;
29
+import net.curisit.securis.db.LicenseStatus;
30
+import net.curisit.securis.db.Pack;
31
+import net.curisit.securis.db.User;
3132 import net.curisit.securis.security.BasicSecurityContext;
3233 import net.curisit.securis.security.Securable;
3334 import net.curisit.securis.services.exception.SeCurisServiceException;
3435 import net.curisit.securis.services.exception.SeCurisServiceException.ErrorCodes;
36
+import net.curisit.securis.services.helpers.LicenseHelper;
37
+import net.curisit.securis.utils.JsonUtils;
38
+import net.curisit.securis.utils.LicUtils;
39
+import net.curisit.securis.utils.SignatureHelper;
3540 import net.curisit.securis.utils.TokenHelper;
3641
37
-import org.apache.commons.io.IOUtils;
3842 import org.apache.commons.lang.time.DateUtils;
3943 import org.apache.logging.log4j.LogManager;
4044 import org.apache.logging.log4j.Logger;
....@@ -57,10 +61,15 @@
5761 TokenHelper tokenHelper;
5862
5963 @Inject
64
+ private LicenseHelper licenseHelper;
65
+
66
+ @Inject
6067 Provider<EntityManager> emProvider;
6168
6269 @Inject
6370 LicenseGenerator licenseGenerator;
71
+
72
+ private static final String CLIENT_USERNAME = "_client";
6473
6574 public ApiResource() {
6675 }
....@@ -116,15 +125,9 @@
116125 SeCurisException {
117126 LOG.info("Request to get license: {}", request);
118127
119
- Map<String, Object> metadata = getLicenseMetadata(request);
120
- License licDB = getLicenseData(request);
128
+ SignedLicenseBean lic = createLicense(request, emProvider.get(), false);
121129
122
- Date expirationDate = licDB.getExpirationDate();
123
- String licenseTypeCode = licDB.getPack().getLicenseType().getCode();
124
- String licenseCode = licDB.getCode();
125
- LicenseBean lic = licenseGenerator.generateLicense(request, metadata, expirationDate, licenseTypeCode, licenseCode);
126
- SignedLicenseBean signedLic = new SignedLicenseBean(lic);
127
- return Response.ok(signedLic).build();
130
+ return Response.ok(lic).build();
128131 }
129132
130133 /**
....@@ -186,14 +189,41 @@
186189 throw new SeCurisServiceException(ErrorCodes.LICENSE_NOT_READY_FOR_RENEW, "The license is still valid, not ready for renew");
187190 }
188191
189
- Map<String, Object> metadata = getLicenseMetadata(previousLic);
190
- License licDB = getLicenseData(previousLic);
192
+ SignedLicenseBean lic = createLicense(previousLic, emProvider.get(), true);
191193
192
- Date expirationDate = licDB.getExpirationDate();
193
- String licenseTypeCode = licDB.getPack().getLicenseType().getCode();
194
- String licenseCode = licDB.getCode();
195
- LicenseBean lic = licenseGenerator.generateLicense(previousLic, metadata, expirationDate, licenseTypeCode, licenseCode);
196194 return Response.ok(lic).build();
195
+ }
196
+
197
+ /**
198
+ * License validation on server side, in this case we validate that the
199
+ * current licenses has not been cancelled.
200
+ *
201
+ * @param currentLic
202
+ * @param bsc
203
+ * @return
204
+ * @throws IOException
205
+ * @throws SeCurisServiceException
206
+ * @throws SeCurisException
207
+ */
208
+ @POST
209
+ @Path("/validate")
210
+ @Consumes(MediaType.APPLICATION_JSON)
211
+ // TODO: Enable this: @Securable
212
+ @Produces({
213
+ MediaType.APPLICATION_JSON
214
+ })
215
+ @Transactional
216
+ public Response validate(LicenseBean currentLic, @Context BasicSecurityContext bsc) throws IOException, SeCurisServiceException, SeCurisException {
217
+ LOG.info("Validate license: {}", currentLic);
218
+ EntityManager em = emProvider.get();
219
+ try {
220
+ SignatureHelper.getInstance().validateSignature(currentLic);
221
+ } catch (SeCurisException ex) {
222
+ throw new SeCurisServiceException(ErrorCodes.LICENSE_DATA_IS_NOT_VALID, "The license signature is not valid");
223
+ }
224
+ licenseHelper.assertLicenseStatusIsActive(currentLic, em);
225
+
226
+ return Response.ok(currentLic).build();
197227 }
198228
199229 /**
....@@ -236,49 +266,90 @@
236266 return createFromRequest(lic, bsc);
237267 }
238268
239
- private License getLicenseData(RequestBean req) throws SeCurisException {
240
- // TODO: The dummy expiration date is temporal, this info should be read
241
- // from DB
242
- License lic = new License();
243
- // TODO: IMPLEMENT LICENSE GENERATION
244
-
245
- // lic.setExpirationDate(new Date(new Date().getTime() + (1000L * 3600 *
246
- // 24 * 30)));
247
- // lic.setCode(req.getPackCode() + "-LIC-INTERNAL");
248
- // LicenseType lt = new LicenseType();
249
- // lt.setCode("TYPE-" + req.getAppCode());
250
- // Pack pack = new Pack();
251
- // pack.setLicenseType(lt);
252
- // lic.setPack(pack);
253
- return lic;
254
- }
255
-
256269 /**
257
- * Extract the corresponding metadata for the Request license given
270
+ * Creates a new signed license from request data or from previous license
271
+ * if It's a renew
258272 *
259273 * @param req
274
+ * @param em
275
+ * @param renew
260276 * @return
261
- * @throws SeCurisException
277
+ * @throws SeCurisServiceException
262278 */
263
- @SuppressWarnings("unchecked")
264
- private Map<String, Object> getLicenseMetadata(RequestBean req) throws SeCurisException {
265
- // TODO: The dummy metadata file is temporal, this info should be read
266
- // from DB
267
- File dummyMetadata = new File(System.getProperty("user.home") + File.separator + ".SeCuris" + File.separator + "dummy_metadata.json");
268
- Map<String, Object> metadata = null;
269
- try {
270
- String metadataJson = IOUtils.toString(dummyMetadata.toURI());
271
- metadata = (Map<String, Object>) JsonUtils.json2map(metadataJson).get(req.getLicenseTypeCode());
272
- if (metadata == null) {
273
- throw new SeCurisException("App code in request is unknown: " + req.getLicenseTypeCode());
279
+ private SignedLicenseBean createLicense(RequestBean req, EntityManager em, boolean renew) throws SeCurisServiceException {
280
+ LicenseBean previousLicenseBean = null;
281
+ License lic = null;
282
+ if (renew) {
283
+ previousLicenseBean = (LicenseBean) req;
284
+ lic = License.findLicenseByCode(previousLicenseBean.getLicenseCode(), em);
285
+ if (lic.getStatus() != LicenseStatus.ACTIVE && lic.getStatus() != LicenseStatus.PRE_ACTIVE) {
286
+ throw new SeCurisServiceException(ErrorCodes.INVALID_DATA, "The current license has been cancelled");
274287 }
275
- metadata = new TreeMap<>(metadata);
276
- } catch (IOException e) {
277
- LOG.error("Error reading dummy metadata file", e);
278
- throw new SeCurisException("Error reading dummy metadata file");
288
+ } else {
289
+ lic = new License();
279290 }
280291
281
- return metadata;
292
+ if (!renew) {
293
+ License existingLicense = License.findLicenseByRequestData(lic.getRequestData(), em);
294
+ if (existingLicense != null) {
295
+ throw new SeCurisServiceException(ErrorCodes.DUPLICATED_REQUEST_DATA, "There is already an active license for current request data");
296
+ }
297
+ }
298
+ Pack pack = em.createNamedQuery("pack-by-code", Pack.class).setParameter("code", req.getPackCode()).getSingleResult();
299
+
300
+ if (!renew && pack.getNumAvailables() <= 0) {
301
+ throw new SeCurisServiceException(ErrorCodes.NO_AVAILABLE_LICENSES, "The current pack has no licenses availables");
302
+ }
303
+ SignedLicenseBean signedLicense;
304
+ try {
305
+ String licCode;
306
+ if (renew) {
307
+ licCode = previousLicenseBean.getLicenseCode();
308
+ } else {
309
+ licCode = LicUtils.getLicenseCode(pack.getCode(), licenseHelper.getNextCodeSuffix(pack.getId(), em));
310
+ }
311
+ Date expirationDate = licenseHelper.getExpirationDateFromPack(pack, !renew);
312
+
313
+ LicenseBean lb = licenseGenerator.generateLicense(req, licenseHelper.extractPackMetadata(pack.getMetadata()), expirationDate, licCode,
314
+ pack.getAppName());
315
+ signedLicense = new SignedLicenseBean(lb);
316
+ } catch (SeCurisException e) {
317
+ throw new SeCurisServiceException(ErrorCodes.INVALID_LICENSE_REQUEST_DATA, "Error generating license: " + e.toString());
318
+ }
319
+ try {
320
+ lic.setRequestData(JsonUtils.toJSON(signedLicense, RequestBean.class));
321
+ if (BlockedRequest.isRequestBlocked(lic.getRequestData(), em)) {
322
+ throw new SeCurisServiceException(ErrorCodes.BLOCKED_REQUEST_DATA, "Given request data is blocked and cannot be activated");
323
+ }
324
+ lic.setLicenseData(JsonUtils.toJSON(signedLicense));
325
+ } catch (SeCurisException e) {
326
+ LOG.error("Error generating license JSON", e);
327
+ throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Error generating license JSON");
328
+ }
329
+
330
+ lic.setModificationTimestamp(new Date());
331
+ lic.setExpirationDate(signedLicense.getExpirationDate());
332
+ User user = em.find(User.class, CLIENT_USERNAME);
333
+ if (!renew) {
334
+
335
+ lic.setPack(pack);
336
+ lic.setCreatedBy(user);
337
+ lic.setCreationTimestamp(new Date());
338
+ lic.setStatus(LicenseStatus.PRE_ACTIVE);
339
+ lic.setCode(signedLicense.getLicenseCode());
340
+ lic.setCodeSuffix(LicUtils.getLicenseCodeSuffix(signedLicense.getLicenseCode()));
341
+ em.persist(lic);
342
+ em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.CREATE));
343
+ if (lic.getStatus() == LicenseStatus.ACTIVE) {
344
+ em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.PRE_ACTIVATE, "Pre-activated on creation"));
345
+ }
346
+ } else {
347
+ lic.setStatus(LicenseStatus.ACTIVE);
348
+ em.merge(lic);
349
+ em.persist(licenseHelper.createLicenseHistoryAction(lic, user, LicenseHistory.Actions.RENEW));
350
+ }
351
+
352
+ return signedLicense;
282353 }
283354
284355 }