diff --git a/chfs-ng/cmd/chfs/main.go b/chfs-ng/cmd/chfs/main.go index cd1a832..991f77d 100644 --- a/chfs-ng/cmd/chfs/main.go +++ b/chfs-ng/cmd/chfs/main.go @@ -11,6 +11,7 @@ import ( "chfs-ng/internal/api" "chfs-ng/internal/auth" "chfs-ng/internal/config" + "chfs-ng/internal/opslog" "chfs-ng/internal/storage" ) @@ -67,7 +68,7 @@ func main() { if len(cfg.Path) == 1 { store = storage.Local{Root: root} } - srv := &api.Server{Store: store, Auth: mgr, Sessions: map[string]*auth.Account{}, WebDAVRoot: root, Allow: cfg.Allow, MultiRoot: len(cfg.Path) > 1, RemoveMode: cfg.FileRemove} + srv := &api.Server{Store: store, Auth: mgr, Sessions: map[string]*auth.Account{}, WebDAVRoot: root, Allow: cfg.Allow, MultiRoot: len(cfg.Path) > 1, RemoveMode: cfg.FileRemove, Log: opslog.New(cfg.Log)} addr := ":" + itoa(cfg.Port) log.Printf("chfs-ng listening on %s root=%s removeMode=%d", addr, filepath.Clean(root), cfg.FileRemove) if cfg.SSLCert != "" && cfg.SSLKey != "" { diff --git a/chfs-ng/internal/api/server.go b/chfs-ng/internal/api/server.go index 548051d..1a54d14 100644 --- a/chfs-ng/internal/api/server.go +++ b/chfs-ng/internal/api/server.go @@ -15,6 +15,7 @@ import ( "time" "chfs-ng/internal/auth" + "chfs-ng/internal/opslog" "chfs-ng/internal/storage" "github.com/emersion/go-webdav" ) @@ -27,6 +28,7 @@ type Server struct { Allow string MultiRoot bool RemoveMode int + Log *opslog.Logger } type fileInfo struct { Name string `json:"name"` @@ -68,6 +70,26 @@ func account(r *http.Request, s *Server) *auth.Account { } return s.Auth.Guest } + +func (s *Server) logOp(r *http.Request, action string) { + if s.Log == nil { + return + } + a := account(r, s) + user := "" + if a != nil { + user = a.Username + } + _ = s.Log.Write(clientIPString(r), user, action) +} + +func clientIPString(r *http.Request) string { + ip := clientIP(r) + if ip == nil { + return "-" + } + return ip.String() +} func writeJSON(w http.ResponseWriter, v any) { w.Header().Set("Content-Type", "application/json; charset=utf-8") json.NewEncoder(w).Encode(v) @@ -140,6 +162,7 @@ func (s *Server) newdir(w http.ResponseWriter, r *http.Request) { http.Error(w, e.Error(), 500) return } + s.logOp(r, fmt.Sprintf("created directory:'%s'", p)) writeJSON(w, map[string]any{"ok": true}) } func (s *Server) rename(w http.ResponseWriter, r *http.Request) { @@ -154,6 +177,7 @@ func (s *Server) rename(w http.ResponseWriter, r *http.Request) { http.Error(w, e.Error(), 500) return } + s.logOp(r, fmt.Sprintf("renamed '%s' to '%s'", old, neu)) writeJSON(w, map[string]any{"ok": true}) } func (s *Server) remove(w http.ResponseWriter, r *http.Request) { @@ -173,6 +197,7 @@ func (s *Server) remove(w http.ResponseWriter, r *http.Request) { http.Error(w, e.Error(), 500) return } + s.logOp(r, fmt.Sprintf("removed '%s'", strings.Trim(p, "/"))) } writeJSON(w, map[string]any{"ok": true}) } @@ -256,6 +281,7 @@ func (s *Server) newtext(w http.ResponseWriter, r *http.Request) { } defer f.Close() io.WriteString(f, r.FormValue("text")) + s.logOp(r, fmt.Sprintf("create a text file:'%s'", p)) writeJSON(w, map[string]any{"ok": true}) } func (s *Server) updatetext(w http.ResponseWriter, r *http.Request) { @@ -277,6 +303,7 @@ func (s *Server) updatetext(w http.ResponseWriter, r *http.Request) { http.Error(w, e.Error(), 500) return } + s.logOp(r, fmt.Sprintf("update text file:'%s'", p)) writeJSON(w, map[string]any{"ok": true}) } func (s *Server) upload(w http.ResponseWriter, r *http.Request) { @@ -305,6 +332,9 @@ func (s *Server) upload(w http.ResponseWriter, r *http.Request) { saved = append(saved, h.Filename) } } + for _, name := range saved { + s.logOp(r, fmt.Sprintf("upload '%s'", path.Join(dir, name))) + } w.WriteHeader(http.StatusCreated) writeJSON(w, map[string]any{"ok": true, "files": saved}) } @@ -515,6 +545,7 @@ func (s *Server) downloadDir(w http.ResponseWriter, r *http.Request) { } return nil } + s.logOp(r, fmt.Sprintf("download directory '%s'", p)) if err := walk(p, ""); err != nil { return } diff --git a/chfs-ng/internal/opslog/opslog.go b/chfs-ng/internal/opslog/opslog.go new file mode 100644 index 0000000..a0842a1 --- /dev/null +++ b/chfs-ng/internal/opslog/opslog.go @@ -0,0 +1,39 @@ +package opslog + +import ( + "fmt" + "os" + "path/filepath" + "sync" + "time" +) + +type Logger struct { + dir string + mu sync.Mutex +} + +func New(dir string) *Logger { + if dir == "" { + return nil + } + return &Logger{dir: dir} +} + +func (l *Logger) Write(ip, user, action string) error { + if l == nil || l.dir == "" { + return nil + } + l.mu.Lock() + defer l.mu.Unlock() + if err := os.MkdirAll(l.dir, 0755); err != nil { + return err + } + f, err := os.OpenFile(filepath.Join(l.dir, "ops.log"), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) + if err != nil { + return err + } + defer f.Close() + _, err = fmt.Fprintf(f, "%s - %s - user(%s) %s\\n", time.Now().Format("2006-01-02 15:04:05"), ip, user, action) + return err +}