mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 11:09:18 +02:00
feat: multi-type file upload with sort order, labels, and expanded MIME support
- DB migration 007: add sort_order + display_label to thesis_files - Database: getThesisFiles ordered by sort_order; insertThesisFile accepts label/order; new reorderThesisFiles() and updateThesisFileLabel() methods - ThesisCreateController + ThesisEditController: expand allowed MIME/exts to include audio (mp3/ogg/wav/flac/aac/m4a), video (webm/mov/ogv), image (gif/webp), archives (tar/gz), any-ext via octet-stream; max size raised to 500 MB; accept file_labels[] and file_orders[] POST fields; detectFileType() helper - MediaController: expanded MIME allowlist; HTTP Range support for audio/video; force-download for unknown types; inline for known displayable types - fieldset-files.php: sortable queue UI with SortableJS, per-file labels, 500 MB hint - templates/admin/edit.php: existing files as sortable list with drag handles, type icons, label inputs, delete checkboxes, hidden sort-order fields - file-upload-queue.js: new JS replacing file-preview.js — sortable new-file queue, per-file labels, hidden order fields on submit, backward-compat legacy preview - tfe.php: renders audio (<audio>), all video formats, images, PDF, and download-only 'other' files; reads display_label; sorted by sort_order - tfe.css + form.css: styles for audio player, download files, sortable queue, drag handles, file type badges, label inputs - .htaccess + .user.ini: upload_max_filesize=512M / post_max_size=520M
This commit is contained in:
153
TODO.md
153
TODO.md
@@ -1,131 +1,28 @@
|
||||
# TODO
|
||||
# XAMXAM TODO
|
||||
|
||||
## Admin area cleanup
|
||||
## File Upload & Display System
|
||||
|
||||
- [x] Combine `acces-etudiante.php` + `file-access.php` into `acces.php` (two `<section>` blocks)
|
||||
- [x] Move `system.php` content into `parametres.php` (system section + logs section)
|
||||
- [x] Use `<section>` for sections, `<fieldset>` only where form fields are present
|
||||
- [x] Redirect legacy URLs (acces-etudiante.php, file-access.php, system.php) with 301
|
||||
- [x] Update action redirects to point to new pages
|
||||
- [x] Update admin nav header (merged 3 items → 2)
|
||||
- [x] **DB migration 007** — add `sort_order` and `display_label` columns to `thesis_files`
|
||||
- [x] **Database.php** — `getThesisFiles` ordered by `sort_order ASC`; `insertThesisFile` accepts `display_label` + `sort_order`; new `reorderThesisFiles()` and `updateThesisFileLabel()` methods
|
||||
- [x] **ThesisCreateController** — expand MIME/ext allowlist (audio: mp3/ogg/wav/flac/aac/m4a; video: webm/mov/ogv; image: gif/webp; archives: tar/gz; any-ext via octet-stream); raise max size to 500 MB; accept `file_labels[]` and `file_orders[]` POST fields; `detectFileType()` helper
|
||||
- [x] **ThesisEditController** — same expansions; handle `file_sort_order[]`, `file_label[id]` POST fields; reorder + label-update methods called; `detectFileType()` helper
|
||||
- [x] **MediaController** — expanded MIME allowlist; HTTP Range support for audio/video seeking; force-download for "other" types; inline display for known displayable types
|
||||
- [x] **fieldset-files.php** (shared partial) — replaced old multi-file input with sortable queue UI using SortableJS; per-file label inputs; wide accept attribute; 500 MB hint
|
||||
- [x] **templates/admin/edit.php** — existing files rendered as sortable list with drag handles, file type icons, label inputs, delete checkboxes; hidden `file_sort_order[]` inputs; new-file queue widget
|
||||
- [x] **file-upload-queue.js** — new JS: sortable queue for new uploads (SortableJS), per-file label fields, hidden order fields injected on submit; existing-file drag-sort; backward-compatible legacy preview for cover/banner inputs
|
||||
- [x] **tfe.php** (public template) — handles audio (`<audio>`), video (all exts), image, PDF, "other" (download link); reads `display_label`; files already sorted by `sort_order`
|
||||
- [x] **tfe.css** — styles for `.tfe-audio`, `.tfe-download-file`, `.tfe-download-link`
|
||||
- [x] **form.css** — styles for `.tfe-file-queue`, `.fq-item`, `.admin-file-list-item` (sortable), drag handles, label inputs, ghost class
|
||||
- [x] **PHP upload limits** — `.htaccess` + `.user.ini` in `public/` with `upload_max_filesize=512M` / `post_max_size=520M`
|
||||
- [x] **add.php / edit.php / partage/index.php** — use `sortable.min.js` + `file-upload-queue.js` instead of `file-preview.js`
|
||||
|
||||
## Bug fixes
|
||||
|
||||
- [x] Fix `$enabledAccessTypes` undefined / `array_map()` TypeError on edit page — controller was fetching `getAccessTypes()` instead of `getEnabledFormAccessTypes()` and returning it under the wrong key
|
||||
- [x] Fix fatal TypeError: `old()` called with wrong arity in `jury-fieldset.php` partial under partage context — removed `?: null` coercions so `$juryPresident`/`$juryPromoteur` are `''` not `null`, keeping `$addMode` false
|
||||
- [x] Fix `$formData` destroyed by included partials (`fieldset-academic.php`, `fieldset-metadata.php`, `fieldset-licence-explanation.php` were incorrectly unsetting `$formData`/wrong variable in caller scope)
|
||||
|
||||
## Form help blocks — sortable admin UI
|
||||
|
||||
- [x] Migration 005: add `sort_order` column to `form_help_blocks`
|
||||
- [x] `Database::getAllFormHelpBlocks()` — ORDER BY sort_order, expose sort_order in returned data
|
||||
- [x] `Database::reorderFormHelpBlocks(array $keys)` — persist new order
|
||||
- [x] `actions/form-help-reorder.php` — HTMX POST handler (CSRF-protected, 204 response)
|
||||
- [x] `templates/admin/contenus.php` — replace table with two-panel layout:
|
||||
- Left: SortableJS + htmx drag-and-drop card list
|
||||
- Right: static form structure reference (fieldsets + inputs)
|
||||
- [x] CSS in admin.css: `.fhb-*` classes for layout, cards, ghost/chosen/drag states
|
||||
- [x] `schema.sql` — updated `form_help_blocks` DDL with `sort_order`
|
||||
- [x] Vendor SortableJS 1.15.2 into `assets/js/sortable.min.js` (remove CDN dependency)
|
||||
|
||||
## Bug fixes (continued)
|
||||
|
||||
- [x] Fix missing favicon tags in `partage/recapitulatif.php`
|
||||
- [x] Fix fatal `Class "SmtpRelay" not found` in `StudentEmail.php` — add `require_once SmtpRelay.php` before `StudentEmail.php` in `partage/index.php`
|
||||
|
||||
- [x] Add missing favicon tags to all three `<head>` blocks in `partage/index.php` (error page, password gate, main form)
|
||||
|
||||
## Rename posterg → xamxam throughout codebase
|
||||
|
||||
- [x] Rename `nginx/posterg.conf` → `nginx/xamxam.conf` (+ `.conf.reference`)
|
||||
- [x] Update nginx conf: `server_name`, log paths, htpasswd path, header comments
|
||||
- [x] Update `justfile`: SSH host alias, group, DB filename, conf path, tmp paths
|
||||
- [x] Update `scripts/deploy-server.sh`: group, conf paths, site names, URLs
|
||||
- [x] Update `scripts/setup-server.sh`: APP_DIR, APP_GROUP, comments
|
||||
- [x] Update `scripts/manage-admin-users.sh`: htpasswd path
|
||||
- [x] Update `scripts/migrate.sh`: DB filename
|
||||
- [x] Update `scripts/setup-dev.sh`: DB filename
|
||||
- [x] Update `scripts/copy_crash_logs.sh`: log filenames, hostname
|
||||
- [x] Update `README.md`: SSH host, paths, DB name
|
||||
- [x] Update `nginx/README.md`, `nginx/SETUP.md`, and all `nginx/docs/*.md`
|
||||
- [x] Update PHP source: `Database.php`, `SystemController.php`, `MediaController.php`, `LiveReloadController.php`, `SmtpRelay.php`, `live-reload.php`, export actions
|
||||
- [x] Update `app/migrations/run.php`, `app/tests/README.md`, `app/storage/README.md`
|
||||
- [x] Replace all remaining "Post-ERG" branding with "XAMXAM" (scripts, PHP source, schema, docs)
|
||||
- [x] `deploy-server.sh`: remove legacy `sites-enabled/posterg` symlink to fix duplicate `limit_req_zone` nginx error
|
||||
- [x] `deploy-server.sh`: auto-migrate `.htpasswd-posterg` → `.htpasswd-xamxam` if new file absent
|
||||
- [x] `deploy-server.sh`: auto-migrate `posterg.db` → `xamxam.db` if new DB missing/empty; remove legacy file
|
||||
- [x] `deploy-server.sh`: clean up legacy posterg nginx configs and prune old backups
|
||||
- [x] Rename local `storage/posterg.db` → `storage/xamxam.db`
|
||||
|
||||
## LDAP auth migration (pending client access)
|
||||
|
||||
- [ ] Get LDAP server hostname, port, service-account DN+password, base DN, user attr, group DN from client
|
||||
- [ ] Verify TCP reachability from XAMXAM VM to LDAP server (port 636)
|
||||
- [ ] See `docs/LDAP_AUTH_PLAN.md` for full phase-by-phase plan
|
||||
|
||||
## SMTP transport security hardening
|
||||
|
||||
- [x] Enable TLS peer verification (`verify_peer`, `verify_peer_name`, `peer_name`) on both `smtpSend` and `smtpProbe` — removes MITM vulnerability from `verify_peer: false`
|
||||
- [x] Add `caBundlePath()` — resolves system CA bundle path (php.ini → Debian/RHEL/Alpine candidates → PHP built-in fallback)
|
||||
- [x] Set SSL context options explicitly on socket before `stream_socket_enable_crypto()` for STARTTLS (both probe and send paths)
|
||||
- [x] Add `sanitiseEnvelope()` — strips CR/LF from envelope addresses to prevent SMTP command injection
|
||||
- [x] Fix RFC 5321 §4.5.2 dot-stuffing: replace `preg_replace` with correct CRLF-normalise → `str_replace("\r\n.", "\r\n..")` sequence
|
||||
|
||||
## SMTP notify_email fix
|
||||
|
||||
- [x] Migration 006: add `notify_email` column to `smtp_settings`
|
||||
- [x] `SmtpRelay::getSettings()` — include `notify_email` in SELECT + defaults
|
||||
- [x] `SmtpRelay::updateSettings()` — persist `notify_email`
|
||||
- [x] `SmtpRelay::getNotifyEmail()` — returns `notify_email` ?? `from_email`
|
||||
- [x] `request-access.php` — use `getNotifyEmail()` instead of `from_email` for admin notifications
|
||||
- [x] `actions/settings.php` — wire `smtp_notify_email` POST field
|
||||
- [x] Template: add "Adresse de notification admin" field to SMTP form
|
||||
- [x] `schema.sql` — updated DDL
|
||||
|
||||
## SMTP credential validation
|
||||
|
||||
- [x] Add `SmtpProbeException` with `field` property for structured error classification
|
||||
- [x] Add `SmtpRelay::test()` — returns `{ok, error, field}` with field = input id to highlight
|
||||
- [x] `smtpProbe()` throws typed exceptions per failure point:
|
||||
- connect fail → name resolution error → `smtp_host`
|
||||
- connect fail → port refused → `smtp_port`
|
||||
- connect fail → timeout → `smtp_host`
|
||||
- bad greeting / timeout after connect → `smtp_host` / `smtp_port`
|
||||
- STARTTLS not supported / TLS negotiation fail → `smtp_encryption`
|
||||
- AUTH rejected, code 535 → `smtp_password`; other auth failures → `smtp_username`
|
||||
- [x] `actions/settings.php`: store `$_SESSION['_flash_smtp_field']` on probe failure
|
||||
- [x] `parametres.php` controller: consume + clear `_flash_smtp_field` into `$smtpErrorField`
|
||||
- [x] Template: `aria-invalid`, `aria-describedby`, inline `<small class="param-field-error">` per field
|
||||
- [x] JS: scroll + focus the offending field on page load
|
||||
- [x] CSS: red `border-bottom` on `[aria-invalid]`, `.param-field-error` error text style
|
||||
|
||||
## Répertoire layout
|
||||
|
||||
- [x] Make column headings sticky/non-scrollable; only `ul` scrolls per column
|
||||
- [x] Remove padding from `.search-main` and `.repertoire-index`
|
||||
- [x] Minimal horizontal padding inside columns (`var(--space-2xs)`)
|
||||
- [x] Align all column headings to the same baseline row (2-row grid via `display: contents`)
|
||||
|
||||
## SMTP 550 recipient-rejected handling
|
||||
|
||||
- [x] Add `SmtpSendException` — carries `smtpCode` + `smtpResponse`; `isRecipientRejected()` for 550–554
|
||||
- [x] `smtpSend()` `$expect` closure throws `SmtpSendException` (with code) instead of plain `RuntimeException`
|
||||
- [x] `SmtpRelay::send()` re-throws `SmtpSendException` so callers can react
|
||||
- [x] `request-access.php` (new auto-approve): catch 550 → roll back token + approval, return HTTP 422 with user-facing message
|
||||
- [x] `request-access.php` (resend path): catch 550 → return HTTP 422 instead of silent "access approved"
|
||||
- [x] `StudentEmail::sendConfirmation()`: catch `SmtpSendException` → log + return false (submission must not be aborted)
|
||||
- [x] `admin/actions/access-request.php`: catch `SmtpSendException` after approval → flash warning distinguishing recipient-rejected vs transient
|
||||
- [x] `docs/SMTP_550_POSTFIX_FIX.md` — report for Postfix admin (diagnosis, 3 fix options, verification steps)
|
||||
|
||||
## CSS refactor
|
||||
|
||||
- [x] Move semantic HTML element baseline styles into common.css
|
||||
- `fieldset` (background, border, padding, radius)
|
||||
- `legend` (font, weight, color, transform)
|
||||
- `small` (size, color, display, margin)
|
||||
- `table`, `th`, `td` (collapse, sizing, spacing)
|
||||
- `dialog` + `::backdrop`
|
||||
- `details > summary`
|
||||
- [x] Remove duplicated rules from admin.css, form.css, system.css, file-access.css
|
||||
- [x] Fix file-access.css to use real design tokens (was using undefined --border, --surface, --accent, etc.)
|
||||
- [x] Remove redundant @import url("./variables.css") from admin.css, system.css, file-access.css
|
||||
## Previously completed
|
||||
- [x] Multi-file upload for thesis files (basic)
|
||||
- [x] File access restriction system (email approval workflow)
|
||||
- [x] Share link system for student submission
|
||||
- [x] Admin CRUD for theses
|
||||
- [x] Public TFE detail page with file display
|
||||
- [x] Search and repertoire
|
||||
- [x] Tag management
|
||||
- [x] Form help blocks
|
||||
- [x] SMTP notification
|
||||
|
||||
Reference in New Issue
Block a user