mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
130 lines
3.4 KiB
Markdown
130 lines
3.4 KiB
Markdown
# User Activity Controller Documentation
|
|
|
|
**File:** `controllers/admin/user_activity.controller.js`
|
|
**Base URL:** `/api/admin/activity` and `/api/admin/users/:id/activity`
|
|
**Guards:** `authenticate → requireAdmin() → adminLimiter`
|
|
|
|
---
|
|
|
|
## Table of Contents
|
|
- [Get Global Activity Feed](#get-global-activity-feed)
|
|
- [Get Per-User Activity](#get-per-user-activity)
|
|
|
|
---
|
|
|
|
## Notes
|
|
|
|
- `user_activity` rows are **never soft-deleted** — this is an append-only audit log.
|
|
- `created_at` is the timestamp column (no `createdAt` alias — Sequelize `timestamps: false`).
|
|
- The global feed endpoint joins the `users` table and enriches each row with `full_name` and `avatar_url`.
|
|
- The per-user endpoint skips the join for performance since user context is already known.
|
|
|
|
---
|
|
|
|
## Activity Object Shape
|
|
|
|
```json
|
|
{
|
|
"activity_id": 1,
|
|
"user_id": 42,
|
|
"email": "user@example.com",
|
|
"full_name": "Kenneth Obsequio",
|
|
"avatar_url": "https://...",
|
|
"acc_type": "admin",
|
|
"action": "login",
|
|
"entity_type": "session",
|
|
"entity_id": 7,
|
|
"details": { "session_id": 7, "reg_type": "system" },
|
|
"created_at": "2026-06-21T08:00:00.000Z"
|
|
}
|
|
```
|
|
|
|
### Common `action` Values
|
|
| Action | Entity Type | Details Keys |
|
|
|--------|-------------|--------------|
|
|
| `login` | `session` | `session_id`, `reg_type` |
|
|
| `deactivate_user` | `user` | `target_email` |
|
|
| `lesson_read` | `lesson` | `lesson_uuid`, `status` |
|
|
| `submit_task` | `task` | `task_id` |
|
|
| `set_user_status` | `user` | `is_active` |
|
|
| `create_course` | `course` | `title` |
|
|
| `update_course` | `course` | `title` |
|
|
| `archive_course` | `course` | — |
|
|
| `create_task_list` | `task_list` | `name` |
|
|
| `create_advertisement` | `advertisement` | `type` |
|
|
| `grant_tier` | `tier` | `user_id`, `tier`, `plan_id` |
|
|
| `revoke_tier` | `tier` | `user_id`, `tier` |
|
|
|
|
---
|
|
|
|
## Get Global Activity Feed
|
|
|
|
**`GET /api/admin/activity`**
|
|
|
|
Returns a paginated, reverse-chronological feed of all user activity across the system.
|
|
|
|
### Query Parameters
|
|
| Parameter | Type | Required | Description |
|
|
|-----------|--------|----------|-------------|
|
|
| `page` | number | No | Default: `1` |
|
|
| `limit` | number | No | Default: `20`, max: `100` |
|
|
| `action` | string | No | Filter by exact action string (e.g. `login`) |
|
|
| `from` | date | No | ISO date — `created_at >= from` |
|
|
| `to` | date | No | ISO date — `created_at <= to` |
|
|
|
|
### Response `200`
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"message": "Activity feed retrieved.",
|
|
"data": {
|
|
"total": 500,
|
|
"page": 1,
|
|
"totalPages": 25,
|
|
"activities": [ ... ]
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Get Per-User Activity
|
|
|
|
**`GET /api/admin/users/:id/activity`**
|
|
|
|
Returns a paginated, reverse-chronological activity log for a single user.
|
|
|
|
### Query Parameters
|
|
Same as global feed (`page`, `limit`, `action`, `from`, `to`).
|
|
|
|
### Response `200`
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"message": "User activity retrieved.",
|
|
"data": {
|
|
"total": 45,
|
|
"page": 1,
|
|
"totalPages": 3,
|
|
"activities": [
|
|
{
|
|
"activity_id": 1,
|
|
"user_id": 42,
|
|
"session_id": null,
|
|
"action": "update_course",
|
|
"entity_type": "course",
|
|
"entity_id": 3,
|
|
"details": { "title": "Advanced JS" },
|
|
"created_at": "2026-06-21T09:00:00.000Z"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Error Responses
|
|
| Status | Message |
|
|
|--------|---------|
|
|
| `400` | `Invalid User ID.` |
|
|
| `404` | `User not found.` |
|