Partage en lecture seule par lien signé
- Lien /s/<jeton> : jeton = id aléatoire 128 bits + HMAC-SHA256 tronqué par la
clé du serveur (SHARE_SECRET, sinon DATA_DIR/.share-secret générée en 0600).
Valide si la signature est correcte, le lien présent dans .shares.json et non
expiré (1, 7, 30 jours ou sans expiration).
- API : GET/POST/DELETE /api/shares, POST /api/shares/revoke-all (renouvelle la
clé), GET /api/public/{jeton} hors authentification (nom, titre, logo, scène).
- Auth Basic : /s/, /api/public/, /healthz et les fichiers statiques du build
sont publics ; le reste de l'API et l'index restent protégés. Le serveur
statique ne liste plus les répertoires. X-Robots-Tag: noindex sur les liens.
- Les liens suivent renommages et déplacements, disparaissent à la suppression.
- Interface : dialogue Partager (barre du haut, menu de l'explorateur), section
Liens de partage dans Paramètres, vue publique Excalidraw en lecture seule
avec téléchargement et bascule clair/sombre.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H6J7vKwXx7uopxKhWfFJpm
This commit is contained in:
1 parent
c1ea1e84a7
commit
50d40cd929
18 files changed
+1076
-12
No files matched your search
@@ -1227,3 +1227,66 @@ button.chip.on,
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
/* --- Partage en lecture seule ---------------------------------------------- */
|
||||
|
||||
.share-view {
|
||||
display: grid;
|
||||
grid-template-rows: var(--topbar-h) 1fr;
|
||||
grid-template-columns: 1fr;
|
||||
height: 100dvh;
|
||||
}
|
||||
.share-view .canvas {
|
||||
grid-area: 2 / 1;
|
||||
}
|
||||
.share-view .brand {
|
||||
cursor: default;
|
||||
}
|
||||
.status.readonly {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
color: var(--ex-primary);
|
||||
}
|
||||
.share-dialog {
|
||||
width: min(520px, 100%);
|
||||
}
|
||||
.share-create {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.share-create .radio-group button {
|
||||
min-width: 0;
|
||||
padding: 6px 10px;
|
||||
}
|
||||
.share-list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.share-list li {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
.share-list .empty {
|
||||
font-size: 13px;
|
||||
}
|
||||
.share-list .cmd code {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.share-view .status.readonly {
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user