Implementing more advanced feature: audit and more
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const definitionsFile = "controllogic.json"
|
||||
@@ -17,16 +18,18 @@ var ErrNotFound = errors.New("control logic graph not found")
|
||||
// Store persists control-logic graphs as a single JSON file in the storage dir.
|
||||
// Writes are atomic (tmp file + rename); all access is mutex-guarded.
|
||||
type Store struct {
|
||||
mu sync.RWMutex
|
||||
path string
|
||||
items map[string]Graph
|
||||
mu sync.RWMutex
|
||||
path string
|
||||
trashDir string
|
||||
items map[string]Graph
|
||||
}
|
||||
|
||||
// NewStore opens (or initialises) the control-logic store under storageDir.
|
||||
func NewStore(storageDir string) (*Store, error) {
|
||||
s := &Store{
|
||||
path: filepath.Join(storageDir, definitionsFile),
|
||||
items: map[string]Graph{},
|
||||
path: filepath.Join(storageDir, definitionsFile),
|
||||
trashDir: filepath.Join(storageDir, "trash", "controllogic"),
|
||||
items: map[string]Graph{},
|
||||
}
|
||||
if err := s.load(); err != nil {
|
||||
return nil, err
|
||||
@@ -99,13 +102,32 @@ func (s *Store) Save(g Graph) error {
|
||||
return s.saveLocked()
|
||||
}
|
||||
|
||||
// Delete removes a graph by id.
|
||||
// Delete removes a graph by id, first writing a copy into the trash folder so it
|
||||
// can be recovered if needed. The trash backup is best-effort: a failure to write
|
||||
// it does not prevent the delete (but is reported).
|
||||
func (s *Store) Delete(id string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if _, ok := s.items[id]; !ok {
|
||||
g, ok := s.items[id]
|
||||
if !ok {
|
||||
return ErrNotFound
|
||||
}
|
||||
if err := s.trash(g); err != nil {
|
||||
return fmt.Errorf("move control logic to trash: %w", err)
|
||||
}
|
||||
delete(s.items, id)
|
||||
return s.saveLocked()
|
||||
}
|
||||
|
||||
// trash writes a single graph as a timestamped JSON file under the trash folder.
|
||||
func (s *Store) trash(g Graph) error {
|
||||
if err := os.MkdirAll(s.trashDir, 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := json.MarshalIndent(g, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dst := filepath.Join(s.trashDir, fmt.Sprintf("%s.%d.json", g.ID, time.Now().UnixMilli()))
|
||||
return os.WriteFile(dst, data, 0o644)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user