src/controllers/user.controller.ts, src/models/user.model.ts
User creation (admin)
- Admin calls
POST /api/userwith profile, role, andpageAccessObjectIds. - If email exists and is soft-deleted, user is restored with new credentials.
- If MFA is enabled at creation, a TOTP secret is generated via
speakeasy. - Password is bcrypt-hashed on save.
Login flow
Login request
Session rules
loginTokenon the user document must match the JWT on every authenticated request.isLoggedInprevents concurrent sessions unlessisForceLoginis used.IGNORE_EMAILenv var bypasses single-session check for a designated email.
MFA flow
Check MFA status
POST /api/user/check-mfa with { email } returns { isMfaEnabled: user.isMfaVerified }.
Enable MFA (admin update)
WhenisMfaEnabled: true is set via PUT /api/user:
- If no secret exists,
speakeasy.generateSecretcreates one. isMfaVerifiedis reset tofalseuntil OTP is confirmed.
Verify MFA
POST /api/user/verify-mfa (authenticated) with { otp }:
- Validates TOTP against
mfaSecret(±30s window). - Sets
isMfaVerified: true.
MFA login
Users withisMfaVerified: true submit their TOTP code as the password field at login. No separate OTP endpoint is needed for login itself.
Token verification
GET /api/user/verifyToken returns the full user document with populated pageAccess. Used by the frontend on app bootstrap to restore session state.
Logout
POST /api/user/logout/:id clears loginToken and sets isLoggedIn: false.
Password management
Passwords must match pattern
^[a-zA-Z0-9!@#$%^&*_=+-]{3,30}$ with length 6–20.
Soft delete
DELETE /api/user/:id sets:
deleted: trueisActive: falseisLoggedIn: falseloginToken: null
findOne queries.
Active / inactive toggle
PATCH /api/user/activeInactive/:id flips isActive. Inactive non-admin users cannot log in.
UI preferences
Stored on the user document and updated viaPUT /api/user:
Changes emit
userSettingUpdated via Socket.IO for real-time sync.