63 lines
1.6 KiB
TypeScript
63 lines
1.6 KiB
TypeScript
import type { PageServerLoad } from './$types';
|
|
import { error } from '@sveltejs/kit';
|
|
import { prisma } from '$lib/db';
|
|
import { rotateApiKey } from '$lib/server/api-key';
|
|
import { isSuper } from '$lib/server/roles';
|
|
|
|
export const load: PageServerLoad = async ({ locals }) => {
|
|
if (!isSuper(locals)) {
|
|
throw error(403, 'Only Super admins can manage API keys');
|
|
}
|
|
|
|
const now = new Date();
|
|
const activeKey = await prisma.apiKey.findFirst({
|
|
where: {
|
|
revokedAt: null,
|
|
OR: [{ expiresAt: null }, { expiresAt: { gt: now } }]
|
|
},
|
|
select: { keyPrefix: true, createdAt: true, expiresAt: true },
|
|
orderBy: { createdAt: 'desc' }
|
|
});
|
|
|
|
const expiredCount = await prisma.apiKey.count({
|
|
where: {
|
|
OR: [{ revokedAt: { not: null, lte: now } }, { expiresAt: { not: null, lte: now } }]
|
|
}
|
|
});
|
|
|
|
return {
|
|
activeKey: activeKey
|
|
? {
|
|
prefix: activeKey.keyPrefix,
|
|
createdAt: activeKey.createdAt.toISOString(),
|
|
expiresAt: activeKey.expiresAt?.toISOString() ?? null
|
|
}
|
|
: null,
|
|
totalRotated: expiredCount
|
|
};
|
|
};
|
|
|
|
export const actions = {
|
|
rotate: async ({ locals }) => {
|
|
if (!isSuper(locals)) {
|
|
return { success: false, error: 'Not authorized' };
|
|
}
|
|
|
|
const result = await rotateApiKey(false);
|
|
return {
|
|
success: true,
|
|
newKey: result.plaintext,
|
|
mode: 'normal' as const,
|
|
expiresAt: result.previousExpiresAt?.toISOString() ?? null
|
|
};
|
|
},
|
|
rotateEmergency: async ({ locals }) => {
|
|
if (!isSuper(locals)) {
|
|
return { success: false, error: 'Not authorized' };
|
|
}
|
|
|
|
const result = await rotateApiKey(true);
|
|
return { success: true, newKey: result.plaintext, mode: 'emergency' as const };
|
|
}
|
|
};
|