# 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.