187 lines
4.3 KiB
TypeScript
187 lines
4.3 KiB
TypeScript
// 许可证类型
|
||
export type LicenseType = 'FREE' | 'STANDARD' | 'PRO';
|
||
|
||
// 许可证配置
|
||
export interface LicenseConfig {
|
||
type: LicenseType;
|
||
limits: {
|
||
maxUsers: number; // -1 表示无限
|
||
maxMaterials: number; // -1 表示无限
|
||
};
|
||
features: {
|
||
customTemplates: boolean;
|
||
systemSettings: boolean;
|
||
departmentIsolation: boolean;
|
||
apiAccess: boolean;
|
||
intranetPenetration: boolean;
|
||
};
|
||
expiresAt: string | null; // ISO 日期字符串,null 表示永久
|
||
leaseExpiresAt: string | null; // 在线租约到期时间,旧许可证可为 null
|
||
}
|
||
|
||
// 签名许可证的绑定信息:用于证明这张许可证只属于指定项目、激活码和本机实例。
|
||
export interface LicenseBinding {
|
||
projectCode: string;
|
||
licenseKey: string;
|
||
instanceId: string;
|
||
fingerprintHash: string;
|
||
activationId?: string;
|
||
}
|
||
|
||
export type SignedLicenseData = LicenseConfig & LicenseBinding & { issuedAt: string };
|
||
|
||
// 签名后的许可证
|
||
export interface SignedLicense {
|
||
data: SignedLicenseData;
|
||
signature: string;
|
||
issuedAt: string;
|
||
}
|
||
|
||
// 硬件指纹
|
||
export interface HardwareFingerprint {
|
||
machineId: string;
|
||
hostname: string;
|
||
macAddress: string;
|
||
cpuId?: string;
|
||
instanceId: string;
|
||
}
|
||
|
||
// 许可证服务请求签名字段
|
||
export interface LicenseRequestSignatureFields {
|
||
nonce: string;
|
||
signature: string;
|
||
}
|
||
|
||
// 激活请求
|
||
export interface ActivateRequest extends LicenseRequestSignatureFields {
|
||
licenseKey: string;
|
||
fingerprint: HardwareFingerprint;
|
||
timestamp: number;
|
||
}
|
||
|
||
// 激活响应
|
||
export interface ActivateResponse {
|
||
success: boolean;
|
||
license?: SignedLicense;
|
||
error?: string;
|
||
}
|
||
|
||
// 验证请求
|
||
export interface VerifyRequest extends LicenseRequestSignatureFields {
|
||
instanceId: string;
|
||
fingerprint: HardwareFingerprint;
|
||
timestamp: number;
|
||
}
|
||
|
||
// 验证响应
|
||
export interface VerifyResponse {
|
||
valid: boolean;
|
||
license?: SignedLicense;
|
||
error?: string;
|
||
}
|
||
|
||
// 心跳请求
|
||
export interface HeartbeatRequest extends LicenseRequestSignatureFields {
|
||
instanceId: string;
|
||
fingerprint: HardwareFingerprint;
|
||
usage: {
|
||
userCount: number;
|
||
materialCount: number;
|
||
};
|
||
timestamp: number;
|
||
}
|
||
|
||
// 心跳响应
|
||
export interface HeartbeatResponse {
|
||
acknowledged: boolean;
|
||
license?: SignedLicense;
|
||
}
|
||
|
||
// 版本检查响应
|
||
export interface VersionCheckResponse {
|
||
latestVersion: string;
|
||
minRequiredVersion: string | null;
|
||
releaseNotes: string | null;
|
||
releaseDate: string;
|
||
isSecurityUpdate: boolean;
|
||
isCriticalUpdate: boolean;
|
||
downloadSize: string | null;
|
||
}
|
||
|
||
// 各版本默认在线租约:免费版更短,付费版更宽松
|
||
export const LICENSE_LEASE_DAYS: Record<LicenseType, number> = {
|
||
FREE: 3,
|
||
STANDARD: 30,
|
||
PRO: 60,
|
||
};
|
||
|
||
// 各版本的默认配置
|
||
export const LICENSE_CONFIGS: Record<LicenseType, Omit<LicenseConfig, 'expiresAt' | 'leaseExpiresAt'>> = {
|
||
FREE: {
|
||
type: 'FREE',
|
||
limits: {
|
||
maxUsers: 10,
|
||
maxMaterials: 100,
|
||
},
|
||
features: {
|
||
customTemplates: false,
|
||
systemSettings: false,
|
||
departmentIsolation: false,
|
||
apiAccess: false,
|
||
intranetPenetration: false,
|
||
},
|
||
},
|
||
STANDARD: {
|
||
type: 'STANDARD',
|
||
limits: {
|
||
maxUsers: -1,
|
||
maxMaterials: -1,
|
||
},
|
||
features: {
|
||
customTemplates: true,
|
||
systemSettings: true,
|
||
departmentIsolation: true,
|
||
apiAccess: false,
|
||
intranetPenetration: false,
|
||
},
|
||
},
|
||
PRO: {
|
||
type: 'PRO',
|
||
limits: {
|
||
maxUsers: -1,
|
||
maxMaterials: -1,
|
||
},
|
||
features: {
|
||
customTemplates: true,
|
||
systemSettings: true,
|
||
departmentIsolation: true,
|
||
apiAccess: false,
|
||
intranetPenetration: true,
|
||
},
|
||
},
|
||
};
|
||
|
||
/**
|
||
* 根据许可证类型生成配置
|
||
*/
|
||
export function generateLicenseConfig(
|
||
type: LicenseType,
|
||
expiresAt?: Date | null,
|
||
leaseExpiresAt?: Date
|
||
): LicenseConfig {
|
||
const baseConfig = LICENSE_CONFIGS[type];
|
||
const defaultLeaseExpiresAt = new Date(
|
||
Date.now() + LICENSE_LEASE_DAYS[type] * 24 * 60 * 60 * 1000
|
||
);
|
||
const resolvedLeaseExpiresAt = leaseExpiresAt || defaultLeaseExpiresAt;
|
||
const boundedLeaseExpiresAt = expiresAt && resolvedLeaseExpiresAt && expiresAt < resolvedLeaseExpiresAt
|
||
? expiresAt
|
||
: resolvedLeaseExpiresAt;
|
||
|
||
return {
|
||
...baseConfig,
|
||
expiresAt: expiresAt ? expiresAt.toISOString() : null,
|
||
leaseExpiresAt: boundedLeaseExpiresAt.toISOString(),
|
||
};
|
||
}
|