fix(auth): restore password helper compatibility and prevent API restart loop
Merge Request
Overview
This MR fixes an authentication regression that caused startup failures and Docker restart loops. Compared with develop, this branch contains one commit and one file change focused on password utility compatibility and resilience.
What does this MR do and why?
fix(auth): restore password helper compatibility to prevent restart loop
The motivation was to resolve runtime import and compatibility issues in auth password handling and stabilize validation flows for edge-case hash inputs. The approach was to replace passlib context usage with a minimal bcrypt-based wrapper while preserving the existing interface expected by the rest of the codebase. Trade-off: this keeps behavior stable for current callers without broader auth refactors, and does not address unrelated project-wide deprecation warnings.
Changes Made
- Modified app/utils/password_utils.py
- Replaced passlib CryptContext usage with a bcrypt-backed PasswordContext wrapper
- Added get_password_hash alias for backward compatibility
- Updated verify_password signature to accept nullable hash input
- Added defensive handling for empty or invalid hashes to return false instead of raising
- Added explicit type casts to satisfy mypy checks
Technical Details
Root cause:
- Auth flows expected compatibility around get_password_hash and verification behavior.
- Password utility implementation drift caused import/runtime instability and fragile handling of invalid hash inputs.
How this fix addresses it:
- Introduces a stable context-compatible wrapper (hash and verify) over bcrypt.
- Restores get_password_hash symbol compatibility.
- Hardens verify_password against None, empty, and invalid hash values.
- Keeps typing strict and hook-compliant (Ruff and mypy).
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
Screenshots or Screen Recordings
Please Refer Comments
How to Validate Locally
- Checkout this branch and install dependencies.
- Run lint and type checks.
- Run auth-focused tests.
- Run full test suite with coverage.
- Start the API and verify no restart loop from password utility issues.
Testing Done
-
Unit tests added/updated -
API endpoint tests passing
Test Cases Covered:
| Scenario | Expected Result | Status |
|---|---|---|
| get_password_hash compatibility | Auth import and call paths work | |
| verify_password with empty hash | Returns false, no crash | |
| verify_password with None hash | Returns false, no crash | |
| verify_password with invalid hash | Returns false, no crash | |
| Auth service valid password path | User authenticates successfully | |
| Auth service invalid password path | Authentication rejected | |
| Forgot-password with book number | Password reset route succeeds with valid OTP | |
| Full test suite | No failures |
Test Commands Run:
uv run ruff check app/utils/password_utils.py
uv run mypy app/utils/password_utils.py
uv run pytest tests/test_services/test_auth_service.py tests/test_api/test_auth_routes.py -q
uv run pytest --cov=app tests/ -q
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 Any unless 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.example updated (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
- This MR intentionally focuses on password utility compatibility and robustness only.
- Existing unrelated deprecation warnings remain out of scope.
Additional Notes
- Diff versus develop includes:
- 1 commit: fix(auth): restore password helper compatibility to prevent restart loop
- 1 modified file: app/utils/password_utils.py
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