Espaces personnels et favoris par utilisateur (stockage)

- DATA_DIR/.users/<id>/home : espace personnel, Store complet (historique,
  miniatures, corbeille, tags, partages), exposé sous le préfixe virtuel .perso.
- DATA_DIR/.users/<id>/favoris : un lien symbolique relatif par favori, exposé
  sous .favoris. Les liens suivent renommages et déplacements (y compris entre
  espaces) pour tous les utilisateurs et disparaissent à la suppression.
- Identifiant : email OIDC normalisé (UserID), utilisateur « local » sinon.
- Reprise unique des favoris de .meta.json à la création d'un espace.
- Les espaces personnels signent leurs liens de partage avec la clé du Store
  principal ; Tout révoquer couvre aussi les espaces personnels.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0174sFqehj4uGqJHQZvWy1gn
This commit is contained in:
claude BotandClaude Opus 5.5 committed 2026-10-08 10:24:55 +02:00
1 parent c7a43ff12b
commit 781fc8f5f5
3 files changed
+944 -2

No files matched your search

+12 -2
View File
@@ -63,6 +63,9 @@ func (s *Store) SetShareSecret(secret string) {
// key renvoie la clé de signature, créée au besoin ; appelé sous sharesMu.
func (s *Store) key() ([]byte, error) {
if s.keyFrom != nil {
return s.keyFrom.lockedKey()
}
if s.shareKey != nil {
return s.shareKey, nil
}
@@ -79,6 +82,13 @@ func (s *Store) key() ([]byte, error) {
return s.newKey()
}
// lockedKey renvoie la clé de signature pour un espace personnel.
func (s *Store) lockedKey() ([]byte, error) {
s.sharesMu.Lock()
defer s.sharesMu.Unlock()
return s.key()
}
func (s *Store) newKey() ([]byte, error) {
k := make([]byte, 32)
if _, err := rand.Read(k); err != nil {
@@ -230,11 +240,11 @@ func (s *Store) RevokeShare(id string) error {
}
// RevokeAllShares supprime tous les liens et change la clé de signature
// (sauf si elle est imposée par SHARE_SECRET).
// (sauf si elle est imposée par SHARE_SECRET ou reprise du Store principal).
func (s *Store) RevokeAllShares() error {
return s.editShares(func(m map[string]shareDisk) (bool, error) {
clear(m)
if !s.fixedKey {
if !s.fixedKey && s.keyFrom == nil {
if _, err := s.newKey(); err != nil {
return false, err
}