Skip to content
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

::invite! modifies existing users #747

Open
rlue opened this issue Mar 8, 2018 · 0 comments
Open

::invite! modifies existing users #747

rlue opened this issue Mar 8, 2018 · 0 comments

Comments

@rlue
Copy link
Contributor

rlue commented Mar 8, 2018

Summary

In some cases, User.invite! can alter DB records for the associations of existing (registered) users.

Description

In my app, for instance, a User has_many :teams, through: :user_teams. When inviting a new user, you can specify which teams they belong to:

def configure_permitted_parameters
  devise_parameter_sanitizer.permit(:invite, keys: [team_ids: []])
end

Currently, you can reassign these associations on an existing user through the ::invite! method:

User.invite!(email: 'sergio@entrecables.com', team_ids: [1, 5])

Here's the relevant portion of the server logs:

Started POST "/companies/399930040/invitation" for 127.0.0.1 at 2018-03-08 13:48:41 +0800
Processing by Companies::InvitationsController#create as JS
  Parameters: {..., "user"=>{"email"=>"sergio@entrecables.com", "team_ids"=>["1", "5"]}, "commit"=>"Send invite", "company_uid"=>"399930040"}
...
   (0.7ms)  BEGIN
  ↳ app/controllers/companies/invitations_controller.rb:60
  TeamUser Destroy (2.3ms)  DELETE FROM "team_users" WHERE "team_users"."user_id" = $1 AND "team_users"."team_id" IN ($2, $3, $4)  [["user_id", 1], ["team_id", 2], ["team_id", 3], ["team_id", 4]]
  ↳ app/controllers/companies/invitations_controller.rb:60
   (0.4ms)  COMMIT
  ↳ app/controllers/companies/invitations_controller.rb:60
...

Cause

This problem occurs because of the following two lines in the ::_invite method:

invitable = find_or_initialize_with_errors(invite_key_array, attributes_hash)
invitable.assign_attributes(attributes)

The assign_attributes call is not supposed to persist any changes to the database (yet), but because the team_ids association is stored on a join model, they're persisted immediately upon assignment.

Solution

I've prepared some changes in my own fork (I've also refactored the ::_invite method and given some methods more precise names, IMO).

Unfortunately, it's not ready for a PR just yet, because the refactoring offloads some of the work to Devise (Authenticatable / ParameterFilter), and I discovered a bug there in the process. I'll create a PR for this issue once (if) that bugfix is merged into the next release of Devise.

@rlue rlue changed the title ::invite! modifies (associations on) existing users ::invite! modifies existing users Mar 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant