mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 19:19:19 +02:00
docs: add maintenance mode + TFE visibility tasks to TODO
This commit is contained in:
114
TODO.md
114
TODO.md
@@ -203,6 +203,120 @@ These must remain unbroken after the tag-management UI is live:
|
||||
- [ ] `storage/fixtures/CreateTestDatabase.php`: update to use `tags` / `thesis_tags`
|
||||
table names and `findOrCreateTag()`
|
||||
|
||||
## Feature: Mode Maintenance
|
||||
|
||||
Adds "Déployer" / "Maintenance" buttons in admin. When maintenance mode is on,
|
||||
the public site is unavailable (503) while the admin section keeps working.
|
||||
|
||||
### Implementation
|
||||
|
||||
- [ ] **Storage** — store maintenance flag as a file on disk (`storage/maintenance.flag`)
|
||||
so it requires no DB and survives restarts; flag presence = maintenance mode ON
|
||||
- [ ] **Public gate** — add a check at the top of every public-facing PHP entry-point
|
||||
(`public/index.php`, `public/search.php`, `public/tfe.php`, `public/media.php`,
|
||||
`public/apropos.php`) via a shared helper in `config/bootstrap.php`:
|
||||
`checkMaintenanceMode()` — if flag exists, render a 503 maintenance page and exit
|
||||
- [ ] **Maintenance page** — create `public/maintenance.php` (503 HTML page, styled
|
||||
minimally, not imported via bootstrap so it never recurses)
|
||||
- [ ] **Admin action** — create `public/admin/actions/maintenance.php` (POST handler):
|
||||
CSRF-validated, two actions: `enable` (touch flag file) and `disable` (unlink flag)
|
||||
- [ ] **Admin UI** — add a "Site en ligne / Maintenance" status bar in
|
||||
`public/admin/index.php` with "Déployer" (→ disable) and "Maintenance" (→ enable)
|
||||
buttons; display current state clearly (green = en ligne, orange = maintenance)
|
||||
- [ ] **Admin exemption** — admin pages (`/admin/*`) must NOT be gated; the maintenance
|
||||
check must only run on public routes; admin bootstrap already bypasses it by
|
||||
not calling `checkMaintenanceMode()`
|
||||
- [ ] **`src/config.php`** — add `MAINTENANCE_FLAG_PATH` constant pointing to
|
||||
`storage/maintenance.flag`
|
||||
|
||||
## Feature: TFE Visibility States (publique / interne / interdit)
|
||||
|
||||
Replaces the binary `is_published` with a three-state `visibility` field on each TFE,
|
||||
controlling what the public site exposes. Default: `interne`.
|
||||
|
||||
### States
|
||||
|
||||
| State | DB value | Public page: metadata | Public page: files | Note displayed |
|
||||
|------------|----------|-----------------------|--------------------|----------------|
|
||||
| `publique` | `public` | ✓ full | ✓ via media.php | — |
|
||||
| `interne` | `intern` | ✓ full | ✗ hidden | "Copies physiques disponibles aux archives de l'école." |
|
||||
| `interdit` | `forbid` | ✓ full | ✗ hidden | `context_note` from DB (jury note, editable in admin) |
|
||||
|
||||
### Schema
|
||||
|
||||
- [ ] **DB migration** — `storage/migrations/002_add_visibility.sql`:
|
||||
- `ALTER TABLE theses ADD COLUMN visibility TEXT NOT NULL DEFAULT 'intern'`
|
||||
- `UPDATE theses SET visibility = 'public' WHERE is_published = 1` (migrate existing data)
|
||||
- update `v_theses_full` view to expose `visibility` (DROP + CREATE in migration)
|
||||
- update `v_theses_public` view: change filter from `is_published = 1` to
|
||||
`is_published = 1` (keep; `is_published` stays for "show in listings" gate)
|
||||
- **Note**: `is_published` keeps its meaning (appears in public listings at all);
|
||||
`visibility` controls *what* is accessible once found; a TFE can be
|
||||
`is_published = 1` + `visibility = 'intern'` → appears in list, files hidden
|
||||
- [ ] **`storage/schema.sql`** — add `visibility` column + update views + add
|
||||
`idx_theses_visibility` index
|
||||
- [ ] **`storage/fixtures/CreateTestDatabase.php`** — seed some TFEs with each visibility
|
||||
state (default: `intern`)
|
||||
|
||||
### Backend
|
||||
|
||||
- [ ] **`src/Database.php`**:
|
||||
- `getThesisById($id)` — already used by `tfe.php`; ensure it returns `visibility`
|
||||
and `context_note`
|
||||
- `getThesis($id)` (admin) — already returns all columns; ensure `visibility` and
|
||||
`context_note` pass through
|
||||
- `getThesesList()` — add `visibility` to SELECT for admin list display
|
||||
- `setVisibility(int $thesisId, string $state): void` — UPDATE
|
||||
`theses SET visibility = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?`;
|
||||
validate `$state` ∈ `['public', 'intern', 'forbid']`
|
||||
- `bulkSetVisibility(array $ids, string $state): void` — batch UPDATE for the
|
||||
bulk-action bar
|
||||
|
||||
### Public site
|
||||
|
||||
- [ ] **`public/media.php`** — add visibility check:
|
||||
1. Load `thesis_files` row by `path` to get `thesis_id`
|
||||
2. Load `theses.visibility` for that `thesis_id` (one extra query)
|
||||
3. If `visibility !== 'public'` → return 403
|
||||
(This is the critical security gate; all other changes are UX)
|
||||
- [ ] **`public/tfe.php`** — conditional rendering based on `$data['visibility']`:
|
||||
- `publique`: render files normally (existing logic)
|
||||
- `interne`: skip files block; show notice "Les copies physiques de ce travail
|
||||
sont disponibles dans les archives de l'école."
|
||||
- `interdit`: skip files block; show `$data['context_note']` (jury note) if set,
|
||||
otherwise a generic access-restricted message
|
||||
- [ ] **`public/index.php`** / **`public/search.php`** — no change needed (thumbnail
|
||||
logic: if `visibility !== 'public'`, skip thumbnail even if file exists; adjust
|
||||
the thumbnail-lookup block in index.php)
|
||||
|
||||
### Admin UI
|
||||
|
||||
- [ ] **`public/admin/edit.php`**:
|
||||
- Replace the current `is_published` checkbox with a `<select name="visibility">`
|
||||
with three labelled options (Publique / Interne / Interdit)
|
||||
- Keep `is_published` checkbox separately (controls listing visibility)
|
||||
- Add `<textarea name="context_note">` for jury note (shown only when
|
||||
`visibility = interdit`, via JS toggle, but always submitted so admin can
|
||||
pre-fill before switching state)
|
||||
- Update the POST handler to save `visibility` and `context_note` via
|
||||
`UPDATE theses SET visibility = ?, context_note = ? …`
|
||||
- [ ] **`public/admin/index.php`**:
|
||||
- Update status badge column: show three-state badge instead of binary
|
||||
"Publié / En attente":
|
||||
- `publique` → green "Publique"
|
||||
- `interne` → blue "Interne"
|
||||
- `interdit` → red "Interdit"
|
||||
- Update stats bar: counts for each state instead of published/pending
|
||||
- Add bulk-action buttons for visibility: "Rendre publique", "Rendre interne",
|
||||
"Rendre interdit" (replaces or supplements existing publish/unpublish)
|
||||
- Update JS `bulkAction()` to support new action names
|
||||
- [ ] **`public/admin/actions/publish.php`** — extend to handle new visibility actions:
|
||||
`set_public`, `set_intern`, `set_forbid` for single and bulk modes;
|
||||
keep existing `publish`/`unpublish` actions for `is_published` toggle;
|
||||
alternatively rename/create `public/admin/actions/visibility.php` as a
|
||||
dedicated handler and keep `publish.php` for `is_published` only
|
||||
- [ ] **`public/admin/thanks.php`** — add "Visibilité" row to the info display
|
||||
|
||||
## Pending
|
||||
|
||||
- [x] Add flake.nix for Nix-based PHP dev environment
|
||||
|
||||
Reference in New Issue
Block a user