diff --git a/.env.template b/.env.template
new file mode 100644
index 0000000..f320767
--- /dev/null
+++ b/.env.template
@@ -0,0 +1,8 @@
+#Local mode, set to true to access admin pages with any users
+LOCAL=true
+
+POSTGRES_HOST = db
+POSTGRES_PORT = 5432
+POSTGRES_PASS = astrongpass
+POSTGRES_USER = postgres
+POSTGRES_DB = polympr
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
deleted file mode 100644
index d2a8d16..0000000
--- a/.github/workflows/test.yml
+++ /dev/null
@@ -1,79 +0,0 @@
-name: "Tests"
-
-on:
- pull_request:
- branches:
- - main
- - develop
- push:
- branches:
- - develop
-
-jobs:
- unit:
- name: "Unit tests"
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - uses: denoland/setup-deno@v2
- with:
- deno-version: v2.x
-
- - name: Install dependencies
- run: deno install
-
- - name: Run unit tests
- run: deno task test:unit
-
- integration:
- name: "Integration tests"
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - uses: actions/setup-node@v4
- with:
- node-version: "20"
-
- - uses: denoland/setup-deno@v2
- with:
- deno-version: v2.x
-
- - name: Start postgres
- run: |
- sudo apt-get update -qq && sudo apt-get install -y -qq postgresql > /dev/null
- PG_VER=$(ls /etc/postgresql/)
- sudo sed -i "s/^#*listen_addresses\s*=.*/listen_addresses = '127.0.0.1'/" /etc/postgresql/$PG_VER/main/postgresql.conf
- echo "host all all 127.0.0.1/32 md5" | sudo tee -a /etc/postgresql/$PG_VER/main/pg_hba.conf
- sudo pg_ctlcluster $PG_VER main restart
- until sudo -u postgres pg_isready -h 127.0.0.1; do sleep 1; done
- sudo -u postgres psql -c "CREATE USER test WITH PASSWORD 'test';"
- sudo -u postgres psql -c "CREATE DATABASE polympr_test OWNER test;"
- sudo -u postgres psql -d polympr_test -c "GRANT ALL ON SCHEMA public TO test;"
-
- - name: Apply migrations
- run: |
- sed 's/--> statement-breakpoint/;/g' databases/migrations/0000_square_jetstream.sql | \
- PGPASSWORD=test psql -h 127.0.0.1 -U test -d polympr_test
-
- - name: Install dependencies
- run: npm install --ignore-scripts && deno install
-
- - name: Run integration tests
- env:
- POSTGRES_HOST: 127.0.0.1
- POSTGRES_PORT: 5432
- POSTGRES_USER: test
- POSTGRES_PASS: test
- POSTGRES_DB: polympr_test
- run: deno task test:integration
-
- - name: Run e2e tests
- env:
- POSTGRES_HOST: 127.0.0.1
- POSTGRES_PORT: 5432
- POSTGRES_USER: test
- POSTGRES_PASS: test
- POSTGRES_DB: polympr_test
- run: deno task test:e2e
diff --git a/CLAUDE.md b/CLAUDE.md
deleted file mode 100644
index f3f37b8..0000000
--- a/CLAUDE.md
+++ /dev/null
@@ -1,354 +0,0 @@
-# PolyMPR - Claude Code Context
-
-## π Project Overview
-
-**PolyMPR** (Poly Management Platform for Resources) is a modular HR management
-system built with **Deno + Fresh** framework. It's designed to help
-organizations manage HR, student records, notes, mobility programs, and
-role-based administration.
-
-### Stack
-
-- **Runtime**: Deno
-- **Framework**: Fresh (edge-ready web framework)
-- **Database**: PostgreSQL with Drizzle ORM
-- **Frontend**: Preact with signals
-- **Authentication**: JWT-based via cookies
-- **Testing**: Deno test framework with HappyDOM for DOM testing
-
-### Current Status
-
-π§ **In Progress** - API layer largely complete, UI pages not yet built. The
-schema below is the **final/definitive schema** that guides all development.
-
----
-
-## ποΈ Architecture
-
-### Module Structure
-
-The application uses a **modulith architecture** with the following modules:
-
-```
-routes/(apps)/
-βββ students/ - Student management & promotions
-βββ notes/ - Grade management & academic records
-βββ mobility/ - Mobility programs & exchanges
-βββ admin/ - Role & permission management
-```
-
-### Key Directories
-
-- `/routes` - Fresh routes and components
-- `/databases` - Database connection, schema, and migrations
-- `/defaults` - Interfaces and shared types
-- `/tests` - Unit, integration, and E2E tests
-- `/static` - Public assets
-
-### Authentication Flow
-
-1. User authenticates via CAS (Polytech)
-2. JWT token stored in `sessionToken` cookie
-3. Middleware validates token on each request
-4. Public routes: `/`, `/login`, `/logout`, `/about`, `/contact`
-5. All other routes require authentication
-
----
-
-## π Database Schema (Final/Definitive)
-
-```mermaid
-erDiagram
- USER {
- string id PK
- string nom
- string prenom
- int idRole FK
- }
- ROLE {
- int id PK
- string nom
- }
- PERMISSION {
- int id PK
- string nom
- }
- ROLE_PERMISSION {
- int idRole PK,FK
- int idPermission PK,FK
- }
- STUDENT {
- int numEtud PK
- string nom
- string prenom
- string idPromo FK
- }
- PROMOTION {
- string idPromo PK
- string annee
- }
- MODULE {
- string id PK
- string nom
- }
- ENSEIGNEMENT {
- string idProf PK,FK
- string idModule PK,FK
- string idPromo PK,FK
- }
- UE {
- int id PK
- string nom
- }
- UE_MODULE {
- string idModule PK,FK
- int idUE PK,FK
- string idPromo PK,FK
- float coeff
- }
- NOTE {
- int numEtud PK,FK
- string idModule PK,FK
- float note
- }
- AJUSTEMENT {
- int numEtud PK,FK
- int idUE PK,FK
- float valeur
- }
-
- USER }o--|| ROLE : "a"
- ROLE_PERMISSION }o--|| ROLE : "accorde"
- ROLE_PERMISSION }o--|| PERMISSION : "inclut"
- ENSEIGNEMENT }o--|| USER : "rΓ©alisΓ© par"
- ENSEIGNEMENT }o--|| MODULE : "porte sur"
- ENSEIGNEMENT }o--|| PROMOTION : "concerne"
- STUDENT }o--|| PROMOTION : "appartient Γ "
- UE_MODULE }o--|| MODULE : "associe"
- UE_MODULE }o--|| UE : "appartient Γ "
- UE_MODULE }o--|| PROMOTION : "pour"
- NOTE }o--|| STUDENT : "reΓ§oit"
- NOTE }o--|| MODULE : "dans"
- AJUSTEMENT }o--|| STUDENT : "concerne"
- AJUSTEMENT }o--|| UE : "dans"
-```
-
-### Current Schema
-
-The Drizzle ORM schema in `/databases/schema.ts` implements all tables: `roles`,
-`permissions`, `rolePermissions`, `users`, `promotions`, `students`, `modules`,
-`enseignements`, `ues`, `ueModules`, `notes`, `ajustements`, `mobility`.
-
----
-
-## π― Open Issues (69 total)
-
-### UI Pages
-
-**Catalog**
-
-- π UI - Page Catalogue d'applications (#71)
-
-**Components**
-
-- π¨ UI (composant) - Popup RΓ©sultats d'import (#75)
-
-**Students**
-
-- π UI - Admin β Liste des Γ©lΓ¨ves (#79)
-- π UI - Admin β Gestion des promotions (#80)
-- π UI - Admin β Import xlsx Γ©lΓ¨ves (#81)
-- π UI - Admin β Γdition d'un Γ©lΓ¨ve (#82)
-
-**Notes**
-
-- π UI - Page ΓlΓ¨ve β Mes Notes (#72)
-- π UI - Admin β Consulter les notes (#73)
-- π UI - Admin β Importer des notes (.xlsx) (#74)
-- π UI - Admin β Γdition notes d'un Γ©lΓ¨ve (#76)
-- π UI - Admin β RΓ©cap notes Γ©lΓ¨ve / semestre (#77)
-- π UI - Admin β Gestion des UEs (#78)
-
-**Administration**
-
-- π UI - Gestion des utilisateurs (#83)
-- π UI - Gestion des rΓ΄les (#84)
-- π UI - Permissions d'un rΓ΄le (#85)
-- π UI - Vue des permissions (#86)
-- π UI - Gestion des modules (#87)
-- π UI - Enseignements (Assignations) (#88)
-
----
-
-### API Endpoints
-
-Legend: β
implemented & tested | π not yet implemented
-
-**Students API**
-
-- β
GET `/students` (#7)
-- β
POST `/students` (#8)
-- β
POST `/students/import-csv` (#9)
-- β
GET `/students/{numEtud}` (#10)
-- β
PUT `/students/{numEtud}` (#11)
-- β
DELETE `/students/{numEtud}` (#12)
-- β
GET `/promotions` (#13)
-- β
POST `/promotions` (#14)
-- β
GET `/promotions/{idPromo}` (#15)
-- β
PUT `/promotions/{idPromo}` (#16)
-- β
DELETE `/promotions/{idPromo}` (#17)
-
-**Administration API - Modules & Enseignements**
-
-- β
GET `/modules` (#23)
-- β
POST `/modules` (#24)
-- β
GET `/modules/{idModule}` (#25)
-- β
PUT `/modules/{idModule}` (#26)
-- β
DELETE `/modules/{idModule}` (#27)
-- β
POST `/enseignements` (#29)
-- β
GET `/enseignements/{idProf}/{idModule}/{idPromo}` (#30)
-- β
DELETE `/enseignements/{idProf}/{idModule}/{idPromo}` (#31)
-
-**Notes API - UEs & UE-Modules**
-
-- β
GET `/ues` (#32)
-- β
POST `/ues` (#33)
-- β
GET `/ues/{idUE}` (#34)
-- β
PUT `/ues/{idUE}` (#35)
-- β
DELETE `/ues/{idUE}` (#36)
-- β
GET `/ue-modules` (#37)
-- β
POST `/ue-modules` (#38)
-- β
GET `/ue-modules/{idModule}/{idUE}/{idPromo}` (#39)
-- β
PUT `/ue-modules/{idModule}/{idUE}/{idPromo}` (#40)
-- β
DELETE `/ue-modules/{idModule}/{idUE}/{idPromo}` (#41)
-
-**Notes API - Notes & Ajustements**
-
-- β
GET `/notes` (#42)
-- β
POST `/notes` (#43)
-- π POST `/notes/import-xlsx` (#44)
-- β
GET `/notes/{numEtud}/{idModule}` (#45)
-- β
PUT `/notes/{numEtud}/{idModule}` (#46)
-- β
DELETE `/notes/{numEtud}/{idModule}` (#47)
-- β
GET `/ajustements` (#48)
-- β
POST `/ajustements` (#49)
-- β
GET `/ajustements/{numEtud}/{idUE}` (#50)
-- β
PUT `/ajustements/{numEtud}/{idUE}` (#51)
-- β
DELETE `/ajustements/{numEtud}/{idUE}` (#52)
-
-**Administration API - Users, Roles & Permissions**
-
-- β
GET `/users` (#60)
-- β
POST `/users` (#61)
-- β
GET `/users/{id}` (#62)
-- β
PUT `/users/{id}` (#63)
-- β
DELETE `/users/{id}` (#64)
-- β
GET `/roles` (#65)
-- β
POST `/roles` (#66)
-- β
GET `/roles/{idRole}` (#67)
-- β
PUT `/roles/{idRole}` (#68)
-- β
DELETE `/roles/{idRole}` (#69)
-- β
GET `/permissions` (#70)
-
----
-
-## π¨ Design Reference
-
-**Figma Prototype**:
-https://www.figma.com/design/La79bsUsWnJCtMsrrt2zGd/Prototype?node-id=0-1
-
-This is the **final design specification** for the UI. All UI implementations
-should follow this design.
-
----
-
-## π Development Guidelines
-
-### Getting Started
-
-```bash
-# Run tests
-deno task test
-
-# Start development server
-deno task start
-
-# Build for production
-deno task build
-
-# Format & lint
-deno task check
-```
-
-### Git Workflow
-
-1. Create branch: `git checkout -b PMPR-{ISSUE_ID}`
-2. Implement changes
-3. Run tests and linting
-4. Submit PR
-
-### Code Style
-
-- Format: Follow Deno defaults (enforced via `deno fmt`)
-- Linting: Fresh recommended rules
-- TypeScript strict mode enabled
-- Use Drizzle ORM for database operations
-
-### Testing
-
-3-level architecture β all 149 tests pass:
-
-- **Unit** (`tests/unit/`) β pure logic with mock DB + mock API, no real DB
-- **Integration** (`tests/integration/`) β Drizzle ORM direct on real DB
-- **E2E** (`tests/e2e/`) β Fresh handler + real DB (handler-level, not browser)
-
-Helpers in `tests/helpers/`:
-
-- `handler.ts` β builds fake Fresh contexts (`makeEmployeeContext`,
- `makeJsonRequest`β¦)
-- `db_integration.ts` β seed functions + `truncateAll()` for test isolation
-- `db_mock.ts` / `api_mock.ts` β in-memory mocks for unit tests
-
-```bash
-deno task test # run all tests
-deno task test:coverage # coverage report (terminal)
-deno task test:coverage:html # coverage report (HTML β coverage/html/index.html)
-nix run nixpkgs#act -- -j unit --no-cache-server # unit tests via GitHub Actions
-nix run nixpkgs#act -- -j integration --no-cache-server # integration + e2e via GitHub Actions
-```
-
----
-
-## π¦ Key Dependencies
-
-- **fresh@1.7.3** - Web framework
-- **drizzle-orm@0.45.2** - ORM
-- **pg@8.20.0** - PostgreSQL driver
-- **@popov/jwt@1.0.1** - JWT utilities
-- **preact@10.22.0** - UI library
-- **happy-dom@16.0.0** - DOM testing
-
----
-
-## π Related Resources
-
-- **Repository**: https://git.polytech.djalim.fr/djalim/PolyMPR
-- **Issue Tracker**: Gitea (via `tea` CLI)
-- **Wiki**: Check CONTRIBUTING.md for dev setup
-- **Database**: PostgreSQL (configured in `.env`)
-
----
-
-## π‘ Important Notes
-
-1. **Only missing API**: `POST /notes/import-xlsx` (#44) β all other endpoints
- are implemented.
-2. **Next priority**: UI pages (none built yet) β follow the Figma prototype.
-3. **Module Pattern**: Each module should follow the same pattern: routes, API
- endpoints, components, and tests.
-4. **Permissions**: All admin operations should respect the ROLE_PERMISSION
- system.
-5. **Fresh Conventions**: Routes use Fresh's file-based routing convention
- (e.g., `routes/path/index.tsx`).
-6. **Drizzle `.where()` pitfall**: Always wrap multiple conditions with `and()`.
- `.where(eq(a), eq(b))` silently ignores the second argument.
diff --git a/compose.yml b/compose.yml
deleted file mode 100644
index f2abf83..0000000
--- a/compose.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-services:
- app:
- image: registry.docker.polytech.djalim.fr/polympr:latest
- ports:
- - "8008:80"
- - "4430:443"
- volumes:
- - /home/kevin/PolyMPR/:/app
- command: deno run -A main.ts
- deploy:
- replicas: 1
- placement:
- constraints: [node.role == manager]
-
- db:
- image: postgres
- restart: always
- shm_size: 128mb
- environment:
- POSTGRES_PASSWORD: ${POSTGRES_PASS}
- deploy:
- replicas: 1
- placement:
- constraints: [node.role == manager]
diff --git a/routes/(_components)/Footer.tsx b/routes/(_components)/Footer.tsx
index f71930f..ee9a6c1 100644
--- a/routes/(_components)/Footer.tsx
+++ b/routes/(_components)/Footer.tsx
@@ -6,7 +6,7 @@ export default function Footer(_props: FooterProps) {
return (
);
diff --git a/routes/(apps)/mobility/(_props)/props.ts b/routes/(apps)/mobility/(_props)/props.ts
index 3efac01..37e9c17 100644
--- a/routes/(apps)/mobility/(_props)/props.ts
+++ b/routes/(apps)/mobility/(_props)/props.ts
@@ -7,10 +7,11 @@ const properties: AppProperties = {
pages: {
index: "Accueil",
overview: "Suivi des mobilitΓ©s",
- "my-mobility": "Ma mobilitΓ©",
+ // "my-mobility": "Ma mobilitΓ©", // TODO Fix ma mobilitΓ© page, so it renders correctly for students
},
adminOnly: ["overview"],
studentOnly: ["my-mobility"],
+ employeeOnly: true, // TODO Fix ma mobilitΓ© page, so it renders correctly for students
};
export default properties;
diff --git a/routes/login.tsx b/routes/login.tsx
index dd35867..3b1da1e 100644
--- a/routes/login.tsx
+++ b/routes/login.tsx
@@ -45,8 +45,6 @@ function createUserJWT(casResponse: CasResponse): Promise {
}
});
- console.log(fullUserInfos);
-
const now = Math.floor(Date.now() / 1000);
const payload: LoginJWT = {
iss: "PolyMPR",