feat: added activity log
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user