Files
starr-philproperties/apps/api/controllers/admin/documentation/users.md
T

463 lines
11 KiB
Markdown

# Users Controller Documentation
**File:** `controllers/admin/users.controller.js`
**Base URL:** `/api/admin/users`
**Guards:** `authenticate → requireAdmin() → adminLimiter`
---
## Table of Contents
- [Get All Users](#get-all-users)
- [Get Single User](#get-single-user)
- [Add Staff User](#add-staff-user)
- [Update User](#update-user)
- [Deactivate User](#deactivate-user)
- [Bulk Deactivate Users](#bulk-deactivate-users)
- [Restore User](#restore-user)
- [Bulk Restore Users](#bulk-restore-users)
- [Get Archived Users](#get-archived-users)
- [Get User Field Values](#get-user-field-values)
- [Get User Sessions](#get-user-sessions)
- [Terminate Session](#terminate-session)
---
## Get All Users
**`GET /api/admin/users`**
Returns a paginated list of active users.
### Query Parameters
| Parameter | Type | Required | Description |
|-----------|--------|----------|--------------------------------------------------|
| page | number | No | Page number. Default: `1` |
| limit | number | No | Records per page. Default: `20` |
| search | string | No | Search across user fields |
| sort_by | string | No | Column to sort by. Default: `createdAt` |
| sort_dir | string | No | Sort direction: `ASC` or `DESC`. Default: `DESC` |
| filters | array | No | Column filters from DataTable |
### Response `200`
```json
{
"status": "success",
"message": "Users retrieved.",
"data": {
"rows": [
{
"user_id": 1,
"email": "john@example.com",
"acc_type": "admin",
"reg_type": "system",
"is_active": true,
"is_verified": true,
"personal_info": {
"name": {
"given_name": "John",
"middle_name": null,
"last_name": "Doe",
"extension_name": null,
"full_name": "John Doe"
},
"date_of_birth": null,
"occupation": null,
"addresses": [],
"phone_number": []
},
"groups": [],
"createdAt": "2025-01-01T00:00:00.000Z",
"updatedAt": "2025-01-01T00:00:00.000Z",
"deletedAt": null
}
],
"pagination": {
"total": 100,
"page": 1,
"limit": 20,
"totalPages": 5
}
}
}
```
---
## Get Single User
**`GET /api/admin/users/:id`**
Returns a single user with their group memberships.
### Path Parameters
| Parameter | Type | Required | Description |
|-----------|--------|----------|-------------|
| id | number | Yes | User ID |
### Response `200`
```json
{
"status": "success",
"message": "User retrieved.",
"data": {
"user_id": 1,
"email": "john@example.com",
"acc_type": "admin",
"is_active": true,
"is_verified": true,
"personal_info": { ... },
"groups": [
{ "group_id": 1, "name": "Administrators" }
],
"createdAt": "2025-01-01T00:00:00.000Z",
"updatedAt": "2025-01-01T00:00:00.000Z"
}
}
```
### Response `404`
```json
{
"status": "error",
"message": "User not found."
}
```
---
## Add Staff User
**`POST /api/admin/users/staff`**
Creates a new staff user with an auto-generated temporary password.
A welcome email is sent with the credentials and a 24-hour expiry notice.
The user is forced to change their password on first login.
### Request Body `application/json`
| Field | Type | Required | Description |
|-----------------------------|--------|----------|--------------------------------------|
| email | string | Yes | Staff user email address |
| personal_info.name.given_name | string | Yes | First name |
| personal_info.name.last_name | string | Yes | Last name |
| personal_info.name.middle_name | string | No | Middle name |
| personal_info.name.extension_name | string | No | Extension name e.g. `Jr.` |
| personal_info.date_of_birth | string | No | Date of birth |
| personal_info.occupation | string | No | Occupation |
### Response `201`
```json
{
"status": "success",
"message": "Staff user created successfully.",
"data": {
"user_id": 5,
"email": "staff@example.com",
"acc_type": "staff"
}
}
```
### Response `409`
```json
{
"status": "error",
"message": "Email is already in use."
}
```
---
## Update User
**`PUT /api/admin/users/:id`**
Updates a user's account type, active status, or personal information.
Admins cannot change their own `acc_type`.
### Path Parameters
| Parameter | Type | Required | Description |
|-----------|--------|----------|-------------|
| id | number | Yes | User ID |
### Request Body `application/json`
| Field | Type | Required | Description |
|--------------|---------|----------|----------------------------------------------|
| acc_type | string | No | `admin`, `staff`, `user` |
| is_active | boolean | No | Active status |
| personal_info | object | No | Personal information object |
### Response `200`
```json
{
"status": "success",
"message": "User updated.",
"data": { ...user }
}
```
### Response `400`
```json
{
"status": "error",
"message": "Admins cannot change their own role."
}
```
---
## Deactivate User
**`DELETE /api/admin/users/:id`**
Soft deletes a user by setting `deletedAt` and `is_active: false`.
All active sessions are force-terminated.
Admins cannot deactivate their own account.
### Path Parameters
| Parameter | Type | Required | Description |
|-----------|--------|----------|-------------|
| id | number | Yes | User ID |
### Response `200`
```json
{
"status": "success",
"message": "User deactivated successfully."
}
```
### Response `400`
```json
{
"status": "error",
"message": "You cannot deactivate your own account."
}
```
---
## Bulk Deactivate Users
**`DELETE /api/admin/users/bulk`**
Soft deletes multiple users at once.
Already-deactivated users are skipped and reported.
All active sessions for deactivated users are force-terminated.
### Request Body `application/json`
| Field | Type | Required | Description |
|-------|----------|----------|--------------------------|
| ids | number[] | Yes | Array of user IDs |
### Response `200`
```json
{
"status": "success",
"message": "3 user(s) deactivated successfully.",
"data": {
"deactivated_ids": [1, 2, 3],
"skipped_ids": [4]
}
}
```
---
## Restore User
**`POST /api/admin/users/:id/restore`**
Restores a soft-deleted user by clearing `deletedAt` and setting `is_active: true`.
### Path Parameters
| Parameter | Type | Required | Description |
|-----------|--------|----------|-------------|
| id | number | Yes | User ID |
### Response `200`
```json
{
"status": "success",
"message": "User restored successfully."
}
```
### Response `400`
```json
{
"status": "error",
"message": "User is not deactivated."
}
```
---
## Bulk Restore Users
**`POST /api/admin/users/bulk/restore`**
Restores multiple soft-deleted users at once.
Already-active users are skipped and reported.
### Request Body `application/json`
| Field | Type | Required | Description |
|-------|----------|----------|--------------------------|
| ids | number[] | Yes | Array of user IDs |
### Response `200`
```json
{
"status": "success",
"message": "3 user(s) restored successfully.",
"data": {
"restored_ids": [1, 2, 3],
"skipped_ids": [4]
}
}
```
---
## Get Archived Users
**`GET /api/admin/users/archived`**
Returns a paginated list of soft-deleted users.
### Query Parameters
Same as [Get All Users](#get-all-users).
### Response `200`
```json
{
"status": "success",
"message": "Archived users retrieved.",
"data": {
"rows": [ ...soft-deleted users ],
"pagination": { ... }
}
}
```
---
## Get User Field Values
**`GET /api/admin/users/field-values`**
Returns distinct values for a given column — used to populate filter dropdowns in the DataTable.
Supports regular columns, date fields, audit fields, and JSONB dot-notation.
### Query Parameters
| Parameter | Type | Required | Description |
|----------|--------|----------|------------------------------------------------------|
| field | string | Yes | Column name or JSONB path e.g. `personal_info.name.given_name` |
### Supported Field Types
| Type | Example | Returns |
|-------------|----------------------------------|--------------------------------|
| Regular | `acc_type` | Distinct string values |
| Date | `createdAt` | Distinct dates (no time) |
| Audit by | `createdBy` | Full names of referenced users |
| JSONB | `personal_info.name.given_name` | Distinct JSONB path values |
### Response `200`
```json
{
"status": "success",
"message": "Field values retrieved.",
"data": ["admin", "staff", "user"]
}
```
### Response `400`
```json
{
"status": "error",
"message": "Invalid or restricted field."
}
```
---
## Get User Sessions
**`GET /api/admin/users/:id/sessions`**
Returns all sessions for a specific user, ordered by most recent.
### Path Parameters
| Parameter | Type | Required | Description |
|-----------|--------|----------|-------------|
| id | number | Yes | User ID |
### Response `200`
```json
{
"status": "success",
"message": "Sessions retrieved.",
"data": [
{
"session_id": 1,
"user_id": 1,
"is_active": true,
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0...",
"createdAt": "2025-01-01T00:00:00.000Z",
"logout_info": null
}
]
}
```
---
## Terminate Session
**`DELETE /api/admin/users/:id/sessions/:sid`**
Force-terminates a specific user session.
### Path Parameters
| Parameter | Type | Required | Description |
|-----------|--------|----------|--------------|
| id | number | Yes | User ID |
| sid | number | Yes | Session ID |
### Response `200`
```json
{
"status": "success",
"message": "Session terminated."
}
```
### Response `404`
```json
{
"status": "error",
"message": "Session not found."
}
```
---
## Error Responses
All endpoints return the following on server error:
```json
{
"status": "error",
"message": "Internal server error."
}
```
---
## Notes
- **Excluded fields** — `password`, `otp_code`, `otp_expires_at`, `must_change_password`, `password_expires_at` are never returned in any response.
- **Soft delete** — deactivation sets `deletedAt` + `is_active: false`. Users are excluded from all queries unless explicitly queried with `paranoid: false`.
- **Session termination** — deactivating a user (single or bulk) always force-terminates all their active sessions.
- **Audit fields** — `createdBy`, `updatedBy`, `deletedBy` store the `user_id` of the admin who performed the action.