Initial open-source self-hosted Songs2YT edition
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
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 },
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user