Poubelle par utilisateur (backend) : dossier virtuel .poubelle, restauration, suppression définitive, purge automatique (trashDays)
This commit is contained in:
1 parent
8c29eb35e7
commit
8a1417055b
9 files changed
+634
-37
No files matched your search
@@ -0,0 +1,128 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestTrash(t *testing.T) {
|
||||
main := newStore(t)
|
||||
sp := NewSpaces(main)
|
||||
u, err := sp.For("alice")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
main.Write("d/a.excalidraw", []byte(doc), "", true)
|
||||
main.Write("d/b.excalidraw", []byte(doc), "", true)
|
||||
u.Write(".perso/p.excalidraw", []byte(doc), "", true)
|
||||
if err := u.EditTags([]string{"d/a.excalidraw"}, []string{"NSX"}, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, p := range []string{"d/a.excalidraw", ".perso/p.excalidraw"} {
|
||||
if err := u.Delete(p, false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
if err := u.Delete("d", true); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
root, _ := u.List("")
|
||||
if len(root) < 3 || root[2].Special != "poubelle" || root[2].Count != 3 {
|
||||
t.Fatalf("racine = %+v", root)
|
||||
}
|
||||
items, err := u.List(TrashPrefix)
|
||||
if err != nil || len(items) != 3 {
|
||||
t.Fatalf("poubelle = %+v, %v", items, err)
|
||||
}
|
||||
// Plus récent en premier : le dossier d, puis p, puis a.
|
||||
if items[0].Name != "d" || !items[0].IsDir || items[0].Origin != "d" || items[0].By != "alice" ||
|
||||
items[1].Origin != ".perso/p.excalidraw" || items[2].Origin != "d/a.excalidraw" {
|
||||
t.Fatalf("poubelle = %+v", items)
|
||||
}
|
||||
// Les éléments de la poubelle ne s'ouvrent pas.
|
||||
if _, _, err := u.Read(items[2].Path); err == nil {
|
||||
t.Fatal("lecture dans la poubelle acceptée")
|
||||
}
|
||||
|
||||
// a revient dans d (recréé), avec son tag.
|
||||
res := u.RestoreTrash([]string{items[2].Path})
|
||||
if res[0].Error != "" || res[0].To != "d/a.excalidraw" {
|
||||
t.Fatalf("restauration = %+v", res)
|
||||
}
|
||||
if l, _ := u.List("d"); len(l) != 1 || len(l[0].Tags) != 1 {
|
||||
t.Fatalf("d = %+v", l)
|
||||
}
|
||||
// Le dossier d revient sous un autre nom, la place étant prise.
|
||||
res = u.RestoreTrash([]string{items[0].Path})
|
||||
if res[0].Error != "" || res[0].To != "d (restauré)" {
|
||||
t.Fatalf("restauration = %+v", res)
|
||||
}
|
||||
if l, _ := u.List("d (restauré)"); len(l) != 1 || l[0].Name != "b.excalidraw" {
|
||||
t.Fatalf("d (restauré) = %+v", l)
|
||||
}
|
||||
|
||||
// Suppression définitive, puis poubelle vide.
|
||||
if err := u.Delete(items[1].Path, false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if l, _ := u.Trash(); len(l) != 0 {
|
||||
t.Fatalf("poubelle = %+v", l)
|
||||
}
|
||||
if err := u.Delete(TrashPrefix+"/c-x", false); !errors.Is(err, ErrInvalidPath) {
|
||||
t.Fatalf("élément inconnu : %v", err)
|
||||
}
|
||||
|
||||
// Vider la poubelle.
|
||||
u.Delete("d/a.excalidraw", false)
|
||||
if err := u.Delete(TrashPrefix, true); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if main.TrashCount() != 0 {
|
||||
t.Fatal("poubelle non vidée")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrashPurge(t *testing.T) {
|
||||
main := newStore(t)
|
||||
sp := NewSpaces(main)
|
||||
u, _ := sp.For("bob")
|
||||
main.Write("old.excalidraw", []byte(doc), "", true)
|
||||
main.Write("new.excalidraw", []byte(doc), "", true)
|
||||
u.Write(".perso/old.excalidraw", []byte(doc), "", true)
|
||||
u.Delete("old.excalidraw", false)
|
||||
u.Delete(".perso/old.excalidraw", false)
|
||||
// Vieillit les deux entrées de 10 jours.
|
||||
for _, st := range []*Store{main, u.home} {
|
||||
items, _ := st.TrashItems()
|
||||
old := time.Now().UTC().Add(-240 * time.Hour).Format(trashLayout)
|
||||
if err := os.Rename(st.trashAbs(items[0].ID), st.trashAbs(old)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
u.Delete("new.excalidraw", false)
|
||||
|
||||
// Sans durée de conservation, rien n'est purgé.
|
||||
if err := sp.PurgeTrash(); err != nil || main.TrashCount() != 2 || u.home.TrashCount() != 1 {
|
||||
t.Fatalf("purge sans durée : %v", err)
|
||||
}
|
||||
if _, err := main.WriteTrashDays(-1); err == nil {
|
||||
t.Fatal("durée négative acceptée")
|
||||
}
|
||||
if st, err := main.WriteTrashDays(7); err != nil || st.TrashDays != 7 {
|
||||
t.Fatalf("WriteTrashDays = %+v, %v", st, err)
|
||||
}
|
||||
if err := sp.PurgeTrash(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if main.TrashCount() != 1 || u.home.TrashCount() != 0 {
|
||||
t.Fatalf("après purge : %d / %d", main.TrashCount(), u.home.TrashCount())
|
||||
}
|
||||
// L'historique de l'élément purgé disparaît avec lui.
|
||||
if des, _ := os.ReadDir(filepath.Join(main.root, trashDir)); len(des) != 1 {
|
||||
t.Fatalf("corbeille = %v", des)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user