SPB Git forge

spb/immbot-ai

Public
1commits 1branches 0releases
1.5 MBsize
maindefault branch
20 days agolast push
TypeScript 98.3% CSS 0.9% Shell 0.7%
2.4 KB · 51 lines typescript
Raw Blame History
1// Connexion en un clic au compte de démonstration (accès aux deux cours).2// Compte étudiant PARTAGÉ, prévu pour l'essai de la plateforme — désactivable3// via DEMO_ACCOUNT_ENABLED=false.4import { NextResponse } from "next/server";5import { randomBytes } from "node:crypto";6import { apiError } from "@/lib/api.ts";7import { hashPassword } from "@/lib/auth/password.ts";8import { rateLimit } from "@/lib/auth/rate-limit.ts";9import { SESSION_COOKIE, assertSameOrigin, createSession, logAuthEvent } from "@/lib/auth/session.ts";10import { get, run } from "@/lib/db/index.ts";1112const DEMO_USERNAME = "demo.etudiant";1314export async function POST(req: Request) {15  try {16    await assertSameOrigin();17    if (process.env.DEMO_ACCOUNT_ENABLED === "false") {18      return NextResponse.json({ error: "Le compte de démonstration est désactivé." }, { status: 403 });19    }20    const ip = req.headers.get("x-forwarded-for")?.split(",")[0]?.trim() || "local";21    const rl = rateLimit(`demo:${ip}`, 10, 60 * 60 * 1000);22    if (!rl.ok) return NextResponse.json({ error: "Trop de connexions démo. Réessayez plus tard." }, { status: 429 });2324    let user = get<{ id: number; disabled: number }>("SELECT id, disabled FROM users WHERE username = ?", DEMO_USERNAME);25    if (!user) {26      // Mot de passe aléatoire jamais communiqué : ce compte ne se connecte que par ce bouton.27      const r = run(28        "INSERT INTO users (username, display_name, password_hash, role) VALUES (?, 'Étudiant·e démo', ?, 'student')",29        DEMO_USERNAME, hashPassword(randomBytes(24).toString("hex"))30      );31      user = { id: Number(r.lastInsertRowid), disabled: 0 };32    }33    if (user.disabled) return NextResponse.json({ error: "Le compte de démonstration est désactivé." }, { status: 403 });34    run("INSERT OR IGNORE INTO enrollments (user_id, course_code) VALUES (?, 'IMM1003'), (?, 'IMM1033')", user.id, user.id);3536    const { token, expiresAt } = createSession(user.id, ip, req.headers.get("user-agent") ?? undefined);37    logAuthEvent("demo-login", { userId: user.id, username: DEMO_USERNAME, ip });38    const res = NextResponse.json({ ok: true });39    res.cookies.set(SESSION_COOKIE, token, {40      httpOnly: true,41      sameSite: "lax",42      secure: process.env.NODE_ENV === "production" && (process.env.APP_URL ?? "").startsWith("https"),43      expires: expiresAt,44      path: "/",45    });46    return res;47  } catch (e) {48    return apiError(e);49  }50}51