PERF: optimise front page category security lookup query

This commit is contained in:
Sam 2015-05-14 12:19:22 +10:00
parent b0306fd613
commit e6f73a1c80
2 changed files with 26 additions and 14 deletions

View file

@ -86,27 +86,35 @@ class Category < ActiveRecord::Base
def self.scoped_to_permissions(guardian, permission_types)
if guardian && guardian.is_staff?
all
elsif !guardian || guardian.anonymous?
if permission_types.include?(:readonly)
where("NOT categories.read_restricted")
else
where("1 = 0")
end
else
permission_types = permission_types.map{ |permission_type|
CategoryGroup.permission_types[permission_type]
}
where("categories.id in (
SELECT c.id FROM categories c
WHERE (
NOT c.read_restricted AND
(
NOT EXISTS(
SELECT 1 FROM category_groups cg WHERE cg.category_id = categories.id )
) OR EXISTS(
SELECT 1 FROM category_groups cg
WHERE permission_type in (?) AND
cg.category_id = categories.id AND
group_id IN (
SELECT g.group_id FROM group_users g where g.user_id = ? UNION SELECT ?
)
SELECT cg.category_id FROM category_groups cg
WHERE permission_type in (:permissions) AND
(
group_id IN (
SELECT g.group_id FROM group_users g where g.user_id = :user_id
)
)
)
OR
categories.id in (
SELECT cg.category_id FROM category_groups cg
WHERE permission_type in (:permissions) AND group_id = :everyone
)
)", permission_types,(!guardian || guardian.user.blank?) ? -1 : guardian.user.id, Group[:everyone].id)
OR
categories.id NOT in (SELECT cg.category_id FROM category_groups cg)
", permissions: permission_types,
user_id: guardian.user.id,
everyone: Group[:everyone].id)
end
end

View file

@ -73,6 +73,8 @@ describe Category do
expect(Category.post_create_allowed(guardian).count).to be(4)
expect(Category.topic_create_allowed(guardian).count).to be(3) # explicitly allowed once, default allowed once
expect(Category.scoped_to_permissions(nil, [:readonly]).count).to be(2)
# everyone has special semantics, test it as well
can_post_category.set_permissions(:everyone => :create_post)
can_post_category.save
@ -82,6 +84,8 @@ describe Category do
# anonymous has permission to create no topics
guardian = Guardian.new(nil)
expect(Category.post_create_allowed(guardian).count).to be(0)
expect(Category.topic_create_allowed(guardian).count).to be(0)
expect(Category.scoped_to_permissions(guardian, [:readonly]).count).to be(3)
end