mirror of
https://github.com/hpd840321/craftlabs-authorization-sdk.git
synced 2026-06-09 10:00:30 +08:00
feat(platform): add LicenseSigner, LicenseService, LicenseController, and persistence entities
This commit is contained in:
+45
@@ -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<Map<String, Object>> create(@RequestBody Map<String, Object> 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<Map<String, Object>> get(@PathVariable String licenseId) {
|
||||
Map<String, Object> 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<Void> revoke(@PathVariable String licenseId, @RequestBody Map<String, String> request) {
|
||||
licenseService.revoke(licenseId, request.getOrDefault("reason", "manual"));
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
}
|
||||
+138
@@ -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<String, Object> create(Map<String, Object> 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<String, Boolean> features = (Map<String, Boolean>) request.getOrDefault("features", new HashMap<>());
|
||||
payload.setFeatures(features);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> custom = (Map<String, String>) 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<String, Object> 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<String, Object> get(String licenseId) {
|
||||
PlatformLicense entity = licenseMapper.selectOne(
|
||||
new LambdaQueryWrapper<PlatformLicense>().eq(PlatformLicense::getLicenseId, licenseId));
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> 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<PlatformLicense>().eq(PlatformLicense::getLicenseId, licenseId));
|
||||
if (entity != null) {
|
||||
entity.setStatus("revoked");
|
||||
entity.setRevokedAt(OffsetDateTime.now());
|
||||
entity.setRevokedReason(reason);
|
||||
licenseMapper.updateById(entity);
|
||||
}
|
||||
}
|
||||
|
||||
private PlatformLicenseKey findActiveKey() {
|
||||
List<PlatformLicenseKey> keys = keyMapper.selectList(
|
||||
new LambdaQueryWrapper<PlatformLicenseKey>()
|
||||
.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);
|
||||
}
|
||||
}
|
||||
+180
@@ -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<String, Boolean> features;
|
||||
private Map<String, String> 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<String, Boolean> getFeatures() { return features; }
|
||||
public void setFeatures(Map<String, Boolean> features) { this.features = features; }
|
||||
public Map<String, String> getCustom() { return custom; }
|
||||
public void setCustom(Map<String, String> 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; }
|
||||
}
|
||||
}
|
||||
+54
@@ -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; }
|
||||
}
|
||||
+29
@@ -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; }
|
||||
}
|
||||
+8
@@ -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<PlatformLicenseActivation> {
|
||||
}
|
||||
+27
@@ -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; }
|
||||
}
|
||||
+8
@@ -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<PlatformLicenseKey> {
|
||||
}
|
||||
+8
@@ -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<PlatformLicense> {
|
||||
}
|
||||
Reference in New Issue
Block a user