flnxi-Wu/license-server/lib/module-grants.ts
2026-06-02 19:25:48 +08:00

121 lines
3.1 KiB
TypeScript

import type { LicenseType } from './types';
import {
getDefaultModuleGrantSpecs,
getModuleLimits,
getPremiumModuleArtifact,
type PremiumModuleArtifact,
} from './premium-module-catalog';
import type { AuthorizedPremiumModuleGrant } from './premium-module-manifest';
type ProjectPrismaLike = {
licenseModuleGrant: {
findUnique: (args: any) => Promise<any>;
findMany: (args: any) => Promise<any[]>;
create: (args: any) => Promise<any>;
};
};
export interface LicenseForModuleGrant {
id: string;
licenseType: LicenseType;
expiresAt: Date | null;
}
function buildArtifactFromGrant(grant: any): PremiumModuleArtifact {
const defaultArtifact = getPremiumModuleArtifact(grant.moduleId);
return {
type: 'registry-image',
image: grant.image || defaultArtifact.image,
version: grant.version || defaultArtifact.version,
digest: grant.digest ?? defaultArtifact.digest ?? null,
};
}
export async function ensureDefaultModuleGrants(
prisma: ProjectPrismaLike,
license: LicenseForModuleGrant
): Promise<void> {
const defaultGrants = getDefaultModuleGrantSpecs(license.licenseType);
for (const grant of defaultGrants) {
const existing = await prisma.licenseModuleGrant.findUnique({
where: {
licenseId_moduleId: {
licenseId: license.id,
moduleId: grant.moduleId,
},
},
});
if (existing) continue;
await prisma.licenseModuleGrant.create({
data: {
licenseId: license.id,
moduleId: grant.moduleId,
status: 'active',
image: grant.artifact.image,
version: grant.artifact.version,
digest: grant.artifact.digest || null,
expiresAt: license.expiresAt,
},
});
}
}
export async function listAuthorizedModuleGrants(
prisma: ProjectPrismaLike,
license: LicenseForModuleGrant,
now: Date = new Date()
): Promise<AuthorizedPremiumModuleGrant[]> {
await ensureDefaultModuleGrants(prisma, license);
const grants = await prisma.licenseModuleGrant.findMany({
where: {
licenseId: license.id,
status: 'active',
revokedAt: null,
OR: [
{ expiresAt: null },
{ expiresAt: { gt: now } },
],
},
orderBy: { moduleId: 'asc' },
});
return grants.map((grant) => ({
moduleId: grant.moduleId,
artifact: buildArtifactFromGrant(grant),
limits: getModuleLimits(grant.moduleId, license.licenseType),
}));
}
export async function getAuthorizedModuleGrant(
prisma: ProjectPrismaLike,
license: LicenseForModuleGrant,
moduleId: string,
now: Date = new Date()
): Promise<AuthorizedPremiumModuleGrant | null> {
await ensureDefaultModuleGrants(prisma, license);
const grant = await prisma.licenseModuleGrant.findUnique({
where: {
licenseId_moduleId: {
licenseId: license.id,
moduleId,
},
},
});
if (!grant) return null;
if (grant.status !== 'active') return null;
if (grant.revokedAt) return null;
if (grant.expiresAt && grant.expiresAt <= now) return null;
return {
moduleId: grant.moduleId,
artifact: buildArtifactFromGrant(grant),
limits: getModuleLimits(grant.moduleId, license.licenseType),
};
}