feat: added activity log

This commit is contained in:
2026-06-10 14:17:33 +02:00
parent 96f1a40266
commit 0442e4f699
16 changed files with 1027 additions and 579 deletions

View File

@@ -74,6 +74,23 @@ func InitDB(filepath string) error {
expires_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS activity_logs (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL DEFAULT '',
username TEXT NOT NULL DEFAULT '',
action TEXT NOT NULL,
entity_type TEXT NOT NULL DEFAULT '',
entity_id TEXT NOT NULL DEFAULT '',
details TEXT NOT NULL DEFAULT '',
method TEXT NOT NULL DEFAULT '',
path TEXT NOT NULL DEFAULT '',
status_code INTEGER NOT NULL DEFAULT 0,
success INTEGER NOT NULL DEFAULT 0,
ip_address TEXT NOT NULL DEFAULT '',
user_agent TEXT NOT NULL DEFAULT '',
created_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
@@ -121,6 +138,10 @@ func InitDB(filepath string) error {
return err
}
if err := ensureActivityLogIndexes(); err != nil {
return err
}
return nil
}
@@ -139,6 +160,97 @@ func ensureUserTwoFactorColumns() error {
return nil
}
func ensureActivityLogIndexes() error {
indexes := []string{
"CREATE INDEX IF NOT EXISTS idx_activity_logs_user_created ON activity_logs(user_id, created_at DESC)",
"CREATE INDEX IF NOT EXISTS idx_activity_logs_created ON activity_logs(created_at DESC)",
"CREATE INDEX IF NOT EXISTS idx_activity_logs_action ON activity_logs(action)",
}
for _, stmt := range indexes {
if _, err := DB.Exec(stmt); err != nil {
return err
}
}
return nil
}
// Activity logs
func AddActivityLog(entry models.ActivityLogEntry) error {
if DB == nil {
return errors.New("db not initialized")
}
if entry.ID == "" {
entry.ID = utils.GenerateUUID()
}
if entry.CreatedAt == 0 {
entry.CreatedAt = time.Now().Unix()
}
success := 0
if entry.Success {
success = 1
}
_, err := DB.Exec(`
INSERT INTO activity_logs(
id, user_id, username, action, entity_type, entity_id, details,
method, path, status_code, success, ip_address, user_agent, created_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`, entry.ID, entry.UserID, entry.Username, entry.Action, entry.EntityType, entry.EntityID, entry.Details,
entry.Method, entry.Path, entry.StatusCode, success, entry.IPAddress, entry.UserAgent, entry.CreatedAt)
return err
}
func ListActivityLogs(userID string, includeAll bool, limit, offset int) ([]models.ActivityLogEntry, error) {
if DB == nil {
return nil, errors.New("db not initialized")
}
if limit <= 0 {
limit = 50
}
if limit > 100 {
limit = 100
}
if offset < 0 {
offset = 0
}
query := `
SELECT id, user_id, username, action, entity_type, entity_id, details,
method, path, status_code, success, ip_address, user_agent, created_at
FROM activity_logs
`
args := []interface{}{}
if !includeAll {
query += " WHERE user_id = ?"
args = append(args, userID)
}
query += " ORDER BY created_at DESC, id DESC LIMIT ? OFFSET ?"
args = append(args, limit, offset)
rows, err := DB.Query(query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
logs := []models.ActivityLogEntry{}
for rows.Next() {
var entry models.ActivityLogEntry
var success int
if err := rows.Scan(
&entry.ID, &entry.UserID, &entry.Username, &entry.Action, &entry.EntityType, &entry.EntityID, &entry.Details,
&entry.Method, &entry.Path, &entry.StatusCode, &success, &entry.IPAddress, &entry.UserAgent, &entry.CreatedAt,
); err != nil {
return nil, err
}
entry.Success = success == 1
logs = append(logs, entry)
}
return logs, rows.Err()
}
// Users
func AddUser(user *models.User) error {
_, err := DB.Exec("INSERT INTO users(id, username, password, role) VALUES (?, ?, ?, ?)", user.ID, strings.ToLower(user.Username), user.Password, user.Role)