package net.curisit.securis.db; import java.io.Serializable; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Map; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EntityListeners; import javax.persistence.EntityManager; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.NoResultException; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.TypedQuery; import net.curisit.integrity.commons.Utils; import net.curisit.securis.db.common.CreationTimestampEntity; import net.curisit.securis.db.common.ModificationTimestampEntity; import net.curisit.securis.db.listeners.CreationTimestampListener; import net.curisit.securis.db.listeners.ModificationTimestampListener; import net.curisit.securis.services.exception.SeCurisServiceException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.hibernate.annotations.Type; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; /** * Entity implementation class for Entity: license * */ @JsonAutoDetect @JsonInclude(Include.NON_NULL) @Entity @EntityListeners({ CreationTimestampListener.class, ModificationTimestampListener.class }) @Table(name = "license") @JsonIgnoreProperties(ignoreUnknown = true) @NamedQueries({ @NamedQuery(name = "license-by-code", query = "SELECT l FROM License l where l.code = :code"), @NamedQuery(name = "last-code-suffix-used-in-pack", query = "SELECT max(l.codeSuffix) FROM License l where l.pack.id = :packId"), @NamedQuery(name = "list-licenses-by-pack", query = "SELECT l FROM License l where l.pack.id = :packId"), @NamedQuery(name = "list-licenses-by-req-data", query = "SELECT l FROM License l where l.reqDataHash = :hash"), @NamedQuery(name = "list-active-licenses-by-req-data", query = "SELECT l FROM License l where l.reqDataHash = :hash and l.status in ('AC', 'PA')"), @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')") }) public class License implements CreationTimestampEntity, ModificationTimestampEntity, Serializable { private static final long serialVersionUID = 2700310404904877227L; private static final Logger LOG = LogManager.getLogger(License.class); @Id @GeneratedValue private int id; private String code; @Column(name = "code_suffix") @JsonProperty("code_suffix") private Integer codeSuffix; @JsonIgnore @ManyToOne @JoinColumn(name = "pack_id") private Pack pack; @JsonIgnore @ManyToOne @JoinColumn(name = "created_by") private User createdBy; @JsonIgnore @ManyToOne @JoinColumn(name = "cancelled_by") private User cancelledBy; @Type(type = "net.curisit.securis.db.common.LicenseStatusType") private LicenseStatus status; @Column(name = "full_name") @JsonProperty("full_name") private String fullName; private String email; @Column(name = "request_data") @JsonProperty("request_data") private String requestData; /** * request data hash is automatically set when we use * {@link License#setRequestData(String)} method */ @Column(name = "request_data_hash") @JsonIgnore private String reqDataHash; @Column(name = "license_data") @JsonProperty("license_data") @JsonIgnore // The license data is sent to user as a separate file, It doesn't need to // be included as License attribute on browser private String licenseData; @Column(name = "creation_timestamp") @JsonProperty("creation_timestamp") private Date creationTimestamp; @Column(name = "modification_timestamp") @JsonProperty("modification_timestamp") private Date modificationTimestamp; @Column(name = "last_access_timestamp") @JsonProperty("last_access_timestamp") private Date lastAccessTimestamp; @Column(name = "expiration_date") @JsonProperty("expiration_date") private Date expirationDate; private String comments; @OneToMany(fetch = FetchType.LAZY, mappedBy = "license") @JsonIgnore private List history; public int getId() { return id; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } @Override public Date getCreationTimestamp() { return creationTimestamp; } @Override public void setCreationTimestamp(Date creationTimestamp) { this.creationTimestamp = creationTimestamp; } public User getCreatedBy() { return createdBy; } public void setCreatedBy(User createdBy) { this.createdBy = createdBy; } public Pack getPack() { return pack; } public void setPack(Pack pack) { this.pack = pack; } @JsonProperty("created_by_id") public String getCreatedById() { return createdBy == null ? null : createdBy.getUsername(); } @JsonProperty("created_by_id") public void setCreatedById(String username) { if (username == null) { createdBy = null; } else { createdBy = new User(); createdBy.setUsername(username); } } @JsonProperty("cancelled_by_id") public String getCancelledById() { return cancelledBy == null ? null : cancelledBy.getUsername(); } @JsonProperty("cancelled_by_id") public void setCancelledById(String username) { if (username == null) { cancelledBy = null; } else { cancelledBy = new User(); cancelledBy.setUsername(username); } } @JsonProperty("pack_code") public String getPackCode() { return pack == null ? null : pack.getCode(); } @JsonProperty("pack_id") public Integer getPackId() { return pack == null ? null : pack.getId(); } @JsonProperty("pack_id") public void setPackId(Integer idPack) { if (idPack == null) { pack = null; } else { pack = new Pack(); pack.setId(idPack); } } public LicenseStatus getStatus() { return status; } public void setStatus(LicenseStatus status) { this.status = status; } @Override public Date getModificationTimestamp() { return modificationTimestamp; } @Override public void setModificationTimestamp(Date modificationTimestamp) { this.modificationTimestamp = modificationTimestamp; } public String getFullName() { return fullName; } public void setFullName(String fullName) { this.fullName = fullName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public void setId(int id) { this.id = id; } public User getCancelledBy() { return cancelledBy; } public void setCancelledBy(User cancelledBy) { this.cancelledBy = cancelledBy; } public Date getLastAccessTimestamp() { return lastAccessTimestamp; } public void setLastAccessTimestamp(Date lastAccessTimestamp) { this.lastAccessTimestamp = lastAccessTimestamp; } public String getRequestData() { return requestData; } public void setRequestData(String requestData) { this.requestData = requestData; this.reqDataHash = BlockedRequest.generateHash(this.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 List getHistory() { return history; } public void setHistory(List history) { this.history = history; } public Date getExpirationDate() { return expirationDate; } public void setExpirationDate(Date expirationDate) { this.expirationDate = expirationDate; } public String getReqDataHash() { return reqDataHash; } public static class Action { public static final int CREATE = 1; public static final int REQUEST = 2; public static final int ACTIVATION = 3; public static final int SEND = 4; public static final int DOWNLOAD = 5; public static final int CANCEL = 6; public static final int DELETE = 7; public static final int BLOCK = 8; public static final int UNBLOCK = 9; } public static class Status { private static final Map> transitions = Utils.createMap( // Action.REQUEST, Arrays.asList(LicenseStatus.CREATED, LicenseStatus.REQUESTED), // Action.ACTIVATION, Arrays.asList(LicenseStatus.CREATED, LicenseStatus.REQUESTED, LicenseStatus.PRE_ACTIVE, LicenseStatus.EXPIRED), // Action.SEND, Arrays.asList(LicenseStatus.ACTIVE, LicenseStatus.PRE_ACTIVE), // Action.DOWNLOAD, Arrays.asList(LicenseStatus.ACTIVE, LicenseStatus.PRE_ACTIVE), // Action.CANCEL, Arrays.asList(LicenseStatus.ACTIVE, LicenseStatus.PRE_ACTIVE, LicenseStatus.REQUESTED, LicenseStatus.EXPIRED), // Action.DELETE, Arrays.asList(LicenseStatus.CANCELLED, LicenseStatus.CREATED, LicenseStatus.BLOCKED), // Action.UNBLOCK, Arrays.asList(LicenseStatus.BLOCKED), // Action.BLOCK, Arrays.asList(LicenseStatus.CANCELLED) // ); /** * It checks if a given action is valid for the License, passing the * action and the current license status * * @param oldStatus * @param newStatus * @return */ public static boolean isActionValid(Integer action, LicenseStatus currentStatus) { List validStatuses = transitions.get(action); LOG.info("Action {} is valid ? => {} current: {} OK? {}", action, validStatuses, currentStatus, validStatuses.contains(currentStatus)); return validStatuses != null && validStatuses.contains(currentStatus); } } /** * Return licenses with status: REquested, ACtive, Pre-Active for a given * request data * * @param requestData * @param em * @return * @throws SeCurisServiceException */ public static License findValidLicenseByRequestData(String requestData, EntityManager em) throws SeCurisServiceException { TypedQuery query = em.createNamedQuery("list-valid-licenses-by-req-data", License.class); query.setParameter("hash", BlockedRequest.generateHash(requestData)); try { List list = query.getResultList(); if (list.size() == 0) { return null; } if (list.size() > 1) { LOG.error("There are more than 1 active or requested license for request data: {}\nHash: {}", requestData, BlockedRequest.generateHash(requestData)); } return list.get(0); } catch (NoResultException e) { // There is no license for request data return null; } } public static License findActiveLicenseByRequestData(String requestData, EntityManager em) throws SeCurisServiceException { TypedQuery query = em.createNamedQuery("list-active-licenses-by-req-data", License.class); query.setParameter("hash", BlockedRequest.generateHash(requestData)); try { List list = query.getResultList(); if (list.size() == 0) { return null; } if (list.size() > 1) { LOG.error("There are more than 1 active license for request data: {}\nHash: {}", requestData, BlockedRequest.generateHash(requestData)); } return list.get(0); } catch (NoResultException e) { // There is no license for request data return null; } } public static License findLicenseByCode(String code, EntityManager em) throws SeCurisServiceException { TypedQuery query = em.createNamedQuery("license-by-code", License.class); query.setParameter("code", code); try { return query.getSingleResult(); } catch (NoResultException e) { // There is no license for request data return null; } } public Integer getCodeSuffix() { return codeSuffix; } public void setCodeSuffix(Integer codeSuffix) { this.codeSuffix = codeSuffix; } }