From 6f79bb97d9d914f76c680e93bdb16fd7b1d23603 Mon Sep 17 00:00:00 2001 From: huangping Date: Mon, 18 May 2026 22:27:03 +0800 Subject: [PATCH] feat(platform): add LicenseSigner, LicenseService, LicenseController, and persistence entities --- .../api/license/LicenseController.java | 45 +++++ .../platform/api/license/LicenseService.java | 138 ++++++++++++++ .../platform/api/license/LicenseSigner.java | 180 ++++++++++++++++++ .../persistence/license/PlatformLicense.java | 54 ++++++ .../license/PlatformLicenseActivation.java | 29 +++ .../PlatformLicenseActivationMapper.java | 8 + .../license/PlatformLicenseKey.java | 27 +++ .../license/PlatformLicenseKeyMapper.java | 8 + .../license/PlatformLicenseMapper.java | 8 + 9 files changed, 497 insertions(+) create mode 100644 services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/license/LicenseController.java create mode 100644 services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/license/LicenseService.java create mode 100644 services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/license/LicenseSigner.java create mode 100644 services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicense.java create mode 100644 services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseActivation.java create mode 100644 services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseActivationMapper.java create mode 100644 services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseKey.java create mode 100644 services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseKeyMapper.java create mode 100644 services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseMapper.java diff --git a/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/license/LicenseController.java b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/license/LicenseController.java new file mode 100644 index 0000000..78faa8c --- /dev/null +++ b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/license/LicenseController.java @@ -0,0 +1,45 @@ +package cn.craftlabs.platform.api.license; + +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +@RestController +@RequestMapping("/api/v1/licenses") +public class LicenseController { + + private final LicenseService licenseService; + + public LicenseController(LicenseService licenseService) { + this.licenseService = licenseService; + } + + @PostMapping + @PreAuthorize("hasRole('LICENSE_OPS') or hasRole('ADMIN')") + public ResponseEntity> create(@RequestBody Map request) { + try { + return ResponseEntity.ok(licenseService.create(request)); + } catch (Exception e) { + return ResponseEntity.internalServerError().body(Map.of("error", e.getMessage())); + } + } + + @GetMapping("/{licenseId}") + @PreAuthorize("hasRole('LICENSE_OPS') or hasRole('ADMIN')") + public ResponseEntity> get(@PathVariable String licenseId) { + Map result = licenseService.get(licenseId); + if (result == null) { + return ResponseEntity.notFound().build(); + } + return ResponseEntity.ok(result); + } + + @PostMapping("/{licenseId}/revoke") + @PreAuthorize("hasRole('LICENSE_OPS') or hasRole('ADMIN')") + public ResponseEntity revoke(@PathVariable String licenseId, @RequestBody Map request) { + licenseService.revoke(licenseId, request.getOrDefault("reason", "manual")); + return ResponseEntity.ok().build(); + } +} diff --git a/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/license/LicenseService.java b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/license/LicenseService.java new file mode 100644 index 0000000..7d1b267 --- /dev/null +++ b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/license/LicenseService.java @@ -0,0 +1,138 @@ +package cn.craftlabs.platform.api.license; + +import cn.craftlabs.platform.api.persistence.license.*; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.OffsetDateTime; +import java.util.*; + +@Service +public class LicenseService { + + private final PlatformLicenseMapper licenseMapper; + private final PlatformLicenseActivationMapper activationMapper; + private final PlatformLicenseKeyMapper keyMapper; + private final LicenseSigner signer; + + public LicenseService(PlatformLicenseMapper licenseMapper, + PlatformLicenseActivationMapper activationMapper, + PlatformLicenseKeyMapper keyMapper, + LicenseSigner signer) { + this.licenseMapper = licenseMapper; + this.activationMapper = activationMapper; + this.keyMapper = keyMapper; + this.signer = signer; + } + + @Transactional + public Map create(Map request) throws Exception { + PlatformLicenseKey activeKey = findActiveKey(); + if (activeKey == null) { + throw new IllegalStateException("No active license key configured"); + } + + LicenseSigner.LicensePayload payload = new LicenseSigner.LicensePayload(); + payload.setLicenseId(UUID.randomUUID().toString().replace("-", "").substring(0, 26)); + payload.setTenantId((String) request.get("tenantId")); + payload.setProduct((String) request.getOrDefault("product", "default")); + + LicenseSigner.Grant grant = new LicenseSigner.Grant(); + grant.setType((String) request.getOrDefault("grantType", "subscription")); + grant.setNotBefore(toEpoch(request.get("notBefore"))); + grant.setNotAfter(toEpoch(request.get("notAfter"))); + grant.setOfflineGraceDays((Integer) request.getOrDefault("offlineGraceDays", 7)); + grant.setHeartbeatIntervalHours((Integer) request.getOrDefault("heartbeatIntervalHours", 24)); + payload.setGrant(grant); + + LicenseSigner.Constraints constraints = new LicenseSigner.Constraints(); + constraints.setMaxDevices((Integer) request.getOrDefault("maxDevices", 1)); + constraints.setMaxConcurrentUsers((Integer) request.getOrDefault("maxConcurrentUsers", 0)); + constraints.setMaxActivations((Integer) request.getOrDefault("maxActivations", 0)); + payload.setConstraints(constraints); + + @SuppressWarnings("unchecked") + Map features = (Map) request.getOrDefault("features", new HashMap<>()); + payload.setFeatures(features); + + @SuppressWarnings("unchecked") + Map custom = (Map) request.getOrDefault("custom", new HashMap<>()); + payload.setCustom(custom); + + String signedJson = signer.sign(payload, activeKey); + + PlatformLicense entity = new PlatformLicense(); + entity.setId(UUID.randomUUID()); + entity.setLicenseId(payload.getLicenseId()); + entity.setTenantId(payload.getTenantId()); + entity.setGrantType(grant.getType()); + entity.setNotBefore(grant.getNotBefore() != null ? toOffsetDateTime(grant.getNotBefore()) : OffsetDateTime.now()); + entity.setNotAfter(grant.getNotAfter() != null ? toOffsetDateTime(grant.getNotAfter()) : null); + entity.setOfflineGraceDays(grant.getOfflineGraceDays()); + entity.setHeartbeatIntervalHours(grant.getHeartbeatIntervalHours()); + entity.setMaxDevices(constraints.getMaxDevices()); + entity.setMaxConcurrentUsers(constraints.getMaxConcurrentUsers()); + entity.setMaxActivations(constraints.getMaxActivations()); + entity.setStatus("active"); + entity.setIssuedAt(OffsetDateTime.now()); + entity.setSignedPayload(signedJson); + entity.setKeyId(activeKey.getKeyId()); + licenseMapper.insert(entity); + + Map response = new HashMap<>(); + response.put("licenseId", payload.getLicenseId()); + response.put("status", "active"); + response.put("signedPayload", signedJson); + response.put("issuedAt", OffsetDateTime.now().toString()); + return response; + } + + public Map get(String licenseId) { + PlatformLicense entity = licenseMapper.selectOne( + new LambdaQueryWrapper().eq(PlatformLicense::getLicenseId, licenseId)); + if (entity == null) { + return null; + } + Map resp = new HashMap<>(); + resp.put("licenseId", entity.getLicenseId()); + resp.put("tenantId", entity.getTenantId()); + resp.put("status", entity.getStatus()); + resp.put("grantType", entity.getGrantType()); + resp.put("maxDevices", entity.getMaxDevices()); + resp.put("offlineGraceDays", entity.getOfflineGraceDays()); + resp.put("issuedAt", entity.getIssuedAt() != null ? entity.getIssuedAt().toString() : null); + return resp; + } + + @Transactional + public void revoke(String licenseId, String reason) { + PlatformLicense entity = licenseMapper.selectOne( + new LambdaQueryWrapper().eq(PlatformLicense::getLicenseId, licenseId)); + if (entity != null) { + entity.setStatus("revoked"); + entity.setRevokedAt(OffsetDateTime.now()); + entity.setRevokedReason(reason); + licenseMapper.updateById(entity); + } + } + + private PlatformLicenseKey findActiveKey() { + List keys = keyMapper.selectList( + new LambdaQueryWrapper() + .eq(PlatformLicenseKey::getStatus, "active") + .orderByDesc(PlatformLicenseKey::getCreatedAt) + .last("LIMIT 1")); + return keys.isEmpty() ? null : keys.get(0); + } + + private static Long toEpoch(Object value) { + if (value instanceof Number) return ((Number) value).longValue(); + if (value instanceof String) return Long.parseLong((String) value); + return null; + } + + private static OffsetDateTime toOffsetDateTime(long epochSeconds) { + return OffsetDateTime.ofInstant(java.time.Instant.ofEpochSecond(epochSeconds), java.time.ZoneOffset.UTC); + } +} diff --git a/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/license/LicenseSigner.java b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/license/LicenseSigner.java new file mode 100644 index 0000000..8b85764 --- /dev/null +++ b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/license/LicenseSigner.java @@ -0,0 +1,180 @@ +package cn.craftlabs.platform.api.license; + +import cn.craftlabs.platform.api.persistence.license.PlatformLicenseKey; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.stereotype.Service; + +import javax.crypto.Cipher; +import javax.crypto.Mac; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.security.*; +import java.security.spec.PKCS8EncodedKeySpec; +import java.time.Instant; +import java.util.Base64; +import java.util.Map; + +@Service +public class LicenseSigner { + + private static final ObjectMapper MAPPER = new ObjectMapper(); + private static final String AES_ALGO = "AES/GCM/NoPadding"; + private static final int GCM_TAG_LEN = 128; + private static final int GCM_NONCE_LEN = 12; + private static final String EMBEDDED_SALT = "craftlabs-license-salt-v1-2026-05"; + + public String sign(LicensePayload payload, PlatformLicenseKey key) throws Exception { + byte[] payloadJson = MAPPER.writeValueAsBytes(payload); + + byte[] aesKey = deriveAesKey(EMBEDDED_SALT, payload.getLicenseId()); + byte[] encrypted = aesGcmEncrypt(aesKey, payloadJson); + String payloadB64 = Base64.getUrlEncoder().withoutPadding().encodeToString(encrypted); + + PrivateKey privateKey = loadPrivateKey(key.getPrivateKey()); + Signature sig = Signature.getInstance("SHA256withRSA"); + sig.initSign(privateKey); + sig.update(encrypted); + String sigB64 = Base64.getUrlEncoder().withoutPadding().encodeToString(sig.sign()); + + LicenseDocument doc = new LicenseDocument(); + doc.setVersion(1); + doc.setLicenseId(payload.getLicenseId()); + doc.setIssuedAt(Instant.now().toString()); + doc.setPayload(payloadB64); + + SignatureBlock block = new SignatureBlock(); + block.setAlgorithm("RS256"); + block.setKeyId(key.getKeyId()); + block.setValue(sigB64); + doc.setSignature(block); + + return MAPPER.writeValueAsString(doc); + } + + private byte[] deriveAesKey(String salt, String licenseId) throws Exception { + Mac mac = Mac.getInstance("HmacSHA256"); + mac.init(new SecretKeySpec(salt.getBytes("UTF-8"), "HmacSHA256")); + byte[] prk = mac.doFinal(new byte[0]); + mac.init(new SecretKeySpec(prk, "HmacSHA256")); + mac.update(licenseId.getBytes("UTF-8")); + mac.update((byte) 0x01); + return mac.doFinal(); + } + + private byte[] aesGcmEncrypt(byte[] key, byte[] plaintext) throws Exception { + SecureRandom sr = new SecureRandom(); + byte[] nonce = new byte[GCM_NONCE_LEN]; + sr.nextBytes(nonce); + + Cipher cipher = Cipher.getInstance(AES_ALGO); + GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LEN, nonce); + cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), spec); + byte[] ct = cipher.doFinal(plaintext); + + byte[] result = new byte[GCM_NONCE_LEN + ct.length]; + System.arraycopy(nonce, 0, result, 0, GCM_NONCE_LEN); + System.arraycopy(ct, 0, result, GCM_NONCE_LEN, ct.length); + return result; + } + + private PrivateKey loadPrivateKey(String pem) throws Exception { + String key = pem + .replace("-----BEGIN PRIVATE KEY-----", "") + .replace("-----END PRIVATE KEY-----", "") + .replaceAll("\\s", ""); + byte[] decoded = Base64.getDecoder().decode(key); + PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decoded); + return KeyFactory.getInstance("RSA").generatePrivate(spec); + } + + // Inner DTOs + + public static class LicenseDocument { + private int version; + private String licenseId; + private String issuedAt; + private String payload; + private SignatureBlock signature; + + public int getVersion() { return version; } + public void setVersion(int version) { this.version = version; } + public String getLicenseId() { return licenseId; } + public void setLicenseId(String licenseId) { this.licenseId = licenseId; } + public String getIssuedAt() { return issuedAt; } + public void setIssuedAt(String issuedAt) { this.issuedAt = issuedAt; } + public String getPayload() { return payload; } + public void setPayload(String payload) { this.payload = payload; } + public SignatureBlock getSignature() { return signature; } + public void setSignature(SignatureBlock signature) { this.signature = signature; } + } + + public static class SignatureBlock { + private String algorithm; + private String keyId; + private String value; + + public String getAlgorithm() { return algorithm; } + public void setAlgorithm(String algorithm) { this.algorithm = algorithm; } + public String getKeyId() { return keyId; } + public void setKeyId(String keyId) { this.keyId = keyId; } + public String getValue() { return value; } + public void setValue(String value) { this.value = value; } + } + + public static class LicensePayload { + private String licenseId; + private String tenantId; + private String product; + private Grant grant; + private Constraints constraints; + private Map features; + private Map custom; + + public String getLicenseId() { return licenseId; } + public void setLicenseId(String licenseId) { this.licenseId = licenseId; } + public String getTenantId() { return tenantId; } + public void setTenantId(String tenantId) { this.tenantId = tenantId; } + public String getProduct() { return product; } + public void setProduct(String product) { this.product = product; } + public Grant getGrant() { return grant; } + public void setGrant(Grant grant) { this.grant = grant; } + public Constraints getConstraints() { return constraints; } + public void setConstraints(Constraints constraints) { this.constraints = constraints; } + public Map getFeatures() { return features; } + public void setFeatures(Map features) { this.features = features; } + public Map getCustom() { return custom; } + public void setCustom(Map custom) { this.custom = custom; } + } + + public static class Grant { + private String type; + private Long notBefore; + private Long notAfter; + private int offlineGraceDays; + private int heartbeatIntervalHours; + + public String getType() { return type; } + public void setType(String type) { this.type = type; } + public Long getNotBefore() { return notBefore; } + public void setNotBefore(Long notBefore) { this.notBefore = notBefore; } + public Long getNotAfter() { return notAfter; } + public void setNotAfter(Long notAfter) { this.notAfter = notAfter; } + public int getOfflineGraceDays() { return offlineGraceDays; } + public void setOfflineGraceDays(int offlineGraceDays) { this.offlineGraceDays = offlineGraceDays; } + public int getHeartbeatIntervalHours() { return heartbeatIntervalHours; } + public void setHeartbeatIntervalHours(int heartbeatIntervalHours) { this.heartbeatIntervalHours = heartbeatIntervalHours; } + } + + public static class Constraints { + private int maxDevices; + private int maxConcurrentUsers; + private int maxActivations; + + public int getMaxDevices() { return maxDevices; } + public void setMaxDevices(int maxDevices) { this.maxDevices = maxDevices; } + public int getMaxConcurrentUsers() { return maxConcurrentUsers; } + public void setMaxConcurrentUsers(int maxConcurrentUsers) { this.maxConcurrentUsers = maxConcurrentUsers; } + public int getMaxActivations() { return maxActivations; } + public void setMaxActivations(int maxActivations) { this.maxActivations = maxActivations; } + } +} diff --git a/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicense.java b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicense.java new file mode 100644 index 0000000..8f8e6a8 --- /dev/null +++ b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicense.java @@ -0,0 +1,54 @@ +package cn.craftlabs.platform.api.persistence.license; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.time.OffsetDateTime; +import java.util.UUID; + +@TableName("platform_licenses") +public class PlatformLicense { + @TableId private UUID id; + @TableField("license_id") private String licenseId; + @TableField("tenant_id") private String tenantId; + @TableField("contract_id") private UUID contractId; + @TableField("policy_id") private UUID policyId; + @TableField("grant_type") private String grantType; + @TableField("not_before") private OffsetDateTime notBefore; + @TableField("not_after") private OffsetDateTime notAfter; + @TableField("offline_grace_days") private Integer offlineGraceDays; + @TableField("heartbeat_interval_hours") private Integer heartbeatIntervalHours; + @TableField("max_devices") private Integer maxDevices; + @TableField("max_concurrent_users") private Integer maxConcurrentUsers; + @TableField("max_activations") private Integer maxActivations; + private String status; + @TableField("issued_at") private OffsetDateTime issuedAt; + @TableField("revoked_at") private OffsetDateTime revokedAt; + @TableField("revoked_reason") private String revokedReason; + @TableField("signed_payload") private String signedPayload; + @TableField("key_id") private String keyId; + @TableField("created_at") private OffsetDateTime createdAt; + @TableField("updated_at") private OffsetDateTime updatedAt; + + public UUID getId() { return id; } public void setId(UUID id) { this.id = id; } + public String getLicenseId() { return licenseId; } public void setLicenseId(String licenseId) { this.licenseId = licenseId; } + public String getTenantId() { return tenantId; } public void setTenantId(String tenantId) { this.tenantId = tenantId; } + public UUID getContractId() { return contractId; } public void setContractId(UUID contractId) { this.contractId = contractId; } + public UUID getPolicyId() { return policyId; } public void setPolicyId(UUID policyId) { this.policyId = policyId; } + public String getGrantType() { return grantType; } public void setGrantType(String grantType) { this.grantType = grantType; } + public OffsetDateTime getNotBefore() { return notBefore; } public void setNotBefore(OffsetDateTime notBefore) { this.notBefore = notBefore; } + public OffsetDateTime getNotAfter() { return notAfter; } public void setNotAfter(OffsetDateTime notAfter) { this.notAfter = notAfter; } + public Integer getOfflineGraceDays() { return offlineGraceDays; } public void setOfflineGraceDays(Integer d) { this.offlineGraceDays = d; } + public Integer getHeartbeatIntervalHours() { return heartbeatIntervalHours; } public void setHeartbeatIntervalHours(Integer h) { this.heartbeatIntervalHours = h; } + public Integer getMaxDevices() { return maxDevices; } public void setMaxDevices(Integer v) { this.maxDevices = v; } + public Integer getMaxConcurrentUsers() { return maxConcurrentUsers; } public void setMaxConcurrentUsers(Integer v) { this.maxConcurrentUsers = v; } + public Integer getMaxActivations() { return maxActivations; } public void setMaxActivations(Integer v) { this.maxActivations = v; } + public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } + public OffsetDateTime getIssuedAt() { return issuedAt; } public void setIssuedAt(OffsetDateTime v) { this.issuedAt = v; } + public OffsetDateTime getRevokedAt() { return revokedAt; } public void setRevokedAt(OffsetDateTime v) { this.revokedAt = v; } + public String getRevokedReason() { return revokedReason; } public void setRevokedReason(String v) { this.revokedReason = v; } + public String getSignedPayload() { return signedPayload; } public void setSignedPayload(String v) { this.signedPayload = v; } + public String getKeyId() { return keyId; } public void setKeyId(String v) { this.keyId = v; } + public OffsetDateTime getCreatedAt() { return createdAt; } public void setCreatedAt(OffsetDateTime v) { this.createdAt = v; } + public OffsetDateTime getUpdatedAt() { return updatedAt; } public void setUpdatedAt(OffsetDateTime v) { this.updatedAt = v; } +} diff --git a/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseActivation.java b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseActivation.java new file mode 100644 index 0000000..40cb212 --- /dev/null +++ b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseActivation.java @@ -0,0 +1,29 @@ +package cn.craftlabs.platform.api.persistence.license; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import java.time.OffsetDateTime; +import java.util.UUID; + +@TableName("platform_license_activations") +public class PlatformLicenseActivation { + private UUID id; + @TableField("license_id") private String licenseId; + @TableField("device_hash") private String deviceHash; + @TableField("stability_score") private Short stabilityScore; + @TableField("server_uuid") private String serverUuid; + private String status; + @TableField("first_seen_at") private OffsetDateTime firstSeenAt; + @TableField("last_heartbeat") private OffsetDateTime lastHeartbeat; + @TableField("deactivated_at") private OffsetDateTime deactivatedAt; + + public UUID getId() { return id; } public void setId(UUID id) { this.id = id; } + public String getLicenseId() { return licenseId; } public void setLicenseId(String v) { this.licenseId = v; } + public String getDeviceHash() { return deviceHash; } public void setDeviceHash(String v) { this.deviceHash = v; } + public Short getStabilityScore() { return stabilityScore; } public void setStabilityScore(Short v) { this.stabilityScore = v; } + public String getServerUuid() { return serverUuid; } public void setServerUuid(String v) { this.serverUuid = v; } + public String getStatus() { return status; } public void setStatus(String v) { this.status = v; } + public OffsetDateTime getFirstSeenAt() { return firstSeenAt; } public void setFirstSeenAt(OffsetDateTime v) { this.firstSeenAt = v; } + public OffsetDateTime getLastHeartbeat() { return lastHeartbeat; } public void setLastHeartbeat(OffsetDateTime v) { this.lastHeartbeat = v; } + public OffsetDateTime getDeactivatedAt() { return deactivatedAt; } public void setDeactivatedAt(OffsetDateTime v) { this.deactivatedAt = v; } +} diff --git a/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseActivationMapper.java b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseActivationMapper.java new file mode 100644 index 0000000..f524d73 --- /dev/null +++ b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseActivationMapper.java @@ -0,0 +1,8 @@ +package cn.craftlabs.platform.api.persistence.license; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface PlatformLicenseActivationMapper extends BaseMapper { +} diff --git a/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseKey.java b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseKey.java new file mode 100644 index 0000000..957003f --- /dev/null +++ b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseKey.java @@ -0,0 +1,27 @@ +package cn.craftlabs.platform.api.persistence.license; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import java.time.OffsetDateTime; +import java.util.UUID; + +@TableName("platform_license_keys") +public class PlatformLicenseKey { + private UUID id; + @TableField("key_id") private String keyId; + @TableField("public_key") private String publicKey; + @TableField("private_key") private String privateKey; + private String algorithm; + private String status; + @TableField("created_at") private OffsetDateTime createdAt; + @TableField("rotated_at") private OffsetDateTime rotatedAt; + + public UUID getId() { return id; } public void setId(UUID id) { this.id = id; } + public String getKeyId() { return keyId; } public void setKeyId(String v) { this.keyId = v; } + public String getPublicKey() { return publicKey; } public void setPublicKey(String v) { this.publicKey = v; } + public String getPrivateKey() { return privateKey; } public void setPrivateKey(String v) { this.privateKey = v; } + public String getAlgorithm() { return algorithm; } public void setAlgorithm(String v) { this.algorithm = v; } + public String getStatus() { return status; } public void setStatus(String v) { this.status = v; } + public OffsetDateTime getCreatedAt() { return createdAt; } public void setCreatedAt(OffsetDateTime v) { this.createdAt = v; } + public OffsetDateTime getRotatedAt() { return rotatedAt; } public void setRotatedAt(OffsetDateTime v) { this.rotatedAt = v; } +} diff --git a/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseKeyMapper.java b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseKeyMapper.java new file mode 100644 index 0000000..0c1dec1 --- /dev/null +++ b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseKeyMapper.java @@ -0,0 +1,8 @@ +package cn.craftlabs.platform.api.persistence.license; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface PlatformLicenseKeyMapper extends BaseMapper { +} diff --git a/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseMapper.java b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseMapper.java new file mode 100644 index 0000000..c4c61c6 --- /dev/null +++ b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/license/PlatformLicenseMapper.java @@ -0,0 +1,8 @@ +package cn.craftlabs.platform.api.persistence.license; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface PlatformLicenseMapper extends BaseMapper { +}