feat: enhance authentication flow by adding API key support and refactoring user session retrieval

This commit is contained in:
암냥 2026-06-25 21:13:29 +09:00
commit f8a6893f01
No known key found for this signature in database

View file

@ -5,7 +5,7 @@ import { AuditLog } from "@/models/audit";
import { ApiKey } from "@/models/api-key";
import { USER_ROLES, User } from "@/models/user";
import { createAuditLog } from "@/lib/audit";
import { createPlainApiKey } from "@/lib/api-key";
import { authenticateApiKey, createPlainApiKey } from "@/lib/api-key";
import { ulid } from "ulid";
const hardcodedOwners = new Set<string>(
@ -14,6 +14,8 @@ const hardcodedOwners = new Set<string>(
: [],
);
type HeaderBag = Record<string, string | undefined>;
async function getSessionUser(jwt: { verify: (token: string) => Promise<unknown> }, mizuki: { value?: unknown }) {
const rawToken = mizuki.value;
if (typeof rawToken !== "string" || rawToken.length === 0) {
@ -28,8 +30,23 @@ async function getSessionUser(jwt: { verify: (token: string) => Promise<unknown>
return await User.findOne({ userId: payload.id });
}
async function getAdminSessionUser(jwt: { verify: (token: string) => Promise<unknown> }, mizuki: { value?: unknown }) {
const requester = await getSessionUser(jwt, mizuki);
async function getAuthenticatedUser(
jwt: { verify: (token: string) => Promise<unknown> },
mizuki: { value?: unknown },
headers: HeaderBag,
) {
const sessionUser = await getSessionUser(jwt, mizuki);
if (sessionUser) return sessionUser;
return await authenticateApiKey(headers);
}
async function getAdminAuthenticatedUser(
jwt: { verify: (token: string) => Promise<unknown> },
mizuki: { value?: unknown },
headers: HeaderBag,
) {
const requester = await getAuthenticatedUser(jwt, mizuki, headers);
if (!requester || requester.role !== "admin") {
return null;
}
@ -44,20 +61,10 @@ export default new Elysia({ prefix: "/auth" })
secret: config.auth.jwt_secret,
})
)
.get("/me", async ({ jwt, cookie: { mizuki }, status }) => {
const rawToken = mizuki.value;
if (typeof rawToken !== "string" || rawToken.length === 0) {
return status(401, "Unauthorized");
}
const payload = await jwt.verify(rawToken);
if (!payload || typeof payload !== "object" || !("id" in payload) || typeof payload.id !== "string") {
return status(401, "Unauthorized");
}
const user = await User.findOne({ userId: payload.id });
.get("/me", async ({ jwt, cookie: { mizuki }, headers, status }) => {
const user = await getAuthenticatedUser(jwt, mizuki, headers);
if (!user) {
return status(404, "User not found");
return status(401, "Unauthorized");
}
return {
@ -197,18 +204,8 @@ export default new Elysia({ prefix: "/auth" })
})
})
.post("/role", async ({ jwt, body, cookie: { mizuki }, status }) => {
const rawToken = mizuki.value;
if (typeof rawToken !== "string" || rawToken.length === 0) {
return status(401, "Unauthorized");
}
const payload = await jwt.verify(rawToken);
if (!payload || typeof payload !== "object" || !("id" in payload) || typeof payload.id !== "string") {
return status(401, "Unauthorized");
}
const requester = await User.findOne({ userId: payload.id });
.post("/role", async ({ jwt, body, cookie: { mizuki }, headers, status }) => {
const requester = await getAuthenticatedUser(jwt, mizuki, headers);
if (!requester) {
return status(401, "Unauthorized");
}
@ -288,19 +285,9 @@ export default new Elysia({ prefix: "/auth" })
}),
})
.delete("/user/:id", async ({ params, jwt, cookie: { mizuki }, status }) => {
const rawToken = mizuki.value;
if (typeof rawToken !== "string" || rawToken.length === 0) {
return status(401, "Unauthorized");
}
const payload = await jwt.verify(rawToken);
if (!payload || typeof payload !== "object" || !("id" in payload) || typeof payload.id !== "string") {
return status(401, "Unauthorized");
}
const requester = await User.findOne({ userId: payload.id });
if (!requester || requester.role !== "admin") {
.delete("/user/:id", async ({ params, jwt, cookie: { mizuki }, headers, status }) => {
const requester = await getAdminAuthenticatedUser(jwt, mizuki, headers);
if (!requester) {
return status(403, "Forbidden");
}
@ -339,23 +326,9 @@ export default new Elysia({ prefix: "/auth" })
})
})
.get("/users", async ({ jwt, cookie: { mizuki }, status }) => {
const rawToken = mizuki.value;
if (typeof rawToken !== "string" || rawToken.length === 0) {
return status(401, "Unauthorized");
}
const payload = await jwt.verify(rawToken);
if (!payload || typeof payload !== "object" || !("id" in payload) || typeof payload.id !== "string") {
return status(401, "Unauthorized");
}
const requester = await User.findOne({ userId: payload.id });
.get("/users", async ({ jwt, cookie: { mizuki }, headers, status }) => {
const requester = await getAdminAuthenticatedUser(jwt, mizuki, headers);
if (!requester) {
return status(401, "Unauthorized");
}
if (requester.role !== "admin") {
return status(403, "Forbidden");
}
@ -370,23 +343,9 @@ export default new Elysia({ prefix: "/auth" })
}));
})
.post("/user", async ({ jwt, body, cookie: { mizuki }, status }) => {
const rawToken = mizuki.value;
if (typeof rawToken !== "string" || rawToken.length === 0) {
return status(401, "Unauthorized");
}
const payload = await jwt.verify(rawToken);
if (!payload || typeof payload !== "object" || !("id" in payload) || typeof payload.id !== "string") {
return status(401, "Unauthorized");
}
const requester = await User.findOne({ userId: payload.id });
.post("/user", async ({ jwt, body, cookie: { mizuki }, headers, status }) => {
const requester = await getAdminAuthenticatedUser(jwt, mizuki, headers);
if (!requester) {
return status(401, "Unauthorized");
}
if (requester.role !== "admin") {
return status(403, "Forbidden");
}
@ -443,8 +402,8 @@ export default new Elysia({ prefix: "/auth" })
}),
})
.get("/api-keys", async ({ jwt, cookie: { mizuki }, status }) => {
const requester = await getAdminSessionUser(jwt, mizuki);
.get("/api-keys", async ({ jwt, cookie: { mizuki }, headers, status }) => {
const requester = await getAdminAuthenticatedUser(jwt, mizuki, headers);
if (!requester) {
return status(403, "Forbidden");
}
@ -461,8 +420,8 @@ export default new Elysia({ prefix: "/auth" })
}));
})
.post("/api-keys", async ({ jwt, body, cookie: { mizuki }, status }) => {
const requester = await getAdminSessionUser(jwt, mizuki);
.post("/api-keys", async ({ jwt, body, cookie: { mizuki }, headers, status }) => {
const requester = await getAdminAuthenticatedUser(jwt, mizuki, headers);
if (!requester) {
return status(403, "Forbidden");
}
@ -512,8 +471,8 @@ export default new Elysia({ prefix: "/auth" })
}),
})
.delete("/api-keys/:id", async ({ jwt, params, cookie: { mizuki }, status }) => {
const requester = await getAdminSessionUser(jwt, mizuki);
.delete("/api-keys/:id", async ({ jwt, params, cookie: { mizuki }, headers, status }) => {
const requester = await getAdminAuthenticatedUser(jwt, mizuki, headers);
if (!requester) {
return status(403, "Forbidden");
}
@ -552,23 +511,9 @@ export default new Elysia({ prefix: "/auth" })
}),
})
.get("/audit-logs", async ({ jwt, cookie: { mizuki }, query, status }) => {
const rawToken = mizuki.value;
if (typeof rawToken !== "string" || rawToken.length === 0) {
return status(401, "Unauthorized");
}
const payload = await jwt.verify(rawToken);
if (!payload || typeof payload !== "object" || !("id" in payload) || typeof payload.id !== "string") {
return status(401, "Unauthorized");
}
const requester = await User.findOne({ userId: payload.id });
.get("/audit-logs", async ({ jwt, cookie: { mizuki }, headers, query, status }) => {
const requester = await getAdminAuthenticatedUser(jwt, mizuki, headers);
if (!requester) {
return status(401, "Unauthorized");
}
if (requester.role !== "admin") {
return status(403, "Forbidden");
}