Files
Socialflow/server/routes/legal.ts
T
Claude 3e00a3ca67 feat(legal): préremplir les mentions légales de la société exploitante
Renseigne l'identité de FROUARD DISTRIBUTION (enseigne LA FOIR'FOUILLE)
comme valeur par défaut des pages /terms et /privacy : forme juridique,
capital, siège et numéro RCS. Les relecteurs TikTok ouvrent ces pages
pendant l'audit et refusent les mentions incomplètes.

Chaque champ reste surchargeable par variable d'environnement si l'outil
venait à être exploité par une autre société du groupe.

L'adresse de contact reste à fournir via LEGAL_CONTACT_EMAIL : elle ne
figure pas au registre, et le RGPD impose un point de contact pour
l'exercice des droits.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018uUPZ1GNpEkYB1dpXHYPek
2026-08-11 16:19:16 +00:00

270 lines
11 KiB
TypeScript

/**
* Pages légales publiques (conditions d'utilisation et politique de confidentialité).
*
* TikTok exige une URL publique pour chacune lors de la création de l'application
* développeur, et les relecteurs les ouvrent réellement pendant l'audit. Elles sont
* servies en HTML depuis le serveur, sans authentification, pour rester lisibles
* même par un robot qui n'exécute pas le JavaScript du client.
*
* Les mentions de l'exploitant sont préremplies avec l'identité de la société
* exploitante et restent surchargeables par variables d'environnement :
* LEGAL_COMPANY_NAME, LEGAL_TRADE_NAME, LEGAL_COMPANY_LEGAL_FORM,
* LEGAL_COMPANY_RCS, LEGAL_COMPANY_ADDRESS, LEGAL_CONTACT_EMAIL
*/
import { Router, Request, Response } from 'express';
export const legalRouter = Router();
function getCompanyInfo() {
return {
name: process.env.LEGAL_COMPANY_NAME || 'FROUARD DISTRIBUTION',
tradeName: process.env.LEGAL_TRADE_NAME || "LA FOIR'FOUILLE",
legalForm: process.env.LEGAL_COMPANY_LEGAL_FORM
|| 'Société par actions simplifiée au capital de 50 000 €',
rcs: process.env.LEGAL_COMPANY_RCS || '478 693 518 R.C.S. Nancy',
address: process.env.LEGAL_COMPANY_ADDRESS || '13 rue du Saule Gaillard, 54390 Frouard',
// Aucune adresse de contact ne figure au registre : elle doit être fournie,
// le RGPD imposant un point de contact pour l'exercice des droits.
email: process.env.LEGAL_CONTACT_EMAIL || '[Adresse e-mail de contact à renseigner]',
};
}
function escapeHtml(value: string): string {
return value
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
}
function renderPage(title: string, body: string): string {
return `<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>${escapeHtml(title)}</title>
<style>
:root { color-scheme: light dark; }
body {
max-width: 46rem;
margin: 0 auto;
padding: 2.5rem 1.25rem 4rem;
font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
line-height: 1.65;
color: #1f2328;
background: #ffffff;
}
h1 { font-size: 1.75rem; margin-bottom: 0.25rem; }
h2 { font-size: 1.15rem; margin-top: 2.25rem; }
.updated { color: #6b7280; font-size: 0.875rem; margin-top: 0; }
ul { padding-left: 1.25rem; }
li { margin-bottom: 0.35rem; }
code { background: rgba(127, 127, 127, 0.15); padding: 0.1rem 0.3rem; border-radius: 0.25rem; font-size: 0.9em; }
footer { margin-top: 3rem; padding-top: 1.25rem; border-top: 1px solid rgba(127,127,127,0.3); color: #6b7280; font-size: 0.875rem; }
a { color: #2563eb; }
@media (prefers-color-scheme: dark) {
body { color: #e6e6e6; background: #0f1115; }
.updated, footer { color: #9ca3af; }
a { color: #7aa7ff; }
}
</style>
</head>
<body>
${body}
</body>
</html>`;
}
function renderFooter(): string {
const company = getCompanyInfo();
return `<footer>
<p>
${escapeHtml(company.name)} &ndash; enseigne ${escapeHtml(company.tradeName)}<br>
${escapeHtml(company.legalForm)}<br>
${escapeHtml(company.address)}<br>
${escapeHtml(company.rcs)}<br>
Contact : ${escapeHtml(company.email)}
</p>
<p><a href="/terms">Conditions d'utilisation</a> &middot; <a href="/privacy">Politique de confidentialité</a></p>
</footer>`;
}
legalRouter.get('/terms', (_req: Request, res: Response) => {
const company = getCompanyInfo();
const body = `
<h1>Conditions d'utilisation</h1>
<p class="updated">Dernière mise à jour : 11 août 2026</p>
<p>
Cette application est un outil interne de gestion des réseaux sociaux exploité par
${escapeHtml(company.name)}, ${escapeHtml(company.legalForm)}, dont le siège est situé
${escapeHtml(company.address)}, immatriculée au ${escapeHtml(company.rcs)}, qui exploite le
magasin sous l'enseigne ${escapeHtml(company.tradeName)} (« nous »). Elle permet à nos équipes
de créer des vidéos et des publications promotionnelles, puis de les diffuser sur les comptes
et pages officiels de nos magasins.
</p>
<h2>1. Accès au service</h2>
<p>
L'accès est réservé aux personnes que nous avons expressément autorisées, au moyen d'un compte
nominatif. Chaque utilisateur est responsable de la confidentialité de ses identifiants et des
actions effectuées depuis son compte. Nous pouvons suspendre ou retirer un accès à tout moment.
</p>
<h2>2. Comptes de réseaux sociaux connectés</h2>
<p>
L'application publie sur des comptes Facebook et TikTok qui nous appartiennent ou que nous
sommes habilités à administrer. En connectant un compte, l'utilisateur déclare disposer des
droits nécessaires pour le faire. Un compte peut être déconnecté à tout moment depuis
l'application, ou par le retrait de l'autorisation directement dans les réglages de la
plateforme concernée.
</p>
<h2>3. Contenus publiés</h2>
<p>
Les utilisateurs restent responsables des contenus qu'ils créent et diffusent. Ces contenus
doivent respecter la loi applicable ainsi que les règles des plateformes de destination,
notamment les Conditions d'utilisation et les Règles communautaires de TikTok et de Meta.
Sont notamment proscrits les contenus dont les utilisateurs ne détiennent pas les droits,
y compris pour les images et les musiques utilisées.
</p>
<h2>4. Disponibilité</h2>
<p>
Le service est fourni « en l'état ». Il dépend de services tiers (plateformes de publication,
hébergement, traitement vidéo) dont les interruptions ou modifications peuvent affecter son
fonctionnement. Nous ne garantissons ni une disponibilité continue, ni la publication effective
d'un contenu par une plateforme tierce, celle-ci pouvant la refuser selon ses propres règles.
</p>
<h2>5. Responsabilité</h2>
<p>
Dans les limites permises par la loi, notre responsabilité ne saurait être engagée au titre des
dommages indirects résultant de l'utilisation du service, notamment une perte de contenu, une
publication manquée ou la suspension d'un compte par une plateforme tierce.
</p>
<h2>6. Modification des conditions</h2>
<p>
Ces conditions peuvent être modifiées. La date de dernière mise à jour figure en tête de page.
</p>
<h2>7. Contact</h2>
<p>Pour toute question relative à ces conditions : ${escapeHtml(company.email)}</p>
${renderFooter()}`;
res.type('html').send(renderPage("Conditions d'utilisation", body));
});
legalRouter.get('/privacy', (_req: Request, res: Response) => {
const company = getCompanyInfo();
const body = `
<h1>Politique de confidentialité</h1>
<p class="updated">Dernière mise à jour : 11 août 2026</p>
<p>
Cette politique décrit les données traitées par notre outil interne de gestion des réseaux
sociaux. Le responsable de traitement est ${escapeHtml(company.name)},
${escapeHtml(company.legalForm)}, dont le siège est situé ${escapeHtml(company.address)},
immatriculée au ${escapeHtml(company.rcs)}, exploitant le magasin sous l'enseigne
${escapeHtml(company.tradeName)}.
</p>
<h2>1. Données de nos utilisateurs internes</h2>
<p>
Pour chaque personne autorisée à utiliser l'outil, nous conservons un identifiant de connexion,
un mot de passe stocké sous forme chiffrée, un rôle et la liste des comptes auxquels elle a
accès. Ces données servent uniquement à l'authentification et à la gestion des droits.
</p>
<h2>2. Données issues des comptes de réseaux sociaux connectés</h2>
<p>
Lorsqu'un compte TikTok est connecté, nous recevons de TikTok, avec l'autorisation explicite du
titulaire du compte et dans le cadre du périmètre <code>user.info.basic</code> :
</p>
<ul>
<li>l'identifiant technique du compte (<code>open_id</code>) ;</li>
<li>le nom d'affichage du compte ;</li>
<li>l'image de profil du compte ;</li>
<li>un jeton d'accès et un jeton de renouvellement, qui nous permettent de publier en son nom.</li>
</ul>
<p>
Nous procédons de manière équivalente pour les pages Facebook connectées. Nous ne collectons ni
la liste des abonnés, ni les messages privés, ni les données de navigation des visiteurs de ces
comptes.
</p>
<h2>3. Finalités</h2>
<p>
Ces données sont utilisées exclusivement pour identifier le compte de destination dans
l'interface et y publier les vidéos et publications créées par nos équipes, immédiatement ou à
l'heure programmée. Elles ne servent à aucune autre finalité.
</p>
<h2>4. Données que nous transmettons aux plateformes</h2>
<p>
Lors d'une publication, nous transmettons à la plateforme concernée le fichier vidéo ou image,
le texte de la publication, ainsi que les paramètres de diffusion associés (niveau de
confidentialité, autorisation des commentaires). Ces contenus sont ensuite régis par la
politique de confidentialité de la plateforme concernée.
</p>
<h2>5. Conservation et sécurité</h2>
<ul>
<li>Les jetons d'accès et de renouvellement sont chiffrés au repos (AES-256-GCM).</li>
<li>
Ils sont conservés tant que le compte reste connecté à l'application, et supprimés
immédiatement lorsque le compte en est retiré.
</li>
<li>Les médias sources sont supprimés automatiquement après leur publication et leur péremption.</li>
<li>L'accès à l'application est restreint aux personnes autorisées et protégé par mot de passe.</li>
</ul>
<h2>6. Partage avec des tiers</h2>
<p>
Nous ne vendons ni ne louons ces données, et ne les transmettons à aucun tiers à des fins
publicitaires ou de profilage. Elles ne sont communiquées qu'aux plateformes de destination
(TikTok, Meta) dans la stricte mesure nécessaire à la publication demandée, ainsi qu'à nos
prestataires techniques d'hébergement et de traitement vidéo agissant sur nos instructions.
</p>
<h2>7. Retirer une autorisation</h2>
<p>
Le titulaire d'un compte connecté peut retirer son autorisation à tout moment :
</p>
<ul>
<li>en demandant la déconnexion du compte depuis l'application, ce qui supprime les jetons ;</li>
<li>
ou directement dans TikTok, via <em>Profil &rsaquo; Paramètres et confidentialité &rsaquo;
Sécurité et autorisations &rsaquo; Gérer les autorisations des applications</em>.
</li>
</ul>
<p>
Le retrait de l'autorisation empêche toute publication ultérieure. Il n'entraîne pas la
suppression des contenus déjà publiés sur la plateforme, qui doivent être supprimés depuis
celle-ci.
</p>
<h2>8. Vos droits</h2>
<p>
Conformément au Règlement général sur la protection des données, vous disposez d'un droit
d'accès, de rectification, d'effacement, de limitation et de portabilité des données vous
concernant, ainsi que du droit d'introduire une réclamation auprès de la CNIL. Pour exercer ces
droits, écrivez à ${escapeHtml(company.email)}.
</p>
<h2>9. Modification de cette politique</h2>
<p>
Cette politique peut être mise à jour. La date de dernière mise à jour figure en tête de page.
</p>
${renderFooter()}`;
res.type('html').send(renderPage('Politique de confidentialité', body));
});