Defect #24156

Redmine might create many AnonymousUser and AnonymousGroup entries

Added by Holger Just 3 months ago. Updated about 1 month ago.

Status:ClosedStart date:
Priority:NormalDue date:
Assignee:Jean-Philippe Lang% Done:

0%

Category:Code cleanup/refactoring
Target version:3.2.5
Resolution:Fixed Affected version:

Description

Under certain conditions (and due to Rails' decision to hold global query state on models), under certain conditions, there might be multiple instances of the AnonymousUser and AnonymousGroup being created. Consider this example:

User.current
# => #<AnonymousUser id: 4 ...>

# Create a new public projects with no project members
project = Project.create(name: 'Public test', identifier: 'public-test', public: true)

# Now, gather the list of visible principals of the project
# This is e.g. called by IssueQuery#initialize_available_filters
project.principals.visible

As you can see, this creates (depending a bit on the settings) a new AnonymousGroup and a new AnonymousUser object. The reason for that with the call above this is called:

Principal.active.joins(:members).where("#{Member.table_name}.project_id = ?", project,id).uniq.visible

Now, in the visible scope of the Principle, a call to AnonymousUser.first class is used to find the anonymous user (and equivalently the AnonymousGroup later). Unfortunately this happens while the query scope for the outer query is still active. The new and unrelated query for the anonymous user appears to inherits the existing scope on the Principle class of the outer query which results in Redmine not finding the anonymous user and subsequently creating a new one.

This behavior can be reliably reproduced when browsing as Anonymous a public project without any explicit members.

The attached patch against current trunk was developed for one of our customers at Planio who experiences this issue. The problem does also occur in all Redmine versions which support the user visibility feature (that is all Redmine 3 version iirc).

The patch fixes the problem by performing the queries for the qlobal anonymous objects with an explicit call to unscoped which should remove the inherited outer scope. When merging this, it might be a good idea to also provide a migration which removes any erroneous AnonymousUser, AnonymousGroup, NonMemberGroup and AnonymousRole instances in the database.

(Boy, this was no fun to find and fix...)

0001-Explicitly-remove-the-potential-global-scope-on-role.patch Magnifier (2.51 KB) Holger Just, 2016-10-24 17:28

Associated revisions

Revision 16049
Added by Jean-Philippe Lang about 1 month ago

Use .unscoped when querying and creating builtin objects (#24156).

Patch by Holger Just.

History

#1 Updated by Jan from Planio www.plan.io 3 months ago

  • Target version set to Candidate for next minor release

#2 Updated by Toshi MARUYAMA 2 months ago

  • Description updated (diff)

#3 Updated by Toshi MARUYAMA 2 months ago

  • Target version changed from Candidate for next minor release to 3.4.0

#4 Updated by Jean-Philippe Lang about 1 month ago

  • Category changed from Permissions and roles to Code cleanup/refactoring
  • Status changed from New to Resolved
  • Assignee set to Jean-Philippe Lang
  • Target version changed from 3.4.0 to 3.2.5
  • Resolution set to Fixed

Patch committed, thanks.

#5 Updated by Jean-Philippe Lang about 1 month ago

  • Status changed from Resolved to Closed

Also available in: Atom PDF