-
-
Notifications
You must be signed in to change notification settings - Fork 313
Fix: Enforce email verification when changing email via profile edit #4804
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
Fix: Enforce email verification when changing email via profile edit #4804
Conversation
WalkthroughThe profile_edit view now detects and validates email changes, preserves the original User.email on save, removes the user's unverified Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant ProfileEdit as Profile Edit View
participant DB as Database
participant Email as Email Service
User->>ProfileEdit: GET /profile/edit
ProfileEdit->>DB: Read user & current email
ProfileEdit->>User: Render form prepopulated with current email
User->>ProfileEdit: POST form with updated data
ProfileEdit->>ProfileEdit: Capture original email
ProfileEdit->>DB: Save other profile fields (do not overwrite User.email)
alt New email != original email
ProfileEdit->>DB: Delete user's unverified EmailAddress records
ProfileEdit->>DB: Create new unverified EmailAddress(new email)
ProfileEdit->>Email: send_email_confirmation(new EmailAddress)
ProfileEdit->>User: Redirect with informational message (verification sent)
else Email unchanged
ProfileEdit->>User: Redirect with standard success message
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 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
🧹 Nitpick comments (1)
website/views/user.py (1)
147-147: Optional: Silence the unused variable warning.The
createdvariable fromget_or_createis never used. Consider using_to indicate it's intentionally ignored.- user_profile, created = UserProfile.objects.get_or_create(user=request.user) + user_profile, _ = UserProfile.objects.get_or_create(user=request.user)Based on static analysis hints.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
📒 Files selected for processing (1)
website/views/user.py(2 hunks)
🧰 Additional context used
🪛 Ruff (0.14.4)
website/views/user.py
147-147: Unpacked variable created is never used
Prefix it with an underscore or any other dummy variable pattern
(RUF059)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Run Tests
- GitHub Check: docker-test
🔇 Additional comments (4)
website/views/user.py (4)
143-144: Good use of django-allauth for email verification.The function-scoped imports are appropriate here since these utilities are only needed in this specific view.
169-188: Email verification flow looks solid.The implementation correctly:
- Clears stale unverified email entries to prevent confusion
- Creates a new unverified
EmailAddressentry withprimary=False- Sends verification email using django-allauth's utility
- Provides clear user feedback
- Follows the Post-Redirect-Get pattern
Minor note: There's a small TOCTOU (time-of-check to time-of-use) window between the uniqueness check (line 159) and the
EmailAddresscreation (line 174), butget_or_createwill handle this gracefully, so this is not a significant concern.
198-201: Good UX: Form correctly pre-populates the email field.Using
initialto populate the email field ensures users see their current email address when editing their profile, which is the expected behavior.
166-167: ✓ Verified:form.save()does not updaterequest.user.emailThe concern has been validated and found to be already addressed correctly in the code:
- The
UserProfileFormis declared but not included inMeta.fields(lines 28-44 of website/forms.py)- Django's
ModelForm.save()only saves fields listed inMeta.fields, so email will not be updated- Any custom
save()method that would updateUser.emailis commented out (lines 60-68 of website/forms.py), confirming this behavior was intentional- Email is handled correctly via the
EmailAddressmodel (lines 174-177 of user.py) as an unverified record, preventing immediate activationThe code is correct as-is. No action required.
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: 2
🧹 Nitpick comments (2)
website/views/user.py (2)
163-165: Consider checking if the email already exists for the current user.The uniqueness check excludes all EmailAddress entries for
request.user, but this could miss edge cases:
- If the user has this email as an existing unverified secondary email from a previous attempt, the check passes.
- Then line 175 deletes it, which is fine.
- But if the user has this email as a verified secondary (non-primary) EmailAddress, the check passes, but line 175 won't delete it (only deletes unverified), and then line 178's
get_or_createwill find the existing verified entry without updating it properly.Consider refining the check:
+ # Check if email already exists for current user + existing_user_email = EmailAddress.objects.filter(user=request.user, email=new_email).first() + if existing_user_email: + if existing_user_email.verified and existing_user_email.primary: + # This is their current primary email, will be caught by email_changed check + pass + else: + form.add_error("email", "This email is already associated with your account") + return render(request, "profile_edit.html", {"form": form}) + - if EmailAddress.objects.exclude(user=request.user).filter(email=new_email).exists(): + # Check if email exists for other users + if EmailAddress.objects.exclude(user=request.user).filter(email=new_email).exists(): form.add_error("email", "This email is already registered or pending verification") return render(request, "profile_edit.html", {"form": form})
173-192: Consider guarding against race conditions in email creation.Between the uniqueness check (line 163-165) and the EmailAddress creation (line 178-182), another concurrent request could create an
EmailAddresswith the same email, potentially causing anIntegrityErrordepending on database constraints.Consider wrapping the email change logic in a try-except block:
if email_changed: try: # Remove any pending unverified emails EmailAddress.objects.filter(user=request.user, verified=False).delete() # Create new unverified email entry EmailAddress.objects.create( user=request.user, email=new_email, verified=False, primary=False, ) # Send verification email send_email_confirmation(request, request.user, email=new_email) messages.info( request, "A verification link has been sent to your new email. " "Please verify to complete the update." ) except IntegrityError: messages.error(request, "This email is already in use. Please try a different email.") except Exception as e: logger.error(f"Error during email change: {e}") messages.error(request, "An error occurred. Please try again.") return redirect("profile", slug=request.user.username)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
📒 Files selected for processing (1)
website/views/user.py(2 hunks)
🧰 Additional context used
🪛 Ruff (0.14.4)
website/views/user.py
147-147: Unpacked variable created is never used
Prefix it with an underscore or any other dummy variable pattern
(RUF059)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Run Tests
- GitHub Check: docker-test
🔇 Additional comments (1)
website/views/user.py (1)
170-171: No issues found – the comment is accurate.The form defines an
Meta.fields(lines 28-44 inwebsite/forms.py). Since the email field is not in the form's fields list,form.save()does not persist it anywhere. The actual email update is handled separately via theEmailAddressmodel whenemail_changedis true, which is the correct approach. The comment accurately reflects this behavior.
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 (2)
website/views/user.py (2)
147-147: Tidy up unusedcreatedfromget_or_create
createdis never used; to satisfy Ruff and reduce noise, consider:- user_profile, created = UserProfile.objects.get_or_create(user=request.user) + user_profile, _ = UserProfile.objects.get_or_create(user=request.user)Based on static analysis hints.
173-205: EmailAddress flow is solid; refine exception handling & loggingDeleting any unverified
EmailAddressrows, creating a fresh unverified entry fornew_email, and only then sendingsend_email_confirmationcorrectly keepsrequest.user.emailunchanged until verification, while preserving profile-field updates.To improve robustness and satisfy Ruff:
- Prefer more specific exceptions for the email send failure if feasible (e.g., SMTP/email‑backend exceptions) instead of a blind
except Exception.- Use
logger.exceptionso the stack trace is recorded:- try: - send_email_confirmation(request, request.user, email=new_email) - except Exception as e: - logger.error(f"Failed to send email confirmation to {new_email}: {e}") + try: + send_email_confirmation(request, request.user, email=new_email) + except Exception: + logger.exception("Failed to send email confirmation to %s", new_email) messages.error( request, "Failed to send verification email. Please try again later." ) return redirect("profile", slug=request.user.username)Based on static analysis hints.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
📒 Files selected for processing (1)
website/views/user.py(2 hunks)
🧰 Additional context used
🪛 Ruff (0.14.4)
website/views/user.py
147-147: Unpacked variable created is never used
Prefix it with an underscore or any other dummy variable pattern
(RUF059)
189-189: Do not catch blind exception: Exception
(BLE001)
190-190: Use logging.exception instead of logging.error
Replace with exception
(TRY400)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Run Tests
- GitHub Check: docker-test
🔇 Additional comments (2)
website/views/user.py (2)
143-145: Local imports for email verification helpers are fineImporting the allauth email models/utils inside
profile_editis reasonable here (and can help avoid import cycles); no change required.
149-169: Verification confirms email-change flow is secureThe problematic
save()method that was directly mutatingUser.emailhas been removed (it's now commented out at lines 60-68). Additionally, any fields not included in Meta.fields will not be set by the form's save() method, andUserProfileForm.Meta.fields. This means the form cannot inadvertently update the User model's email field—email changes are now isolated to the verification branch as intended.
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
🧹 Nitpick comments (2)
website/tests/test_user_profile.py (2)
107-109: Update the comment to reflect the new verification flow.The comment describes the old behavior focusing on uniqueness validation. It should now explain that the implementation creates an unverified EmailAddress entry and sends a verification link, keeping the User.email unchanged until verification completes.
Apply this diff to clarify the comment:
- # The current implementation doesn't update the User model's email - # It only validates that the email is unique - # So we just verify that the form was submitted successfully + # The implementation triggers email verification flow when email changes + # It validates uniqueness, creates an unverified EmailAddress entry, + # and sends a verification link while keeping User.email unchanged
110-112: Consider verifying EmailAddress creation and email sending.The test correctly validates the user-facing message, but it doesn't verify that the underlying verification infrastructure was set up. Consider adding assertions to check:
- An unverified
EmailAddressobject was created for the new email- A verification email was sent (using
django.core.mail.outbox)Example additions to enhance test coverage:
from allauth.account.models import EmailAddress from django.core import mail # After line 111, add: # Verify EmailAddress object was created as unverified email_address = EmailAddress.objects.get(user=self.user, email=new_email) self.assertFalse(email_address.verified) self.assertTrue(email_address.primary) # or False depending on implementation # Verify verification email was sent self.assertEqual(len(mail.outbox), 1) self.assertIn(new_email, mail.outbox[0].to)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
📒 Files selected for processing (1)
website/tests/test_user_profile.py(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Run Tests
- GitHub Check: docker-test
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
🧹 Nitpick comments (3)
website/views/user.py (3)
145-145: Consider prefixing unused variable with underscore.The
createdvariable fromget_or_create()is never used. While this is a common pattern, prefixing it with an underscore makes the intent explicit.Apply this diff:
- user_profile, created = UserProfile.objects.get_or_create(user=request.user) + user_profile, _created = UserProfile.objects.get_or_create(user=request.user)
161-163: Consider checking if the user already has this email verified.The uniqueness check on line 161 excludes the current user's
EmailAddressentries, which means if the user already hasnew_emailas a verified secondary email, this check won't catch it. They would then create a duplicate unverified entry for an email they've already verified.Consider adding an additional check:
if EmailAddress.objects.exclude(user=request.user).filter(email=new_email).exists(): form.add_error("email", "This email is already registered or pending verification") return render(request, "profile_edit.html", {"form": form}) + + # Check if user already has this email verified + if EmailAddress.objects.filter(user=request.user, email=new_email, verified=True).exists(): + form.add_error("email", "You already have this email verified. Use email management to set it as primary.") + return render(request, "profile_edit.html", {"form": form})
168-168: Remove unnecessary quotation marks in comment.The quotation marks around "not" are unnecessary and make the comment look odd.
Apply this diff:
- # Save profile form (does "not" touch email in user model) + # Save profile form (does not touch email in user model)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
📒 Files selected for processing (1)
website/views/user.py(1 hunks)
🧰 Additional context used
🪛 Ruff (0.14.4)
website/views/user.py
145-145: Unpacked variable created is never used
Prefix it with an underscore or any other dummy variable pattern
(RUF059)
186-186: Do not catch blind exception: Exception
(BLE001)
187-187: Use logging.exception instead of logging.error
Replace with exception
(TRY400)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Run Tests
- GitHub Check: docker-test
🔇 Additional comments (3)
website/views/user.py (3)
141-142: LGTM! Local imports appropriately scoped.The local imports of
EmailAddressandsend_email_confirmationare correctly placed within the function scope, which is a valid pattern for avoiding potential circular import issues or keeping allauth dependencies localized to this specific view.
171-199: Excellent implementation of email verification flow!The email change handling correctly addresses the security issue described in the PR objectives:
- Preserves original email:
User.emailis not updated until verification completes- Creates unverified entry: New email is added to
EmailAddresstable withverified=False- Cleans up pending changes: Removes stale unverified emails before creating the new entry
- User feedback: Clear messaging differentiates between email changes and other profile updates
- Error resilience: Handles email sending failures gracefully
The separation of concerns between email changes (lines 171-195) and normal profile updates (lines 198-199) is well-structured.
205-208: LGTM! Form correctly prepopulated with current email.The form initialization properly prepopulates the email field with
request.user.email, ensuring users see their current email address when editing their profile.
|
looks good, please make sure to get a peer review and check all comments are resolved |
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
🧹 Nitpick comments (2)
website/views/user.py (2)
184-189: Remove redundant exception object from logging message.When using
logger.exception(), the exception information is automatically captured and logged with the full traceback. Including{e}in the message is redundant.Apply this diff:
try: send_email_confirmation(request, request.user, email=new_email) except Exception as e: - logger.exception(f"Failed to send email confirmation to {new_email}: {e}") + logger.exception(f"Failed to send email confirmation to {new_email}") messages.error(request, "Failed to send verification email. Please try again later.") return redirect("profile", slug=request.user.username)Based on static analysis hints.
145-145: Consider using underscore prefix for unused variable.The
createdvariable is unpacked but never used. Consider prefixing with underscore to indicate it's intentionally unused.Apply this diff:
- user_profile, created = UserProfile.objects.get_or_create(user=request.user) + user_profile, _ = UserProfile.objects.get_or_create(user=request.user)Based on static analysis hints.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
📒 Files selected for processing (1)
website/views/user.py(1 hunks)
🧰 Additional context used
🪛 Ruff (0.14.4)
website/views/user.py
145-145: Unpacked variable created is never used
Prefix it with an underscore or any other dummy variable pattern
(RUF059)
187-187: Redundant exception object included in logging.exception call
(TRY401)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Run Tests
- GitHub Check: docker-test
🔇 Additional comments (5)
website/views/user.py (5)
141-142: LGTM! Local imports are appropriate.The local imports of
EmailAddressandsend_email_confirmationhelp avoid circular dependencies and keep the dependencies clear for this specific flow.
147-148: LGTM! Capturing original email is correct.Storing the original email before form processing enables accurate change detection later.
165-166: LGTM! Email change detection is correct.The comparison correctly identifies whether the email has changed.
168-169: LGTM! Form save correctly preserves User.email.The comment accurately reflects that
User.emailis not modified here, which is essential for the verification flow.
205-208: LGTM! Form initialization correctly prepopulates the email.Using
initial={"email": request.user.email}ensures the form displays the user's current email on the initial page load, providing a good user experience.
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 (4)
website/views/user.py (4)
144-145: Prefix unused variable with underscore.The
createdreturn value fromget_or_createis unpacked but never used. Prefix it with an underscore to indicate it's intentionally unused.Apply this diff:
Tag.objects.get_or_create(name="GSOC") -user_profile, created = UserProfile.objects.get_or_create(user=request.user) +user_profile, _ = UserProfile.objects.get_or_create(user=request.user)
162-166: Clarify how to set email as primary.The error message tells users to "set it as primary instead" but doesn't indicate where or how to do this. Consider either:
- Providing a link or instructions on how to set an email as primary
- Automatically setting it as primary if it's already verified
- Removing this suggestion if the functionality isn't available to users
Example improvement:
if existing_email.verified: - form.add_error("email", "You already have this email verified. Please set it as primary instead.") + form.add_error("email", "This email is already verified for your account.") return render(request, "profile_edit.html", {"form": form})
192-197: Remove redundant exception object from log message.When using
logger.exception(), the exception and stack trace are automatically appended to the log output. Including the exception object in the message string is redundant.Apply this diff:
try: send_email_confirmation(request, request.user, email=new_email) except Exception as e: - logger.exception(f"Failed to send email confirmation to {new_email}: {e}") + logger.exception(f"Failed to send email confirmation to {new_email}") messages.error(request, "Failed to send verification email. Please try again later.") return redirect("profile", slug=request.user.username)
199-207: Consider consolidating the message string.The success message on lines 200-201 uses string concatenation. For better readability, consider using a single string or parentheses for implicit concatenation.
Apply this diff:
-messages.info( - request, - "A verification link has been sent to your new email. " "Please verify to complete the update.", -) +messages.info( + request, + "A verification link has been sent to your new email. Please verify to complete the update.", +)Otherwise, the flow correctly handles both email-changed and email-unchanged cases with appropriate messages.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
📒 Files selected for processing (1)
website/views/user.py(1 hunks)
🧰 Additional context used
🪛 Ruff (0.14.4)
website/views/user.py
145-145: Unpacked variable created is never used
Prefix it with an underscore or any other dummy variable pattern
(RUF059)
195-195: Redundant exception object included in logging.exception call
(TRY401)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Run Tests
- GitHub Check: docker-test
🔇 Additional comments (5)
website/views/user.py (5)
141-142: LGTM: Local imports for email verification flow.The scoped imports for
EmailAddressandsend_email_confirmationare appropriate and keep the dependencies explicit for this email verification feature.
147-148: LGTM: Original email captured correctly.Capturing the user's current email before form processing is essential for detecting email changes. This is implemented correctly.
179-189: LGTM: Email change handling is correct.The implementation correctly:
- Deletes pending unverified emails for the user
- Uses
update_or_createwith appropriate defaults to handle edge cases- Sets the new email as unverified and non-primary
The use of
update_or_createinstead ofcreateis appropriate as it gracefully handles race conditions and edge cases.
213-216: LGTM: Form correctly prepopulated with current email.The form initialization properly prepopulates the email field with the user's current email address, providing a good user experience.
173-177: The email handling is secure and the comment is accurate.The verification confirms that
form.save()on line 177 does not touchUser.email. The email field is declared in the form but excluded fromMeta.fields, so it won't be saved by the ModelForm'ssave()method.The email change is correctly handled separately:
- New email is stored as unverified in the
EmailAddresstable (verified=False)- A verification email is sent via
send_email_confirmation()User.emailis never directly updated with unverified addressesThe commented-out code in
website/forms.py:60-68shows the previous implementation that directly saved toUser.email—this has been properly removed and replaced with the current secure flow.
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 (2)
website/views/user.py (2)
145-145: Prefix unused variable with underscore.The
createdvariable is unpacked but never used. Follow Python conventions by prefixing it with an underscore to indicate it's intentionally unused.Apply this diff:
- user_profile, created = UserProfile.objects.get_or_create(user=request.user) + user_profile, _created = UserProfile.objects.get_or_create(user=request.user)
194-194: Remove redundant exception object from log message.
logging.exception()automatically includes the exception and stack trace, so including{e}in the formatted string is redundant.Apply this diff:
- logger.exception(f"Failed to send email confirmation to {new_email}: {e}") + logger.exception(f"Failed to send email confirmation to {new_email}")
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
📒 Files selected for processing (1)
website/views/user.py(1 hunks)
🧰 Additional context used
🪛 Ruff (0.14.4)
website/views/user.py
145-145: Unpacked variable created is never used
Prefix it with an underscore or any other dummy variable pattern
(RUF059)
194-194: Redundant exception object included in logging.exception call
(TRY401)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Run Tests
- GitHub Check: docker-test
🔇 Additional comments (2)
website/views/user.py (2)
156-202: Well-structured email verification flow.The implementation demonstrates solid security practices:
- Comprehensive validation: Three-tier uniqueness checks prevent conflicts with other users, existing verified emails, and pending verifications.
- Proper verification flow: Uses django-allauth's
EmailAddressmodel andsend_email_confirmationfollowing framework conventions.- Graceful error handling: Try-except block with logging and user-friendly error messages ensures failures don't leave the system in an inconsistent state.
- Clear user communication: Info message explains what to expect after email change.
The conditional logic correctly separates email-change handling from normal profile updates, preserving existing behavior for other fields.
139-217: UserProfileForm correctly excludes email from model save—verification successful.The email field is defined on
UserProfileFormbut is not included inMeta.fields(lines 26-44 of website/forms.py). This ensures thatform.save()at line 176 will not modifyUser.email. The commented-outsave()method (lines 60-68) confirms this was an intentional design decision—email auto-save to the User model was explicitly removed. The view correctly handles email updates separately through theEmailAddressmodel, preserving the verification flow.
gojo-satorou-v7
left a 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.
|
Thank you @DonnieBLT ! I've requested a peer review and confirmed that all comments from CodeRabbit are now resolved. |
|
Thank you for the review @gojo-satorou-v7! |
|
Thanks! |
Summary
What This Fix Does:
Implementation Details:
Added logic in profile_edit:
How to Test:
Expect:
Related Issue:
Fixes: #4783
Summary by CodeRabbit
New Features
Bug Fixes / Validation
Tests