Commit graph

9 commits

Author SHA1 Message Date
1b429049c2 Upload fragmenté et reprenable pour les gros fichiers
Some checks failed
Publier l'image Docker / test (push) Successful in 19s
Publier l'image Docker / publish (push) Failing after 9s
Serveur :
- POST /upload/init -> session { id, chunkSize (16 Mo), chunkCount }
- PUT /upload/:id/:index -> écrit le morceau à son offset (octet-stream brut,
  bufferisé, parser dédié) ; renvoie { received, total }
- POST /upload/:id/complete -> vérifie tous les morceaux + la taille, renomme
  le .mediadrop-part vers le chemin final ; 201 + métadonnées
- DELETE /upload/:id -> abandon, supprime le fichier partiel
- src/lib/upload-sessions.ts : registre en mémoire, purge après 30 min
  d'inactivité, 100 sessions max
- src/lib/targets.ts : resolveTarget / resolvePlacement extraits et partagés
- writeChunkAt / createEmptyFile / finalizeFile / removeFile dans storage.ts
- limites, allowDirectories, jokers MIME et confinement dans la cible
  s'appliquent aussi au chemin fragmenté

Page :
- bascule automatique en fragmenté au-delà de 32 Mo : 3 morceaux en parallèle,
  3 réessais par morceau, progression et annulation agrégées
- makeReporter partagé (débit + ETA) ; job.cancel unifié (simple / fragmenté /
  en file d'attente)

Tests : +tests/upload-chunked.test.ts (9), +writeChunkAt (storage) ; 73 tests.
Vérifié en live : 40 Mio -> 3 morceaux // -> octets exacts, DELETE nettoie.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 18:25:27 +02:00
5a1219f00d Page : progression détaillée, annulation, file d'attente
Some checks failed
Publier l'image Docker / test (push) Failing after 0s
Publier l'image Docker / publish (push) Has been skipped
- Progression en temps réel par fichier : transféré / total, %, débit
  (moyenne glissante), ETA.
- Annulation : bouton « Annuler » par fichier (en attente ou en cours) +
  « Tout annuler ». xhr.abort() -> le serveur nettoie déjà le fichier partiel.
- File d'attente : au plus 3 transferts simultanés, le reste patiente
  (évite de saturer le lien sur un dépôt de dossier). Bandeau récap.

Changements purement page ; aucune modif serveur. 62 tests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 17:59:18 +02:00
0f5bdb7080 allowedMimeTypes : jokers de préfixe
Some checks failed
Publier l'image Docker / test (push) Successful in 18s
Publier l'image Docker / publish (push) Failing after 11s
isAllowedMedia gère désormais "video/*", "*/*" et "*" en plus des types
exacts (comparaison insensible à la casse). parseConfig valide la forme des
entrées et lève ConfigError sur un joker malformé ("video/**", "vi*deo/mp4",
"video/") au lieu de laisser passer une liste qui ne matche rien.

Schéma + doc mis à jour. 62 tests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 09:18:52 +02:00
5bff28fefe CI : checkout Git direct dans le job publish
Some checks failed
Publier l'image Docker / test (push) Successful in 24s
Publier l'image Docker / publish (push) Failing after 7s
Le conteneur docker:27-cli (Alpine) n'a pas Node -> actions/checkout (action
JS) échoue avec « exec: "node": not found ». Remplacé par un clone Git du
dépôt public (git init + fetch --depth 1 + checkout FETCH_HEAD).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 08:58:10 +02:00
7be173e08e CI Forgejo : test + publication de l'image Docker
Some checks failed
Publier l'image Docker / test (push) Successful in 1m32s
Publier l'image Docker / publish (push) Failing after 19s
.forgejo/workflows/publish-docker.yml
- job `test` : npm ci / lint / typecheck / test (conteneur node:22-bookworm)
- job `publish` (needs: test) : docker build + push vers
  git.dev.kyuno.fr/kyuno/mediadrop (conteneur docker:27-cli)
- push main -> latest + <sha court> ; tag vX.Y.Z -> X.Y.Z, X.Y, latest ;
  workflow_dispatch pour lancement manuel
- auth registre via secrets.GITHUB_TOKEN (permissions: packages: write),
  repli documenté sur un secret REGISTRY_TOKEN
- prérequis (runner, socket Docker, accès réseau) détaillés en tête du fichier

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 08:48:23 +02:00
b85607b096 Dépôt de dossiers + très gros fichiers
Dépôt de dossiers :
- flag `allowDirectories` (défaut false) par cible dans config.json + schéma.
- POST /upload accepte `?path=<chemin relatif>` : l'arborescence est recréée
  sous `dir`, nom d'origine conservé, fichier écrasé si présent.
- src/lib/paths.ts : assainissement segment par segment (pas de `..`, pas de
  séparateur) + vérification de confinement dans storage.ts -> aucune sortie
  possible de la cible. Refus 400 si la cible n'autorise pas les dossiers.
- GET /targets expose `allowDirectories`.
- Page : glisser-déposer d'un dossier (parcours récursif webkitGetAsEntry) +
  bouton « parcourir un dossier », visibles selon la cible.

Très gros fichiers (~10 Go) :
- `requestTimeout: 0` / `connectionTimeout: 0` : aucun timeout serveur imposé.
- écriture disque avec un tampon de 1 Mio.
- doc : `maxFileSizeMb` à l'échelle Go, réglages reverse proxy.

Tests : +paths.test.ts, +placement (storage), +dossier & gros fichier (upload) ;
60 tests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 00:19:20 +02:00
f9f17bd169 Ajout d'un compose.yaml
- Service unique : build local (ou image publiée en commentaire), non-root,
  restart: unless-stopped.
- config.json monté en lecture seule ; un montage ./data:/data pour les
  dossiers de dépôt (les `dir` des targets pointent sous /data).
- Commentaires sur l'uid 1000, le remap de port, l'override `user:`.
- .gitignore / .dockerignore : ajout de data/ ; README : section Docker
  réécrite autour de Compose.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 23:25:11 +02:00
f32a04c56f Ajout d'un Dockerfile multi-stage + .dockerignore
- Build en 3 étapes (deps prod / compilation TS / runtime), image
  node:22-bookworm-slim exécutée en non-root (utilisateur `node`).
- Debian slim et non Alpine : @fastify/secure-session dépend de
  sodium-native, dont les prebuilds linux-x64/arm64 ciblent la glibc.
- config.json et dossiers de dépôt montés en volumes, jamais dans l'image
  (.dockerignore exclut .env, config.json, uploads, node_modules, dist...).
- HEALTHCHECK sur GET /health ; section Docker ajoutée au README.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 23:12:21 +02:00
fe8bd26bb7 Initial commit: mediaDrop — serveur de dépôt de fichiers médias
Serveur TypeScript (Fastify 5) permettant de déposer des fichiers médias
dans des dossiers nommés, via une page web de glisser-déposer.

- Authentification OpenID Connect gérée côté serveur (Authorization Code +
  PKCE, client confidentiel, openid-client) ; session via cookie chiffré
  (@fastify/secure-session).
- Configuration dans un fichier JSON (schéma fourni) ; l'environnement ne
  porte que le pointeur MEDIADROP_CONFIG.
- Cibles de dépôt nommées : liste { name, label, dir }, sélection par
  ?target=, première cible par défaut.
- Upload multipart en streaming : nom de fichier dérivé côté serveur (pas
  de path traversal), liste blanche de types MIME, plafond de taille.
- TypeScript strict, ESLint + Prettier sans warning, 46 tests Vitest.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 23:06:53 +02:00