Help: dedicated webhooks section with examples, event table, API details
CI / lint (push) Failing after 4s
CI / test (push) Has been skipped
CI / build (push) Has been skipped
CI / security (push) Successful in 8s

This commit is contained in:
2026-06-03 09:42:08 -04:00
parent 01af74a43f
commit 91366212d4
+129 -10
View File
@@ -798,6 +798,7 @@
<li><a href="#help-palette" class="help-nav-link">⌨️ Palette</a></li>
<li><a href="#help-raccourcis" class="help-nav-link">⌨️ Raccourcis</a></li>
<li><a href="#help-partage" class="help-nav-link">🔗 Partage</a></li>
<li><a href="#help-webhooks" class="help-nav-link">🪝 Webhooks</a></li>
<li><a href="#help-sauvegardes" class="help-nav-link">💾 Sauvegardes</a></li>
<li><a href="#help-securite" class="help-nav-link">🛡️ Sécurité</a></li>
<li><a href="#help-personnalisation" class="help-nav-link">🎨 Personnalisation</a></li>
@@ -1319,18 +1320,136 @@
<li><strong>Gestion des liens</strong> : Liste et révocation dans les Configurations</li>
<li><strong>Export PDF</strong> : Téléchargement du document partagé en PDF via <code>/s/{token}/pdf</code></li>
</ul>
<h3>Webhooks</h3>
<p>Les webhooks notifient des services externes lors des changements de fichiers.</p>
<ul>
<li><strong>Événements</strong> : Création, modification, suppression, renommage</li>
<li><strong>Format</strong> : POST JSON avec détails complets de l'événement</li>
<li><strong>Signature HMAC-SHA256</strong> : Optionnelle pour vérifier l'origine</li>
<li><strong>Configuration</strong> : Gestion via le modal Configurations</li>
</ul>
</section>
<!-- 💾 Sauvegardes -->
<!-- 🪝 Webhooks -->
<section class="help-section" id="help-webhooks">
<h2>🪝 Webhooks</h2>
<p>Les webhooks permettent à ObsiGate de <strong>notifier automatiquement des services externes</strong> lorsque des fichiers ou dossiers sont modifiés. Chaque événement déclenche un <code>POST</code> HTTP vers l'URL de votre choix, avec un payload JSON détaillé.</p>
<h3>Cas d'usage</h3>
<ul>
<li><strong>Automatisation CI/CD</strong> : Déclencher un build quand une note de procédure est mise à jour</li>
<li><strong>Synchronisation</strong> : Copier les nouveaux fichiers vers un autre système (SharePoint, Google Drive)</li>
<li><strong>Notifications</strong> : Alerter un canal Slack/Discord quand un document est créé</li>
<li><strong>Audit externe</strong> : Logger toutes les modifications dans une base de données externe</li>
<li><strong>Déploiement</strong> : Publier un article de blog quand un fichier est marqué <code>publish: true</code></li>
</ul>
<h3>Événements supportés</h3>
<div style="overflow-x:auto">
<table style="width:100%;border-collapse:collapse;font-size:0.85rem;margin:8px 0 16px">
<tr style="background:var(--bg-secondary)">
<th style="padding:8px 12px;text-align:left;border-bottom:1px solid var(--border)">Événement</th>
<th style="padding:8px 12px;text-align:left;border-bottom:1px solid var(--border)">Déclencheur</th>
<th style="padding:8px 12px;text-align:left;border-bottom:1px solid var(--border)">Données</th>
</tr>
<tr>
<td style="padding:8px 12px;border-bottom:1px solid var(--border)"><code>file_created</code></td>
<td style="padding:8px 12px;border-bottom:1px solid var(--border)">Création via l'API ou la palette</td>
<td style="padding:8px 12px;border-bottom:1px solid var(--border)"><code>vault</code>, <code>path</code></td>
</tr>
<tr style="background:var(--bg-secondary)">
<td style="padding:8px 12px;border-bottom:1px solid var(--border)"><code>file_deleted</code></td>
<td style="padding:8px 12px;border-bottom:1px solid var(--border)">Suppression via l'API ou l'éditeur</td>
<td style="padding:8px 12px;border-bottom:1px solid var(--border)"><code>vault</code>, <code>path</code></td>
</tr>
<tr>
<td style="padding:8px 12px;border-bottom:1px solid var(--border)"><code>file_renamed</code></td>
<td style="padding:8px 12px;border-bottom:1px solid var(--border)">Renommage via l'API</td>
<td style="padding:8px 12px;border-bottom:1px solid var(--border)"><code>vault</code>, <code>old_path</code>, <code>new_path</code></td>
</tr>
<tr style="background:var(--bg-secondary)">
<td style="padding:8px 12px;border-bottom:1px solid var(--border)"><code>directory_created</code></td>
<td style="padding:8px 12px;border-bottom:1px solid var(--border)">Création de dossier via l'API</td>
<td style="padding:8px 12px;border-bottom:1px solid var(--border)"><code>vault</code>, <code>path</code></td>
</tr>
<tr>
<td style="padding:8px 12px;border-bottom:1px solid var(--border)"><code>directory_deleted</code></td>
<td style="padding:8px 12px;border-bottom:1px solid var(--border)">Suppression de dossier via l'API</td>
<td style="padding:8px 12px;border-bottom:1px solid var(--border)"><code>vault</code>, <code>path</code></td>
</tr>
<tr style="background:var(--bg-secondary)">
<td style="padding:8px 12px;border-bottom:1px solid var(--border)"><code>directory_renamed</code></td>
<td style="padding:8px 12px;border-bottom:1px solid var(--border)">Renommage de dossier via l'API</td>
<td style="padding:8px 12px;border-bottom:1px solid var(--border)"><code>vault</code>, <code>old_path</code>, <code>new_path</code></td>
</tr>
</table>
</div>
<p><em>Note : l'événement <code>file_modified</code> est réservé pour usage futur. Les modifications de contenu via l'éditeur ne déclenchent pas encore de webhook.</em></p>
<h3>Format du payload</h3>
<p>Chaque webhook reçoit un <code>POST</code> avec <code>Content-Type: application/json</code> :</p>
<pre style="background:var(--bg-secondary);padding:12px;border-radius:8px;overflow-x:auto;font-size:0.78rem"><code>{
"event": "file_created",
"timestamp": "2026-06-03T14:30:00.123456+00:00",
"data": {
"vault": "IT",
"path": "procedures/deploiement.md"
}
}</code></pre>
<h3>Sécurité : signature HMAC-SHA256</h3>
<p>Si vous configurez un secret, chaque requête inclut un header <code>X-ObsiGate-Signature</code> :</p>
<pre style="background:var(--bg-secondary);padding:12px;border-radius:8px;overflow-x:auto;font-size:0.78rem"><code>X-ObsiGate-Signature: sha256=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08</code></pre>
<p>Pour vérifier côté récepteur : calculez <code>HMAC-SHA256(corps_brut, secret)</code> et comparez. Le header <code>X-ObsiGate-Event</code> contient aussi le type d'événement pour un routage rapide.</p>
<h3>Configuration</h3>
<p>Les webhooks se gèrent dans le modal <strong>Configurations</strong> (⚙️ menu Options), section Webhooks. Réservé aux administrateurs.</p>
<ol>
<li>Allez dans ⚙️ Configurations → onglet Webhooks</li>
<li>Remplissez : <strong>Nom</strong> (descriptif), <strong>URL</strong> (endpoint cible), <strong>Secret</strong> (optionnel)</li>
<li>Cochez les événements à écouter</li>
<li>Cliquez <strong>Ajouter</strong></li>
</ol>
<p>Les webhooks peuvent être activés/désactivés, modifiés ou supprimés à tout moment. Le <code>last_fired_at</code> indique la dernière exécution.</p>
<h3>Exemples concrets</h3>
<h4>Récepteur Python (Flask)</h4>
<pre style="background:var(--bg-secondary);padding:12px;border-radius:8px;overflow-x:auto;font-size:0.78rem"><code>from flask import Flask, request\nimport hmac, hashlib\n\napp = Flask(__name__)\nWEBHOOK_SECRET = "mon-secret" # même que dans ObsiGate\n\[email protected]("/webhook", methods=["POST"])\ndef webhook():\n # Vérifier la signature\n signature = request.headers.get("X-ObsiGate-Signature", "")\n body = request.get_data()\n expected = "sha256=" + hmac.new(\n WEBHOOK_SECRET.encode(), body, hashlib.sha256\n ).hexdigest()\n if not hmac.compare_digest(signature, expected):\n return "Invalid signature", 403\n\n payload = request.get_json()\n print(f"Événement: {payload['event']}")\n print(f"Fichier: {payload['data']['vault']}/{payload['data']['path']}")\n return "OK", 200\n\napp.run(port=5000)</code></pre>
<h4>n8n / Make (no-code)</h4>
<ol>
<li>Créez un <strong>Webhook Trigger</strong> dans n8n ou Make</li>
<li>Copiez l'URL générée (ex: <code>https://n8n.monserveur.com/webhook/abc123</code>)</li>
<li>Dans ObsiGate, ajoutez un webhook pointant vers cette URL</li>
<li>Sélectionnez les événements souhaités</li>
<li>Le workflow se déclenche automatiquement à chaque événement</li>
</ol>
<h4>Notification Discord</h4>
<p>Utilisez un webhook relais (n8n, Make, ou un script) pour transformer le payload ObsiGate en message Discord :</p>
<pre style="background:var(--bg-secondary);padding:12px;border-radius:8px;overflow-x:auto;font-size:0.78rem"><code># Exemple avec curl + jq dans un script bash
WEBHOOK_URL="https://discord.com/api/webhooks/..."
OBSIGATE_SECRET="mon-secret"
# Lire le payload depuis stdin
read -r payload
event=$(echo "$payload" | jq -r '.event')
path=$(echo "$payload" | jq -r '.data.path')
curl -H "Content-Type: application/json" -d "{
\"content\": \"📝 **$event** — $path\"
}" "$WEBHOOK_URL"</code></pre>
<h4>Tester avec curl</h4>
<pre style="background:var(--bg-secondary);padding:12px;border-radius:8px;overflow-x:auto;font-size:0.78rem"><code># Simuler ce qu'ObsiGate envoie (pour tester votre endpoint)
curl -X POST https://votre-serveur.com/webhook \
-H "Content-Type: application/json" \
-H "X-ObsiGate-Event: file_created" \
-H "X-ObsiGate-Signature: sha256=$(echo -n '{"event":"file_created",...}' | openssl dgst -sha256 -hmac 'mon-secret' | cut -d' ' -f2)" \
-d '{"event":"file_created","timestamp":"2026-06-03T14:30:00Z","data":{"vault":"IT","path":"notes/test.md"}}'</code></pre>
<h3>Limitations actuelles</h3>
<ul>
<li>Timeout de <strong>5 secondes</strong> par requête — les webhooks sont "fire and forget" (pas de retry)</li>
<li>Les modifications détectées par le watcher filesystem (watchdog) <strong>ne déclenchent pas</strong> de webhooks — seules les opérations via l'API REST sont prises en compte</li>
<li><code>file_modified</code> n'est pas encore dispatché (réservé pour version future)</li>
<li>Pas de retry automatique en cas d'échec</li>
<li>Pas de filtrage par vault — un webhook écoute toutes les vaults</li>
</ul>
</section>
<section class="help-section" id="help-sauvegardes">
<h2>💾 Sauvegardes et Audits</h2>