import { Elysia, t } from "elysia"; import { html } from "@elysiajs/html"; import { cookie } from "@elysiajs/cookie"; import { KeyCloak, generateState, generateCodeVerifier } from "arctic"; import * as elements from "typed-html"; import { BaseHtml } from "../components/BaseHtml"; import { InputGroup, TextAreaGroup, ExperienceForm, EducationForm, ProjectForm } from "../components/AdminForms"; import { getAdminProfile, getAdminExperience, getAdminEducation, getAdminProjects, getAdminExperienceById, getAdminEducationById, getAdminProjectById } from "../db/queries"; import { updateProfile, createExperience, updateExperience, deleteExperience, createEducation, updateEducation, deleteEducation, updateExperienceOrder, updateEducationOrder, createProject, updateProject, deleteProject, updateProjectOrder } from "../db/mutations"; // Initialize Keycloak (Arctic) const realmURL = process.env.KEYCLOAK_REALM_URL || ""; const clientId = process.env.KEYCLOAK_CLIENT_ID || ""; const clientSecret = process.env.KEYCLOAK_CLIENT_SECRET || ""; const redirectURI = process.env.KEYCLOAK_REDIRECT_URI || "http://localhost:3000/admin/callback"; const keycloak = new KeyCloak(realmURL, clientId, clientSecret, redirectURI); const AdminLayout = ({ children }: elements.Children) => (
{children}
{/* SortableJS Initialization Script */}
); export const adminRoutes = new Elysia() .use(cookie()) .use(html()) // Auth Middleware .derive(({ cookie: { auth_session } }) => { return { isLoggedIn: !!auth_session?.value }; }) // 1. Login Page .get("/admin/login", ({ isLoggedIn, set, html, cookie: { oauth_state, oauth_code_verifier } }) => { if (isLoggedIn) return Response.redirect("/admin/dashboard"); const state = generateState(); const codeVerifier = generateCodeVerifier(); oauth_state.set({ value: state, path: "/", secure: process.env.NODE_ENV === "production", httpOnly: true, maxAge: 600 }); oauth_code_verifier.set({ value: codeVerifier, path: "/", secure: process.env.NODE_ENV === "production", httpOnly: true, maxAge: 600 }); try { const url = keycloak.createAuthorizationURL(state, codeVerifier, ["openid", "profile", "email"]); return html(
); } catch (e) { return "Error generating Keycloak URL. Check .env configuration."; } }) // 2. Callback Handler .get("/admin/callback", async ({ query, cookie: { oauth_state, oauth_code_verifier, auth_session }, set }) => { const code = query.code as string; const state = query.state as string; const storedState = oauth_state.value; const storedVerifier = oauth_code_verifier.value; if (!code || !state || !storedState || !storedVerifier || state !== storedState) { return new Response("Invalid State or Code", { status: 400 }); } try { const tokens = await keycloak.validateAuthorizationCode(code, storedVerifier); auth_session.set({ value: tokens.accessToken(), httpOnly: true, path: "/", secure: process.env.NODE_ENV === "production", maxAge: 86400 // 1 day }); oauth_state.remove(); oauth_code_verifier.remove(); return Response.redirect("/admin/dashboard"); } catch (e: any) { console.error("Keycloak Error:", e); return new Response(`Authentication failed: ${e.message}\n\nStack: ${e.stack}`, { status: 500 }); } }) .get("/admin/logout", ({ cookie: { auth_session }, set }) => { auth_session.remove(); return Response.redirect("/admin/login"); }) // Protected Routes Guard .onBeforeHandle(({ isLoggedIn, set }) => { if (!isLoggedIn) return Response.redirect("/admin/login"); }) // Dashboard .get("/admin/dashboard", ({ html }) => { const profile = getAdminProfile(); const experience = getAdminExperience(); const education = getAdminEducation(); const projects = getAdminProjects(); return html(

Dashboard

{/* Profile Section */}

Profile

English

German

{/* Projects Section */}

Projects

{projects.map((proj: any) => ( ))}
{/* Experience Section */}

Experience

{experience.map((exp: any) => ( ))}
{/* Education Section */}

Education

{education.map((edu: any) => ( ))}
); }) // POST Handlers .post("/admin/profile", ({ body, set }) => { updateProfile(1, body); return Response.redirect("/admin/dashboard"); }) // Projects .post("/admin/project/new", ({ set }) => { const id = createProject(); const newItem = getAdminProjectById(Number(id)); if (!newItem) return ""; return ; }) .post("/admin/project/reorder", ({ body }) => { const { ids } = body as { ids: string[] }; updateProjectOrder(ids.map(Number)); return "OK"; }) .post("/admin/project/:id", ({ params, body, set }) => { const id = Number(params.id); updateProject(id, body); const updatedProj = getAdminProjectById(id); if (!updatedProj) return ""; return ; }) .post("/admin/project/:id/delete", ({ params, set }) => { deleteProject(Number(params.id)); return ""; }) // Experience .post("/admin/experience/new", ({ set }) => { const id = createExperience(); const newItem = getAdminExperienceById(Number(id)); if (!newItem) return ""; return ; }) .post("/admin/experience/reorder", ({ body }) => { const { ids } = body as { ids: string[] }; updateExperienceOrder(ids.map(Number)); return "OK"; }) .post("/admin/experience/:id", ({ params, body, set }) => { const id = Number(params.id); updateExperience(id, body); const updatedExp = getAdminExperienceById(id); if (!updatedExp) return ""; return ; }) .post("/admin/experience/:id/delete", ({ params, set }) => { deleteExperience(Number(params.id)); return ""; }) // Education .post("/admin/education/new", ({ set }) => { const id = createEducation(); const newItem = getAdminEducationById(Number(id)); if (!newItem) return ""; return ; }) .post("/admin/education/reorder", ({ body }) => { const { ids } = body as { ids: string[] }; updateEducationOrder(ids.map(Number)); return "OK"; }) .post("/admin/education/:id", ({ params, body, set }) => { const id = Number(params.id); updateEducation(id, body); const updatedEdu = getAdminEducationById(id); if (!updatedEdu) return ""; return ; }) .post("/admin/education/:id/delete", ({ params, set }) => { deleteEducation(Number(params.id)); return ""; });