dynors-media - Hub Central de Stockage¶
Service interne DYNORS - Stockage centralisé de tous les fichiers
🎯 Objectif¶
dynors-media est le hub central de stockage pour TOUT l'écosystème DYNORS. Il gère tous les types de fichiers (images, documents, PDF, audio, vidéo) pour toutes les applications (FISCAL, RAGNAR, ELISA, DAWALALE, etc.).
Principe Fondamental¶
┌────────────────────────────────────────────┐
│ UN SEUL SERVICE pour TOUS les fichiers │
│ Pas d'exception. Pas de stockage custom. │
└────────────────────────────────────────────┘
📋 Informations Générales¶
| Propriété | Valeur |
|---|---|
| Nom | dynors-media |
| Type | Service interne (webservice) |
| Domaine | Stockage, CRUD médias |
| Port | 8085 |
| Repository | dynors-extensions/packages/extensions/media |
| Status | 🟡 MVP Phase 1 — webservice dynors-internal/applications/media/backend ; contrat v2 SLY /media/** |
Contrat inter-app v2 (SLY)
Clients DYNORS appellent Media uniquement via SLY :
- POST /media/media/upload → backend /media/upload
- GET /media/media/{fileId}/signed-url → URLs de lecture
- Legacy /api/v1/files/** interdit pour nouveaux développements.
URLs signées sans tenant visible en query (tenant résolu serveur) — cf. étude DAWALALE · AR-20260620-001.
🏗️ Architecture¶
Stack Technique¶
- Backend : Java 21, Spring Boot 3.x
- Base de données : PostgreSQL 15
- Cache : Redis 7
- Storage : MinIO (dev/staging), S3 (production)
- Modules CORE : commons, security, db
Types de Fichiers Supportés¶
| Catégorie | Types | Usage typique |
|---|---|---|
| Images | JPG, PNG, GIF, WebP, SVG | Logos clients, photos livraison |
| Documents | PDF, DOC, DOCX, XLS, XLSX | Factures, contrats, documents permis |
| Audio | MP3, WAV, OGG, M4A | Podcasts, enregistrements |
| Vidéo | MP4, AVI, MOV, WebM | Tutorials, formations |
| Autres | ZIP, RAR, TXT, CSV, JSON | Archives, données |
✨ Fonctionnalités Principales¶
CRUD Complet¶
1. CREATE (Upload/Déposer)¶
- ✅ Upload fichier simple
- ✅ Upload multiple (batch)
- ✅ Validation types MIME
- ✅ Validation taille
- ✅ Checksum MD5 (intégrité)
2. READ (Récupérer/Chercher)¶
- ✅ Récupérer par ID
- ✅ Récupérer par code (
logo-client-X) - ✅ Recherche (nom, type, tags)
- ✅ URLs publiques/privées
- ✅ Presigned URLs (accès temporaire)
3. UPDATE (Modifier)¶
- ✅ Mise à jour métadonnées
- ⏳ Optimisation images (resize, compression)
- ⏳ Génération thumbnails
4. DELETE (Supprimer)¶
- ✅ Soft delete (archivage)
- ✅ Restauration possible
- ⏳ Hard delete (après X jours)
🔄 Intégrations¶
Consommateurs¶
| Application | Usage | Exemples |
|---|---|---|
| FISCAL | Logos clients + PDFs factures | logo-client-teranga, facture-INV-2025-001.pdf |
| dynors-pdf | Logos dans templates | Logo dans facture PDF |
| ELISA | Photos livraison | Pickup, delivery, signature |
| DAWALALE | Documents permis | Dossiers candidats, pièces d'identité |
| RAGNAR | Contrats, documents | Contrats clients signés |
📊 Modèle de Données¶
FileMetadata¶
@Entity
public class FileMetadata {
private UUID id;
private String tenantCode; // Isolation tenant
private String code; // Code unique (ex: "logo-client-teranga")
private String filename; // facture-001.pdf
private String originalFilename; // Nom original uploadé
private String mimeType; // image/jpeg, application/pdf
private MediaType type; // IMAGE, DOCUMENT, AUDIO, VIDEO
private long size; // Bytes
private String storagePath; // Chemin MinIO/S3
private String publicUrl; // URL publique (si public)
private boolean isPublic; // Accès public ou privé
private String checksum; // MD5 (intégrité)
// Source Tracking (CRITIQUE pour stats)
private String sourceApplication; // "fiscal", "elisa", "ragnar"
private String sourceVersion; // "1.0.0"
private String sourceInstance; // "fiscal-pod-3"
// Relations
private String entityType; // "invoice", "delivery", "contract"
private String entityId; // ID entité métier
// Métadonnées custom
private Map<String, String> metadata;
private List<String> tags;
// Audit
private LocalDateTime uploadedAt;
private UUID uploadedBy;
private LocalDateTime deletedAt; // Soft delete
}
🔐 Sécurité & Quotas¶
Multi-tenancy¶
- Isolation stricte par
tenantCode - Storage dédié par tenant
- Pas de fuite entre tenants
Quotas¶
| Tier | Storage | Max File Size |
|---|---|---|
| FREE | 100 MB | 5 MB |
| TIER_3 | 500 MB | 10 MB |
| TIER_2 | 1 GB | 20 MB |
| TIER_1 | 5 GB | 50 MB |
| SOVEREIGN | ∞ | 100 MB |
Authentification¶
- JWT obligatoire
- Header :
X-Tenant-Coderequis - Permissions : Lecture/Écriture par tenant
🚀 Flux Métier Exemples¶
Cas 1 : FISCAL génère facture PDF¶
1. FISCAL → dynors-media : GET /api/media/by-code/logo-client-teranga
(Récupère logo client)
↓
2. FISCAL → dynors-pdf : génère PDF avec logo
↓
3. FISCAL → dynors-media : POST /api/media/upload
Body: {
file: facture-INV-2025-001.pdf,
code: "facture-INV-2025-001",
sourceApplication: "fiscal"
}
↓
4. dynors-media : stocke PDF + retourne URL
Cas 2 : ELISA upload photos livraison¶
1. ELISA → dynors-media : POST /api/media/upload/bulk
Body: {
files: [pickup.jpg, delivery.jpg, signature.jpg],
metadata: {
deliveryId: "DEL-123",
sourceApplication: "elisa"
}
}
↓
2. dynors-media : stocke 3 fichiers + retourne URLs
📚 API REST¶
Endpoints Principaux¶
| Méthode | Endpoint | Description |
|---|---|---|
POST |
/api/media/upload |
Upload fichier |
POST |
/api/media/upload/bulk |
Upload multiple |
GET |
/api/media/{id} |
Récupérer par ID |
GET |
/api/media/by-code/{code} |
Récupérer par code |
GET |
/api/media/search |
Recherche (query params) |
DELETE |
/api/media/{id} |
Soft delete |
GET |
/api/media/quotas |
Consulter quotas tenant |
Exemple Upload¶
curl -X POST http://localhost:8085/api/media/upload \
-H "Authorization: Bearer <JWT>" \
-H "X-Tenant-Code: teranga-cereales" \
-F "file=@logo.png" \
-F "code=logo-client-teranga" \
-F "description=Logo client Teranga"
📊 Source Tracking (Stats)¶
Chaque fichier uploadé inclut :
- `source_application: "elisa", ragnar)
source_version: Version de l'appsource_instance: Instance (pour load balancing)
Usage : Identifier quelles apps génèrent le plus de fichiers, détecter goulots d'étranglement.
🎯 Roadmap¶
✅ Phase 1 : MVP (En cours)¶
- ✅ Upload/Download basique
- ✅ Multi-tenant strict
- ✅ Quotas enforced
- ✅ Source tracking
- ✅ Checksum validation
- ⏳ Storage MinIO
📋 Phase 2 : Features Avancées¶
- Thumbnails automatiques (images)
- Optimisation images (resize, compression)
- Recherche full-text
- Presigned URLs expirables
- Webhooks (upload completed)
📋 Phase 3 : Production¶
- Storage S3/Azure Blob
- CDN pour fichiers publics
- Versioning fichiers
- Backup automatique
🚀 Démarrage Rapide¶
Infrastructure Locale¶
cd dynors-internal/applications/media/backend
docker-compose up -d # Lance PostgreSQL + Redis + MinIO
Backend¶
./gradlew bootRun
URL : http://localhost:8085
Health : http://localhost:8085/actuator/health
MinIO Console : http://localhost:9001
📚 Documentation¶
- Guide d’intégration :
core/GUIDE_INTEGRATION_DYNORS_MEDIA.md(stockage, quotas, sécurité) - Architecture :
core/ARCHITECTURE.md(section extensions) - NAS / déploiement médias (ex. DAWALALE) :
core/DEPLOYMENT_DAWALALE_MEDIA_NAS.md
👥 Équipe¶
- Product Owner : Direction DYNORS
- Tech Lead : À définir
- Développeurs : Équipe DYNORS
📞 Contact¶
- Support : support@dynors.com
- Issues : GitLab
dynors-internal/media
Dernière mise à jour : 2026-03-05