-
Notifications
You must be signed in to change notification settings - Fork 766
Fix Identity#destroy callback ordering and enable user reactivation #2003
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: main
Are you sure you want to change the base?
Fix Identity#destroy callback ordering and enable user reactivation #2003
Conversation
ref: #2003 Co-authored-by: Dylan <dylan@restaurantcare.com.au>
|
@dilberryhoundog Thanks so much for opening this! I've got a few notes that I hope you're open to hearing. We ideally want to add tests for either bug fixes or new features. The app's test coverage isn't currently great because we pivoted so much during product development; and that's resulted in some rough edges like the bug you found! Going forward we very much want to improve that situation, and prevent bugs from regressing. Also, this PR seems like it contains two separate concerns: a bug fix, and a feature for user reactivation. We'd really prefer to get one pull request per change. I've created #2017 for the Identity destruction bug fix, and added test coverage for it. You're credited as a co-author! I really like the idea of allow user reactivation. Are you willing to add some tests for that features and continue this PR? 🙏 |
flavorjones
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.
See previous note.
ref: basecamp#2003 Co-authored-by: Dylan <dylan@restaurantcare.com.au>
cf46a8a to
d092d7b
Compare
Add prepend: true to before_destroy callback so deactivation runs before dependent: :nullify clears identity_id. Preserve identity link in User#deactivate to enable reactivation when rejoining via join code. Also improves Identity::Joinable#join to properly reactivate inactive users and grant board access.
d092d7b to
208da8d
Compare
|
@flavorjones Thank you for reviewing. Yes there was a cascade with the three files, that meant I couldn't propose the improvement without the fix. The most impactful was the The answer was to remove the The current situation is that we have merged the The testing situatuation you asked for me to address is as follow.
I have tried to stay within your testing methodology and patterns identified. I have run all the test locally (they passed). So I hope that helps. Thankyou for considering this fix and improvement. |
Title: Fix Identity#destroy callback ordering and enable user reactivation
Summary
This PR fixes a bug where
Identity#destroyfails to properly deactivate users due to callback ordering, and includes an enhancement to enable user reactivation when rejoining an account.The Bug
When an Identity is destroyed, the
deactivate_userscallback runs afterdependent: :nullifybecause Rails adds association callbacks in declaration order. By the timedeactivate_usersiterates overusers.find_each, the association is already empty (identity_idhas been set to NULL).Result: Users are orphaned with
active: true, accesses intact, butidentity_id: nil.Reproduction
Historical Context
Looking at the git history, this appears to stem from the membership refactor:
7124835edf837fhas_many :users, dependent: :nullify34d83aaidentity: niltoUser#deactivate, transaction re-added6e9381acreate!tofind_or_create_by!injoinThe
identity: nilinUser#deactivatewas added as a quick test fix after dropping memberships, but it created a cascade:find_or_create_by!On Transactions
DHH's original reasoning for removing the transaction from
deactivate(commit7124835):This reasoning still applies - without
identity: nil, all operations indeactivateare independently safe:accesses.destroy_all- partial completion is fineupdate! active: false- atomicclose_remote_connections- side effect, doesn't affect data integrityThe transaction was re-added alongside
identity: nilbut isn't needed if we remove that assignment.Changes
Bug Fix
identity.rb: Addprepend: trueto ensure deactivation runs before nullificationEnhancement: User Reactivation
user.rb: Removeidentity: niland transaction wrapper indeactivatemethod - preserves identity link so rejoining users can be found. This also ensures Identity destroy works correctly and avoids unique constraint issues.joinable.rb: Handle reactivation - if an inactive user with matching identity exists, reactivate them and re-grant board accessBehavior Change
identity: nil, fresh start on rejoin