← LemonDocuments

JOURNAL DES VERSIONS

Tout ce qui a changé
dans LemonDocuments.

Tous les documents d'un client au même endroit

Version en cours 1.0.0 Dolibarr 22 et supérieur

1.0.0 — 2026-09-14

Première version publiée. Le module rassemble sur un seul écran les documents d’un tiers, éparpillés jusque-là dans le dossier de chaque devis, commande ou facture, et permet de les renvoyer sans quitter Dolibarr.

Onglet Documents sur la fiche tiers

  • New: Onglet Documents réunissant les pièces jointes déposées sur les devis, commandes, factures, factures et commandes fournisseur, contrats, projets, expéditions, interventions et tickets du client.
  • New: Rangement par nature — logos et sources graphiques, images, vidéos, sons, documents, archives — déduit de l’extension, sans aucune saisie.
  • New: Chaque fichier garde un lien cliquable vers l’objet où il a été déposé.
  • New: Épinglage d’un fichier comme référence du tiers : le logo ou la charte remontent en tête quel que soit l’objet d’origine. Le fichier n’est ni déplacé ni recopié, le module ne pose qu’un repère.
  • New: Aperçu en ligne des images, PDF, sons et vidéos ; téléchargement pour le reste. Les images et documents passent par la visionneuse de Dolibarr, les sons et vidéos par un lecteur dédié — le cœur les afficherait dans un cadre sans contrôles.
  • New: Les documents fabriqués par Dolibarr sont écartés de cet écran. Le tri s’appuie sur llx_ecm_files.gen_or_uploaded et non sur le nom du fichier : sur une propale, REF.pdf et REF_signed-*.pdf sont tous deux générés, là où une règle sur le nom ne rattrape que le premier.

Envoi par mail

  • New: Bloc de sélection sur tous les écrans d’envoi — devis, commande, facture, achat, contrat, projet, expédition, intervention, ticket, et la fiche tiers elle-même.
  • New: Trois sections : les documents de l’objet courant, les autres documents du client, et ses devis, commandes et factures.
  • New: Envoi en pièces jointes, ou derrière un lien de téléchargement à durée de vie limitée. Bascule automatique sur le lien au-delà d’un seuil réglable (10 Mo par défaut), pour ne pas se faire rejeter par le serveur du destinataire.
  • New: Page publique de téléchargement aux couleurs de Dolibarr, avec aperçu et téléchargement par fichier, date d’expiration affichée, non indexée.

Liens émis

  • New: Écran Documents ▸ Liens de téléchargement : qui a partagé quoi, pour quel client, combien de fichiers, combien de téléchargements, depuis quelle adresse, jusqu’à quand. Filtres par client, libellé et statut.
  • New: Révocation d’un lien en un geste, avec confirmation. Il cesse de fonctionner immédiatement, y compris pour les destinataires déjà servis.

Administration

  • New: Onglet Mode d’emploi dans la configuration du module : mise en route, déroulé d’usage, ce qui surprend, tableau des droits et limites connues.
  • New: Trois droits distincts — consulter, envoyer, épingler. Seul le premier est accordé par défaut.
  • New: Notification de mise à jour par url_last_version.

Sécurité

  • Sec: Aucun fichier n’est servi d’après un chemin reçu en paramètre. Le fichier demandé doit figurer dans la liste réelle du tiers, recalculée à chaque appel : une liste blanche, pas une validation de chaîne.
  • Sec: Après résolution des liens symboliques, tout fichier servi doit se trouver sous DOL_DATA_ROOT.
  • Sec: Ni SVG ni HTML ne sont jamais affichés en ligne, sur la page publique comme dans Dolibarr — sur le domaine de l’ERP, cela reviendrait à y exécuter du code fourni par un tiers. Le paramètre d’aperçu est ignoré pour ces types, et le fichier part en téléchargement. Content-Security-Policy et nosniff sur tout ce qui est servi.
  • Sec: Jetons de partage de 32 caractères hexadécimaux tirés de random_bytes, à durée de vie limitée et révocables.
  • Sec: Toute écriture passe par un POST avec jeton CSRF ; le périmètre du tiers est contrôlé par restrictedArea(), et la liste des liens suit le périmètre commercial de l’utilisateur — il ne coupe que ce qu’il voit.

Compatibilité

  • Éprouvé sur Dolibarr 22 / MySQL-MariaDB et Dolibarr 23 / PostgreSQL 16. Le plancher est fixé à 22 : les versions antérieures ne sont pas annoncées, faute d’avoir été exercées.
  • PHP 7.4 minimum.
  • Aucun fichier du cœur n’est modifié : l’intégration passe par les onglets, les hooks et le menu.
  • remove() ne supprime aucune donnée. Désactiver puis réactiver le module conserve les épinglages, les liens émis et les réglages.

Corrigé avant publication

Une revue externe du code a été passée avant la mise en vente. Sept défauts en sont sortis, tous corrigés ici — la 1.0.0 n’ayant jamais été distribuée, ils n’ont atteint aucun client.

  • Fix: Les quatre actions écrites — créer un lien depuis l’onglet, épingler, désépingler, révoquer — appelaient verifCsrfToken(), qui n’existe dans aucune version de Dolibarr. Elles échouaient toutes. Les pages déclarent désormais CSRFCHECK_WITH_TOKEN, le mécanisme que le cœur emploie pour ses propres pages sensibles : le jeton est exigé même quand l’instance n’a pas activé MAIN_SECURITY_CSRF_WITH_TOKEN, dont la valeur par défaut est 0.
  • Sec: Le hook d’envoi s’exécutait sur les sous-actions du formulaire de mail. La branche removeAll du cœur appelle dol_delete_file() sur chaque chemin présent en session, où nous inscrivions les originaux : un POST portant cette sous-action pouvait donc faire supprimer des documents du client. Le hook sort maintenant sur removeAll, removedfile, addfile, cancel et modelselected, exactement comme le cœur.
  • Sec: L’écran des liens émis ne filtrait pas les utilisateurs externes — la condition testait l’absence de socid, vraie seulement pour les internes. Un externe muni du droit d’envoi voyait les liens actifs de tous les clients, donc leurs fichiers. L’écran leur est désormais fermé.
  • Sec: Les documents étaient servis sans vérifier le droit de lecture de l’objet d’origine : voir un client suffisait à voir les pièces jointes de ses factures fournisseur. Chaque type exige maintenant le droit natif de son module, et les projets privés passent par getProjectsAuthorizedForUser().
  • Fix: Le balayage disque réintroduisait les fichiers que la configuration venait d’écarter, faute de distinguer « inconnu de l’index » de « connu mais exclu ». L’index est désormais lu sans filtre, et le tri se fait ensuite.
  • Fix: L’agrégation par tiers n’avait aucun balayage de secours, contrairement à celle par objet : un fichier non indexé restait invisible depuis la fiche client, soit précisément ce que le module promet de régler. Le balayage est ajouté, borné à 200 objets par client (LEMONDOCUMENTS_SCAN_MAX_OBJECTS).
  • Fix: Les liens publics étaient cherchés dans l’entité de la session. Un visiteur anonyme arrivant en entité 1, un lien créé depuis une autre société restait introuvable alors qu’il fonctionnait chez son auteur. Le jeton, unique et à 128 bits, résout maintenant l’entité, sur laquelle la page publique bascule.
  • Enh: Le total de l’écran des liens passe par COUNT(*) au lieu de relire toutes les lignes ; l’inventaire des objets d’un client est mutualisé entre les deux interrogations de l’écran d’envoi ; la révocation distingue succès réel, aucune ligne touchée et erreur ; le JSON injecté dans la page est encodé de façon à ne pouvoir refermer aucune balise.

Angles de recette traités dans la foulée

  • Fix: L’URL publique codait /custom/ en dur. Le cœur accepte aussi une installation sous htdocs/lemondocuments/, où tous les liens émis auraient été morts. Le chemin réel est maintenant déduit par dol_buildpath().
  • Fix: Les fichiers d’un lien étaient désignés par leur rang. Un document supprimé ou renommé après l’envoi décalait la liste, et le lien servait le voisin. Ils le sont désormais par l’empreinte de leur chemin ; les liens déjà envoyés au format numérique restent acceptés.
  • Sec: La page publique servait encore les fichiers après désactivation du module. Désactiver est pourtant le geste par lequel on coupe la diffusion.
  • Fix: Un fichier dont le nom contient un point-virgule décalait les listes de pièces jointes en session — Dolibarr s’en sert comme séparateur — et le mail partait avec le mauvais fichier. Ces fichiers sont écartés, et l’expéditeur en est averti nommément.

Origine

Ce module reprend l’identifiant 210008 et le mécanisme de partage de LemonTransfer, un module jamais déployé ni publié. L’énumération des fichiers a été refaite : LemonTransfer excluait les documents générés par leur nom, ce qui écartait au passage toute pièce jointe nommée d’après la référence de l’objet — le cas courant quand on nomme ses fichiers proprement.