Check for permissions on each routes

This commit is contained in:
Zoe Roux 2025-04-05 16:50:35 +02:00
parent 8110f7de66
commit 49f700ca6e
No known key found for this signature in database
2 changed files with 64 additions and 29 deletions

View File

@ -1,6 +1,6 @@
import Elysia, { getSchemaValidator, t } from "elysia";
import { TypeCompiler } from "@sinclair/typebox/compiler";
import Elysia, { t } from "elysia";
import { createRemoteJWKSet, jwtVerify } from "jose";
import { KError } from "./models/error";
const jwtSecret = process.env.JWT_SECRET
? new TextEncoder().encode(process.env.JWT_SECRET)
@ -16,33 +16,40 @@ const Jwt = t.Object({
sub: t.String({ description: "User id" }),
username: t.String(),
sid: t.String({ description: "Session id" }),
permissions: t.Array(t.String()),
});
const validator = getSchemaValidator(Jwt);
const validator = TypeCompiler.Compile(Jwt);
export const auth = new Elysia({ name: "auth" })
.guard({
// Those are not applied for now. See https://github.com/elysiajs/elysia/issues/1139
detail: {
security: [{ bearer: ["read"] }, { api: ["read"] }],
},
response: {
401: { ...KError, description: "" },
403: { ...KError, description: "" },
},
})
.macro({
permissions(perms: string[]) {
return {
resolve: async ({ headers: { authorization }, error }) => {
console.log(process.env.JWT_ISSUER);
const bearer = authorization?.slice(7);
if (!bearer) return { jwt: false };
if (!bearer) {
return error(500, {
status: 500,
message: "No jwt, auth server configuration error.",
});
}
// @ts-expect-error ts can't understand that there's two overload idk why
const { payload } = await jwtVerify(bearer, jwtSecret ?? jwks, {
issuer: process.env.JWT_ISSUER,
});
// TODO: use perms
return { jwt: validator.Decode<typeof Jwt>(payload) };
const jwt = validator.Decode(payload);
for (const perm of perms) {
if (!jwt.permissions.includes(perm)) {
return error(403, {
status: 403,
message: `Missing permission: '${perm}'.`,
details: { current: jwt.permissions, required: perms },
});
}
}
return { jwt };
},
};
},

View File

@ -1,4 +1,5 @@
import { Elysia, t } from "elysia";
import { auth } from "./auth";
import { entriesH } from "./controllers/entries";
import { imagesH } from "./controllers/images";
import { seasonsH } from "./controllers/seasons";
@ -10,7 +11,7 @@ import { showsH } from "./controllers/shows/shows";
import { staffH } from "./controllers/staff";
import { studiosH } from "./controllers/studios";
import { videosH } from "./controllers/videos";
import type { KError } from "./models/error";
import { KError } from "./models/error";
export const base = new Elysia({ name: "base" })
.onError(({ code, error }) => {
@ -53,6 +54,21 @@ export const base = new Elysia({ name: "base" })
export const prefix = process.env.KYOO_PREFIX ?? "";
export const app = new Elysia({ prefix })
.use(base)
.use(auth)
.guard(
{
// Those are not applied for now. See https://github.com/elysiajs/elysia/issues/1139
detail: {
security: [{ bearer: ["core.read"] }, { api: ["core.read"] }],
},
response: {
401: { ...KError, description: "" },
403: { ...KError, description: "" },
},
perms: ["core.read"],
},
(app) =>
app
.use(showsH)
.use(movies)
.use(series)
@ -61,6 +77,18 @@ export const app = new Elysia({ prefix })
.use(seasonsH)
.use(studiosH)
.use(staffH)
.use(videosH)
.use(imagesH)
.use(seed);
.use(imagesH),
)
.guard(
{
detail: {
security: [{ bearer: ["core.write"] }, { api: ["core.write"] }],
},
response: {
401: { ...KError, description: "" },
403: { ...KError, description: "" },
},
perms: ["core.read"],
},
(app) => app.use(videosH).use(seed),
);