package hammerhead import ( "bufio" "encoding/json" "os" "path/filepath" "time" "git.veillax.com/Veillax/reef/model" ) type AuditEntry struct { ID int64 `json:"id"` Time time.Time `json:"time"` OrgID string `json:"orgId,omitempty"` Actor string `json:"actor"` Action string `json:"action"` Detail string `json:"detail,omitempty"` } // logStore is a thin wrapper so the handlers don't care where logs live. type logStore struct{ db *DB } func (l *logStore) addAccess(es []model.LogEntry) { l.db.addAccess(es) } func (l *logStore) addAudit(e AuditEntry) { l.db.addAudit(e) } func (l *logStore) queryAccess(f accessFilter) []model.LogEntry { return l.db.queryAccess(f) } // queryAudit returns newest-first entries; org "" selects server-level events. func (l *logStore) queryAudit(org string, limit int, before int64) []AuditEntry { return l.db.queryAudit(org, limit, before) } func (s *Server) audit(orgID, actor, action, detail string) { s.logs.addAudit(AuditEntry{Time: time.Now(), OrgID: orgID, Actor: actor, Action: action, Detail: detail}) } // importLegacyLogs moves logs from the old JSONL files into the database, once. func (s *Server) importLegacyLogs() { dir := filepath.Join(s.dir, "logs") read := func(name string, each func([]byte)) { path := filepath.Join(dir, name) f, err := os.Open(path) if err != nil { return } sc := bufio.NewScanner(f) sc.Buffer(make([]byte, 1<<20), 1<<20) for sc.Scan() { each(append([]byte(nil), sc.Bytes()...)) } f.Close() os.Rename(path, path+".migrated") } var batch []model.LogEntry read("access.jsonl", func(b []byte) { var e model.LogEntry if json.Unmarshal(b, &e) == nil { batch = append(batch, e) } }) s.db.addAccess(batch) read("audit.jsonl", func(b []byte) { var e AuditEntry if json.Unmarshal(b, &e) == nil { s.db.addAudit(e) } }) }