Implementing more advanced feature: audit and more
This commit is contained in:
+45
-3
@@ -9,14 +9,18 @@ import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"os/signal"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
"github.com/uopi/uopi/internal/access"
|
||||
"github.com/uopi/uopi/internal/audit"
|
||||
"github.com/uopi/uopi/internal/broker"
|
||||
"github.com/uopi/uopi/internal/config"
|
||||
"github.com/uopi/uopi/internal/controllogic"
|
||||
"github.com/uopi/uopi/internal/datasource/epics"
|
||||
"github.com/uopi/uopi/internal/datasource/pva"
|
||||
"github.com/uopi/uopi/internal/datasource/servervar"
|
||||
"github.com/uopi/uopi/internal/datasource/stub"
|
||||
"github.com/uopi/uopi/internal/datasource/synthetic"
|
||||
"github.com/uopi/uopi/internal/panelacl"
|
||||
@@ -41,6 +45,16 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// In an unproxied/local deployment (no trusted_user_header) without an explicit
|
||||
// default_user, attribute actions to the OS user running the process so the UI
|
||||
// and audit log show a real identity instead of anonymous.
|
||||
if cfg.Server.TrustedUserHeader == "" && cfg.Server.DefaultUser == "" {
|
||||
if u, err := user.Current(); err == nil && u.Username != "" {
|
||||
cfg.Server.DefaultUser = u.Username
|
||||
log.Info("no default_user configured; defaulting to OS user", "user", u.Username)
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(cfg.Server.StorageDir, 0o755); err != nil {
|
||||
log.Error("failed to create storage dir", "dir", cfg.Server.StorageDir, "err", err)
|
||||
os.Exit(1)
|
||||
@@ -122,6 +136,15 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Server variables: a small persistent key/value source ("srv") that the
|
||||
// control-logic engine writes (e.g. sequence state) and panels can read.
|
||||
srvVars, err := servervar.New(cfg.Server.StorageDir)
|
||||
if err != nil {
|
||||
log.Error("server variables init", "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
brk.Register(srvVars)
|
||||
|
||||
// Build the global access policy from config: every user is trusted with
|
||||
// full write access unless downgraded by the blacklist; groups are named
|
||||
// sets of users referenced by per-panel sharing.
|
||||
@@ -133,7 +156,26 @@ func main() {
|
||||
for _, g := range cfg.Groups {
|
||||
groups[g.Name] = g.Members
|
||||
}
|
||||
policy := access.New(cfg.Server.DefaultUser, blacklist, groups, cfg.Server.LogicEditors)
|
||||
policy := access.New(cfg.Server.DefaultUser, blacklist, groups, cfg.Server.LogicEditors, cfg.Audit.Readers)
|
||||
|
||||
// Audit log: when enabled, every system-affecting action (user/automated
|
||||
// signal writes, interface and control-logic mutations) is recorded to SQLite.
|
||||
// When disabled a no-op recorder is used so call sites need no guards.
|
||||
recorder := audit.Nop()
|
||||
if cfg.Audit.Enabled {
|
||||
dbPath := cfg.Audit.DBPath
|
||||
if dbPath == "" {
|
||||
dbPath = filepath.Join(cfg.Server.StorageDir, "audit.db")
|
||||
}
|
||||
r, err := audit.NewSQLite(dbPath, log)
|
||||
if err != nil {
|
||||
log.Error("failed to open audit log", "path", dbPath, "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer r.Close()
|
||||
recorder = r
|
||||
log.Info("audit log enabled", "path", dbPath)
|
||||
}
|
||||
|
||||
// Server-side control logic: flow graphs that run continuously under the root
|
||||
// context, independent of any panel. The store is loaded from disk and the
|
||||
@@ -143,10 +185,10 @@ func main() {
|
||||
log.Error("failed to open control logic store", "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
ctrlEngine := controllogic.NewEngine(ctx, brk, ctrlStore, log)
|
||||
ctrlEngine := controllogic.NewEngine(ctx, brk, ctrlStore, recorder, log)
|
||||
ctrlEngine.Reload()
|
||||
|
||||
srv := server.New(cfg.Server.Listen, webFS, brk, synthDS, store, policy, aclStore, ctrlStore, ctrlEngine, cfg.Datasource.EPICS.ChannelFinderURL, cfg.Datasource.EPICS.ArchiveURL, cfg.Server.TrustedUserHeader, log)
|
||||
srv := server.New(cfg.Server.Listen, webFS, brk, synthDS, store, policy, aclStore, ctrlStore, ctrlEngine, recorder, cfg.Datasource.EPICS.ChannelFinderURL, cfg.Datasource.EPICS.ArchiveURL, cfg.Server.TrustedUserHeader, log)
|
||||
|
||||
if err := srv.Start(ctx); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "server error: %v\n", err)
|
||||
|
||||
Reference in New Issue
Block a user