Files
2026-07-17 02:23:59 +02:00

65 lines
1.5 KiB
TypeScript

import { createHash, randomBytes } from "crypto";
import { prisma } from "./db";
const API_KEY_PREFIX = "s2yt_live_";
export function hashApiKey(token: string) {
return createHash("sha256").update(token).digest("hex");
}
export function generateApiKeyMaterial() {
const secret = randomBytes(24).toString("base64url");
const token = `${API_KEY_PREFIX}${secret}`;
return {
token,
hash: hashApiKey(token),
prefix: token.slice(0, 20),
};
}
export async function createUserApiKey(userId: string) {
const { token, hash, prefix } = generateApiKeyMaterial();
await prisma.user.update({
where: { id: userId },
data: {
apiKeyHash: hash,
apiKeyPrefix: prefix,
},
});
return { token, prefix };
}
export async function revokeUserApiKey(userId: string) {
await prisma.user.update({
where: { id: userId },
data: {
apiKeyHash: null,
apiKeyPrefix: null,
},
});
}
export async function getUserApiKeyStatus(userId: string) {
const user = await prisma.user.findUniqueOrThrow({
where: { id: userId },
select: { apiKeyPrefix: true, apiKeyHash: true },
});
return {
configured: Boolean(user.apiKeyHash),
prefix: user.apiKeyPrefix,
};
}
export async function findUserByApiKey(token: string) {
if (!token.startsWith(API_KEY_PREFIX)) return null;
const hash = hashApiKey(token);
return prisma.user.findFirst({
where: { apiKeyHash: hash },
include: { youtubeConnection: true },
});
}