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

@@ -6,7 +6,7 @@ MiauInv uses SQLite for persistent storage. The schema is initialized in `storag
PRAGMA foreign_keys = ON;
```
The database stores users, refresh tokens, 2FA recovery codes, passkey credentials, passkey challenge state, inventory items, locations, projects, stock mappings, and project allocations.
The database stores users, refresh tokens, 2FA recovery codes, passkey credentials, passkey challenge state, activity log entries, inventory items, locations, projects, stock mappings, and project allocations.
## Entity Overview
@@ -14,6 +14,7 @@ The database stores users, refresh tokens, 2FA recovery codes, passkey credentia
[users] 1 ──── N [refresh_tokens]
[users] 1 ──── N [two_factor_recovery_codes]
[users] 1 ──── N [passkey_credentials]
[users] 1 ──── N [activity_logs]
[passkey_challenges] stores short-lived WebAuthn ceremony state
@@ -96,6 +97,30 @@ Stores short-lived server-side WebAuthn session data for registration and login
Challenge rows are consumed once during the finish step and expired rows are cleaned up opportunistically.
### `activity_logs`
Stores account, authentication, security, and inventory activity metadata. Request bodies, passwords, TOTP codes, recovery codes, passkey payloads, and token values are not stored.
| Column | Type | Constraints | Description |
| --- | --- | --- | --- |
| `id` | `TEXT` | Primary key | Activity row UUID. |
| `user_id` | `TEXT` | Not null, default `''` | User associated with the activity. Empty for unknown-user failed login attempts. |
| `username` | `TEXT` | Not null, default `''` | Username known at the time of the event. |
| `action` | `TEXT` | Not null | Normalized action name, for example `auth.login.succeeded` or `inventory.update`. |
| `entity_type` | `TEXT` | Not null, default `''` | Logical entity, for example `auth`, `security`, `item`, `location`, or `project`. |
| `entity_id` | `TEXT` | Not null, default `''` | Optional target ID when available. |
| `details` | `TEXT` | Not null, default `''` | Short sanitized status summary. |
| `method` | `TEXT` | Not null, default `''` | HTTP method. |
| `path` | `TEXT` | Not null, default `''` | Request path without query parameters. |
| `status_code` | `INTEGER` | Not null, default `0` | Final HTTP status code. |
| `success` | `INTEGER` | Not null, default `0` | Boolean success flag derived from the status code. |
| `ip_address` | `TEXT` | Not null, default `''` | Client IP address, considering common reverse-proxy headers. |
| `user_agent` | `TEXT` | Not null, default `''` | User-Agent metadata. |
| `created_at` | `INTEGER` | Not null | Unix timestamp for the event. |
Indexes are created for per-user timeline lookups, global timestamp ordering, and action filtering. Non-admin users can only read their own activity through `/api/activity`. Admin users can request all activity with `?all=true`.
### `items`
Stores tracked inventory items.