Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 79669d60cf | |||
| d3f1f433e1 | |||
| 022994e5a7 | |||
| 33d023986c | |||
| bbc9ea58e2 | |||
| 96b7edf77f | |||
| a19a1e6c13 | |||
| 2739a01ab5 | |||
| f3c1f10999 | |||
| 92182b952f | |||
| cf3c7c0693 | |||
| 5229453169 | |||
| 6c18189d9f | |||
| 2c1fd7e5ad | |||
| 2f15efe21e | |||
| b2847a4a7d | |||
| 3f0c8d079f | |||
| 4eaea48ebd | |||
| f959cf0d3a | |||
| 0d45bd4c1c |
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { drizzle } from "npm:drizzle-orm/node-postgres";
|
||||
import pg from "npm:pg";
|
||||
import { drizzle } from "npm:drizzle-orm@0.45.2/node-postgres";
|
||||
import pg from "npm:pg@8.20.0";
|
||||
|
||||
const { Pool } = pg;
|
||||
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import {
|
||||
primaryKey,
|
||||
serial,
|
||||
text,
|
||||
} from "npm:drizzle-orm/pg-core";
|
||||
} from "npm:drizzle-orm@0.45.2/pg-core";
|
||||
|
||||
export const roles = pgTable("roles", {
|
||||
id: serial("id").primaryKey(),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { defineConfig } from "drizzle-kit";
|
||||
import process from "node:process";
|
||||
|
||||
export default defineConfig({
|
||||
dialect: "postgresql",
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import { FreshContext, Handlers } from "$fresh/server.ts";
|
||||
import { db } from "$root/databases/db.ts";
|
||||
import { enseignements } from "$root/databases/schema.ts";
|
||||
import { AuthenticatedState } from "$root/defaults/interfaces.ts";
|
||||
import { and, eq } from "npm:drizzle-orm@0.45.2";
|
||||
|
||||
const NOT_FOUND = new Response(
|
||||
JSON.stringify({ error: "Ressource introuvable" }),
|
||||
{ status: 404, headers: { "content-type": "application/json" } },
|
||||
);
|
||||
|
||||
const FORBIDDEN = new Response(null, { status: 403 });
|
||||
|
||||
const CONFLICT = new Response(
|
||||
JSON.stringify({ error: "Cet enseignement existe déjà." }),
|
||||
{ status: 409, headers: { "content-type": "application/json" } },
|
||||
);
|
||||
|
||||
export const handler: Handlers<null, AuthenticatedState> = {
|
||||
// #29 POST /enseignements
|
||||
async POST(
|
||||
request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
if (context.state.session.eduPersonPrimaryAffiliation !== "employee") {
|
||||
return FORBIDDEN;
|
||||
}
|
||||
|
||||
const body: {
|
||||
idProf: string;
|
||||
idModule: string;
|
||||
idPromo: string;
|
||||
} = await request.json();
|
||||
|
||||
if (!body.idProf || !body.idModule || !body.idPromo) {
|
||||
return new Response(null, { status: 400 });
|
||||
}
|
||||
|
||||
// Check if enseignement already exists
|
||||
const existing = await db
|
||||
.select()
|
||||
.from(enseignements)
|
||||
.where(
|
||||
and(
|
||||
eq(enseignements.idProf, body.idProf),
|
||||
eq(enseignements.idModule, body.idModule),
|
||||
eq(enseignements.idPromo, body.idPromo),
|
||||
),
|
||||
)
|
||||
.then((rows) => rows[0] ?? null);
|
||||
|
||||
if (existing) {
|
||||
return CONFLICT;
|
||||
}
|
||||
|
||||
const [created] = await db
|
||||
.insert(enseignements)
|
||||
.values({
|
||||
idProf: body.idProf,
|
||||
idModule: body.idModule,
|
||||
idPromo: body.idPromo,
|
||||
})
|
||||
.returning();
|
||||
|
||||
return new Response(JSON.stringify(created), {
|
||||
status: 201,
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
import { FreshContext, Handlers } from "$fresh/server.ts";
|
||||
import { db } from "$root/databases/db.ts";
|
||||
import { enseignements } from "$root/databases/schema.ts";
|
||||
import { AuthenticatedState } from "$root/defaults/interfaces.ts";
|
||||
import { and, eq } from "npm:drizzle-orm@0.45.2";
|
||||
|
||||
const NOT_FOUND = new Response(
|
||||
JSON.stringify({ error: "Ressource introuvable" }),
|
||||
{ status: 404, headers: { "content-type": "application/json" } },
|
||||
);
|
||||
|
||||
const FORBIDDEN = new Response(null, { status: 403 });
|
||||
|
||||
export const handler: Handlers<null, AuthenticatedState> = {
|
||||
// #30 GET /enseignements/{idProf}/{idModule}/{idPromo}
|
||||
async GET(
|
||||
_request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
if (context.state.session.eduPersonPrimaryAffiliation !== "employee") {
|
||||
return FORBIDDEN;
|
||||
}
|
||||
|
||||
const idProf = context.params.idProf;
|
||||
const idModule = context.params.idModule;
|
||||
const idPromo = context.params.idPromo;
|
||||
|
||||
const enseignement = await db
|
||||
.select()
|
||||
.from(enseignements)
|
||||
.where(
|
||||
and(
|
||||
eq(enseignements.idProf, idProf),
|
||||
eq(enseignements.idModule, idModule),
|
||||
eq(enseignements.idPromo, idPromo),
|
||||
),
|
||||
)
|
||||
.then((rows) => rows[0] ?? null);
|
||||
|
||||
if (!enseignement) return NOT_FOUND;
|
||||
|
||||
return new Response(JSON.stringify(enseignement), {
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
},
|
||||
|
||||
// #31 DELETE /enseignements/{idProf}/{idModule}/{idPromo}
|
||||
async DELETE(
|
||||
_request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
if (context.state.session.eduPersonPrimaryAffiliation !== "employee") {
|
||||
return FORBIDDEN;
|
||||
}
|
||||
|
||||
const idProf = context.params.idProf;
|
||||
const idModule = context.params.idModule;
|
||||
const idPromo = context.params.idPromo;
|
||||
|
||||
const [deleted] = await db
|
||||
.delete(enseignements)
|
||||
.where(
|
||||
and(
|
||||
eq(enseignements.idProf, idProf),
|
||||
eq(enseignements.idModule, idModule),
|
||||
eq(enseignements.idPromo, idPromo),
|
||||
),
|
||||
)
|
||||
.returning();
|
||||
|
||||
if (!deleted) return NOT_FOUND;
|
||||
|
||||
return new Response(null, { status: 204 });
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,63 @@
|
||||
import { FreshContext, Handlers } from "$fresh/server.ts";
|
||||
import { db } from "$root/databases/db.ts";
|
||||
import { modules } from "$root/databases/schema.ts";
|
||||
import { AuthenticatedState } from "$root/defaults/interfaces.ts";
|
||||
import { eq } from "npm:drizzle-orm";
|
||||
|
||||
export const handler: Handlers<null, AuthenticatedState> = {
|
||||
// #23 GET /modules
|
||||
async GET(
|
||||
_request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
if (context.state.session.eduPersonPrimaryAffiliation !== "employee") {
|
||||
return new Response(JSON.stringify([]), {
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
const rows = await db.select().from(modules);
|
||||
return new Response(JSON.stringify(rows), {
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
},
|
||||
|
||||
// #24 POST /modules
|
||||
async POST(
|
||||
request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
if (context.state.session.eduPersonPrimaryAffiliation !== "employee") {
|
||||
return new Response(null, { status: 403 });
|
||||
}
|
||||
|
||||
const body: { id: string; nom: string } = await request.json();
|
||||
|
||||
if (!body.id || !body.nom) {
|
||||
return new Response(null, { status: 400 });
|
||||
}
|
||||
|
||||
const existing = await db
|
||||
.select()
|
||||
.from(modules)
|
||||
.where(eq(modules.id, body.id))
|
||||
.then((rows) => rows[0] ?? null);
|
||||
|
||||
if (existing) {
|
||||
return new Response(
|
||||
JSON.stringify({ error: "Un module avec cet identifiant existe déjà" }),
|
||||
{ status: 409, headers: { "content-type": "application/json" } },
|
||||
);
|
||||
}
|
||||
|
||||
const [created] = await db
|
||||
.insert(modules)
|
||||
.values({ id: body.id, nom: body.nom })
|
||||
.returning();
|
||||
|
||||
return new Response(JSON.stringify(created), {
|
||||
status: 201,
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,65 @@
|
||||
import { FreshContext, Handlers } from "$fresh/server.ts";
|
||||
import { db } from "$root/databases/db.ts";
|
||||
import { modules } from "$root/databases/schema.ts";
|
||||
import { AuthenticatedState } from "$root/defaults/interfaces.ts";
|
||||
import { eq } from "npm:drizzle-orm";
|
||||
|
||||
const NOT_FOUND = new Response(
|
||||
JSON.stringify({ error: "Ressource introuvable" }),
|
||||
{ status: 404, headers: { "content-type": "application/json" } },
|
||||
);
|
||||
|
||||
export const handler: Handlers<null, AuthenticatedState> = {
|
||||
// #25 GET /modules/{idModule}
|
||||
async GET(
|
||||
_request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
const module = await db
|
||||
.select()
|
||||
.from(modules)
|
||||
.where(eq(modules.id, context.params.idModule))
|
||||
.then((rows) => rows[0] ?? null);
|
||||
|
||||
if (!module) return NOT_FOUND;
|
||||
|
||||
return new Response(JSON.stringify(module), {
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
},
|
||||
|
||||
// #26 PUT /modules/{idModule}
|
||||
async PUT(
|
||||
request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
const body: { nom: string } = await request.json();
|
||||
|
||||
const [updated] = await db
|
||||
.update(modules)
|
||||
.set({ nom: body.nom })
|
||||
.where(eq(modules.id, context.params.idModule))
|
||||
.returning();
|
||||
|
||||
if (!updated) return NOT_FOUND;
|
||||
|
||||
return new Response(JSON.stringify(updated), {
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
},
|
||||
|
||||
// #27 DELETE /modules/{idModule}
|
||||
async DELETE(
|
||||
_request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
const [deleted] = await db
|
||||
.delete(modules)
|
||||
.where(eq(modules.id, context.params.idModule))
|
||||
.returning();
|
||||
|
||||
if (!deleted) return NOT_FOUND;
|
||||
|
||||
return new Response(null, { status: 204 });
|
||||
},
|
||||
};
|
||||
@@ -2,7 +2,7 @@ import { FreshContext, Handlers } from "$fresh/server.ts";
|
||||
import { db } from "$root/databases/db.ts";
|
||||
import { rolePermissions, roles } from "$root/databases/schema.ts";
|
||||
import { AuthenticatedState } from "$root/defaults/interfaces.ts";
|
||||
import { eq } from "npm:drizzle-orm";
|
||||
import { eq } from "npm:drizzle-orm@0.45.2";
|
||||
|
||||
async function getRoleWithPermissions(
|
||||
id: number,
|
||||
@@ -20,7 +20,11 @@ async function getRoleWithPermissions(
|
||||
.from(rolePermissions)
|
||||
.where(eq(rolePermissions.idRole, id));
|
||||
|
||||
return { id: role.id, nom: role.nom, permissions: perms.map((p) => p.idPermission) };
|
||||
return {
|
||||
id: role.id,
|
||||
nom: role.nom,
|
||||
permissions: perms.map((p) => p.idPermission),
|
||||
};
|
||||
}
|
||||
|
||||
export const handler: Handlers<null, AuthenticatedState> = {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { FreshContext, Handlers } from "$fresh/server.ts";
|
||||
import { db } from "$root/databases/db.ts";
|
||||
import { rolePermissions, roles } from "$root/databases/schema.ts";
|
||||
import { AuthenticatedState } from "$root/defaults/interfaces.ts";
|
||||
import { eq } from "npm:drizzle-orm";
|
||||
import { eq } from "npm:drizzle-orm@0.45.2";
|
||||
|
||||
const NOT_FOUND = new Response(
|
||||
JSON.stringify({ error: "Ressource introuvable" }),
|
||||
@@ -25,7 +25,11 @@ async function getRoleWithPermissions(
|
||||
.from(rolePermissions)
|
||||
.where(eq(rolePermissions.idRole, id));
|
||||
|
||||
return { id: role.id, nom: role.nom, permissions: perms.map((p) => p.idPermission) };
|
||||
return {
|
||||
id: role.id,
|
||||
nom: role.nom,
|
||||
permissions: perms.map((p) => p.idPermission),
|
||||
};
|
||||
}
|
||||
|
||||
export const handler: Handlers<null, AuthenticatedState> = {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { FreshContext, Handlers } from "$fresh/server.ts";
|
||||
import { db } from "$root/databases/db.ts";
|
||||
import { users } from "$root/databases/schema.ts";
|
||||
import { AuthenticatedState } from "$root/defaults/interfaces.ts";
|
||||
import { eq } from "npm:drizzle-orm";
|
||||
import { eq } from "npm:drizzle-orm@0.45.2";
|
||||
|
||||
export const handler: Handlers<null, AuthenticatedState> = {
|
||||
// #60 GET /users
|
||||
@@ -42,14 +42,21 @@ export const handler: Handlers<null, AuthenticatedState> = {
|
||||
|
||||
if (existing) {
|
||||
return new Response(
|
||||
JSON.stringify({ error: "Un utilisateur avec cet identifiant existe déjà" }),
|
||||
JSON.stringify({
|
||||
error: "Un utilisateur avec cet identifiant existe déjà",
|
||||
}),
|
||||
{ status: 409, headers: { "content-type": "application/json" } },
|
||||
);
|
||||
}
|
||||
|
||||
const [created] = await db
|
||||
.insert(users)
|
||||
.values({ id: body.id, nom: body.nom, prenom: body.prenom, idRole: body.idRole })
|
||||
.values({
|
||||
id: body.id,
|
||||
nom: body.nom,
|
||||
prenom: body.prenom,
|
||||
idRole: body.idRole,
|
||||
})
|
||||
.returning();
|
||||
|
||||
return new Response(JSON.stringify(created), {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { FreshContext, Handlers } from "$fresh/server.ts";
|
||||
import { db } from "$root/databases/db.ts";
|
||||
import { users } from "$root/databases/schema.ts";
|
||||
import { AuthenticatedState } from "$root/defaults/interfaces.ts";
|
||||
import { eq } from "npm:drizzle-orm";
|
||||
import { eq } from "npm:drizzle-orm@0.45.2";
|
||||
|
||||
const NOT_FOUND = new Response(
|
||||
JSON.stringify({ error: "Ressource introuvable" }),
|
||||
@@ -33,8 +33,8 @@ export const handler: Handlers<null, AuthenticatedState> = {
|
||||
request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
const body: { nom: string; prenom: string; idRole: number } =
|
||||
await request.json();
|
||||
const body: { nom: string; prenom: string; idRole: number } = await request
|
||||
.json();
|
||||
|
||||
const [updated] = await db
|
||||
.update(users)
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
import { FreshContext } from "$fresh/server.ts";
|
||||
import { State } from "$root/routes/_middleware.ts";
|
||||
|
||||
export async function Index(request: Request, context: FreshContext<State>) {
|
||||
export function Index(_request: Request, _context: FreshContext<State>) {
|
||||
return <h2>Welcome to Admin.</h2>;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Handlers } from "$fresh/server.ts";
|
||||
import { db } from "$root/databases/db.ts";
|
||||
import { mobility, promotions, students } from "$root/databases/schema.ts";
|
||||
import { eq } from "npm:drizzle-orm";
|
||||
import { eq } from "npm:drizzle-orm@0.45.2";
|
||||
|
||||
export const handler: Handlers = {
|
||||
async GET() {
|
||||
@@ -21,7 +21,11 @@ export const handler: Handlers = {
|
||||
const mobilityRows = await db.select().from(mobility);
|
||||
|
||||
const promotionRows = await db
|
||||
.select({ id: promotions.id, endyear: promotions.endyear, current: promotions.current })
|
||||
.select({
|
||||
id: promotions.id,
|
||||
endyear: promotions.endyear,
|
||||
current: promotions.current,
|
||||
})
|
||||
.from(promotions);
|
||||
|
||||
return new Response(
|
||||
@@ -107,7 +111,9 @@ export const handler: Handlers = {
|
||||
});
|
||||
}
|
||||
|
||||
return new Response("Data inserted/updated successfully", { status: 200 });
|
||||
return new Response("Data inserted/updated successfully", {
|
||||
status: 200,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error inserting mobility data:", error);
|
||||
return new Response("Failed to insert/update data", { status: 500 });
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
import { FreshContext, Handlers } from "$fresh/server.ts";
|
||||
import { db } from "$root/databases/db.ts";
|
||||
import { ajustements } from "$root/databases/schema.ts";
|
||||
import { AuthenticatedState } from "$root/defaults/interfaces.ts";
|
||||
import { eq } from "npm:drizzle-orm@0.45.2";
|
||||
|
||||
export const handler: Handlers<null, AuthenticatedState> = {
|
||||
// #48 GET /ajustements
|
||||
async GET(request) {
|
||||
try {
|
||||
const url = new URL(request.url);
|
||||
const numEtudParam = url.searchParams.get("numEtud");
|
||||
const idUEParam = url.searchParams.get("idUE");
|
||||
|
||||
let query = db.select().from(ajustements).$dynamic();
|
||||
|
||||
if (numEtudParam) {
|
||||
const numEtud = parseInt(numEtudParam);
|
||||
if (isNaN(numEtud)) {
|
||||
return new Response("Paramètre numEtud invalide", { status: 400 });
|
||||
}
|
||||
query = query.where(eq(ajustements.numEtud, numEtud));
|
||||
}
|
||||
|
||||
if (idUEParam) {
|
||||
const idUE = parseInt(idUEParam);
|
||||
if (isNaN(idUE)) {
|
||||
return new Response("Paramètre idUE invalide", { status: 400 });
|
||||
}
|
||||
query = query.where(eq(ajustements.idUE, idUE));
|
||||
}
|
||||
|
||||
const result = await query;
|
||||
|
||||
return new Response(JSON.stringify(result), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error fetching ajustements:", error);
|
||||
return new Response("Failed to fetch data", { status: 500 });
|
||||
}
|
||||
},
|
||||
|
||||
// #49 POST /ajustements
|
||||
async POST(
|
||||
request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
if (context.state.session.eduPersonPrimaryAffiliation !== "employee") {
|
||||
return new Response(null, { status: 403 });
|
||||
}
|
||||
|
||||
try {
|
||||
const body: { numEtud: number; idUE: number; valeur: number } =
|
||||
await request.json();
|
||||
|
||||
if (!body.numEtud || !body.idUE || body.valeur === undefined) {
|
||||
return new Response(
|
||||
JSON.stringify({ error: "Champs requis: numEtud, idUE, valeur" }),
|
||||
{ status: 400, headers: { "content-type": "application/json" } },
|
||||
);
|
||||
}
|
||||
|
||||
const [created] = await db
|
||||
.insert(ajustements)
|
||||
.values({
|
||||
numEtud: body.numEtud,
|
||||
idUE: body.idUE,
|
||||
valeur: body.valeur,
|
||||
})
|
||||
.returning();
|
||||
|
||||
return new Response(JSON.stringify(created), {
|
||||
status: 201,
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error creating ajustement:", error);
|
||||
return new Response("Failed to create ajustement", { status: 500 });
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
import { FreshContext, Handlers } from "$fresh/server.ts";
|
||||
import { db } from "$root/databases/db.ts";
|
||||
import { ajustements } from "$root/databases/schema.ts";
|
||||
import { AuthenticatedState } from "$root/defaults/interfaces.ts";
|
||||
import { eq } from "npm:drizzle-orm@0.45.2";
|
||||
|
||||
const NOT_FOUND = new Response(
|
||||
JSON.stringify({ error: "Ajustement introuvable" }),
|
||||
{ status: 404, headers: { "content-type": "application/json" } },
|
||||
);
|
||||
|
||||
const FORBIDDEN = new Response(null, { status: 403 });
|
||||
|
||||
export const handler: Handlers<null, AuthenticatedState> = {
|
||||
// #50 GET /ajustements/{numEtud}/{idUE}
|
||||
async GET(
|
||||
_request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
if (context.state.session.eduPersonPrimaryAffiliation !== "employee") {
|
||||
return FORBIDDEN;
|
||||
}
|
||||
|
||||
const numEtud = Number(context.params.numEtud);
|
||||
const idUE = Number(context.params.idUE);
|
||||
|
||||
if (isNaN(numEtud) || isNaN(idUE)) {
|
||||
return new Response("Paramètres invalides", { status: 400 });
|
||||
}
|
||||
|
||||
const ajustement = await db
|
||||
.select()
|
||||
.from(ajustements)
|
||||
.where(eq(ajustements.numEtud, numEtud), eq(ajustements.idUE, idUE))
|
||||
.then((rows) => rows[0] ?? null);
|
||||
|
||||
if (!ajustement) return NOT_FOUND;
|
||||
|
||||
return new Response(JSON.stringify(ajustement), {
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
import { Handlers } from "$fresh/server.ts";
|
||||
import { db } from "../../../../databases/db.ts";
|
||||
import { notes } from "../../../../databases/schema.ts";
|
||||
import { eq } from "npm:drizzle-orm";
|
||||
|
||||
export const handler: Handlers = {
|
||||
// #42 GET /notes
|
||||
async GET(request) {
|
||||
try {
|
||||
const url = new URL(request.url);
|
||||
const numEtudParam = url.searchParams.get("numEtud");
|
||||
const idModule = url.searchParams.get("idModule");
|
||||
|
||||
let query = db.select().from(notes).$dynamic();
|
||||
|
||||
if (numEtudParam) {
|
||||
const numEtud = parseInt(numEtudParam);
|
||||
if (isNaN(numEtud)) {
|
||||
return new Response("Paramètre numEtud invalide", { status: 400 });
|
||||
}
|
||||
query = query.where(eq(notes.numEtud, numEtud));
|
||||
}
|
||||
|
||||
if (idModule) {
|
||||
query = query.where(eq(notes.idModule, idModule));
|
||||
}
|
||||
|
||||
const result = await query;
|
||||
|
||||
return new Response(JSON.stringify(result), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error fetching notes:", error);
|
||||
return new Response("Failed to fetch data", { status: 500 });
|
||||
}
|
||||
},
|
||||
|
||||
// #43 POST /notes
|
||||
async POST(request) {
|
||||
try {
|
||||
const body = await request.json();
|
||||
const { note, numEtud, idModule } = body;
|
||||
|
||||
if (note === undefined || !numEtud || !idModule) {
|
||||
return new Response("Champs 'note', 'numEtud' et 'idModule' requis", { status: 400 });
|
||||
}
|
||||
|
||||
const result = await db.insert(notes).values({ note, numEtud, idModule }).returning();
|
||||
|
||||
return new Response(JSON.stringify(result[0]), {
|
||||
status: 201,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error creating note:", error);
|
||||
return new Response("Failed to create note", { status: 500 });
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,58 @@
|
||||
import { Handlers } from "$fresh/server.ts";
|
||||
import { db } from "../../../../databases/db.ts";
|
||||
import { ueModules } from "../../../../databases/schema.ts";
|
||||
import { and, eq } from "npm:drizzle-orm";
|
||||
|
||||
export const handler: Handlers = {
|
||||
// #37 GET /ue-modules
|
||||
async GET(request) {
|
||||
try {
|
||||
const url = new URL(request.url);
|
||||
const idPromo = url.searchParams.get("idPromo");
|
||||
const idUEParam = url.searchParams.get("idUE");
|
||||
|
||||
const idUE = idUEParam ? parseInt(idUEParam) : null;
|
||||
|
||||
if (idUEParam && isNaN(idUE!)) {
|
||||
return new Response("Paramètre idUE invalide", { status: 400 });
|
||||
}
|
||||
|
||||
const result = await db.select().from(ueModules).where(
|
||||
and(
|
||||
idPromo ? eq(ueModules.idPromo, idPromo) : undefined,
|
||||
idUE ? eq(ueModules.idUE, idUE) : undefined,
|
||||
),
|
||||
);
|
||||
|
||||
return new Response(JSON.stringify(result), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error fetching UE-modules:", error);
|
||||
return new Response("Failed to fetch data", { status: 500 });
|
||||
}
|
||||
},
|
||||
|
||||
// #38 POST /ue-modules
|
||||
async POST(request) {
|
||||
try {
|
||||
const body = await request.json();
|
||||
const { idModule, idUE, idPromo, coeff } = body;
|
||||
|
||||
if (!idModule || !idUE || !idPromo || coeff === undefined) {
|
||||
return new Response("Champs 'idModule', 'idUE', 'idPromo' et 'coeff' requis", { status: 400 });
|
||||
}
|
||||
|
||||
const result = await db.insert(ueModules).values({ idModule, idUE, idPromo, coeff }).returning();
|
||||
|
||||
return new Response(JSON.stringify(result[0]), {
|
||||
status: 201,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error creating UE-module:", error);
|
||||
return new Response("Failed to create UE-module", { status: 500 });
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -3,6 +3,7 @@ import { db } from "../../../../databases/db.ts";
|
||||
import { ues } from "../../../../databases/schema.ts";
|
||||
|
||||
export const handler: Handlers = {
|
||||
// #32 GET /ues
|
||||
async GET() {
|
||||
try {
|
||||
const result = await db.select().from(ues);
|
||||
@@ -16,4 +17,26 @@ export const handler: Handlers = {
|
||||
return new Response("Failed to fetch data", { status: 500 });
|
||||
}
|
||||
},
|
||||
|
||||
// #33 POST /ues
|
||||
async POST(request) {
|
||||
try {
|
||||
const body = await request.json();
|
||||
const { nom } = body;
|
||||
|
||||
if (!nom) {
|
||||
return new Response("Champ 'nom' manquant", { status: 400 });
|
||||
}
|
||||
|
||||
const result = await db.insert(ues).values({ nom }).returning();
|
||||
|
||||
return new Response(JSON.stringify(result[0]), {
|
||||
status: 201,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error creating UE:", error);
|
||||
return new Response("Failed to create UE", { status: 500 });
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
import { Handlers } from "$fresh/server.ts";
|
||||
import { db } from "../../../../../databases/db.ts";
|
||||
import { ues } from "../../../../../databases/schema.ts";
|
||||
import { eq } from "npm:drizzle-orm";
|
||||
|
||||
export const handler: Handlers = {
|
||||
// # 34 GET /ues/:idUE
|
||||
async GET(_request, context) {
|
||||
try {
|
||||
const idUE = parseInt(context.params.idUE);
|
||||
|
||||
if (isNaN(idUE)) {
|
||||
return new Response(JSON.stringify({ error: "Paramètre idUE invalide" }), {
|
||||
status: 400,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
const result = await db.select().from(ues).where(eq(ues.id, idUE));
|
||||
|
||||
if (result.length === 0) {
|
||||
return new Response(JSON.stringify({ error: "Ressource introuvable" }), {
|
||||
status: 404,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
return new Response(JSON.stringify(result[0]), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error fetching UE:", error);
|
||||
return new Response("Failed to fetch data", { status: 500 });
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
import { FreshContext, Handlers } from "$fresh/server.ts";
|
||||
import { db } from "$root/databases/db.ts";
|
||||
import { promotions } from "$root/databases/schema.ts";
|
||||
import { AuthenticatedState } from "$root/defaults/interfaces.ts";
|
||||
|
||||
export const handler: Handlers<null, AuthenticatedState> = {
|
||||
// #13 GET /promotions
|
||||
async GET(
|
||||
_request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
if (context.state.session.eduPersonPrimaryAffiliation !== "employee") {
|
||||
return new Response(JSON.stringify([]), {
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
const rows = await db.select().from(promotions);
|
||||
return new Response(JSON.stringify(rows), {
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
},
|
||||
|
||||
// #14 POST /promotions
|
||||
async POST(
|
||||
request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
if (context.state.session.eduPersonPrimaryAffiliation !== "employee") {
|
||||
return new Response(null, { status: 403 });
|
||||
}
|
||||
|
||||
const body: { idPromo: string; annee: string } = await request.json();
|
||||
|
||||
if (!body.idPromo || !body.annee) {
|
||||
return new Response(null, { status: 400 });
|
||||
}
|
||||
|
||||
const [created] = await db
|
||||
.insert(promotions)
|
||||
.values({ id: body.idPromo, annee: body.annee })
|
||||
.returning();
|
||||
|
||||
return new Response(JSON.stringify(created), {
|
||||
status: 201,
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,79 @@
|
||||
import { FreshContext, Handlers } from "$fresh/server.ts";
|
||||
import { db } from "$root/databases/db.ts";
|
||||
import { promotions } from "$root/databases/schema.ts";
|
||||
import { AuthenticatedState } from "$root/defaults/interfaces.ts";
|
||||
import { eq } from "npm:drizzle-orm@0.45.2";
|
||||
|
||||
const NOT_FOUND = new Response(
|
||||
JSON.stringify({ error: "Ressource introuvable" }),
|
||||
{ status: 404, headers: { "content-type": "application/json" } },
|
||||
);
|
||||
|
||||
const FORBIDDEN = new Response(null, { status: 403 });
|
||||
|
||||
export const handler: Handlers<null, AuthenticatedState> = {
|
||||
// #15 GET /promotions/{idPromo}
|
||||
async GET(
|
||||
_request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
if (context.state.session.eduPersonPrimaryAffiliation !== "employee") {
|
||||
return FORBIDDEN;
|
||||
}
|
||||
|
||||
const promo = await db
|
||||
.select()
|
||||
.from(promotions)
|
||||
.where(eq(promotions.id, context.params.idPromo))
|
||||
.then((rows) => rows[0] ?? null);
|
||||
|
||||
if (!promo) return NOT_FOUND;
|
||||
|
||||
return new Response(JSON.stringify(promo), {
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
},
|
||||
|
||||
// #16 PUT /promotions/{idPromo}
|
||||
async PUT(
|
||||
request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
if (context.state.session.eduPersonPrimaryAffiliation !== "employee") {
|
||||
return FORBIDDEN;
|
||||
}
|
||||
|
||||
const body: { annee: string } = await request.json();
|
||||
|
||||
const [updated] = await db
|
||||
.update(promotions)
|
||||
.set({ annee: body.annee })
|
||||
.where(eq(promotions.id, context.params.idPromo))
|
||||
.returning();
|
||||
|
||||
if (!updated) return NOT_FOUND;
|
||||
|
||||
return new Response(JSON.stringify(updated), {
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
},
|
||||
|
||||
// #17 DELETE /promotions/{idPromo}
|
||||
async DELETE(
|
||||
_request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
if (context.state.session.eduPersonPrimaryAffiliation !== "employee") {
|
||||
return FORBIDDEN;
|
||||
}
|
||||
|
||||
const [deleted] = await db
|
||||
.delete(promotions)
|
||||
.where(eq(promotions.id, context.params.idPromo))
|
||||
.returning();
|
||||
|
||||
if (!deleted) return NOT_FOUND;
|
||||
|
||||
return new Response(null, { status: 204 });
|
||||
},
|
||||
};
|
||||
@@ -1,122 +1,61 @@
|
||||
import { FreshContext, Handlers } from "$fresh/server.ts";
|
||||
import { db } from "$root/databases/db.ts";
|
||||
import { promotions, students } from "$root/databases/schema.ts";
|
||||
import { students } from "$root/databases/schema.ts";
|
||||
import { AuthenticatedState } from "$root/defaults/interfaces.ts";
|
||||
import { eq, lt } from "npm:drizzle-orm";
|
||||
|
||||
async function getItself(
|
||||
userId: string,
|
||||
): Promise<{ student: Student | null; promo: Promotion | null }> {
|
||||
const student = await db
|
||||
.select()
|
||||
.from(students)
|
||||
.where(eq(students.userId, userId))
|
||||
.limit(1)
|
||||
.then((rows) => rows[0] ?? null);
|
||||
|
||||
if (!student) {
|
||||
return { student: null, promo: null };
|
||||
}
|
||||
|
||||
const promo = await db
|
||||
.select()
|
||||
.from(promotions)
|
||||
.where(eq(promotions.id, student.promotionId!))
|
||||
.limit(1)
|
||||
.then((rows) => rows[0] ?? null);
|
||||
|
||||
return { student, promo };
|
||||
}
|
||||
|
||||
async function getAll(): Promise<
|
||||
{ students: Student[]; promos: Promotion[] }
|
||||
> {
|
||||
const rows = await db
|
||||
.select({
|
||||
userId: students.userId,
|
||||
firstName: students.firstName,
|
||||
lastName: students.lastName,
|
||||
mail: students.mail,
|
||||
promotionId: students.promotionId,
|
||||
})
|
||||
.from(students)
|
||||
.innerJoin(promotions, eq(students.promotionId, promotions.id))
|
||||
.where(lt(promotions.current, 6));
|
||||
|
||||
const promos = await db
|
||||
.select()
|
||||
.from(promotions)
|
||||
.where(lt(promotions.current, 6));
|
||||
|
||||
return { students: rows as Student[], promos };
|
||||
}
|
||||
|
||||
async function addStudents(
|
||||
studentList: Student[],
|
||||
promoId: number,
|
||||
): Promise<void> {
|
||||
for (const student of studentList) {
|
||||
await db
|
||||
.insert(students)
|
||||
.values({
|
||||
userId: student.userId,
|
||||
firstName: student.firstName,
|
||||
lastName: student.lastName,
|
||||
mail: student.mail,
|
||||
promotionId: promoId,
|
||||
})
|
||||
.onConflictDoNothing();
|
||||
}
|
||||
}
|
||||
import { eq } from "npm:drizzle-orm@0.45.2";
|
||||
|
||||
export const handler: Handlers<null, AuthenticatedState> = {
|
||||
// #7 GET /students
|
||||
async GET(
|
||||
_request: Request,
|
||||
request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
if (context.state.session.eduPersonPrimaryAffiliation == "student") {
|
||||
return new Response(
|
||||
JSON.stringify(await getItself(context.state.session.uid)),
|
||||
{ headers: { "content-type": "application/json" } },
|
||||
);
|
||||
if (context.state.session.eduPersonPrimaryAffiliation !== "employee") {
|
||||
return new Response(JSON.stringify([]), {
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
return new Response(
|
||||
JSON.stringify(await getAll()),
|
||||
{ headers: { "content-type": "application/json" } },
|
||||
);
|
||||
const url = new URL(request.url);
|
||||
const idPromo = url.searchParams.get("idPromo");
|
||||
|
||||
const rows = idPromo
|
||||
? await db.select().from(students).where(eq(students.idPromo, idPromo))
|
||||
: await db.select().from(students);
|
||||
|
||||
return new Response(JSON.stringify(rows), {
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
},
|
||||
|
||||
// #8 POST /students
|
||||
async POST(
|
||||
request: Request,
|
||||
_context: FreshContext<AuthenticatedState>,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
const { students: studentList, promo }: {
|
||||
students: Student[];
|
||||
promo: string;
|
||||
if (context.state.session.eduPersonPrimaryAffiliation !== "employee") {
|
||||
return new Response(null, { status: 403 });
|
||||
}
|
||||
|
||||
const body: {
|
||||
numEtud: number;
|
||||
nom: string;
|
||||
prenom: string;
|
||||
idPromo: string;
|
||||
} = await request.json();
|
||||
|
||||
if (!promo || !promo.match(/^\d{4}-\dA$/) || !Array.isArray(studentList)) {
|
||||
if (!body.nom || !body.prenom || !body.idPromo) {
|
||||
return new Response(null, { status: 400 });
|
||||
}
|
||||
|
||||
const { endyear, current } = promo.match(
|
||||
/^(?<endyear>\d{4})-(?<current>\d)A$/,
|
||||
)?.groups!;
|
||||
const [created] = await db
|
||||
.insert(students)
|
||||
.values({ nom: body.nom, prenom: body.prenom, idPromo: body.idPromo })
|
||||
.returning();
|
||||
|
||||
await db
|
||||
.insert(promotions)
|
||||
.values({ endyear: Number(endyear), current: Number(current) })
|
||||
.onConflictDoNothing();
|
||||
|
||||
const promo_row = await db
|
||||
.select()
|
||||
.from(promotions)
|
||||
.where(eq(promotions.endyear, Number(endyear)))
|
||||
.then((rows) => rows.find((r) => r.current === Number(current))!);
|
||||
|
||||
await addStudents(studentList, promo_row.id);
|
||||
|
||||
return new Response(null, { status: 201 });
|
||||
return new Response(JSON.stringify(created), {
|
||||
status: 201,
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
import { FreshContext, Handlers } from "$fresh/server.ts";
|
||||
import { db } from "$root/databases/db.ts";
|
||||
import { students } from "$root/databases/schema.ts";
|
||||
import { AuthenticatedState } from "$root/defaults/interfaces.ts";
|
||||
import { eq } from "npm:drizzle-orm@0.45.2";
|
||||
|
||||
const NOT_FOUND = new Response(
|
||||
JSON.stringify({ error: "Ressource introuvable" }),
|
||||
{ status: 404, headers: { "content-type": "application/json" } },
|
||||
);
|
||||
|
||||
const FORBIDDEN = new Response(null, { status: 403 });
|
||||
|
||||
export const handler: Handlers<null, AuthenticatedState> = {
|
||||
// #10 GET /students/{numEtud}
|
||||
async GET(
|
||||
_request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
if (context.state.session.eduPersonPrimaryAffiliation !== "employee") {
|
||||
return FORBIDDEN;
|
||||
}
|
||||
|
||||
const numEtud = Number(context.params.numEtud);
|
||||
const student = await db
|
||||
.select()
|
||||
.from(students)
|
||||
.where(eq(students.numEtud, numEtud))
|
||||
.then((rows) => rows[0] ?? null);
|
||||
|
||||
if (!student) return NOT_FOUND;
|
||||
|
||||
return new Response(JSON.stringify(student), {
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
},
|
||||
|
||||
// #11 PUT /students/{numEtud}
|
||||
async PUT(
|
||||
request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
if (context.state.session.eduPersonPrimaryAffiliation !== "employee") {
|
||||
return FORBIDDEN;
|
||||
}
|
||||
|
||||
const numEtud = Number(context.params.numEtud);
|
||||
const body: { nom: string; prenom: string; idPromo: string } = await request
|
||||
.json();
|
||||
|
||||
const [updated] = await db
|
||||
.update(students)
|
||||
.set({ nom: body.nom, prenom: body.prenom, idPromo: body.idPromo })
|
||||
.where(eq(students.numEtud, numEtud))
|
||||
.returning();
|
||||
|
||||
if (!updated) return NOT_FOUND;
|
||||
|
||||
return new Response(JSON.stringify(updated), {
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
},
|
||||
|
||||
// #12 DELETE /students/{numEtud}
|
||||
async DELETE(
|
||||
_request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
if (context.state.session.eduPersonPrimaryAffiliation !== "employee") {
|
||||
return FORBIDDEN;
|
||||
}
|
||||
|
||||
const numEtud = Number(context.params.numEtud);
|
||||
const [deleted] = await db
|
||||
.delete(students)
|
||||
.where(eq(students.numEtud, numEtud))
|
||||
.returning();
|
||||
|
||||
if (!deleted) return NOT_FOUND;
|
||||
|
||||
return new Response(null, { status: 204 });
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
import { FreshContext, Handlers } from "$fresh/server.ts";
|
||||
import { db } from "$root/databases/db.ts";
|
||||
import { students } from "$root/databases/schema.ts";
|
||||
import { AuthenticatedState } from "$root/defaults/interfaces.ts";
|
||||
|
||||
// #9 POST /students/import-csv
|
||||
export const handler: Handlers<null, AuthenticatedState> = {
|
||||
async POST(
|
||||
request: Request,
|
||||
context: FreshContext<AuthenticatedState>,
|
||||
): Promise<Response> {
|
||||
if (context.state.session.eduPersonPrimaryAffiliation !== "employee") {
|
||||
return new Response(null, { status: 403 });
|
||||
}
|
||||
|
||||
const formData = await request.formData();
|
||||
const file = formData.get("file") as File | null;
|
||||
const idPromo = formData.get("idPromo") as string | null;
|
||||
|
||||
if (!file || !idPromo) {
|
||||
return new Response(null, { status: 400 });
|
||||
}
|
||||
|
||||
const text = await file.text();
|
||||
const lines = text.trim().split("\n");
|
||||
|
||||
let imported = 0;
|
||||
const errors: { line: number; message: string }[] = [];
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const lineNum = i + 1;
|
||||
const cols = lines[i].split(",").map((c) => c.trim());
|
||||
|
||||
const [numEtudStr, nom, prenom] = cols;
|
||||
|
||||
if (!numEtudStr) {
|
||||
errors.push({ line: lineNum, message: "Numéro étudiant manquant" });
|
||||
continue;
|
||||
}
|
||||
|
||||
const numEtud = Number(numEtudStr);
|
||||
if (isNaN(numEtud)) {
|
||||
errors.push({ line: lineNum, message: "Numéro étudiant invalide" });
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!nom || !prenom) {
|
||||
errors.push({ line: lineNum, message: "Nom ou prénom manquant" });
|
||||
continue;
|
||||
}
|
||||
|
||||
await db
|
||||
.insert(students)
|
||||
.values({ nom, prenom, idPromo })
|
||||
.onConflictDoNothing();
|
||||
|
||||
imported++;
|
||||
}
|
||||
|
||||
return new Response(JSON.stringify({ imported, errors }), {
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user