Defect #24156
closedRedmine might create many AnonymousUser and AnonymousGroup entries
0%
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...)
Files