115 lines
3.3 KiB
TypeScript
115 lines
3.3 KiB
TypeScript
import { NextResponse } from 'next/server';
|
||
import { getServerSession } from 'next-auth';
|
||
import { authOptions } from '@/lib/auth';
|
||
import { prisma } from '@/lib/prisma';
|
||
import { isCurrentSuperAdmin } from '@/lib/admin-permissions';
|
||
import { getLicense } from '@/lib/license';
|
||
import type { LocalLicenseData } from '@/lib/license/types';
|
||
|
||
function maskLicenseKey(licenseKey: string | null): string | null {
|
||
if (!licenseKey) return null;
|
||
if (licenseKey.length <= 8) return '****';
|
||
return `${licenseKey.slice(0, 4)}****${licenseKey.slice(-4)}`;
|
||
}
|
||
|
||
export async function GET() {
|
||
try {
|
||
const session = await getServerSession(authOptions);
|
||
if (!session) {
|
||
return NextResponse.json({ error: '未登录' }, { status: 401 });
|
||
}
|
||
|
||
if ((session.user as any)?.role !== 'ADMIN') {
|
||
return NextResponse.json({ error: '权限不足' }, { status: 403 });
|
||
}
|
||
|
||
const canReadFullLicenseKey = await isCurrentSuperAdmin(session);
|
||
|
||
// 获取使用统计(无论是否有许可证都需要)
|
||
const [userCount, materialCount] = await Promise.all([
|
||
prisma.user.count(),
|
||
prisma.material.count(),
|
||
]);
|
||
|
||
const license = getLicense();
|
||
|
||
// 如果没有许可证,返回未激活状态(而不是401错误)
|
||
if (!license) {
|
||
return NextResponse.json({
|
||
type: 'FREE' as const,
|
||
status: 'active' as const,
|
||
expiresAt: null,
|
||
licenseKey: null,
|
||
usage: {
|
||
users: {
|
||
current: userCount,
|
||
max: 10, // 免费版默认限制
|
||
},
|
||
materials: {
|
||
current: materialCount,
|
||
max: 100, // 免费版默认限制
|
||
},
|
||
},
|
||
features: {
|
||
customTemplates: false,
|
||
systemSettings: false,
|
||
departmentIsolation: false,
|
||
apiAccess: false,
|
||
intranetPenetration: false,
|
||
},
|
||
lastVerified: new Date().toISOString(),
|
||
activated: false, // 标记为未激活
|
||
});
|
||
}
|
||
|
||
// 获取本地许可证数据
|
||
const localLicense = await prisma.systemConfig.findUnique({
|
||
where: { key: 'license' },
|
||
});
|
||
|
||
let lastVerified = new Date().toISOString();
|
||
let licenseKey: string | null = null;
|
||
if (localLicense) {
|
||
try {
|
||
const data = JSON.parse(localLicense.value) as LocalLicenseData;
|
||
lastVerified = data.lastVerified || lastVerified;
|
||
licenseKey = data.licenseKey || null;
|
||
} catch {
|
||
// ignore
|
||
}
|
||
}
|
||
|
||
// 判断状态
|
||
let status: 'active' | 'expired' | 'grace' = 'active';
|
||
if (license.expiresAt && new Date(license.expiresAt) < new Date()) {
|
||
status = 'expired';
|
||
}
|
||
|
||
return NextResponse.json({
|
||
type: license.type,
|
||
status,
|
||
expiresAt: license.expiresAt,
|
||
usage: {
|
||
users: {
|
||
current: userCount,
|
||
max: license.limits.maxUsers,
|
||
},
|
||
materials: {
|
||
current: materialCount,
|
||
max: license.limits.maxMaterials,
|
||
},
|
||
},
|
||
features: license.features,
|
||
lastVerified,
|
||
activated: true, // 标记为已激活
|
||
licenseKey: canReadFullLicenseKey ? licenseKey : maskLicenseKey(licenseKey),
|
||
});
|
||
} catch (error) {
|
||
console.error('获取许可证信息失败:', error);
|
||
return NextResponse.json(
|
||
{ error: '服务器错误' },
|
||
{ status: 500 }
|
||
);
|
||
}
|
||
}
|