Commit Graph

18 Commits

Author SHA1 Message Date
Pontoporeia
83a5a508ea feat: PeerTube integration — alternate audio/video labels, FilePond pools, shared SMTP credentials, channel by name, test button, resumable upload, embed improvements, fix alt labels/curl_close/deprecation 2026-05-19 00:08:06 +02:00
Pontoporeia
be50ac5eb0 fix(production): fix multiple remote server errors from nginx logs
- Fix 413 Request Entity Too Large: bump client_max_body_size to 256M,
  PHP post_max_size/upload_max_filesize to 256M, fastcgi timeouts to 300s
- Fix missing v_smtp_active view: add IF NOT EXISTS to all CREATE VIEW
  statements in schema.sql for idempotent migrates
- Fix bars.svg 404: create animated SVG spinner in app/public/assets/img/
- Fix nginx rate limiting: increase admin zone from 60r/m (1 r/s) to
  300r/m (5 r/s) with burst=30 to handle ~11 concurrent HTMX fragment
  GETs on contenus.php page load
- Add deploy-nginx recipe to justfile for uploading nginx config to server
- Database readonly issue mitigated by existing --chown + deploy-server.sh
  permissions fix
- Add comprehensive PHP/JS debugging logs for settings checkboxes:
  per-field raw POST values in error_log, console.log on htmx:beforeSend,
  htmx:sendError, htmx:afterRequest, toast lifecycle
- Fix toast auto-remove script: use getElementById with unique ID instead
  of querySelector which could remove wrong toast on rapid clicks
2026-05-19 00:08:06 +02:00
Pontoporeia
43064ccbd7 feat(admin): add htmx toast feedback for settings checkboxes in contenus.php
- Replace hx-swap="none" with hx-target on response divs inside each of the
  three fieldsets (Restrictions d'accès, Degré d'ouverture, Types de travaux)
- Add hxToastSuccess / hxToastError helpers in settings.php that return HTML
  toast fragments with self-referencing auto-dismiss after 3s
- Each response div has aria-live="polite" for accessibility
- Add comprehensive PHP/JS debugging logs:
  - settings.php logs raw POST values per field before resolving to 0/1
  - checkboxes have hx-on::before-request and hx-on::after-request console.log
  - global htmx:beforeSend and htmx:sendError listeners in admin footer
  - toast lifecycle logged (creation + removal) for traceability
- Fix toast auto-remove: use getElementById with random unique ID instead
  of querySelector which could remove wrong toast on rapid clicks
- Follows the Django+HTMX ajax checkbox pattern from the reference tutorial

feat(admin): add htmx toast feedback for settings checkboxes in contenus.php

- Replace hx-swap="none" with hx-target on response divs inside each of the
  three fieldsets (Restrictions d'accès, Degré d'ouverture, Types de travaux)
- Add hxToastSuccess / hxToastError helpers in settings.php that return HTML
  toast fragments with self-referencing auto-dismiss after 3s
- Each response div has aria-live="polite" for accessibility
- Add comprehensive PHP/JS debugging logs:
  - settings.php logs raw POST values per field before resolving to 0/1
  - checkboxes have hx-on::before-request and hx-on::after-request console.log
  - global htmx:beforeSend and htmx:sendError listeners in admin footer
  - toast lifecycle logged (creation + removal) for traceability
- Fix toast auto-remove: use getElementById with random unique ID instead
  of querySelector which could remove wrong toast on rapid clicks
- Fix checkbox unresponsive after toggles: move hidden value="0" inputs
  outside <label> to prevent HTML label double-activation
- Follows the Django+HTMX ajax checkbox pattern from the reference tutorial

feat(admin): add htmx toast feedback for settings checkboxes in contenus.php

- Replace hx-swap="none" with hx-target on response divs inside each of the
  three fieldsets (Restrictions d'accès, Degré d'ouverture, Types de travaux)
- Add hxToastSuccess / hxToastError helpers in settings.php that return HTML
  toast fragments with self-referencing auto-dismiss after 3s
- Each response div has aria-live="polite" for accessibility
- Add comprehensive PHP/JS debugging logs:
  - settings.php logs raw POST values per field before resolving to 0/1
  - checkboxes have hx-on::before-request and hx-on::after-request console.log
  - global htmx:beforeSend and htmx:sendError listeners in admin footer
  - toast lifecycle logged (creation + removal) for traceability
- Fix toast auto-remove: use getElementById with random unique ID instead
  of querySelector which could remove wrong toast on rapid clicks
- Fix checkbox unresponsive after toggles: remove hidden value="0" inputs entirely; unchecked checkboxes are simply absent from POST and server treats missing key as 0
  outside <label> to prevent HTML label double-activation
- Follows the Django+HTMX ajax checkbox pattern from the reference tutorial
2026-05-19 00:08:06 +02:00
Pontoporeia
72f7192156 feat(deploy): add deploy-verify-permissions recipe + upload/run deploy-server.sh before verification + run migrations in deploy 2026-05-19 00:08:06 +02:00
Pontoporeia
3136fa7113 fix: settings checkboxes — fix unchecked state handling, split into separate forms to avoid cross-resets, use HTMX auto-save with hidden value=0 inputs 2026-05-19 00:08:06 +02:00
Pontoporeia
926659087f feat: implement SQLite backup & data integrity plan (Phases 2-4) 2026-05-19 00:08:06 +02:00
Pontoporeia
7e987d281c fix: add hx-swap="none" to admin auto-save checkboxes to prevent page swap 2026-05-19 00:08:06 +02:00
Pontoporeia
cf9bd5cd5d feat: require 3 mots-clés in partage, language asterisk toggle, admin auto-save checkboxes
- tag-search: add minTags/required params, counter shows red if < 3, accent if ≥ 3
- form.php: pass minTags=3 for partage mode keywords
- checkbox-list: support labelHtml for raw HTML label with targetable asterisk span
- language-autre-fragment: OOB swap updates #languages-required-asterisk when autre pills change
- language-search: client-side update #languages-required-asterisk on pill add/remove
- contenus.php: replace 3 form+submit-button fieldsets with HTMX auto-save checkboxes
- settings.php: detect HX-Request header, return OOB CSRF token updates, skip redirect
2026-05-19 00:08:06 +02:00
Pontoporeia
d5fee1acfb fix: repair form submission with queued files + add comprehensive debug logging
- Replace fetch(redirect:manual) with XMLHttpRequest in file-upload-queue.js.
  The previous fetch-based redirect detection was broken because opaque
  redirects hide the Location header. XHR's responseURL reliably exposes
  the final URL after server-side redirects.

- Add console.log tracing at every decision point in submit interception:
  entry, hasFiles check, enctype check, double-submit guard, XHR status,
  redirect detection, error fallback.

- Add error_log entry-point logging to all 16 admin action files plus
  the partage/index.php submission handler and password gate. Each logs:
  request method, content type/length, POST keys, file counts, and
  queue-specific file counts where applicable.

- Add double-submit guard (_xamxamActiveSubmit) to prevent duplicate
  XHR sends when the native submit handler fires after interception.
2026-05-19 00:08:05 +02:00
Pontoporeia
03c5fd217e feat: dual upload system — direct file storage + PeerTube API integration
Adds a parallel PeerTube upload system behind a feature flag (disabled by default
until upload quota is granted). When disabled, the existing direct file upload
path works unchanged.

Files:
- src/PeerTubeService.php — credential storage (encrypted), OAuth2 token
  retrieval, multipart upload to /api/v1/videos/upload
- migrations/021_peertube_settings.sql — peertube_settings singleton table
  + peertube_upload_enabled site_setting (default 0)
- admin/actions/settings.php — peertube section handler
- admin/parametres.php / templates/admin/parametres.php — PeerTube UI section
- partage/fichiers-fragment.php — shows file inputs when enabled, TODO notice otherwise
- ThesisCreateController / ThesisEditController — handlePeerTubeUpload()
- tfe.php — PeerTube iframe embed detection
- AdminLogger — logPeerTubeUpdate()
2026-05-13 17:59:13 +02:00
Pontoporeia
ca5983075d feat: admin audit logging across all admin actions
- AdminLogger: JSON-lines → /var/log/xamxam.log (prod) / storage/logs/admin.log (dev)
  + best-effort DB mirror to admin_audit_log table
- DB: admin_audit_log table, share_links.is_archived column
- ShareLink: archive() replaces delete(), toggleActive() returns new state,
  listActive()/listArchived() split, validateLink blocks archived slugs
- All action handlers wired: publish, unpublish, visibility, delete, csv/db export,
  tfe add/edit, tags, pages, apropos, form-help, access-request, maintenance,
  settings (formulaire toggles, objet types, smtp update), smtp-test
- acces.php: archive button replaces delete; collapsible archived links section
- setup-server.sh: provision /var/log/xamxam.log (www-data:xamxam 640)
2026-05-05 11:04:52 +02:00
Pontoporeia
33987c9b15 smtp: add notify_email field; fix admin notification sent to no-reply sender 2026-05-05 11:04:52 +02:00
Pontoporeia
bdb68479d5 smtp: typed probe errors with per-field UI highlighting on save 2026-05-05 11:04:52 +02:00
Pontoporeia
b750aca2f5 smtp: probe credentials on save (connect+auth+quit, no message sent) 2026-05-05 11:04:52 +02:00
Pontoporeia
68e30abb56 fix: remove Post-ERG branding → XAMXAM; drop legacy posterg nginx symlink in deploy script; rename posterg.db → xamxam.db 2026-05-05 11:04:52 +02:00
Pontoporeia
27e1b6828d Implement TFE file access restriction feature (complete)
Requirements:
- parametres.php toggle: 'restricted_files_enabled' enables/disables the feature
- Public TFE page: when enabled + access_type=Interne, hides files, shows French
  restriction message + access request form (metadata/synopsis still visible)
- ERG emails (@erg.school / @erg.be): auto-approve, send 24h access link immediately
- External emails: show justification textarea, create pending request, notify admin
- Admin panel /admin/file-access.php: approve/reject requests with optional notes,
  sends access email on approval (linked from admin nav with pending count badge)

Security:
- One-time 24h email tokens (used_at + is_valid=0 on first click)
- Token redeemed via POST /validate-access (GET shows confirmation page only)
- Long-lived 30-day browser session in file_access_sessions table
- Cookie: HttpOnly + Secure + SameSite=Strict
- CSRF on all mutations, rate limiting on request submission
- Audit trail: IP, UA, event, timestamp in file_access_audit

Bug fixes:
- admin/file-access.php: $vars never extract()ed → page was blank
- Template had self-contained head/footer includes (double-include)
- Admin approval URL used $requestId instead of $request['thesis_id']
- App::boot() now starts session so CSRF token works on public pages
- Dispatcher routes /validate-access and /request-access through front controller
2026-04-27 20:20:52 +02:00
Pontoporeia
d961f9533c feat: add objet field (tfe/thèse/frart) with share-link restriction and site-settings toggles 2026-04-24 23:03:49 +02:00
Pontoporeia
75f808bee4 feat: extract MediaController, wire into Dispatcher, delete media.php 2026-04-20 12:32:00 +02:00