-
Notifications
You must be signed in to change notification settings - Fork 534
Enforce password validation and add comprehensive regression tests #3434
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
📝 WalkthroughWalkthroughAdds Django password validation to the change-password serializer, refactors validation flow to use DRF's Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
care/users/api/viewsets/change_password.pycare/users/tests/test_change_password.py
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py
📄 CodeRabbit inference engine (.cursorrules)
**/*.py: Prioritize readability and maintainability; follow Django's coding style guide (PEP 8 compliance).
Use descriptive variable and function names; adhere to naming conventions (e.g., lowercase with underscores for functions and variables).
Files:
care/users/api/viewsets/change_password.pycare/users/tests/test_change_password.py
**/tests/**/*.py
📄 CodeRabbit inference engine (.cursorrules)
Use Django’s built-in tools for testing (unittest and pytest-django) to ensure code quality and reliability.
Files:
care/users/tests/test_change_password.py
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: ohcnetwork/care PR: 0
File: .cursorrules:0-0
Timestamp: 2025-07-18T15:17:40.483Z
Learning: Apply Django's security best practices (e.g., CSRF protection, SQL injection protection, XSS prevention).
🧬 Code graph analysis (2)
care/users/api/viewsets/change_password.py (2)
care/emr/resources/user/spec.py (1)
validate_password(110-117)care/users/models.py (1)
User(96-212)
care/users/tests/test_change_password.py (2)
care/users/models.py (1)
User(96-212)care/utils/tests/base.py (1)
create_user(25-28)
🪛 Ruff (0.14.10)
care/users/api/viewsets/change_password.py
21-21: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
33-33: Unused method argument: args
(ARG002)
33-33: Unused method argument: kwargs
(ARG002)
care/users/tests/test_change_password.py
13-13: Possible hardcoded password assigned to argument: "password"
(S106)
🔇 Additional comments (7)
care/users/api/viewsets/change_password.py (3)
2-3: LGTM! Imports align with Django's validation framework.The imports are appropriate for integrating Django's password validation into the serializer.
36-36: Excellent! Core security fix enforces validation.Adding
raise_exception=Trueensures that validation failures are consistently caught and returned to the client, preventing weak passwords from slipping through. This directly addresses the security gap mentioned in the PR objectives.
38-52: LGTM! Clean refactoring with validated_data.The update logic correctly uses
validated_dataafter validation, maintaining the existing behavior while integrating with the new validation flow. The old password check and error response structure remain intact.care/users/tests/test_change_password.py (4)
1-16: LGTM! Well-structured test setup.The setup follows Django testing best practices with proper user creation, authentication, and URL resolution. The test user password ("StrongPass@123") is appropriately strong for testing validation scenarios.
18-28: LGTM! Comprehensive weak password validation test.This test effectively verifies that Django's password validators reject weak passwords and return the appropriate error response. The assertion on
new_passwordbeing in the error keys ensures the validation is properly attributed to the correct field.
30-38: LGTM! Proper verification of old password check.This test ensures that users must provide the correct current password to change it. The assertions correctly verify both the status code and the error field, which aligns with the expected behavior in the view.
40-51: LGTM! Thorough verification of successful password change.This test excellently verifies the complete flow, including the critical step of confirming that the password is actually persisted in the database. The use of
refresh_from_db()followed bycheck_password()ensures the change isn't just a response facade but a genuine database update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
care/users/api/viewsets/change_password.py (1)
22-31: Good work addressing the exception chaining feedback.The validation method correctly uses Django's password validators and now properly preserves the exception chain with
from e. This implementation follows Django best practices.One optional consideration: you might want to validate that the new password differs from the old password, though this is not strictly required by Django and can be deferred if not needed.
💡 Optional enhancement: reject identical passwords
def validate_new_password(self, value): """ Validate the new password against Django's password policies. """ user = self.context["request"].user + if user.check_password(value): + raise serializers.ValidationError( + "New password must be different from the current password." + ) try: validate_password(value, user=user) except DjangoValidationError as e: raise serializers.ValidationError(e.messages) from e return value
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
care/users/api/viewsets/change_password.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py
📄 CodeRabbit inference engine (.cursorrules)
**/*.py: Prioritize readability and maintainability; follow Django's coding style guide (PEP 8 compliance).
Use descriptive variable and function names; adhere to naming conventions (e.g., lowercase with underscores for functions and variables).
Files:
care/users/api/viewsets/change_password.py
🧬 Code graph analysis (1)
care/users/api/viewsets/change_password.py (1)
care/emr/resources/user/spec.py (1)
validate_password(110-117)
🪛 Ruff (0.14.10)
care/users/api/viewsets/change_password.py
46-46: Unused method argument: args
(ARG002)
46-46: Unused method argument: kwargs
(ARG002)
🔇 Additional comments (5)
care/users/api/viewsets/change_password.py (5)
2-3: LGTM! Imports are appropriate for Django password validation.The necessary imports are in place for the new validation logic.
13-17: LGTM! Clear and informative docstring.The updated docstring accurately describes the serializer's validation behavior.
40-40: LGTM! Docstring is clear.
47-49: LGTM! Method documentation added.Nice to see the method documented, even though it might seem somewhat obvious to some.
52-64: LGTM! The update flow is well-structured.The validation enforcement with
raise_exception=Trueand the proper use ofset_password()+save()correctly implement the password change logic. The explicit old password check with clear error messaging is a nice touch.The static analysis hints about unused
argsandkwargsparameters can be safely ignored—they're standard parameters for overriding DRF'sUpdateAPIView.update()method.
|
Hi @ohcnetwork/care-backend-admins, |
Proposed Changes
Associated Issue
N/A
Merge Checklist
cc: @ohcnetwork/care-backend-admins
Summary by CodeRabbit
Improvements
Tests
✏️ Tip: You can customize this high-level summary in your review settings.