diff --git a/app/controllers/config.ts b/app/controllers/config.ts index 5a33e75..344fd24 100644 --- a/app/controllers/config.ts +++ b/app/controllers/config.ts @@ -7,15 +7,17 @@ interface Config { apiEndpoint: string; viewsDir: string; rootUrl: URL; - openid: { - issuer: string; - client: { - client_id: string; - client_secret: string; - }; - request: HttpOptions; - }; - key: KeyObject; + openid: + | false + | { + issuer: string; + client: { + client_id: string; + client_secret: string; + }; + request: HttpOptions; + }; + key: false | KeyObject; } export type { Config }; @@ -31,18 +33,20 @@ function defaultConfig(): Config { apiUrl: new URL(process.env.QUOT_API_URL ?? "http://127.0.0.1:3000"), apiEndpoint: process.env.QUOT_API_ENDPOINT ?? "/api", viewsDir: "views", - openid: { - issuer: process.env.QUOT_OPENID_ISSUER ?? "", + openid: Boolean(process.env.QUOT_OPENID_ISSUER) && { + issuer: process.env.QUOT_OPENID_ISSUER!, client: { - client_id: process.env.QUOT_OPENID_CLIENT_ID ?? "", - client_secret: process.env.QUOT_OPENID_CLIENT_SECRET ?? "", + client_id: process.env.QUOT_OPENID_CLIENT_ID!, + client_secret: process.env.QUOT_OPENID_CLIENT_SECRET!, }, request: { timeout: 5_000 }, }, - key: crypto.createPrivateKey({ - key: JSON.parse(process.env.QUOT_JWK ?? "{}"), - format: "jwk", - }), + key: + Boolean(process.env.QUOT_JWK) && + crypto.createPrivateKey({ + key: JSON.parse(process.env.QUOT_JWK!), + format: "jwk", + }), }; } diff --git a/app/controllers/routes/login.ts b/app/controllers/routes/login.ts index fa10fdc..01d39e5 100644 --- a/app/controllers/routes/login.ts +++ b/app/controllers/routes/login.ts @@ -3,9 +3,21 @@ import { SignJWT } from "jose"; import type { FastifyInstance } from "fastify"; async function login(fastify: FastifyInstance) { - custom.setHttpOptionsDefaults(fastify.config.openid.request); - const issuer = await Issuer.discover(fastify.config.openid.issuer); - const client = new issuer.Client(fastify.config.openid.client); + const key = fastify.config.key; + if (!key) { + fastify.log.warn("The key is required to use login endpoint."); + return; + } + const openid = fastify.config.openid; + if (!openid) { + fastify.log.warn( + "The openid parameters is required to use login endpoint." + ); + return; + } + custom.setHttpOptionsDefaults(openid.request); + const issuer = await Issuer.discover(openid.issuer); + const client = new issuer.Client(openid.client); fastify.get("/login", async (request, reply) => { const params = client.callbackParams(request.raw); @@ -22,7 +34,7 @@ async function login(fastify: FastifyInstance) { .setProtectedHeader({ typ: "JWT", alg: "RS256" }) .setExpirationTime("30days") .setSubject(userUrl.href) - .sign(fastify.config.key); + .sign(key); const url = new URL(fastify.config.rootUrl); url.hash = new URLSearchParams({ jwt }).toString(); return reply.redirect(url.href); diff --git a/app/views/pages/page.tsx b/app/views/pages/page.tsx index 8180afa..f164340 100644 --- a/app/views/pages/page.tsx +++ b/app/views/pages/page.tsx @@ -11,13 +11,12 @@ async function updatePage( content: Pages.RequestContentPage ): Promise { const jwt = window.localStorage.getItem("jwt"); - if (!jwt) return false; const res = await fetch( `${import.meta.env.QUOT_API_ENDPOINT}/pages?id=eq.${id}`, { method: "PUT", headers: { - authorization: `Bearer ${jwt}`, + ...(jwt ? { authorization: `Bearer ${jwt}` } : {}), "content-type": "application/json", }, body: JSON.stringify(content), @@ -28,12 +27,11 @@ async function updatePage( async function deletePage(id: number): Promise { const jwt = window.localStorage.getItem("jwt"); - if (!jwt) return false; const res = await fetch( `${import.meta.env.QUOT_API_ENDPOINT}/pages?id=eq.${id}`, { method: "DELETE", - headers: { authorization: `Bearer ${jwt}` }, + headers: jwt ? { authorization: `Bearer ${jwt}` } : {}, } ); return res.ok; diff --git a/compose.yml b/compose.yml index a7795af..4328151 100644 --- a/compose.yml +++ b/compose.yml @@ -22,8 +22,8 @@ services: restart: unless-stopped ports: ["3000:3000"] environment: - QUOT_JWK: ${QUOT_JWK:?} # https://mkjwk.org DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD}@/postgres?host=/var/run/postgresql + PGRST_DB_ANON_ROLE: postgres volumes: - postgres_socket:/var/run/postgresql depends_on: