feat: implement legacy operation logging
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
|||||||
"chfs-ng/internal/api"
|
"chfs-ng/internal/api"
|
||||||
"chfs-ng/internal/auth"
|
"chfs-ng/internal/auth"
|
||||||
"chfs-ng/internal/config"
|
"chfs-ng/internal/config"
|
||||||
|
"chfs-ng/internal/opslog"
|
||||||
"chfs-ng/internal/storage"
|
"chfs-ng/internal/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -67,7 +68,7 @@ func main() {
|
|||||||
if len(cfg.Path) == 1 {
|
if len(cfg.Path) == 1 {
|
||||||
store = storage.Local{Root: root}
|
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)
|
addr := ":" + itoa(cfg.Port)
|
||||||
log.Printf("chfs-ng listening on %s root=%s removeMode=%d", addr, filepath.Clean(root), cfg.FileRemove)
|
log.Printf("chfs-ng listening on %s root=%s removeMode=%d", addr, filepath.Clean(root), cfg.FileRemove)
|
||||||
if cfg.SSLCert != "" && cfg.SSLKey != "" {
|
if cfg.SSLCert != "" && cfg.SSLKey != "" {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"chfs-ng/internal/auth"
|
"chfs-ng/internal/auth"
|
||||||
|
"chfs-ng/internal/opslog"
|
||||||
"chfs-ng/internal/storage"
|
"chfs-ng/internal/storage"
|
||||||
"github.com/emersion/go-webdav"
|
"github.com/emersion/go-webdav"
|
||||||
)
|
)
|
||||||
@@ -27,6 +28,7 @@ type Server struct {
|
|||||||
Allow string
|
Allow string
|
||||||
MultiRoot bool
|
MultiRoot bool
|
||||||
RemoveMode int
|
RemoveMode int
|
||||||
|
Log *opslog.Logger
|
||||||
}
|
}
|
||||||
type fileInfo struct {
|
type fileInfo struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@@ -68,6 +70,26 @@ func account(r *http.Request, s *Server) *auth.Account {
|
|||||||
}
|
}
|
||||||
return s.Auth.Guest
|
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) {
|
func writeJSON(w http.ResponseWriter, v any) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
json.NewEncoder(w).Encode(v)
|
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)
|
http.Error(w, e.Error(), 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
s.logOp(r, fmt.Sprintf("created directory:'%s'", p))
|
||||||
writeJSON(w, map[string]any{"ok": true})
|
writeJSON(w, map[string]any{"ok": true})
|
||||||
}
|
}
|
||||||
func (s *Server) rename(w http.ResponseWriter, r *http.Request) {
|
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)
|
http.Error(w, e.Error(), 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
s.logOp(r, fmt.Sprintf("renamed '%s' to '%s'", old, neu))
|
||||||
writeJSON(w, map[string]any{"ok": true})
|
writeJSON(w, map[string]any{"ok": true})
|
||||||
}
|
}
|
||||||
func (s *Server) remove(w http.ResponseWriter, r *http.Request) {
|
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)
|
http.Error(w, e.Error(), 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
s.logOp(r, fmt.Sprintf("removed '%s'", strings.Trim(p, "/")))
|
||||||
}
|
}
|
||||||
writeJSON(w, map[string]any{"ok": true})
|
writeJSON(w, map[string]any{"ok": true})
|
||||||
}
|
}
|
||||||
@@ -256,6 +281,7 @@ func (s *Server) newtext(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
io.WriteString(f, r.FormValue("text"))
|
io.WriteString(f, r.FormValue("text"))
|
||||||
|
s.logOp(r, fmt.Sprintf("create a text file:'%s'", p))
|
||||||
writeJSON(w, map[string]any{"ok": true})
|
writeJSON(w, map[string]any{"ok": true})
|
||||||
}
|
}
|
||||||
func (s *Server) updatetext(w http.ResponseWriter, r *http.Request) {
|
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)
|
http.Error(w, e.Error(), 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
s.logOp(r, fmt.Sprintf("update text file:'%s'", p))
|
||||||
writeJSON(w, map[string]any{"ok": true})
|
writeJSON(w, map[string]any{"ok": true})
|
||||||
}
|
}
|
||||||
func (s *Server) upload(w http.ResponseWriter, r *http.Request) {
|
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)
|
saved = append(saved, h.Filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, name := range saved {
|
||||||
|
s.logOp(r, fmt.Sprintf("upload '%s'", path.Join(dir, name)))
|
||||||
|
}
|
||||||
w.WriteHeader(http.StatusCreated)
|
w.WriteHeader(http.StatusCreated)
|
||||||
writeJSON(w, map[string]any{"ok": true, "files": saved})
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
s.logOp(r, fmt.Sprintf("download directory '%s'", p))
|
||||||
if err := walk(p, ""); err != nil {
|
if err := walk(p, ""); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user