users MongoDB collection.
Code: routes/auth.py, routes/users.py, auth/jwt.py, auth/deps.py, models/user.py.
JWT
auth/jwt.py signs an HS-family JWT with settings.jwt_secret/jwt_algorithm:
| Claim | Value |
|---|---|
sub | user email |
role | role string |
name | display name |
exp | now + jwt_expire_minutes |
get_current_user (auth/deps.py) decodes the bearer token, then re-reads the user from MongoDB on every request — so a deactivated or deleted user is rejected immediately even with a still-valid token. The role used for authorization comes from the database record, not the token claim.
Login & self-service
Under/api/v1/auth:
| Method | Path | Auth | Purpose |
|---|---|---|---|
POST | /login | none | Email + password → access_token. 401 on bad credentials or is_active=false. |
POST | /register | admin+ | Create a user (rank-gated, see below) |
GET | /me | any | Current profile |
PUT | /me | any | Update own name |
PUT | /me/password | any | Change own password (verifies current) |
auth/password.py (hash_password/verify_password); raw passwords are never stored.
Role hierarchy
ROLE_RANK (routes/users.py):
| Role | Rank | Typical use |
|---|---|---|
agent | 0 | Agent Desk operator |
supervisor | 1 | Monitors/barge, Agent Assist manager |
admin | 2 | Manage bots, campaigns, users |
super_admin | 3 | Carriers, integrations, delete users |
auth/deps.py: require_admin (admin or super_admin), require_super_admin (exact), require_agent_or_supervisor, require_supervisor, require_agent_assist_manager (admin/super_admin/supervisor), require_any_role.
The same-rank rule
The guard differs between creating/assigning a role and modifying an existing user:- Create / assign role (
register, role change inupdate_user): blocked only whenactor_rank < new_rank. A user may create or promote up to their own rank — e.g. asuper_admincan mint anothersuper_admin. - Modify another user (
_check_hierarchy, used by update/deactivate/reset-password): requiresactor_rank > target_rank(actor_rank <= target_rankis rejected). You cannot modify a peer or someone above you. - Self-modification is always allowed past
_check_hierarchy(the email-equality short-circuit), but you cannot delete or deactivate yourself.
User CRUD
Under/api/v1/users:
| Method | Path | Role | Notes |
|---|---|---|---|
GET | “ | admin | List users |
GET | /{user_id} | admin | Get user |
PUT | /{user_id} | admin | Update (hierarchy + role-rank guards; email uniqueness enforced) |
DELETE | /{user_id} | super_admin | Delete (cannot delete self) |
POST | /{user_id}/deactivate | admin | Toggle is_active (cannot deactivate self) |
POST | /{user_id}/reset-password | admin | Set new password (hierarchy-gated) |
departments, max_concurrent_calls, agent_languages, agent_primary_language) are normalised on write via normalise_agent_languages/normalise_agent_primary_language. Invalid user_id → 400; missing → 404.
Related docs
API keys
Non-JWT auth for CRM-triggered dialout.
Agent Desk
Where agent/supervisor roles are used at runtime.
Agent Assist
Assist-moment management (manager roles).
VoxBridge overview
Control-plane responsibilities.