feat: cascade deletes, student notes, import popups, module reorganization
- Cascade delete on all entities (student, module, UE, user, role, promotion) - Fix Response body reuse bug (factory functions instead of constants) - Student note viewing via CAS uid (strip non-digit prefix) - Fix middleware page visibility for students in LOCAL mode - Import result popup component (shared across all import pages) - Fix student import to use numEtud from Excel - Bulk student selection with promo change and delete - Move UE/UE-Module API and pages from notes to admin module - Move promotions page from students to admin module - Multi-year maquette import with per-year promo selection - Inline promo creation in maquette import - Static Excel templates (students, notes, maquette) - Fix XLSX export using blob download instead of writeFile - Allow students to read modules list (GET /modules)
This commit is contained in:
+53
-21
@@ -4,41 +4,73 @@ import { createJwt } from "@popov/jwt";
|
||||
import { setCookie } from "$std/http/cookie.ts";
|
||||
import { getKey } from "$root/routes/_middleware.ts";
|
||||
|
||||
const FAKE_ADMIN: CasContent = {
|
||||
amuCampus: "local",
|
||||
amuComposante: "local",
|
||||
amuDateValidation: "",
|
||||
coGroup: "",
|
||||
eduPersonPrimaryAffiliation: "employee",
|
||||
eduPersonPrincipalName: "admin@local",
|
||||
mail: "admin@local",
|
||||
displayName: "Admin Local",
|
||||
givenName: "Admin",
|
||||
memberOf: [],
|
||||
sn: "Local",
|
||||
supannCivilite: "",
|
||||
supannEntiteAffectation: "",
|
||||
supannEtuAnneeInscription: "",
|
||||
supannEtuEtape: "",
|
||||
uid: "admin-local",
|
||||
};
|
||||
function makeFakeUser(
|
||||
role: "employee" | "student",
|
||||
numEtud?: string,
|
||||
): CasContent {
|
||||
if (role === "student" && numEtud) {
|
||||
return {
|
||||
amuCampus: "local",
|
||||
amuComposante: "local",
|
||||
amuDateValidation: "",
|
||||
coGroup: "",
|
||||
eduPersonPrimaryAffiliation: "student",
|
||||
eduPersonPrincipalName: `${numEtud}@local`,
|
||||
mail: `${numEtud}@local`,
|
||||
displayName: `Etudiant ${numEtud}`,
|
||||
givenName: "",
|
||||
memberOf: [],
|
||||
sn: "",
|
||||
supannCivilite: "",
|
||||
supannEntiteAffectation: "",
|
||||
supannEtuAnneeInscription: "",
|
||||
supannEtuEtape: "",
|
||||
uid: `e${numEtud}`,
|
||||
};
|
||||
}
|
||||
return {
|
||||
amuCampus: "local",
|
||||
amuComposante: "local",
|
||||
amuDateValidation: "",
|
||||
coGroup: "",
|
||||
eduPersonPrimaryAffiliation: "employee",
|
||||
eduPersonPrincipalName: "admin@local",
|
||||
mail: "admin@local",
|
||||
displayName: "Admin Local",
|
||||
givenName: "Admin",
|
||||
memberOf: [],
|
||||
sn: "Local",
|
||||
supannCivilite: "",
|
||||
supannEntiteAffectation: "",
|
||||
supannEtuAnneeInscription: "",
|
||||
supannEtuEtape: "",
|
||||
uid: "admin-local",
|
||||
};
|
||||
}
|
||||
|
||||
export const handler: Handlers<null, State> = {
|
||||
async GET(_request: Request, _context: FreshContext<State, null>) {
|
||||
async GET(request: Request, _context: FreshContext<State, null>) {
|
||||
if (Deno.env.get("LOCAL") !== "true") {
|
||||
return new Response("Not available outside LOCAL mode.", { status: 403 });
|
||||
}
|
||||
|
||||
const url = new URL(request.url);
|
||||
const role = url.searchParams.get("role") === "student"
|
||||
? "student"
|
||||
: "employee";
|
||||
const numEtud = url.searchParams.get("numEtud") ?? undefined;
|
||||
const user = makeFakeUser(role, numEtud);
|
||||
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const payload: LoginJWT = {
|
||||
iss: "PolyMPR",
|
||||
iat: now,
|
||||
exp: now + 0xe10,
|
||||
aud: "PolyMPR",
|
||||
user: FAKE_ADMIN,
|
||||
user,
|
||||
};
|
||||
|
||||
const token = await createJwt(payload, getKey(FAKE_ADMIN.uid));
|
||||
const token = await createJwt(payload, getKey(user.uid));
|
||||
const headers = new Headers();
|
||||
setCookie(headers, { name: "sessionToken", value: token });
|
||||
headers.set("Location", "/apps");
|
||||
|
||||
Reference in New Issue
Block a user