feat(auth, users): simplify login to book_no-based auth and add user identification endpoint
Merge Request
Overview
This MR simplifies the authentication flow by enforcing login strictly via book_no + password and introduces a new public endpoint to help users identify their accounts using phone_no + password.
It removes ambiguous multi-flow login logic and replaces it with a clear, secure, and user-friendly identification + login process.
What does this MR do and why?
Previously:
- Login supported both
phone_noandbook_no, leading to ambiguity. - Multiple users could share the same phone number, causing confusion.
- Forgot password flow had multiple branches and unnecessary complexity.
Now:
- Login is simplified to book_no + password only
- A new endpoint
/api/v1/users/detailsallows users to:- Enter
phone_no + password - Retrieve all associated accounts (book_no, name, age, role)
- Enter
- Forgot password flow is unified and simplified using
book_no
This improves:
- Clarity in authentication
- Security (no ambiguous login paths)
- Better UX for multi-account users
Changes Made
Authentication
-
Signup Flow (
action = signup)- OTP is sent only if the phone number is not already registered
- If user already exists → returns:
"User already exists. Please login or use forgot password"
- If phone_no is missing → returns:
"Provide phone_no to send otp"
-
Forgot Password Flow (
action = forgot_password)- OTP is sent only if the user exists for the given book_no
- If user does not exist → returns:
"User not found"
- If book_no is missing → returns:
"Provide book_no to send otp"
-
Response Improvement
- Phone number is now masked in response:
- Example:
******3210
- Example:
- Phone number is now masked in response:
New Endpoint
- Added
/api/v1/users/details(public endpoint)- Method: POST
- Input:
phone_no + password - Output:
- All users linked to the phone number:
book_nonameagerole
- All users linked to the phone number:
- No authentication required
Forgot Password Refactor
- Updated
/api/v1/auth/forgot-password- Removed dropdown and multiple flows
- Single unified flow for all users
- Input:
book_nouser_passwordconfirm_passwordotp
-
phone_nois now derived internally usingbook_no - Works for:
- First-time users
- Existing users resetting password
Swagger Improvements
- Removed unnecessary dropdowns
- Simplified examples for:
- login
- forgot-password
- Updated documentation for new endpoint
Technical Details
- Login logic now strictly queries user by
book_no - User identification endpoint:
- Validates password against any user linked to the phone number
- Returns all associated accounts after successful validation
- Forgot password:
- Fetches phone number internally from
book_no - Validates OTP against that phone number
- Fetches phone number internally from
- Removed legacy branching logic for roles and first-time login
Type of Change
-
🐛 Bug fix (non-breaking change that fixes an issue) -
✨ New feature (non-breaking change that adds functionality) -
💥 Breaking change (fix or feature that would cause existing functionality to change) -
📝 Documentation update -
♻ ️ Refactor (no functional changes) -
⚡ Performance improvement -
🧪 Test update -
🔧 Configuration change -
🚨 Security fix -
🗑 ️ Deprecation (removing deprecated code)
Related Issues / References
-closes #39 (closed)
Screenshots or Screen Recordings
Updated Swagger UI for:
- Login (book_no only)
- Forgot Password (single flow)
- Users Details endpoint (multi-account response)
How to Validate Locally
Previous Behavior
- Login allowed both phone_no and book_no
- Multiple users per phone caused ambiguity
- Forgot password had multiple flows
New Behavior
- Login:
- Use
book_no + password - Should return 200 on success
- Use
- User Identification:
- Call
/api/v1/users/details - Input: phone_no + password
- Should return all linked accounts
- Call
- Forgot Password:
- Use
book_no + otp + new password - Password should update successfully
- Use
Testing Done
-
Unit tests added/updated -
API endpoint tests passing
Test Cases Covered:
| Scenario | Expected Result | Status |
|---|---|---|
| Login with phone_no | Successful login | |
| Login with invalid password | Unauthorized | |
| Fetch users with phone_no | Returns all linked accounts | |
| Forgot password with valid OTP | Password updated | |
| Foorgot password with invalid OTP | Error response |
Test Commands Run:
# Example: Run all tests
pytest
# Example: Run specific test file
pytest tests/test_api_v1/test_patient_routes.py -v
# Example: Run with coverage
pytest --cov=app
Code Quality Checklist
Code Standards
-
Code follows project conventions (naming, structure, formatting) -
No debug statements or commented-out code left (unless necessary and intended) -
No unused imports, variables, or functions -
No duplicate code (DRY principle followed) -
Type hints are properly defined (no Anyunless justified and no mypy type check errors) -
Ruff checks pass: ruff check . ruff format . --check
Python & FastAPI Best Practices
-
Functions follow single-responsibility principle -
Async/await used correctly (no blocking calls in async functions) -
Dependency injection used appropriately -
Pydantic models used for request/response validation -
SQLAlchemy queries are optimized (no N+1 queries) -
Error handling is comprehensive (try/except with proper logging)
API Design
-
RESTful conventions followed -
Proper HTTP status codes returned -
Input validation implemented -
Authentication/authorization enforced -
Role Base access control used for user restriction -
API documentation (docstrings) updated
Database & Migrations
-
Database migrations created (if schema changed) -
Database migrations version is pointing to the latest version (and version name follows project conventions) -
Migrations are reversible (migrations contain downgrade scripts) -
Indexes added for frequently queried fields -
No raw SQL queries (using SQLAlchemy ORM) -
Data integrity constraints maintained
Security
-
No sensitive data logged (passwords, tokens, PII) -
SQL injection prevention verified (ORM used) -
Input sanitization implemented -
Authentication tokens handled securely -
CORS settings appropriate -
Security scan passes: bandit -r app/
Error Handling
-
Errors are caught and handled gracefully -
User-friendly error messages returned -
Errors are logged appropriately -
HTTP error responses follow API standards
Documentation
-
README.md updated (if setup steps changed) -
.env.exampleupdated (if new env vars added) -
API documentation updated (docstrings, OpenAPI specs) -
CHANGELOG.md will be updated (if applicable) -
Code comments explain complex logic (not what, but why)
Known Limitations / Technical Debt
Additional Notes
Anything else reviewers should know
- Improves usability for frontend integration and QA testing
- No impact on production logic if OTP exposure is disabled later
MR Acceptance Checklist
Quality & Correctness
-
Code works as intended and solves the stated problem -
No bugs introduced (existing functionality not broken) -
Edge cases handled appropriately
Maintainability
-
Code is readable and well-organized -
Code is testable and well-tested -
Follows project patterns and conventions
Acceptance Review
-
Reviewed by at least 1 teammate -
Reviewed by product owner