#2021 feature - Added blocked request table and refactoring License
actions
3 files added
15 files modified
| .. | .. |
|---|
| 59 | 59 | <dependency> |
|---|
| 60 | 60 | <groupId>net.curisit</groupId> |
|---|
| 61 | 61 | <artifactId>securis-client</artifactId> |
|---|
| 62 | | - <version>0.9.8-SNAPSHOT</version> |
|---|
| 62 | + <version>1.0.1-SNAPSHOT</version> |
|---|
| 63 | 63 | </dependency> |
|---|
| 64 | 64 | <dependency> |
|---|
| 65 | 65 | <groupId>org.hibernate</groupId> |
|---|
| 66 | 66 | <artifactId>hibernate-c3p0</artifactId> |
|---|
| 67 | 67 | <version>4.3.6.Final</version> |
|---|
| 68 | 68 | </dependency> |
|---|
| 69 | + <dependency> |
|---|
| 70 | + <groupId>org.apache.httpcomponents</groupId> |
|---|
| 71 | + <artifactId>httpclient</artifactId> |
|---|
| 72 | + <version>4.4-beta1</version> |
|---|
| 73 | + </dependency> |
|---|
| 74 | + <dependency> |
|---|
| 75 | + <groupId>org.apache.httpcomponents</groupId> |
|---|
| 76 | + <artifactId>httpmime</artifactId> |
|---|
| 77 | + <version>4.4-beta1</version> |
|---|
| 78 | + </dependency> |
|---|
| 69 | 79 | </dependencies> |
|---|
| 70 | 80 | <build> |
|---|
| 71 | 81 | <plugins> |
|---|
| .. | .. |
|---|
| 11 | 11 | import java.security.Signature; |
|---|
| 12 | 12 | import java.security.SignatureException; |
|---|
| 13 | 13 | import java.security.spec.InvalidKeySpecException; |
|---|
| 14 | | -import java.text.MessageFormat; |
|---|
| 15 | 14 | import java.util.Date; |
|---|
| 16 | 15 | import java.util.Map; |
|---|
| 17 | 16 | import java.util.TreeMap; |
|---|
| .. | .. |
|---|
| 57 | 56 | * @return |
|---|
| 58 | 57 | * @throws SeCurisException |
|---|
| 59 | 58 | */ |
|---|
| 60 | | - public LicenseBean generateLicense(RequestBean req, Map<String, Object> metadata, Date expirationDate, String licenseType, String licenseCode) |
|---|
| 59 | + public LicenseBean generateLicense(RequestBean req, Map<String, Object> metadata, Date expirationDate, String licenseCode, String appName) |
|---|
| 61 | 60 | throws SeCurisException { |
|---|
| 62 | | - LOG.info(MessageFormat.format("Generating license: MAC: {0}, Customer code: {1}, AppCode: {2}", req.getMacAddresses(), req.getCustomerCode(), |
|---|
| 63 | | - req.getAppCode())); |
|---|
| 61 | + LOG.debug("Generating license: MAC: {}, Customer code: {}, AppName: {}", req.getMacAddresses(), req.getCustomerCode(), appName); |
|---|
| 64 | 62 | LicenseBean license = new LicenseBean(req); |
|---|
| 65 | | - license.setLicenseType(licenseType); |
|---|
| 66 | | - license.setLicenseCode(licenseCode); |
|---|
| 63 | + license.setAppName(appName); |
|---|
| 67 | 64 | license.setExpirationDate(expirationDate); |
|---|
| 68 | 65 | license.setMetadata(metadata); |
|---|
| 69 | 66 | sign(license); |
|---|
| .. | .. |
|---|
| 82 | 79 | SignedLicenseBean signedLic = new SignedLicenseBean(license); |
|---|
| 83 | 80 | byte[] json; |
|---|
| 84 | 81 | try { |
|---|
| 85 | | - json = JsonUtils.toJSON(signedLic, true).getBytes("utf-8"); |
|---|
| 82 | + json = JsonUtils.toPrettyJSON(signedLic).getBytes("utf-8"); |
|---|
| 86 | 83 | Files.write(Paths.get(file.toURI()), json, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); |
|---|
| 87 | 84 | } catch (UnsupportedEncodingException e) { |
|---|
| 88 | 85 | LOG.error("Error creating json doc from license: " + license, e); |
|---|
| .. | .. |
|---|
| 97 | 94 | } |
|---|
| 98 | 95 | |
|---|
| 99 | 96 | /** |
|---|
| 100 | | - * TODO: This method should be removed from client code. |
|---|
| 101 | 97 | * |
|---|
| 102 | 98 | * @param licBean |
|---|
| 103 | 99 | * @return |
|---|
| .. | .. |
|---|
| 113 | 109 | Signature signature; |
|---|
| 114 | 110 | try { |
|---|
| 115 | 111 | signature = Signature.getInstance(SignatureHelper.SIGNATURE_GENERATION_ALGORITHM); |
|---|
| 116 | | - signature.initSign(sh.generatePrivateKey(new File(System.getProperty("user.home") + File.separator + ".SeCuris" + File.separator + "keys" + File.separator + "securis_private_key.pkcs8"))); |
|---|
| 112 | + signature.initSign(sh.generatePrivateKey(new File(System.getProperty("user.home") + File.separator + ".SeCuris" + File.separator + "keys" |
|---|
| 113 | + + File.separator + "securis_private_key.pkcs8"))); |
|---|
| 117 | 114 | |
|---|
| 118 | 115 | sh.prepareSignature(signature, licBean); |
|---|
| 119 | 116 | |
|---|
| .. | .. |
|---|
| 147 | 144 | metadata.put("timeThreshold", 0); |
|---|
| 148 | 145 | metadata.put("datasetPrefix", "BP"); |
|---|
| 149 | 146 | metadata.put("extendedMode", true); |
|---|
| 150 | | - |
|---|
| 147 | + |
|---|
| 151 | 148 | Date expirationDate = new Date(new Date().getTime() + (1000L * 3600 * 24 * 365 * 10)); |
|---|
| 152 | 149 | LicenseBean lic = LicenseGenerator.getInstance().generateLicense(req, metadata, expirationDate, "CI-01", "LIC-CURISTEC-0001"); |
|---|
| 153 | 150 | LicenseGenerator.getInstance().save(lic, new File("/Users/cproberto/Desktop/AxelLicCI.lic")); |
|---|
| .. | .. |
|---|
| 156 | 153 | |
|---|
| 157 | 154 | } |
|---|
| 158 | 155 | } |
|---|
| 159 | | - |
|---|
| .. | .. |
|---|
| 65 | 65 | CONSOLE.info(" $ ./securis-server.sh {start|stop}");
|
|---|
| 66 | 66 | }
|
|---|
| 67 | 67 |
|
|---|
| 68 | + private void testMail() {
|
|---|
| 69 | +
|
|---|
| 70 | + }
|
|---|
| 71 | +
|
|---|
| 68 | 72 | public static void main(String[] args) throws Exception {
|
|---|
| 69 | 73 | String command;
|
|---|
| 70 | 74 | if (args.length > 0) {
|
|---|
| .. | .. |
|---|
| 1 | +package net.curisit.securis.db; |
|---|
| 2 | + |
|---|
| 3 | +import java.io.Serializable; |
|---|
| 4 | +import java.util.Date; |
|---|
| 5 | + |
|---|
| 6 | +import javax.persistence.Column; |
|---|
| 7 | +import javax.persistence.Entity; |
|---|
| 8 | +import javax.persistence.Id; |
|---|
| 9 | +import javax.persistence.JoinColumn; |
|---|
| 10 | +import javax.persistence.ManyToOne; |
|---|
| 11 | +import javax.persistence.Table; |
|---|
| 12 | + |
|---|
| 13 | +import org.codehaus.jackson.annotate.JsonAutoDetect; |
|---|
| 14 | +import org.codehaus.jackson.annotate.JsonIgnore; |
|---|
| 15 | +import org.codehaus.jackson.annotate.JsonIgnoreProperties; |
|---|
| 16 | +import org.codehaus.jackson.annotate.JsonProperty; |
|---|
| 17 | +import org.codehaus.jackson.map.annotate.JsonSerialize; |
|---|
| 18 | + |
|---|
| 19 | +/** |
|---|
| 20 | + * Entity implementation class for Entity: pack |
|---|
| 21 | + * |
|---|
| 22 | + */ |
|---|
| 23 | +@JsonAutoDetect |
|---|
| 24 | +@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) |
|---|
| 25 | +@Entity |
|---|
| 26 | +@Table(name = "blocked_request") |
|---|
| 27 | +@JsonIgnoreProperties(ignoreUnknown = true) |
|---|
| 28 | +public class BlockedRequest implements Serializable { |
|---|
| 29 | + |
|---|
| 30 | + private static final long serialVersionUID = 1L; |
|---|
| 31 | + |
|---|
| 32 | + @Id |
|---|
| 33 | + private String hash; |
|---|
| 34 | + |
|---|
| 35 | + @Column(name = "request_data") |
|---|
| 36 | + @JsonProperty("request_data") |
|---|
| 37 | + private String requestData; |
|---|
| 38 | + |
|---|
| 39 | + @Column(name = "creation_timestamp") |
|---|
| 40 | + @JsonProperty("creation_timestamp") |
|---|
| 41 | + private Date creationTimestamp; |
|---|
| 42 | + |
|---|
| 43 | + @JsonIgnore |
|---|
| 44 | + @ManyToOne |
|---|
| 45 | + @JoinColumn(name = "blocked_by") |
|---|
| 46 | + private User blockedBy; |
|---|
| 47 | + |
|---|
| 48 | + public Date getCreationTimestamp() { |
|---|
| 49 | + return creationTimestamp; |
|---|
| 50 | + } |
|---|
| 51 | + |
|---|
| 52 | + public void setCreationTimestamp(Date creationTimestamp) { |
|---|
| 53 | + this.creationTimestamp = creationTimestamp; |
|---|
| 54 | + } |
|---|
| 55 | + |
|---|
| 56 | + @Override |
|---|
| 57 | + public boolean equals(Object obj) { |
|---|
| 58 | + if (!(obj instanceof BlockedRequest)) |
|---|
| 59 | + return false; |
|---|
| 60 | + BlockedRequest other = (BlockedRequest) obj; |
|---|
| 61 | + return hash.equals(other.hash); |
|---|
| 62 | + } |
|---|
| 63 | + |
|---|
| 64 | + @Override |
|---|
| 65 | + public int hashCode() { |
|---|
| 66 | + |
|---|
| 67 | + return (hash == null ? 0 : hash.hashCode()); |
|---|
| 68 | + } |
|---|
| 69 | + |
|---|
| 70 | + public String getRequestData() { |
|---|
| 71 | + return requestData; |
|---|
| 72 | + } |
|---|
| 73 | + |
|---|
| 74 | + public void setRequestData(String requestData) { |
|---|
| 75 | + this.requestData = requestData; |
|---|
| 76 | + } |
|---|
| 77 | + |
|---|
| 78 | + public User getBlockedBy() { |
|---|
| 79 | + return blockedBy; |
|---|
| 80 | + } |
|---|
| 81 | + |
|---|
| 82 | + public void setBlockedBy(User blockedBy) { |
|---|
| 83 | + this.blockedBy = blockedBy; |
|---|
| 84 | + } |
|---|
| 85 | +} |
|---|
| .. | .. |
|---|
| 63 | 63 | @JoinColumn(name = "canceled_by") |
|---|
| 64 | 64 | private User canceledBy; |
|---|
| 65 | 65 | |
|---|
| 66 | | - private int status; |
|---|
| 66 | + private LicenseStatus status; |
|---|
| 67 | 67 | |
|---|
| 68 | 68 | @Column(name = "full_name") |
|---|
| 69 | 69 | @JsonProperty("full_name") |
|---|
| .. | .. |
|---|
| 186 | 186 | } |
|---|
| 187 | 187 | } |
|---|
| 188 | 188 | |
|---|
| 189 | | - public int getStatus() { |
|---|
| 189 | + public LicenseStatus getStatus() { |
|---|
| 190 | 190 | return status; |
|---|
| 191 | 191 | } |
|---|
| 192 | 192 | |
|---|
| 193 | | - public void setStatus(int status) { |
|---|
| 193 | + public void setStatus(LicenseStatus status) { |
|---|
| 194 | 194 | this.status = status; |
|---|
| 195 | 195 | } |
|---|
| 196 | 196 | |
|---|
| .. | .. |
|---|
| 289 | 289 | } |
|---|
| 290 | 290 | |
|---|
| 291 | 291 | public static class Status { |
|---|
| 292 | | - public static final int CREATED = 1; |
|---|
| 293 | | - public static final int REQUESTED = 2; |
|---|
| 294 | | - public static final int PREACTIVE = 3; |
|---|
| 295 | | - public static final int ACTIVE = 4; |
|---|
| 296 | | - public static final int EXPIRED = 5; |
|---|
| 297 | | - public static final int CANCELED = 6; |
|---|
| 298 | | - public static final int DELETED = 7; |
|---|
| 299 | 292 | |
|---|
| 300 | 293 | private static final Map<Integer, List<Integer>> transitions = Utils.createMap( // |
|---|
| 301 | | - Action.REQUEST, Arrays.asList(CREATED, REQUESTED), // |
|---|
| 302 | | - Action.ACTIVATION, Arrays.asList(REQUESTED, PREACTIVE, EXPIRED), // |
|---|
| 303 | | - Action.SEND, Arrays.asList(ACTIVE, PREACTIVE), // |
|---|
| 304 | | - Action.DOWNLOAD, Arrays.asList(ACTIVE, PREACTIVE), // |
|---|
| 305 | | - Action.CANCEL, Arrays.asList(ACTIVE, PREACTIVE, REQUESTED, EXPIRED), // |
|---|
| 306 | | - Action.DELETE, Arrays.asList(CANCELED, CREATED) // |
|---|
| 294 | + Action.REQUEST, Arrays.asList(LicenseStatus.CREATED, LicenseStatus.REQUESTED), // |
|---|
| 295 | + Action.ACTIVATION, Arrays.asList(LicenseStatus.REQUESTED, LicenseStatus.PRE_ACTIVE, LicenseStatus.EXPIRED), // |
|---|
| 296 | + Action.SEND, Arrays.asList(LicenseStatus.ACTIVE, LicenseStatus.PRE_ACTIVE), // |
|---|
| 297 | + Action.DOWNLOAD, Arrays.asList(LicenseStatus.ACTIVE, LicenseStatus.PRE_ACTIVE), // |
|---|
| 298 | + Action.CANCEL, Arrays.asList(LicenseStatus.ACTIVE, LicenseStatus.PRE_ACTIVE, LicenseStatus.REQUESTED, LicenseStatus.EXPIRED), // |
|---|
| 299 | + Action.DELETE, Arrays.asList(LicenseStatus.CANCELLED, LicenseStatus.CREATED) // |
|---|
| 307 | 300 | |
|---|
| 308 | 301 | ); |
|---|
| 309 | 302 | |
|---|
| .. | .. |
|---|
| 315 | 308 | * @param newStatus |
|---|
| 316 | 309 | * @return |
|---|
| 317 | 310 | */ |
|---|
| 318 | | - public static boolean isActionValid(Integer action, Integer currentStatus) { |
|---|
| 311 | + public static boolean isActionValid(Integer action, LicenseStatus currentStatus) { |
|---|
| 319 | 312 | List<Integer> validStatuses = transitions.get(currentStatus); |
|---|
| 320 | 313 | |
|---|
| 321 | 314 | return validStatuses != null && validStatuses.contains(currentStatus); |
|---|
| .. | .. |
|---|
| 111 | 111 | public static final String ADD_REQUEST = "request"; |
|---|
| 112 | 112 | public static final String SEND = "send"; |
|---|
| 113 | 113 | public static final String MODIFY = "modify"; |
|---|
| 114 | + public static final String DOWNLOAD = "download"; |
|---|
| 114 | 115 | public static final String ACTIVATE = "activate"; |
|---|
| 115 | 116 | public static final String CANCEL = "cancel"; |
|---|
| 117 | + public static final String BLOCK = "block"; |
|---|
| 116 | 118 | public static final String DELETE = "delete"; |
|---|
| 117 | 119 | } |
|---|
| 118 | 120 | } |
|---|
| .. | .. |
|---|
| 1 | +package net.curisit.securis.db; |
|---|
| 2 | + |
|---|
| 3 | +import org.codehaus.jackson.annotate.JsonCreator; |
|---|
| 4 | +import org.codehaus.jackson.annotate.JsonValue; |
|---|
| 5 | + |
|---|
| 6 | +/** |
|---|
| 7 | + * Contains the possible license statuses. For further details: |
|---|
| 8 | + * https://redmine.curistec.com/projects/securis/wiki/LicensesServerManagement |
|---|
| 9 | + * |
|---|
| 10 | + * @author rob |
|---|
| 11 | + */ |
|---|
| 12 | +public enum LicenseStatus { |
|---|
| 13 | + CREATED("CR"), REQUESTED("RE"), ACTIVE("AC"), PRE_ACTIVE("PA"), EXPIRED("EX"), CANCELLED("CA"); |
|---|
| 14 | + |
|---|
| 15 | + private final String code; |
|---|
| 16 | + |
|---|
| 17 | + LicenseStatus(String code) { |
|---|
| 18 | + this.code = code; |
|---|
| 19 | + } |
|---|
| 20 | + |
|---|
| 21 | + public String getCode() { |
|---|
| 22 | + return code; |
|---|
| 23 | + } |
|---|
| 24 | + |
|---|
| 25 | + @JsonCreator |
|---|
| 26 | + public static LicenseStatus valueFromCode(String code) { |
|---|
| 27 | + for (LicenseStatus ps : LicenseStatus.values()) { |
|---|
| 28 | + if (ps.code.equals(code)) { |
|---|
| 29 | + return ps; |
|---|
| 30 | + } |
|---|
| 31 | + } |
|---|
| 32 | + return null; |
|---|
| 33 | + } |
|---|
| 34 | + |
|---|
| 35 | + @JsonValue |
|---|
| 36 | + public String getName() { |
|---|
| 37 | + |
|---|
| 38 | + return this.code; |
|---|
| 39 | + } |
|---|
| 40 | +} |
|---|
| .. | .. |
|---|
| 74 | 74 | @Column(name = "num_licenses") |
|---|
| 75 | 75 | @JsonProperty("num_licenses") |
|---|
| 76 | 76 | private int numLicenses; |
|---|
| 77 | | - |
|---|
| 77 | + |
|---|
| 78 | 78 | @Column(name = "init_valid_date") |
|---|
| 79 | 79 | @JsonProperty("init_valid_date") |
|---|
| 80 | 80 | private Date initValidDate; |
|---|
| .. | .. |
|---|
| 155 | 155 | } |
|---|
| 156 | 156 | int num = 0; |
|---|
| 157 | 157 | for (License lic : licenses) { |
|---|
| 158 | | - if (lic.getStatus() == License.Status.ACTIVE) { |
|---|
| 158 | + if (lic.getStatus() == LicenseStatus.ACTIVE || lic.getStatus() == LicenseStatus.PRE_ACTIVE) { |
|---|
| 159 | 159 | num++; |
|---|
| 160 | 160 | } |
|---|
| 161 | 161 | } |
|---|
| .. | .. |
|---|
| 176 | 176 | } |
|---|
| 177 | 177 | int num = 0; |
|---|
| 178 | 178 | for (License lic : licenses) { |
|---|
| 179 | | - if (lic.getStatus() != License.Status.CANCELED) { |
|---|
| 179 | + if (lic.getStatus() != LicenseStatus.CANCELLED) { |
|---|
| 180 | 180 | num++; |
|---|
| 181 | 181 | } |
|---|
| 182 | 182 | } |
|---|
| .. | .. |
|---|
| 190 | 190 | */ |
|---|
| 191 | 191 | @JsonProperty("num_available") |
|---|
| 192 | 192 | public int getNumAvailables() { |
|---|
| 193 | | - return numLicenses - getNumCreations(); |
|---|
| 193 | + return numLicenses - getNumActivations(); |
|---|
| 194 | 194 | } |
|---|
| 195 | 195 | |
|---|
| 196 | 196 | @JsonProperty("organization_name") |
|---|
| .. | .. |
|---|
| 250 | 250 | |
|---|
| 251 | 251 | @JsonProperty("created_by_name") |
|---|
| 252 | 252 | public String getCreatedByname() { |
|---|
| 253 | | - return createdBy == null ? null : String.format("%s %s (%s)", createdBy.getFirstName(), createdBy.getLastName() != null ? createdBy.getLastName() : "", createdBy.getUsername()); |
|---|
| 253 | + return createdBy == null ? null : String.format("%s %s (%s)", createdBy.getFirstName(), |
|---|
| 254 | + createdBy.getLastName() != null ? createdBy.getLastName() : "", createdBy.getUsername()); |
|---|
| 254 | 255 | } |
|---|
| 255 | 256 | |
|---|
| 256 | 257 | @JsonProperty("licensetype_code") |
|---|
| 257 | | - public String getLicenseTypcode() { |
|---|
| 258 | + public String getLicenseTypeCode() { |
|---|
| 258 | 259 | return licenseType == null ? null : licenseType.getCode(); |
|---|
| 259 | 260 | } |
|---|
| 260 | 261 | |
|---|
| .. | .. |
|---|
| 310 | 311 | public boolean equals(Object obj) { |
|---|
| 311 | 312 | if (!(obj instanceof Pack)) |
|---|
| 312 | 313 | return false; |
|---|
| 313 | | - Pack other = (Pack)obj; |
|---|
| 314 | + Pack other = (Pack) obj; |
|---|
| 314 | 315 | return id.equals(other.id); |
|---|
| 315 | 316 | } |
|---|
| 316 | | - |
|---|
| 317 | + |
|---|
| 317 | 318 | @Override |
|---|
| 318 | 319 | public int hashCode() { |
|---|
| 319 | | - |
|---|
| 320 | + |
|---|
| 320 | 321 | return (id == null ? 0 : id.hashCode()); |
|---|
| 321 | 322 | } |
|---|
| 322 | 323 | } |
|---|
| .. | .. |
|---|
| 3 | 3 | import org.codehaus.jackson.annotate.JsonCreator; |
|---|
| 4 | 4 | import org.codehaus.jackson.annotate.JsonValue; |
|---|
| 5 | 5 | |
|---|
| 6 | +/** |
|---|
| 7 | + * Contains the possible pack statuses. For further details: |
|---|
| 8 | + * https://redmine.curistec.com/projects/securis/wiki/LicensesServerManagement |
|---|
| 9 | + * |
|---|
| 10 | + * @author rob |
|---|
| 11 | + */ |
|---|
| 6 | 12 | public enum PackStatus { |
|---|
| 7 | | - PENDING("PE"), ACTIVE("AC"), ON_HOLD("OH"), EXPIRED("EX"), CANCELLED("CA"); |
|---|
| 8 | | - |
|---|
| 13 | + CREATED("CR"), ACTIVE("AC"), ON_HOLD("OH"), EXPIRED("EX"), CANCELLED("CA"); |
|---|
| 14 | + |
|---|
| 9 | 15 | private final String code; |
|---|
| 10 | | - PackStatus(String code ) { |
|---|
| 16 | + |
|---|
| 17 | + PackStatus(String code) { |
|---|
| 11 | 18 | this.code = code; |
|---|
| 12 | 19 | } |
|---|
| 20 | + |
|---|
| 13 | 21 | public String getCode() { |
|---|
| 14 | 22 | return code; |
|---|
| 15 | 23 | } |
|---|
| 16 | | - |
|---|
| 24 | + |
|---|
| 17 | 25 | @JsonCreator |
|---|
| 18 | 26 | public static PackStatus valueFromCode(String code) { |
|---|
| 19 | 27 | for (PackStatus ps : PackStatus.values()) { |
|---|
| .. | .. |
|---|
| 26 | 34 | |
|---|
| 27 | 35 | @JsonValue |
|---|
| 28 | 36 | public String getName() { |
|---|
| 29 | | - |
|---|
| 37 | + |
|---|
| 30 | 38 | return this.code; |
|---|
| 31 | 39 | } |
|---|
| 32 | 40 | } |
|---|
| .. | .. |
|---|
| 67 | 67 | |
|---|
| 68 | 68 | private String lang; |
|---|
| 69 | 69 | |
|---|
| 70 | + private String email; |
|---|
| 71 | + |
|---|
| 70 | 72 | @JsonIgnore |
|---|
| 71 | 73 | @ManyToMany |
|---|
| 72 | 74 | @JoinTable(name = "user_organization", // |
|---|
| .. | .. |
|---|
| 223 | 225 | } |
|---|
| 224 | 226 | } |
|---|
| 225 | 227 | |
|---|
| 228 | + public String getEmail() { |
|---|
| 229 | + return email; |
|---|
| 230 | + } |
|---|
| 231 | + |
|---|
| 232 | + public void setEmail(String email) { |
|---|
| 233 | + this.email = email; |
|---|
| 234 | + } |
|---|
| 235 | + |
|---|
| 226 | 236 | public static class Rol { |
|---|
| 227 | 237 | public static final int ADVANCE = 0x01; |
|---|
| 228 | 238 | public static final int ADMIN = 0x02; |
|---|
| .. | .. |
|---|
| 28 | 28 | import net.curisit.securis.beans.SignedLicenseBean; |
|---|
| 29 | 29 | import net.curisit.securis.beans.StatusBean; |
|---|
| 30 | 30 | import net.curisit.securis.db.License; |
|---|
| 31 | | -import net.curisit.securis.db.LicenseType; |
|---|
| 32 | | -import net.curisit.securis.db.Pack; |
|---|
| 33 | 31 | import net.curisit.securis.security.BasicSecurityContext; |
|---|
| 34 | 32 | import net.curisit.securis.security.Securable; |
|---|
| 35 | 33 | import net.curisit.securis.services.exception.SeCurisServiceException; |
|---|
| .. | .. |
|---|
| 96 | 94 | return Response.ok(status).build(); |
|---|
| 97 | 95 | } |
|---|
| 98 | 96 | |
|---|
| 99 | | - |
|---|
| 100 | 97 | /** |
|---|
| 101 | | - * Request a new license file based in a RequestBean object sent as parameter |
|---|
| 98 | + * Request a new license file based in a RequestBean object sent as |
|---|
| 99 | + * parameter |
|---|
| 100 | + * |
|---|
| 102 | 101 | * @param mpfdi |
|---|
| 103 | 102 | * @param bsc |
|---|
| 104 | 103 | * @return |
|---|
| .. | .. |
|---|
| 108 | 107 | @POST |
|---|
| 109 | 108 | @Path("/request") |
|---|
| 110 | 109 | @Consumes(MediaType.APPLICATION_JSON) |
|---|
| 111 | | - //TODO: Enable this: @Securable |
|---|
| 110 | + // TODO: Enable this: @Securable |
|---|
| 112 | 111 | @Produces({ |
|---|
| 113 | 112 | MediaType.APPLICATION_JSON |
|---|
| 114 | 113 | }) |
|---|
| 115 | 114 | @Transactional |
|---|
| 116 | | - public Response createFromRequest(RequestBean request, @Context BasicSecurityContext bsc) throws IOException, SeCurisServiceException, SeCurisException { |
|---|
| 115 | + public Response createFromRequest(RequestBean request, @Context BasicSecurityContext bsc) throws IOException, SeCurisServiceException, |
|---|
| 116 | + SeCurisException { |
|---|
| 117 | 117 | LOG.info("Request to get license: {}", request); |
|---|
| 118 | 118 | |
|---|
| 119 | 119 | Map<String, Object> metadata = getLicenseMetadata(request); |
|---|
| 120 | 120 | License licDB = getLicenseData(request); |
|---|
| 121 | | - |
|---|
| 121 | + |
|---|
| 122 | 122 | Date expirationDate = licDB.getExpirationDate(); |
|---|
| 123 | 123 | String licenseTypeCode = licDB.getPack().getLicenseType().getCode(); |
|---|
| 124 | 124 | String licenseCode = licDB.getCode(); |
|---|
| .. | .. |
|---|
| 126 | 126 | SignedLicenseBean signedLic = new SignedLicenseBean(lic); |
|---|
| 127 | 127 | return Response.ok(signedLic).build(); |
|---|
| 128 | 128 | } |
|---|
| 129 | | - |
|---|
| 129 | + |
|---|
| 130 | 130 | /** |
|---|
| 131 | 131 | * Returns a License file in JSON format from an uploaded Request file |
|---|
| 132 | + * |
|---|
| 132 | 133 | * @param mpfdi |
|---|
| 133 | 134 | * @param bsc |
|---|
| 134 | 135 | * @return |
|---|
| .. | .. |
|---|
| 145 | 146 | }) |
|---|
| 146 | 147 | @Transactional |
|---|
| 147 | 148 | @SuppressWarnings("unchecked") |
|---|
| 148 | | - public Response createFromRequestFile(MultipartFormDataInput mpfdi, @Context BasicSecurityContext bsc) throws IOException, SeCurisServiceException, SeCurisException { |
|---|
| 149 | + public Response createFromRequestFile(MultipartFormDataInput mpfdi, @Context BasicSecurityContext bsc) throws IOException, |
|---|
| 150 | + SeCurisServiceException, SeCurisException { |
|---|
| 149 | 151 | RequestBean req = new RequestBean(); |
|---|
| 150 | | - req.setAppCode(mpfdi.getFormDataPart("appCode", String.class, null)); |
|---|
| 152 | + req.setPackCode(mpfdi.getFormDataPart("packCode", String.class, null)); |
|---|
| 153 | + req.setLicenseTypeCode(mpfdi.getFormDataPart("licenseTypeCode", String.class, null)); |
|---|
| 154 | + req.setCustomerCode(mpfdi.getFormDataPart("customerCode", String.class, null)); |
|---|
| 151 | 155 | req.setArch(mpfdi.getFormDataPart("arch", String.class, null)); |
|---|
| 152 | 156 | req.setCrcLogo(mpfdi.getFormDataPart("crcLogo", String.class, null)); |
|---|
| 153 | | - req.setCustomerCode(mpfdi.getFormDataPart("customerCode", String.class, null)); |
|---|
| 154 | 157 | req.setMacAddresses(mpfdi.getFormDataPart("macAddresses", List.class, null)); |
|---|
| 155 | 158 | req.setOsName(mpfdi.getFormDataPart("osName", String.class, null)); |
|---|
| 156 | 159 | |
|---|
| .. | .. |
|---|
| 170 | 173 | @POST |
|---|
| 171 | 174 | @Path("/renew") |
|---|
| 172 | 175 | @Consumes(MediaType.APPLICATION_JSON) |
|---|
| 173 | | - //TODO: Enable this: @Securable |
|---|
| 176 | + // TODO: Enable this: @Securable |
|---|
| 174 | 177 | @Produces({ |
|---|
| 175 | 178 | MediaType.APPLICATION_JSON |
|---|
| 176 | 179 | }) |
|---|
| 177 | 180 | @Transactional |
|---|
| 178 | | - public Response renewFromPreviousLicense(LicenseBean previousLic, @Context BasicSecurityContext bsc) throws IOException, SeCurisServiceException, SeCurisException { |
|---|
| 181 | + public Response renewFromPreviousLicense(LicenseBean previousLic, @Context BasicSecurityContext bsc) throws IOException, SeCurisServiceException, |
|---|
| 182 | + SeCurisException { |
|---|
| 179 | 183 | LOG.info("Renew license: {}", previousLic); |
|---|
| 180 | 184 | |
|---|
| 181 | 185 | if (previousLic.getExpirationDate().after(DateUtils.addMonths(new Date(), 1))) { |
|---|
| .. | .. |
|---|
| 184 | 188 | |
|---|
| 185 | 189 | Map<String, Object> metadata = getLicenseMetadata(previousLic); |
|---|
| 186 | 190 | License licDB = getLicenseData(previousLic); |
|---|
| 187 | | - |
|---|
| 191 | + |
|---|
| 188 | 192 | Date expirationDate = licDB.getExpirationDate(); |
|---|
| 189 | 193 | String licenseTypeCode = licDB.getPack().getLicenseType().getCode(); |
|---|
| 190 | 194 | String licenseCode = licDB.getCode(); |
|---|
| 191 | 195 | LicenseBean lic = licenseGenerator.generateLicense(previousLic, metadata, expirationDate, licenseTypeCode, licenseCode); |
|---|
| 192 | 196 | return Response.ok(lic).build(); |
|---|
| 193 | 197 | } |
|---|
| 194 | | - |
|---|
| 198 | + |
|---|
| 195 | 199 | /** |
|---|
| 196 | 200 | * Returns a new License file in JSON format based in a previous license |
|---|
| 201 | + * |
|---|
| 197 | 202 | * @param mpfdi |
|---|
| 198 | 203 | * @param bsc |
|---|
| 199 | 204 | * @return |
|---|
| .. | .. |
|---|
| 210 | 215 | }) |
|---|
| 211 | 216 | @Transactional |
|---|
| 212 | 217 | @SuppressWarnings("unchecked") |
|---|
| 213 | | - public Response renewFromLicenseFile(MultipartFormDataInput mpfdi, @Context BasicSecurityContext bsc) throws IOException, SeCurisServiceException, SeCurisException { |
|---|
| 218 | + public Response renewFromLicenseFile(MultipartFormDataInput mpfdi, @Context BasicSecurityContext bsc) throws IOException, |
|---|
| 219 | + SeCurisServiceException, SeCurisException { |
|---|
| 214 | 220 | LicenseBean lic = new LicenseBean(); |
|---|
| 215 | | - // TODO: Add more license parameters |
|---|
| 216 | | - lic.setAppCode(mpfdi.getFormDataPart("appCode", String.class, null)); |
|---|
| 221 | + |
|---|
| 222 | + lic.setAppName(mpfdi.getFormDataPart("appName", String.class, null)); |
|---|
| 217 | 223 | lic.setArch(mpfdi.getFormDataPart("arch", String.class, null)); |
|---|
| 218 | 224 | lic.setCrcLogo(mpfdi.getFormDataPart("crcLogo", String.class, null)); |
|---|
| 225 | + lic.setPackCode(mpfdi.getFormDataPart("packCode", String.class, null)); |
|---|
| 226 | + lic.setLicenseTypeCode(mpfdi.getFormDataPart("licenseCode", String.class, null)); |
|---|
| 219 | 227 | lic.setCustomerCode(mpfdi.getFormDataPart("customerCode", String.class, null)); |
|---|
| 220 | 228 | lic.setMacAddresses(mpfdi.getFormDataPart("macAddresses", List.class, null)); |
|---|
| 221 | 229 | lic.setOsName(mpfdi.getFormDataPart("osName", String.class, null)); |
|---|
| .. | .. |
|---|
| 227 | 235 | |
|---|
| 228 | 236 | return createFromRequest(lic, bsc); |
|---|
| 229 | 237 | } |
|---|
| 230 | | - |
|---|
| 231 | | - |
|---|
| 232 | | - |
|---|
| 238 | + |
|---|
| 233 | 239 | private License getLicenseData(RequestBean req) throws SeCurisException { |
|---|
| 234 | | - // TODO: The dummy expiration date is temporal, this info should be read from DB |
|---|
| 240 | + // TODO: The dummy expiration date is temporal, this info should be read |
|---|
| 241 | + // from DB |
|---|
| 235 | 242 | License lic = new License(); |
|---|
| 236 | | - lic.setExpirationDate(new Date(new Date().getTime() + (1000L * 3600 * 24 * 30 ))); |
|---|
| 237 | | - lic.setCode(req.getAppCode() + "-LIC-INTERNAL"); |
|---|
| 238 | | - LicenseType lt = new LicenseType(); |
|---|
| 239 | | - lt.setCode("TYPE-" + req.getAppCode()); |
|---|
| 240 | | - Pack pack = new Pack(); |
|---|
| 241 | | - pack.setLicenseType(lt); |
|---|
| 242 | | - lic.setPack(pack); |
|---|
| 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); |
|---|
| 243 | 253 | return lic; |
|---|
| 244 | 254 | } |
|---|
| 245 | | - |
|---|
| 255 | + |
|---|
| 246 | 256 | /** |
|---|
| 247 | 257 | * Extract the corresponding metadata for the Request license given |
|---|
| 258 | + * |
|---|
| 248 | 259 | * @param req |
|---|
| 249 | 260 | * @return |
|---|
| 250 | 261 | * @throws SeCurisException |
|---|
| 251 | 262 | */ |
|---|
| 252 | 263 | @SuppressWarnings("unchecked") |
|---|
| 253 | 264 | private Map<String, Object> getLicenseMetadata(RequestBean req) throws SeCurisException { |
|---|
| 254 | | - // TODO: The dummy metadata file is temporal, this info should be read from DB |
|---|
| 255 | | - File dummyMetadata = new File(System.getProperty("user.home") + File.separator + ".SeCuris" + File.separator + "dummy_metadata.json"); |
|---|
| 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"); |
|---|
| 256 | 268 | Map<String, Object> metadata = null; |
|---|
| 257 | 269 | try { |
|---|
| 258 | 270 | String metadataJson = IOUtils.toString(dummyMetadata.toURI()); |
|---|
| 259 | | - metadata = (Map<String, Object>)JsonUtils.json2map(metadataJson).get(req.getAppCode()); |
|---|
| 260 | | - if (metadata == null) |
|---|
| 261 | | - throw new SeCurisException("App code in request is unknown: " + req.getAppCode()); |
|---|
| 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()); |
|---|
| 274 | + } |
|---|
| 262 | 275 | metadata = new TreeMap<>(metadata); |
|---|
| 263 | 276 | } catch (IOException e) { |
|---|
| 264 | 277 | LOG.error("Error reading dummy metadata file", e); |
|---|
| 265 | 278 | throw new SeCurisException("Error reading dummy metadata file"); |
|---|
| 266 | 279 | } |
|---|
| 267 | | - |
|---|
| 280 | + |
|---|
| 268 | 281 | return metadata; |
|---|
| 269 | 282 | } |
|---|
| 270 | 283 | |
|---|
| 271 | | - |
|---|
| 272 | 284 | } |
|---|
| .. | .. |
|---|
| 1 | 1 | package net.curisit.securis.services; |
|---|
| 2 | 2 | |
|---|
| 3 | 3 | import java.io.File; |
|---|
| 4 | +import java.io.FileWriter; |
|---|
| 4 | 5 | import java.io.IOException; |
|---|
| 6 | +import java.nio.file.Files; |
|---|
| 7 | +import java.text.MessageFormat; |
|---|
| 5 | 8 | import java.util.Date; |
|---|
| 9 | +import java.util.HashMap; |
|---|
| 6 | 10 | import java.util.List; |
|---|
| 7 | 11 | import java.util.Map; |
|---|
| 8 | | -import java.util.TreeMap; |
|---|
| 12 | +import java.util.Set; |
|---|
| 9 | 13 | |
|---|
| 10 | 14 | import javax.inject.Inject; |
|---|
| 11 | 15 | import javax.inject.Provider; |
|---|
| .. | .. |
|---|
| 13 | 17 | import javax.persistence.TypedQuery; |
|---|
| 14 | 18 | import javax.ws.rs.Consumes; |
|---|
| 15 | 19 | import javax.ws.rs.DELETE; |
|---|
| 20 | +import javax.ws.rs.DefaultValue; |
|---|
| 21 | +import javax.ws.rs.FormParam; |
|---|
| 16 | 22 | import javax.ws.rs.GET; |
|---|
| 17 | 23 | import javax.ws.rs.POST; |
|---|
| 18 | 24 | import javax.ws.rs.PUT; |
|---|
| .. | .. |
|---|
| 27 | 33 | |
|---|
| 28 | 34 | import net.curisit.integrity.commons.JsonUtils; |
|---|
| 29 | 35 | import net.curisit.integrity.commons.Utils; |
|---|
| 36 | +import net.curisit.integrity.exception.CurisException; |
|---|
| 30 | 37 | import net.curisit.securis.DefaultExceptionHandler; |
|---|
| 38 | +import net.curisit.securis.LicenseGenerator; |
|---|
| 31 | 39 | import net.curisit.securis.SeCurisException; |
|---|
| 40 | +import net.curisit.securis.beans.LicenseBean; |
|---|
| 32 | 41 | import net.curisit.securis.beans.RequestBean; |
|---|
| 42 | +import net.curisit.securis.beans.SignedLicenseBean; |
|---|
| 43 | +import net.curisit.securis.db.Application; |
|---|
| 33 | 44 | import net.curisit.securis.db.License; |
|---|
| 34 | 45 | import net.curisit.securis.db.LicenseHistory; |
|---|
| 46 | +import net.curisit.securis.db.LicenseStatus; |
|---|
| 35 | 47 | import net.curisit.securis.db.Pack; |
|---|
| 48 | +import net.curisit.securis.db.PackMetadata; |
|---|
| 36 | 49 | import net.curisit.securis.db.User; |
|---|
| 37 | 50 | import net.curisit.securis.security.BasicSecurityContext; |
|---|
| 38 | 51 | import net.curisit.securis.security.Securable; |
|---|
| 39 | 52 | import net.curisit.securis.services.exception.SeCurisServiceException; |
|---|
| 53 | +import net.curisit.securis.services.exception.SeCurisServiceException.ErrorCodes; |
|---|
| 54 | +import net.curisit.securis.utils.EmailManager; |
|---|
| 55 | +import net.curisit.securis.utils.Params; |
|---|
| 40 | 56 | import net.curisit.securis.utils.TokenHelper; |
|---|
| 41 | 57 | |
|---|
| 42 | 58 | import org.apache.commons.io.IOUtils; |
|---|
| .. | .. |
|---|
| 60 | 76 | TokenHelper tokenHelper; |
|---|
| 61 | 77 | |
|---|
| 62 | 78 | @Inject |
|---|
| 79 | + EmailManager emailManager; |
|---|
| 80 | + |
|---|
| 81 | + @Inject |
|---|
| 63 | 82 | Provider<EntityManager> emProvider; |
|---|
| 83 | + |
|---|
| 84 | + @Inject |
|---|
| 85 | + LicenseGenerator licenseGenerator; |
|---|
| 64 | 86 | |
|---|
| 65 | 87 | /** |
|---|
| 66 | 88 | * |
|---|
| .. | .. |
|---|
| 138 | 160 | LOG.error("License with id {} is not active, so It can not downloaded", licId, bsc.getUserPrincipal()); |
|---|
| 139 | 161 | throw new SeCurisServiceException(Status.FORBIDDEN.getStatusCode(), "License is not active, so It can not be downloaded"); |
|---|
| 140 | 162 | } |
|---|
| 141 | | - return Response.ok(lic.getLicenseData()).build(); |
|---|
| 163 | + em.persist(createLicenseHistoryAction(lic, getUser(bsc, em), LicenseHistory.Actions.DOWNLOAD)); |
|---|
| 164 | + return Response |
|---|
| 165 | + .ok(lic.getLicenseData()) |
|---|
| 166 | + .header("Content-Disposition", |
|---|
| 167 | + String.format("attachment; filename=\"%s\"", lic.getPack().getLicenseType().getApplication().getLicenseFilename())).build(); |
|---|
| 142 | 168 | } |
|---|
| 143 | 169 | |
|---|
| 144 | 170 | /** |
|---|
| 145 | 171 | * Activate the given license |
|---|
| 172 | + * |
|---|
| 146 | 173 | * @param licId |
|---|
| 147 | 174 | * @param bsc |
|---|
| 148 | 175 | * @return |
|---|
| .. | .. |
|---|
| 168 | 195 | + " can not be activated from the current license status"); |
|---|
| 169 | 196 | } |
|---|
| 170 | 197 | |
|---|
| 171 | | - lic.setStatus(License.Status.ACTIVE); |
|---|
| 198 | + lic.setStatus(LicenseStatus.ACTIVE); |
|---|
| 172 | 199 | lic.setModificationTimestamp(new Date()); |
|---|
| 200 | + |
|---|
| 173 | 201 | em.persist(lic); |
|---|
| 174 | 202 | User user = getUser(bsc.getUserPrincipal().getName(), em); |
|---|
| 175 | 203 | em.persist(createLicenseHistoryAction(lic, user, LicenseHistory.Actions.ACTIVATE)); |
|---|
| .. | .. |
|---|
| 178 | 206 | |
|---|
| 179 | 207 | /** |
|---|
| 180 | 208 | * Send license file by email to the organization |
|---|
| 209 | + * |
|---|
| 181 | 210 | * @param licId |
|---|
| 182 | 211 | * @param bsc |
|---|
| 183 | 212 | * @return |
|---|
| .. | .. |
|---|
| 192 | 221 | @Produces({ |
|---|
| 193 | 222 | MediaType.APPLICATION_JSON |
|---|
| 194 | 223 | }) |
|---|
| 195 | | - public Response send(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException { |
|---|
| 224 | + public Response send(@PathParam("licId") Integer licId, @DefaultValue("false") @FormParam("add_cc") Boolean addCC, |
|---|
| 225 | + @Context BasicSecurityContext bsc) throws SeCurisServiceException, SeCurisException { |
|---|
| 196 | 226 | |
|---|
| 197 | 227 | EntityManager em = emProvider.get(); |
|---|
| 198 | 228 | License lic = getCurrentLicense(licId, bsc, em); |
|---|
| 229 | + Application app = lic.getPack().getLicenseType().getApplication(); |
|---|
| 230 | + File licFile = null; |
|---|
| 231 | + if (lic.getLicenseData() == null) { |
|---|
| 232 | + throw new SeCurisServiceException(Status.NOT_FOUND.getStatusCode(), "There is no license file available"); |
|---|
| 233 | + } |
|---|
| 199 | 234 | |
|---|
| 200 | 235 | User user = getUser(bsc.getUserPrincipal().getName(), em); |
|---|
| 201 | | - // TODO: Send mail with lic file |
|---|
| 236 | + try { |
|---|
| 237 | + String subject = MessageFormat.format(Params.get(Params.KEYS.EMAIL_LIC_DEFAULT_SUBJECT), lic.getPack().getAppName()); |
|---|
| 238 | + String email_tpl = IOUtils.toString(this.getClass().getResourceAsStream("/lic_email_template.en")); |
|---|
| 239 | + String body = MessageFormat.format(email_tpl, lic.getFullName(), app.getName()); |
|---|
| 240 | + licFile = createTemporaryLicenseFile(lic, app.getLicenseFilename()); |
|---|
| 241 | + |
|---|
| 242 | + emailManager.sendEmail(subject, body, lic.getEmail(), addCC ? user.getEmail() : null, licFile); |
|---|
| 243 | + } catch (IOException e) { |
|---|
| 244 | + LOG.error("Error creating temporary license file", e); |
|---|
| 245 | + throw new SeCurisServiceException(Status.NOT_FOUND.getStatusCode(), "There is no license file available"); |
|---|
| 246 | + } finally { |
|---|
| 247 | + if (licFile != null) { |
|---|
| 248 | + licFile.delete(); |
|---|
| 249 | + } |
|---|
| 250 | + } |
|---|
| 251 | + |
|---|
| 202 | 252 | lic.setModificationTimestamp(new Date()); |
|---|
| 203 | 253 | em.persist(lic); |
|---|
| 204 | 254 | em.persist(createLicenseHistoryAction(lic, user, LicenseHistory.Actions.SEND, "Email sent to: " + lic.getEmail())); |
|---|
| .. | .. |
|---|
| 207 | 257 | |
|---|
| 208 | 258 | /** |
|---|
| 209 | 259 | * Cancel given license |
|---|
| 260 | + * |
|---|
| 210 | 261 | * @param licId |
|---|
| 211 | 262 | * @param bsc |
|---|
| 212 | 263 | * @return |
|---|
| .. | .. |
|---|
| 221 | 272 | @Produces({ |
|---|
| 222 | 273 | MediaType.APPLICATION_JSON |
|---|
| 223 | 274 | }) |
|---|
| 224 | | - public Response cancel(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException { |
|---|
| 275 | + public Response cancel(@PathParam("licId") Integer licId, @FormParam("reason") String reason, @Context BasicSecurityContext bsc) |
|---|
| 276 | + throws SeCurisServiceException { |
|---|
| 225 | 277 | |
|---|
| 226 | 278 | EntityManager em = emProvider.get(); |
|---|
| 227 | 279 | License lic = getCurrentLicense(licId, bsc, em); |
|---|
| .. | .. |
|---|
| 232 | 284 | + " can not be canceled from the current license status"); |
|---|
| 233 | 285 | } |
|---|
| 234 | 286 | |
|---|
| 235 | | - lic.setStatus(License.Status.CANCELED); |
|---|
| 287 | + if (reason == null && (lic.getStatus() == LicenseStatus.ACTIVE || lic.getStatus() == LicenseStatus.PRE_ACTIVE)) { |
|---|
| 288 | + LOG.error("To cancel an active License we need a reason, lic ID: {}, user: {}", lic.getId(), bsc.getUserPrincipal().getName()); |
|---|
| 289 | + throw new SeCurisServiceException(Status.FORBIDDEN.getStatusCode(), "Active license with id " + licId |
|---|
| 290 | + + " can not be canceled without a reason"); |
|---|
| 291 | + } |
|---|
| 292 | + |
|---|
| 293 | + lic.setStatus(LicenseStatus.CANCELLED); |
|---|
| 236 | 294 | lic.setModificationTimestamp(new Date()); |
|---|
| 237 | 295 | em.persist(lic); |
|---|
| 238 | 296 | |
|---|
| 239 | | - User user = getUser(bsc.getUserPrincipal().getName(), em); |
|---|
| 240 | | - em.persist(createLicenseHistoryAction(lic, user, LicenseHistory.Actions.CANCEL)); |
|---|
| 297 | + em.persist(createLicenseHistoryAction(lic, getUser(bsc, em), LicenseHistory.Actions.CANCEL, "Cancelation reason: " + reason)); |
|---|
| 241 | 298 | return Response.ok(lic).build(); |
|---|
| 242 | 299 | } |
|---|
| 243 | 300 | |
|---|
| .. | .. |
|---|
| 250 | 307 | }) |
|---|
| 251 | 308 | @Transactional |
|---|
| 252 | 309 | public Response create(License lic, @Context BasicSecurityContext bsc) throws SeCurisServiceException { |
|---|
| 253 | | - LOG.info("Creating new license from create()"); |
|---|
| 254 | 310 | EntityManager em = emProvider.get(); |
|---|
| 255 | 311 | Pack pack = null; |
|---|
| 256 | 312 | if (lic.getPackId() != null) { |
|---|
| 257 | 313 | pack = em.find(Pack.class, lic.getPackId()); |
|---|
| 258 | | - if (pack == null) { |
|---|
| 259 | | - LOG.error("License pack with id {} not found in DB", lic.getPackId()); |
|---|
| 260 | | - return Response.status(Status.NOT_FOUND) |
|---|
| 261 | | - .header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "License's pack not found with ID: " + lic.getPackId()).build(); |
|---|
| 262 | | - } else { |
|---|
| 263 | | - if (!bsc.isUserInRole(BasicSecurityContext.ROL_ADMIN) && !bsc.getOrganizationsIds().contains(pack.getOrganization().getId())) { |
|---|
| 264 | | - LOG.error("License for pack with id {} can not be created by user {}", pack.getId(), bsc.getUserPrincipal()); |
|---|
| 265 | | - return Response.status(Status.UNAUTHORIZED) |
|---|
| 266 | | - .header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "Unathorized action on pack license").build(); |
|---|
| 267 | | - } |
|---|
| 314 | + } |
|---|
| 315 | + |
|---|
| 316 | + if (pack == null) { |
|---|
| 317 | + LOG.error("License pack with id {} not found in DB", lic.getPackId()); |
|---|
| 318 | + throw new SeCurisServiceException(ErrorCodes.NOT_FOUND, "License's pack not found with ID: " + lic.getPackId()); |
|---|
| 319 | + } else { |
|---|
| 320 | + if (!bsc.isUserInRole(BasicSecurityContext.ROL_ADMIN) && !bsc.getOrganizationsIds().contains(pack.getOrganization().getId())) { |
|---|
| 321 | + LOG.error("License for pack with id {} can not be created by user {}", pack.getId(), bsc.getUserPrincipal()); |
|---|
| 322 | + throw new SeCurisServiceException(ErrorCodes.UNAUTHORIZED_ACCESS, "Unathorized action on pack license"); |
|---|
| 268 | 323 | } |
|---|
| 269 | 324 | } |
|---|
| 270 | 325 | |
|---|
| 271 | 326 | User createdBy = getUser(bsc.getUserPrincipal().getName(), em); |
|---|
| 272 | 327 | |
|---|
| 273 | | - // TODO: Manage status if request data is set |
|---|
| 328 | + if (lic.getRequestData() != null) { |
|---|
| 329 | + SignedLicenseBean signedLicense = generateLicense(lic, em); |
|---|
| 330 | + // If user provide a request data the license status is passed |
|---|
| 331 | + // directly to ACTIVE |
|---|
| 332 | + lic.setStatus(LicenseStatus.ACTIVE); |
|---|
| 333 | + try { |
|---|
| 334 | + lic.setLicenseData(JsonUtils.toJSON(signedLicense)); |
|---|
| 335 | + } catch (CurisException e) { |
|---|
| 336 | + LOG.error("Error generaing license JSON", e); |
|---|
| 337 | + throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Error generaing license JSON"); |
|---|
| 338 | + } |
|---|
| 339 | + } else { |
|---|
| 340 | + lic.setStatus(LicenseStatus.CREATED); |
|---|
| 341 | + } |
|---|
| 274 | 342 | lic.setCreatedBy(createdBy); |
|---|
| 275 | | - lic.setStatus(License.Status.CREATED); |
|---|
| 276 | 343 | lic.setCreationTimestamp(new Date()); |
|---|
| 277 | 344 | lic.setModificationTimestamp(lic.getCreationTimestamp()); |
|---|
| 278 | 345 | em.persist(lic); |
|---|
| 279 | 346 | em.persist(createLicenseHistoryAction(lic, createdBy, LicenseHistory.Actions.CREATE)); |
|---|
| 347 | + if (lic.getStatus() == LicenseStatus.ACTIVE) { |
|---|
| 348 | + em.persist(createLicenseHistoryAction(lic, createdBy, LicenseHistory.Actions.CREATE, "Activated on creation")); |
|---|
| 349 | + } |
|---|
| 280 | 350 | |
|---|
| 281 | 351 | return Response.ok(lic).build(); |
|---|
| 282 | 352 | } |
|---|
| 283 | | - |
|---|
| 284 | 353 | |
|---|
| 285 | | - |
|---|
| 354 | + private SignedLicenseBean generateLicense(License license, EntityManager em) throws SeCurisServiceException { |
|---|
| 355 | + SignedLicenseBean sl = null; |
|---|
| 356 | + Pack pack = em.find(Pack.class, license.getPackId()); |
|---|
| 357 | + RequestBean rb = validateRequestData(pack, license.getRequestData()); |
|---|
| 358 | + try { |
|---|
| 359 | + LicenseBean lb = licenseGenerator.generateLicense(rb, extractPackMetadata(pack.getMetadata()), license.getExpirationDate(), |
|---|
| 360 | + pack.getLicenseTypeCode(), license.getCode()); |
|---|
| 361 | + sl = new SignedLicenseBean(lb); |
|---|
| 362 | + } catch (SeCurisException e) { |
|---|
| 363 | + throw new SeCurisServiceException(ErrorCodes.INVALID_LICENSE_REQUEST_DATA, "Error generating license: " + e.toString()); |
|---|
| 364 | + } |
|---|
| 365 | + return sl; |
|---|
| 366 | + } |
|---|
| 367 | + |
|---|
| 368 | + private Map<String, Object> extractPackMetadata(Set<PackMetadata> packMetadata) { |
|---|
| 369 | + Map<String, Object> metadata = new HashMap<>(); |
|---|
| 370 | + for (PackMetadata md : packMetadata) { |
|---|
| 371 | + metadata.put(md.getKey(), md.getValue()); |
|---|
| 372 | + } |
|---|
| 373 | + |
|---|
| 374 | + return metadata; |
|---|
| 375 | + } |
|---|
| 376 | + |
|---|
| 377 | + /** |
|---|
| 378 | + * We check if the given request data is valid for the current Pack and has |
|---|
| 379 | + * a valid format |
|---|
| 380 | + * |
|---|
| 381 | + * @param pack |
|---|
| 382 | + * @param requestData |
|---|
| 383 | + * @throws SeCurisServiceException |
|---|
| 384 | + */ |
|---|
| 385 | + private RequestBean validateRequestData(Pack pack, String requestData) throws SeCurisServiceException { |
|---|
| 386 | + RequestBean rb = null; |
|---|
| 387 | + try { |
|---|
| 388 | + rb = JsonUtils.json2object(requestData, RequestBean.class); |
|---|
| 389 | + } catch (CurisException e) { |
|---|
| 390 | + throw new SeCurisServiceException(ErrorCodes.INVALID_REQUEST_DATA_FORMAT, "Request data has not a valid format"); |
|---|
| 391 | + } |
|---|
| 392 | + |
|---|
| 393 | + if (!rb.getCustomerCode().equals(pack.getOrganization().getCode())) { |
|---|
| 394 | + throw new SeCurisServiceException(ErrorCodes.INVALID_REQUEST_DATA_FORMAT, "Request data not valid, wrong Organization code"); |
|---|
| 395 | + } |
|---|
| 396 | + if (!rb.getLicenseTypeCode().equals(pack.getLicenseTypeCode())) { |
|---|
| 397 | + throw new SeCurisServiceException(ErrorCodes.INVALID_REQUEST_DATA_FORMAT, "Request data not valid, wrong License type code"); |
|---|
| 398 | + } |
|---|
| 399 | + // TODO: [rsanchez] Verify that if pack code is null we ignore it |
|---|
| 400 | + if (rb.getPackCode() != null && !rb.getPackCode().equals(pack.getCode())) { |
|---|
| 401 | + throw new SeCurisServiceException(ErrorCodes.INVALID_REQUEST_DATA_FORMAT, "Request data not valid, wrong Pack code"); |
|---|
| 402 | + } |
|---|
| 403 | + return rb; |
|---|
| 404 | + } |
|---|
| 405 | + |
|---|
| 286 | 406 | @PUT |
|---|
| 287 | 407 | @POST |
|---|
| 288 | 408 | @Path("/{licId}") |
|---|
| .. | .. |
|---|
| 302 | 422 | currentLicense.setCode(lic.getCode()); |
|---|
| 303 | 423 | currentLicense.setFullName(lic.getFullName()); |
|---|
| 304 | 424 | currentLicense.setEmail(lic.getEmail()); |
|---|
| 305 | | - currentLicense.setRequestData(lic.getRequestData()); |
|---|
| 425 | + if (lic.getRequestData() != null) { |
|---|
| 426 | + SignedLicenseBean signedLicense = generateLicense(lic, em); |
|---|
| 427 | + // If user provide a request data the license status is passed |
|---|
| 428 | + // directly to ACTIVE |
|---|
| 429 | + lic.setStatus(LicenseStatus.ACTIVE); |
|---|
| 430 | + try { |
|---|
| 431 | + lic.setLicenseData(JsonUtils.toJSON(signedLicense)); |
|---|
| 432 | + } catch (CurisException e) { |
|---|
| 433 | + LOG.error("Error generaing license JSON", e); |
|---|
| 434 | + throw new SeCurisServiceException(ErrorCodes.INVALID_FORMAT, "Error generaing license JSON"); |
|---|
| 435 | + } |
|---|
| 436 | + currentLicense.setRequestData(lic.getRequestData()); |
|---|
| 437 | + } |
|---|
| 306 | 438 | currentLicense.setModificationTimestamp(new Date()); |
|---|
| 307 | 439 | em.persist(currentLicense); |
|---|
| 440 | + em.persist(createLicenseHistoryAction(lic, getUser(bsc, em), LicenseHistory.Actions.MODIFY)); |
|---|
| 308 | 441 | |
|---|
| 309 | 442 | return Response.ok(currentLicense).build(); |
|---|
| 310 | 443 | } |
|---|
| .. | .. |
|---|
| 321 | 454 | EntityManager em = emProvider.get(); |
|---|
| 322 | 455 | License lic = getCurrentLicense(licId, bsc, em); |
|---|
| 323 | 456 | |
|---|
| 324 | | - if (lic.getStatus() != License.Status.CANCELED || lic.getStatus() != License.Status.CREATED) { |
|---|
| 457 | + if (lic.getStatus() != LicenseStatus.CANCELLED || lic.getStatus() != LicenseStatus.CREATED) { |
|---|
| 458 | + LOG.error("License {} can not be deleted with status {}", lic.getCode(), lic.getStatus()); |
|---|
| 459 | + return Response.status(Status.FORBIDDEN) |
|---|
| 460 | + .header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "License can not be deleted in current status").build(); |
|---|
| 461 | + } |
|---|
| 462 | + |
|---|
| 463 | + em.remove(lic); |
|---|
| 464 | + return Response.ok(Utils.createMap("success", true, "id", licId)).build(); |
|---|
| 465 | + } |
|---|
| 466 | + |
|---|
| 467 | + @DELETE |
|---|
| 468 | + @Path("/{licId}") |
|---|
| 469 | + @Transactional |
|---|
| 470 | + @Securable |
|---|
| 471 | + @Produces({ |
|---|
| 472 | + MediaType.APPLICATION_JSON |
|---|
| 473 | + }) |
|---|
| 474 | + public Response block(@PathParam("licId") Integer licId, @Context BasicSecurityContext bsc) throws SeCurisServiceException { |
|---|
| 475 | + LOG.info("Deleting license with id: {}", licId); |
|---|
| 476 | + EntityManager em = emProvider.get(); |
|---|
| 477 | + License lic = getCurrentLicense(licId, bsc, em); |
|---|
| 478 | + |
|---|
| 479 | + if (lic.getStatus() != LicenseStatus.CANCELLED || lic.getStatus() != LicenseStatus.CREATED) { |
|---|
| 325 | 480 | LOG.error("License {} can not be deleted with status {}", lic.getCode(), lic.getStatus()); |
|---|
| 326 | 481 | return Response.status(Status.FORBIDDEN) |
|---|
| 327 | 482 | .header(DefaultExceptionHandler.ERROR_MESSAGE_HEADER, "License can not be deleted in current status").build(); |
|---|
| .. | .. |
|---|
| 349 | 504 | return lic; |
|---|
| 350 | 505 | } |
|---|
| 351 | 506 | |
|---|
| 507 | + private User getUser(BasicSecurityContext bsc, EntityManager em) throws SeCurisServiceException { |
|---|
| 508 | + String username = bsc.getUserPrincipal().getName(); |
|---|
| 509 | + return getUser(username, em); |
|---|
| 510 | + } |
|---|
| 511 | + |
|---|
| 352 | 512 | private User getUser(String username, EntityManager em) throws SeCurisServiceException { |
|---|
| 353 | 513 | User user = null; |
|---|
| 354 | 514 | if (username != null) { |
|---|
| .. | .. |
|---|
| 358 | 518 | } |
|---|
| 359 | 519 | } |
|---|
| 360 | 520 | return user; |
|---|
| 521 | + } |
|---|
| 522 | + |
|---|
| 523 | + private File createTemporaryLicenseFile(License lic, String licFileName) throws IOException { |
|---|
| 524 | + File f = Files.createTempDirectory("securis-server").toFile(); |
|---|
| 525 | + f = new File(f, licFileName); |
|---|
| 526 | + IOUtils.write(lic.getLicenseData(), new FileWriter(f)); |
|---|
| 527 | + return f; |
|---|
| 361 | 528 | } |
|---|
| 362 | 529 | |
|---|
| 363 | 530 | private LicenseHistory createLicenseHistoryAction(License lic, User user, String action, String comments) { |
|---|
| .. | .. |
|---|
| 373 | 540 | private LicenseHistory createLicenseHistoryAction(License lic, User user, String action) { |
|---|
| 374 | 541 | return createLicenseHistoryAction(lic, user, action, null); |
|---|
| 375 | 542 | } |
|---|
| 543 | + |
|---|
| 544 | + public static void main(String[] args) throws IOException { |
|---|
| 545 | + File f = Files.createTempDirectory("securis-server").toFile(); |
|---|
| 546 | + |
|---|
| 547 | + LOG.info("f: {}", f); |
|---|
| 548 | + f = new File(f, "config-server.lic"); |
|---|
| 549 | + LOG.info("f: {}", f); |
|---|
| 550 | + } |
|---|
| 376 | 551 | } |
|---|
| .. | .. |
|---|
| 4 | 4 | |
|---|
| 5 | 5 | public class SeCurisServiceException extends CurisException { |
|---|
| 6 | 6 | |
|---|
| 7 | | - private int status = 0; |
|---|
| 7 | + private int errorCode = 0; |
|---|
| 8 | 8 | |
|---|
| 9 | | - public SeCurisServiceException(int status, String msg) { |
|---|
| 9 | + public SeCurisServiceException(int errorCode, String msg) { |
|---|
| 10 | 10 | super(msg); |
|---|
| 11 | | - this.status = status; |
|---|
| 11 | + this.errorCode = errorCode; |
|---|
| 12 | + } |
|---|
| 13 | + |
|---|
| 14 | + public SeCurisServiceException(String msg) { |
|---|
| 15 | + super(msg); |
|---|
| 16 | + this.errorCode = ErrorCodes.UNEXPECTED_ERROR; |
|---|
| 12 | 17 | } |
|---|
| 13 | 18 | |
|---|
| 14 | 19 | public int getStatus() { |
|---|
| 15 | | - return status; |
|---|
| 20 | + return errorCode; |
|---|
| 16 | 21 | } |
|---|
| 17 | 22 | |
|---|
| 18 | 23 | /** |
|---|
| .. | .. |
|---|
| 24 | 29 | public static int UNEXPECTED_ERROR = 1000; |
|---|
| 25 | 30 | public static int INVALID_CREDENTIALS = 1001; |
|---|
| 26 | 31 | public static int UNAUTHORIZED_ACCESS = 1002; |
|---|
| 27 | | - |
|---|
| 32 | + public static int NOT_FOUND = 1003; |
|---|
| 33 | + public static int INVALID_FORMAT = 1004; |
|---|
| 34 | + |
|---|
| 28 | 35 | public static int INVALID_LICENSE_REQUEST_DATA = 1100; |
|---|
| 29 | 36 | public static int LICENSE_NOT_READY_FOR_RENEW = 1101; |
|---|
| 37 | + |
|---|
| 38 | + public static int INVALID_REQUEST_DATA = 1201; |
|---|
| 39 | + public static int INVALID_REQUEST_DATA_FORMAT = 1202; |
|---|
| 30 | 40 | } |
|---|
| 31 | 41 | } |
|---|
| .. | .. |
|---|
| 1 | +package net.curisit.securis.utils; |
|---|
| 2 | + |
|---|
| 3 | +import java.io.File; |
|---|
| 4 | +import java.io.IOException; |
|---|
| 5 | +import java.io.UnsupportedEncodingException; |
|---|
| 6 | +import java.nio.charset.Charset; |
|---|
| 7 | +import java.security.KeyManagementException; |
|---|
| 8 | +import java.security.KeyStore; |
|---|
| 9 | +import java.security.KeyStoreException; |
|---|
| 10 | +import java.security.NoSuchAlgorithmException; |
|---|
| 11 | +import java.security.cert.CertificateException; |
|---|
| 12 | +import java.security.cert.X509Certificate; |
|---|
| 13 | +import java.util.Map; |
|---|
| 14 | +import java.util.concurrent.Executor; |
|---|
| 15 | +import java.util.concurrent.Executors; |
|---|
| 16 | + |
|---|
| 17 | +import javax.inject.Singleton; |
|---|
| 18 | + |
|---|
| 19 | +import net.curisit.securis.SeCurisException; |
|---|
| 20 | + |
|---|
| 21 | +import org.apache.commons.io.IOUtils; |
|---|
| 22 | +import org.apache.http.HttpResponse; |
|---|
| 23 | +import org.apache.http.auth.AuthScope; |
|---|
| 24 | +import org.apache.http.auth.UsernamePasswordCredentials; |
|---|
| 25 | +import org.apache.http.client.CredentialsProvider; |
|---|
| 26 | +import org.apache.http.client.methods.HttpPost; |
|---|
| 27 | +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; |
|---|
| 28 | +import org.apache.http.entity.ContentType; |
|---|
| 29 | +import org.apache.http.entity.mime.HttpMultipartMode; |
|---|
| 30 | +import org.apache.http.entity.mime.MultipartEntityBuilder; |
|---|
| 31 | +import org.apache.http.entity.mime.content.FileBody; |
|---|
| 32 | +import org.apache.http.impl.client.BasicCredentialsProvider; |
|---|
| 33 | +import org.apache.http.impl.client.CloseableHttpClient; |
|---|
| 34 | +import org.apache.http.impl.client.HttpClientBuilder; |
|---|
| 35 | +import org.apache.http.ssl.SSLContextBuilder; |
|---|
| 36 | +import org.apache.http.ssl.TrustStrategy; |
|---|
| 37 | +import org.apache.logging.log4j.LogManager; |
|---|
| 38 | +import org.apache.logging.log4j.Logger; |
|---|
| 39 | + |
|---|
| 40 | +/** |
|---|
| 41 | + * Component that send emails using Mailgun API: |
|---|
| 42 | + * http://documentation.mailgun.com/user_manual.html#sending-messages |
|---|
| 43 | + * |
|---|
| 44 | + * @author roberto <roberto.sanchez@curisit.net> |
|---|
| 45 | + */ |
|---|
| 46 | +@Singleton |
|---|
| 47 | +public class EmailManager { |
|---|
| 48 | + |
|---|
| 49 | + private static final Logger LOG = LogManager.getLogger(EmailManager.class); |
|---|
| 50 | + |
|---|
| 51 | + private final String serverUrl; |
|---|
| 52 | + private final CloseableHttpClient httpClient; |
|---|
| 53 | + |
|---|
| 54 | + /** |
|---|
| 55 | + * |
|---|
| 56 | + * @throws SeCurisException |
|---|
| 57 | + */ |
|---|
| 58 | + private EmailManager() throws SeCurisException { |
|---|
| 59 | + String domain = Params.get(Params.KEYS.MAILGUN_DOMAIN); |
|---|
| 60 | + if (domain == null) { |
|---|
| 61 | + throw new SeCurisException("Please, add '" + Params.KEYS.MAILGUN_DOMAIN + "' parameter to config file"); |
|---|
| 62 | + } |
|---|
| 63 | + serverUrl = String.format("https://api.mailgun.net/v2/%s/messages", domain); |
|---|
| 64 | + httpClient = createHttpClient(); |
|---|
| 65 | + |
|---|
| 66 | + } |
|---|
| 67 | + |
|---|
| 68 | + private CloseableHttpClient createHttpClient() throws SeCurisException { |
|---|
| 69 | + SSLContextBuilder builder = new SSLContextBuilder(); |
|---|
| 70 | + SSLConnectionSocketFactory sslsf = null; |
|---|
| 71 | + try { |
|---|
| 72 | + builder.loadTrustMaterial((KeyStore) null, new TrustStrategy() { |
|---|
| 73 | + @Override |
|---|
| 74 | + public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { |
|---|
| 75 | + return true; |
|---|
| 76 | + } |
|---|
| 77 | + }); |
|---|
| 78 | + sslsf = new SSLConnectionSocketFactory(builder.build()); |
|---|
| 79 | + } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e1) { |
|---|
| 80 | + LOG.error(e1); |
|---|
| 81 | + throw new SeCurisException("Error creating SSL socket factory"); |
|---|
| 82 | + } |
|---|
| 83 | + CredentialsProvider provider = new BasicCredentialsProvider(); |
|---|
| 84 | + UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("api", Params.get(Params.KEYS.MAILGUN_API_KEY)); |
|---|
| 85 | + provider.setCredentials(AuthScope.ANY, credentials); |
|---|
| 86 | + |
|---|
| 87 | + return HttpClientBuilder.create().setDefaultCredentialsProvider(provider).setSSLSocketFactory(sslsf).build(); |
|---|
| 88 | + } |
|---|
| 89 | + |
|---|
| 90 | + /** |
|---|
| 91 | + * Basic method to send emails in text mode with attachment. The method is |
|---|
| 92 | + * synchronous, It waits until server responses. |
|---|
| 93 | + * |
|---|
| 94 | + * @param subject |
|---|
| 95 | + * @param body |
|---|
| 96 | + * @param to |
|---|
| 97 | + * @param file |
|---|
| 98 | + * @throws SeCurisException |
|---|
| 99 | + * @throws UnsupportedEncodingException |
|---|
| 100 | + */ |
|---|
| 101 | + public void sendEmail(String subject, String body, String to, String cc, File file) throws SeCurisException, UnsupportedEncodingException { |
|---|
| 102 | + HttpPost postRequest = new HttpPost(serverUrl); |
|---|
| 103 | + |
|---|
| 104 | + MultipartEntityBuilder builder = MultipartEntityBuilder.create(); |
|---|
| 105 | + |
|---|
| 106 | + builder.setCharset(Charset.forName("utf-8")); |
|---|
| 107 | + builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); |
|---|
| 108 | + builder.addTextBody("from", Params.get(Params.KEYS.EMAIL_FROM_ADDRESS)); |
|---|
| 109 | + builder.addTextBody("to", to); |
|---|
| 110 | + if (cc != null) |
|---|
| 111 | + builder.addTextBody("cc", cc); |
|---|
| 112 | + builder.addTextBody("subject", subject, ContentType.create(ContentType.TEXT_PLAIN.getMimeType(), Charset.forName("utf-8"))); |
|---|
| 113 | + builder.addTextBody("text", body, ContentType.create(ContentType.TEXT_PLAIN.getMimeType(), Charset.forName("utf-8"))); |
|---|
| 114 | + if (file != null) |
|---|
| 115 | + builder.addPart("attachment", new FileBody(file)); |
|---|
| 116 | + |
|---|
| 117 | + postRequest.setEntity(builder.build()); |
|---|
| 118 | + HttpResponse response; |
|---|
| 119 | + try { |
|---|
| 120 | + response = httpClient.execute(postRequest); |
|---|
| 121 | + |
|---|
| 122 | + String jsonLic = IOUtils.toString(response.getEntity().getContent()); |
|---|
| 123 | + if (response.getStatusLine().getStatusCode() == 200) { |
|---|
| 124 | + LOG.debug("Response content read OK: {}", jsonLic); |
|---|
| 125 | + Map<String, Object> responseBean = JsonUtils.json2map(jsonLic); |
|---|
| 126 | + |
|---|
| 127 | + LOG.debug("Response mail read OK: {}", responseBean); |
|---|
| 128 | + } else { |
|---|
| 129 | + throw new SeCurisException("Error sending email, response estatus: " + response.getStatusLine()); |
|---|
| 130 | + } |
|---|
| 131 | + } catch (IOException e) { |
|---|
| 132 | + LOG.error("Error sending email", e); |
|---|
| 133 | + throw new SeCurisException("Error sending email"); |
|---|
| 134 | + } |
|---|
| 135 | + } |
|---|
| 136 | + |
|---|
| 137 | + /** |
|---|
| 138 | + * Basic method to send emails in text mode with attachment. The method is |
|---|
| 139 | + * asynchronous, It returns immediately |
|---|
| 140 | + * |
|---|
| 141 | + * @param subject |
|---|
| 142 | + * @param body |
|---|
| 143 | + * @param to |
|---|
| 144 | + * @param file |
|---|
| 145 | + * @throws SeCurisException |
|---|
| 146 | + * @throws UnsupportedEncodingException |
|---|
| 147 | + */ |
|---|
| 148 | + public void sendEmailAsync(String subject, String body, String to, String cc, File file, EmailCallback callback) throws SeCurisException, |
|---|
| 149 | + UnsupportedEncodingException { |
|---|
| 150 | + Executor ex = Executors.newSingleThreadExecutor(); |
|---|
| 151 | + ex.execute(new Runnable() { |
|---|
| 152 | + |
|---|
| 153 | + @Override |
|---|
| 154 | + public void run() { |
|---|
| 155 | + try { |
|---|
| 156 | + EmailManager.this.sendEmail(subject, body, to, cc, file); |
|---|
| 157 | + callback.success(); |
|---|
| 158 | + } catch (UnsupportedEncodingException e) { |
|---|
| 159 | + callback.error(new SeCurisException("Error sending email", e)); |
|---|
| 160 | + } catch (SeCurisException e) { |
|---|
| 161 | + callback.error(e); |
|---|
| 162 | + } |
|---|
| 163 | + |
|---|
| 164 | + } |
|---|
| 165 | + }); |
|---|
| 166 | + |
|---|
| 167 | + } |
|---|
| 168 | + |
|---|
| 169 | + public static interface EmailCallback { |
|---|
| 170 | + public void success(); |
|---|
| 171 | + |
|---|
| 172 | + public void error(SeCurisException e); |
|---|
| 173 | + } |
|---|
| 174 | + |
|---|
| 175 | + public static void main(String[] args) throws SeCurisException, UnsupportedEncodingException { |
|---|
| 176 | + // new EmailManager().sendEmail("España así de bien", |
|---|
| 177 | + // "Me gusta esta prueba\nCon varias líneas\n\n\n--\nNo response", |
|---|
| 178 | + // "info@r75.es", new File( |
|---|
| 179 | + // "/Users/rob/Downloads/test.req")); |
|---|
| 180 | + new EmailManager().sendEmailAsync("España así de bien", "Me gusta esta prueba\nCon varias líneas\n\n\n--\nNo response", "info@r75.es", |
|---|
| 181 | + "dev@r75.es", new File("/Users/rob/Downloads/test.req"), new EmailCallback() { |
|---|
| 182 | + |
|---|
| 183 | + @Override |
|---|
| 184 | + public void success() { |
|---|
| 185 | + LOG.info("Success!!!"); |
|---|
| 186 | + } |
|---|
| 187 | + |
|---|
| 188 | + @Override |
|---|
| 189 | + public void error(SeCurisException e) { |
|---|
| 190 | + LOG.error("Error: {} !!!", e); |
|---|
| 191 | + } |
|---|
| 192 | + }); |
|---|
| 193 | + LOG.info("Waiting for email to be sent..."); |
|---|
| 194 | + } |
|---|
| 195 | + |
|---|
| 196 | +} |
|---|
| .. | .. |
|---|
| 14 | 14 | last_name VARCHAR(100) NULL , |
|---|
| 15 | 15 | last_login DATETIME NULL , |
|---|
| 16 | 16 | lang VARCHAR(10) NULL , |
|---|
| 17 | + email VARCHAR(150) NULL , |
|---|
| 17 | 18 | creation_timestamp DATETIME NULL , |
|---|
| 18 | 19 | modification_timestamp DATETIME NULL , |
|---|
| 19 | 20 | PRIMARY KEY (username)); |
|---|
| .. | .. |
|---|
| 78 | 79 | num_licenses INT NOT NULL , |
|---|
| 79 | 80 | init_valid_date DATE NOT NULL default today(), |
|---|
| 80 | 81 | end_valid_date DATE NOT NULL default today(), |
|---|
| 81 | | - status VARCHAR(2) NOT NULL default 'PE', |
|---|
| 82 | + status VARCHAR(2) NOT NULL default 'CR', |
|---|
| 82 | 83 | comments VARCHAR(1024) NULL , |
|---|
| 83 | 84 | license_type_id INT NOT NULL, |
|---|
| 84 | 85 | organization_id INT NOT NULL, |
|---|
| .. | .. |
|---|
| 113 | 114 | expiration_date DATETIME NULL , |
|---|
| 114 | 115 | canceled_by varchar(45) NULL , |
|---|
| 115 | 116 | created_by varchar(45) NULL , |
|---|
| 116 | | - status INT NOT NULL default 0, |
|---|
| 117 | + status VARCHAR(2) NOT NULL default 'CR', |
|---|
| 117 | 118 | PRIMARY KEY (id)); |
|---|
| 118 | 119 | |
|---|
| 119 | 120 | |
|---|
| .. | .. |
|---|
| 127 | 128 | comments VARCHAR(512) , |
|---|
| 128 | 129 | PRIMARY KEY (id)); |
|---|
| 129 | 130 | |
|---|
| 130 | | - |
|---|
| 131 | | - |
|---|
| 131 | + |
|---|
| 132 | +drop table IF EXISTS blocked_request; |
|---|
| 133 | +CREATE TABLE IF NOT EXISTS blocked_request ( |
|---|
| 134 | + hash VARCHAR(256) NOT NULL , |
|---|
| 135 | + request_data VARCHAR(1024) NULL , |
|---|
| 136 | + blocked_by varchar(45) NULL , |
|---|
| 137 | + creation_timestamp DATETIME NOT NULL default now(), |
|---|
| 138 | + PRIMARY KEY (id)); |
|---|
| 139 | + |
|---|
| .. | .. |
|---|
| 12 | 12 | ssl.keystore.type = PKCS12 |
|---|
| 13 | 13 | ssl.keystore.password = curist3c |
|---|
| 14 | 14 | ssl.keystore.alias = |
|---|
| 15 | + |
|---|
| 16 | +email.from.address = SeCuris support securis@curisit.net |
|---|
| 17 | +mailgun.domain = m.curisit.net |
|---|
| 18 | +mailgun.api.key = key-7dekyqx56nc0irbnyk4z39ezhsrikqi8 |
|---|
| 19 | +email.lic.default.subject = SeCuris - License file for {0} application |
|---|
| .. | .. |
|---|
| 154 | 154 | "readOnly" : true, |
|---|
| 155 | 155 | "mandatory" : true |
|---|
| 156 | 156 | }, { |
|---|
| 157 | + "name" : "email", |
|---|
| 158 | + "display" : "Email", |
|---|
| 159 | + "type" : "email", |
|---|
| 160 | + "maxlength" : 150, |
|---|
| 161 | + "mandatory" : true |
|---|
| 162 | + }, { |
|---|
| 157 | 163 | "name" : "first_name", |
|---|
| 158 | 164 | "display" : "First name", |
|---|
| 159 | 165 | "type" : "string", |
|---|
| .. | .. |
|---|
| 228 | 228 | </div> |
|---|
| 229 | 229 | |
|---|
| 230 | 230 | <div class="form-group"> |
|---|
| 231 | | - <div class="col-md-offset-3 col-md-10" id="saveContainer"> |
|---|
| 231 | + <div class="col-md-offset-3 col-md-10 " id="saveContainer"> |
|---|
| 232 | 232 | <button id="save" type="submit" class="btn btn-primary"> |
|---|
| 233 | 233 | <span i18n class="glyphicon glyphicon-floppy-disk"></span> Save |
|---|
| 234 | 234 | </button> |
|---|
| 235 | + <button id="acc" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> |
|---|
| 236 | + <span i18n class="glyphicon glyphicon-align-justify"></span> Actions |
|---|
| 237 | + <span class="caret"></span> |
|---|
| 238 | + </button> |
|---|
| 239 | + <ul class="dropdown-menu" role="menu"> |
|---|
| 240 | + <li><a href="#">Activate</a></li> |
|---|
| 241 | + <li><a href="#">On hold</a></li> |
|---|
| 242 | + <li class="divider"></li> |
|---|
| 243 | + <li><a href="#">Invalidate</a></li> |
|---|
| 244 | + <li><a href="#">Delete</a></li> |
|---|
| 245 | + </ul> |
|---|
| 235 | 246 | </div> |
|---|
| 236 | 247 | </div> |
|---|
| 237 | 248 | </form> |
|---|
| .. | .. |
|---|
| 534 | 545 | <button id="save" type="submit" class="btn btn-primary"> |
|---|
| 535 | 546 | <span i18n class="glyphicon glyphicon-floppy-disk"></span> Save |
|---|
| 536 | 547 | </button> |
|---|
| 537 | | - <button id="activate" class="btn btn-success" |
|---|
| 538 | | - ng-click="activateLicense(license)" |
|---|
| 539 | | - ng-if="isActionVisible('activate', license)"> |
|---|
| 540 | | - <span i18n class="glyphicon glyphicon-check"></span> Activate |
|---|
| 548 | + <button id="acc" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> |
|---|
| 549 | + <span i18n class="glyphicon glyphicon-align-justify"></span> Actions |
|---|
| 550 | + <span class="caret"></span> |
|---|
| 541 | 551 | </button> |
|---|
| 542 | | - <button id="send" class="btn btn-info" |
|---|
| 543 | | - ng-click="sendLicense(license)" |
|---|
| 544 | | - ng-if="isActionVisible('send', license)"> |
|---|
| 545 | | - <span i18n class="glyphicon glyphicon-send"></span> Send |
|---|
| 546 | | - </button> |
|---|
| 547 | | - <button id="cancel" class="btn btn-warning" |
|---|
| 548 | | - ng-click="cancelLicense(license)" |
|---|
| 549 | | - ng-if="isActionVisible('cancel', license)"> |
|---|
| 550 | | - <span i18n class="glyphicon glyphicon-ban-circle"></span> Cancel |
|---|
| 551 | | - </button> |
|---|
| 552 | | - <button id="remove" class="btn btn-danger" |
|---|
| 553 | | - ng-click="removeLicense(license)" |
|---|
| 554 | | - ng-if="isActionVisible('delete', license)"> |
|---|
| 555 | | - <span i18n class="glyphicon glyphicon-trash"></span> Delete |
|---|
| 556 | | - </button> |
|---|
| 552 | + <ul class="dropdown-menu" role="menu"> |
|---|
| 553 | + <li ng-if="isActionVisible('activate', license)"><a ng-click="activateLicense(license)" href="#">Activate</a></li> |
|---|
| 554 | + <li ng-if="isActionVisible('download', license)"><a ng-click="downloadLicense(license)" href="#">Download</a></li> |
|---|
| 555 | + <li ng-if="isActionVisible('send', license)"><a ng-click="sendLicense(license)" href="#">Send by email</a></li> |
|---|
| 556 | + <li ng-if="isActionVisible('cancel', license)"><a ng-click="cancelLicense(license)" href="#">Invalidate</a></li> |
|---|
| 557 | + <li ng-if="isActionVisible('delete', license)"><a ng-click="removeLicense(license)" href="#">Delete</a></li> |
|---|
| 558 | + </ul> |
|---|
| 559 | + |
|---|
| 557 | 560 | </div> |
|---|
| 558 | 561 | </div> |
|---|
| 559 | 562 | </form> |
|---|