flnxi-Wu/lib/license/types.ts

191 lines
4.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 许可证类型
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 LocalLicenseData {
instanceId: string;
licenseKey: string;
licenseData: string; // 加密存储的签名许可证
lastVerified: string; // ISO 日期字符串
cachedConfig: LicenseConfig;
lastSeenAt?: string; // 本地最后可信时间,用于识别系统时间回拨
clockRollbackDetectedAt?: string | null; // 检测到明显回拨的时间
clockIntegrity?: string; // 本地时间状态校验签名,防止直接改库绕过
}
// 功能键
export type FeatureKey = keyof LicenseConfig['features'];
// 各版本默认在线租约:免费版更短,付费版更宽松
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(),
};
}