User Management (Admin)
Admin tools for creating, filtering, editing, deleting, exporting, and inspecting users — including direct credential edits and cross-service filters
User Management (Admin)
The User Management area is an admin-only surface where administrators create, filter, edit, monitor, and (soft-)delete platform users.
Accessing User Management
- Sign in as an Admin or Instructor with user management permissions.
- Navigate to Admin → Users (
/admin/users). - Required permission:
user.listto view,user.viewto open profiles.
There are also dedicated sub-lists:
| Page | Path |
|---|---|
| All users | /admin/users |
| Learners | /admin/users/learners |
| Admins | /admin/users/admins |
| Instructors | /admin/users/instructors |
| Roles & Permissions | /admin/users/roles |
User List
A comprehensive, filterable, paginated table of all platform users (GET /v1/users).
Available Columns
- Name and avatar
- Email, phone, username, unique ID
- Status (
active,inactive,suspended,pending_verification,deleted) - User type flags (
is_admin,is_instructor,is_learner) - Roles
- Registration date, last login
Filtering Users
The user list backs onto a rich UserFilters DTO (see auth-service/dto/user.go). Filters can be combined freely.
Identity & status:
| Filter | Description |
|---|---|
| Search | Fuzzy match across name, email, phone, username, unique ID |
| Status / Statuses | One or many of: active, inactive, suspended, pending_verification, deleted |
| User type | Admin, Instructor, Learner (is_admin, is_instructor, is_learner) |
| Verification | email_verified, phone_verified |
| Auth method | email, phone, oauth |
| OAuth | has_oauth, oauth_provider (google / facebook / github / apple) |
| Has password set | has_password |
| Roles | Filter by assigned role(s) |
Profile & demographics:
| Filter | Description |
|---|---|
| Profile complete | profile_complete=true/false (uses backend completeness scoring) |
| Has avatar / bio / location | Boolean filters |
| Country / city / state / continent / timezone / locale | Geographic filters |
| Gender, designation, expertise, age min/max | Demographic filters |
Activity:
| Filter | Description |
|---|---|
created_after / created_before | Date range on registration |
created_in_last_days | "registered within last N days" |
last_login_after / last_login_before / active_in_last_days / inactive_for_days | Activity windows |
is_locked, failed_login_attempts_min, failed_login_attempts_max | Account security state |
Cross-Service Filters
The user list joins data from other microservices when those service databases are reachable:
| Filter | Source service | Description |
|---|---|---|
has_enrollments | Learning | Users with at least one enrollment |
enrollment_status | Learning | active, completed, cancelled, expired, suspended |
enrolled_program_type, enrolled_program_ids | Learning | Filter to specific course/program types or IDs |
progress_min, progress_max | Learning | Learners within a progress range |
total_time_spent_min | Learning | Minimum aggregate learning time |
last_learning_activity_after | Learning | Active in learning since a given date |
Cross-service filters require the auth-service to have a working DB connection to the learning-service database. Failures are non-fatal — affected filters are simply skipped.
Filter Values & Suggestions
GET /v1/users/filter-values— returns all available values for static filters (statuses, roles, countries, oauth_providers, auth_methods, etc.).GET /v1/users/field-values— paginated dynamic field-value lookup for autocomplete (e.g. while typing a designation).
Sorting & Pagination
Sort by name, email, registration date, last login, or status. Page size is configurable; total count is returned with each page.
Creating a New User
Admins can create user accounts directly without registration.
- Click Create User at
/admin/users/create(requiresuser.create). - Fill in the form:
| Field | Required | Notes |
|---|---|---|
| Name | Yes | Display name |
| Conditional | Required if no phone | |
| Phone | Conditional | Required if no email |
| Username | No | 3+ chars, lowercase letters/digits/.-_, unique per tenant |
| Password | No | If omitted, the user must reset before logging in |
| Status | Yes | Default: active |
| User type flags | At least one | is_admin, is_instructor, is_learner |
| Roles | Required for admin/instructor | Pick at least one role for those types |
| Direct permissions | No | Optional one-off grants |
- Click Create.
API: POST /v1/users.
Editing a User
Open a user's edit form at /admin/users/{userID}/edit/edit-user (requires user.update). The edit form is split into multiple tabs:
| Tab | Path | What it does |
|---|---|---|
| Overview | …/edit/overview | Profile snapshot |
| Edit user | …/edit/edit-user | Main form (name, email, phone, username, password, status, roles, profile fields) |
| Sessions | …/edit/users-sessions | View / terminate sessions |
| Impersonation | …/edit/impersonation | Start impersonation or masquerade |
| Audit logs & admin notes | …/edit/audit-logs-admin-notes | Per-user audit trail |
| Unique ID generation | …/edit/unique-id-generation | Generate or update unique ID |
| Account deletion | …/edit/account-deletation | Initiate user account deletion |
Admin Direct Credential Edits
The edit form lets admins change another user's email, phone, username, or password directly — no OTP, no password-reset email, no user consent required. This is intentionally privileged: admins are trusted to perform out-of-band identity verification.
- Endpoint:
PUT /v1/users/{user_id}(requiresuser.update) - Affected fields:
email,phone,username,password - A successful credential change is published as an audit event so the admin who performed it is recorded.
- Best practice: terminate the user's existing sessions after a password change so any stale tokens stop working.
Updating Status
Status changes flow through the same edit endpoint — set status to one of:
| Value | Effect |
|---|---|
pending_verification | Forces the user back through email/phone verification on next login |
active | Normal operating state |
inactive | Temporarily disables login |
suspended | Disables login with a "suspended" message |
deleted | Soft delete — same effect as user-initiated deletion |
Updating Unique ID
Open the Unique ID Generation tab to assign or change a user's tenant-unique identifier.
- Endpoint:
PUT /v1/users/{user_id}/unique-id(requiresuser.update)
Deleting Users
Single User Delete
- Click Delete in the user row or from the user's edit page (requires
user.delete). - Confirm.
- The user is soft-deleted (
deleted_atset, status set todeleted). - All sessions are terminated.
API: DELETE /v1/users/{user_id}.
Bulk Delete
- Apply filters or select multiple users.
- Click Bulk Delete (requires
user.delete). - Confirm.
API: DELETE /v1/users/bulk/delete.
See Account Deletion for what soft-delete preserves and how reactivation works.
Exporting Users
Export user data as a CSV for reporting or external analysis.
- Apply your filters (the export respects current filters).
- Click Export (requires
user.export). - A CSV download includes name, email, phone, username, status, user type, registration / last login timestamps, country, timezone, and all profile fields.
API: GET /v1/users/bulk/export.
Managing User Sessions (Admin)
From the Sessions tab on a user's edit page:
- View all active sessions with device + IP-geolocation details.
- Terminate a single session:
DELETE /v1/users/{user_id}/sessions/{session_id} - Terminate all of a user's sessions:
DELETE /v1/users/{user_id}/sessions
Both require user.update.
OAuth Account Linking (Admin)
Admins can link/unlink OAuth providers programmatically:
- Link:
POST /v1/users/{user_id}/oauth/link - Unlink:
POST /v1/users/{user_id}/oauth/unlink
These accept a provider_user_id and are intended for scripted account migration rather than ad-hoc UI use, since admins typically don't have the user's raw provider ID.
User Statistics & Analytics
Available straight from the user-management area:
| Endpoint | Use |
|---|---|
GET /v1/users/stats | Counts by status, type, verification, recent registrations |
GET /v1/users/analytics/overview | Quick stats dashboard (period-over-period) |
GET /v1/users/analytics/growths | Daily / weekly / monthly growth time series |
See User Analytics for details. Backed by the mv_user_quick_stats materialized view, refreshed every 2 minutes.
System API (Inter-Service)
The auth-service exposes system-protected APIs (separate auth scheme via system token, not user JWT) for other microservices to consume:
| Endpoint | Purpose |
|---|---|
POST /v1/system/users/get-or-create | Idempotent upsert by email/phone — used during invitations and cross-service user resolution |
GET /v1/system/users/search | Cross-service user search |
GET /v1/system/users/by-ids | Batch fetch by ID list |
POST /v1/system/users/{user_id}/roles | Assign roles |
POST /v1/system/users/{user_id}/permissions | Assign direct permissions |
PATCH /v1/system/users/{user_id}/flags | Set is_admin / is_instructor / is_learner |
GET /v1/system/roles | Look up role by name |
These are not accessible to regular users.
Troubleshooting
| Issue | Solution |
|---|---|
| Can't see User Management | Ensure you have user.list |
| Can't create users | Ensure you have user.create |
| Can't delete users | Ensure you have user.delete |
| Export not working | Ensure you have user.export, and try fewer filters |
| Cross-service filters return nothing | The learning-service DB may be unreachable — check service health |
| Direct password edit didn't end the user's existing sessions | Terminate sessions explicitly from the Sessions tab |
| Bulk filters slow | Cross-service joins (enrollment, progress) can be slow on large datasets — narrow the time window first |
Roles & Permissions (RBAC)
Role-Based Access Control system for managing user access — roles, permissions, direct assignments, and how checks happen
User Impersonation
Admin feature to log in as another user for support and debugging — supports two modes: read-only Impersonation and full-access Masquerade

