Skip to content

Inconsistent state between `Project#team.members` vs. `Project#project_members`

Project#project_members uses the members table, but Project#team.members uses the project_authorizations table. This can lead to an inconsistent state seen in gitlab-com/infrastructure#1486 where the user can see the project, but the admin cannot see that the user has access to the project. For example:

irb(main):015:0> ProjectAuthorization.where(user_id: user.id)
D, [2017-04-04T23:34:58.688574 #23742] DEBUG -- :   ProjectAuthorization Load (0.7ms)  SELECT "project_authorizations".* FROM "project_authorizations" WHERE "project_authorizations"."user_id" = $1  [["user_id", 843529]]
=> #<ActiveRecord::Relation [#<ProjectAuthorization user_id: 843529, project_id: 2010956, access_level: 40>, #<ProjectAuthorization user_id: 843529, project_id: 2333233, access_level: 40>]>
irb(main):004:0> project.team.members.map(&:username)
D, [2017-04-04T23:32:19.132321 #23742] DEBUG -- :   User Load (3.9ms)  SELECT "users".* FROM "users" INNER JOIN "project_authorizations" ON "users"."id" = "project_authorizations"."user_id" WHERE "project_authorizations"."project_id" = $1  ORDER BY "users"."id" DESC  [["project_id", 2333233]]
=> ["sam1", "lion1", "grac1", "zhang1", "ivant1", "cat1", "god1"]

I think running User#refresh_authorized_projects makes things consistent, but we should design the system so that is difficult or impossible to get into this state. For example, if we're going to update one thing, we should update both in a transaction.