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) def self.scoped_to_permissions(guardian, permission_types)
if guardian && guardian.is_staff? if guardian && guardian.is_staff?
all all
elsif !guardian || guardian.anonymous?
if permission_types.include?(:readonly)
where("NOT categories.read_restricted")
else
where("1 = 0")
end
else else
permission_types = permission_types.map{ |permission_type| permission_types = permission_types.map{ |permission_type|
CategoryGroup.permission_types[permission_type] CategoryGroup.permission_types[permission_type]
} }
where("categories.id in ( where("categories.id in (
SELECT c.id FROM categories c SELECT cg.category_id FROM category_groups cg
WHERE ( WHERE permission_type in (:permissions) AND
NOT c.read_restricted AND (
( group_id IN (
NOT EXISTS( SELECT g.group_id FROM group_users g where g.user_id = :user_id
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 ?
)
) )
)
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
end end

View File

@ -73,6 +73,8 @@ describe Category do
expect(Category.post_create_allowed(guardian).count).to be(4) 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.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 # everyone has special semantics, test it as well
can_post_category.set_permissions(:everyone => :create_post) can_post_category.set_permissions(:everyone => :create_post)
can_post_category.save can_post_category.save
@ -82,6 +84,8 @@ describe Category do
# anonymous has permission to create no topics # anonymous has permission to create no topics
guardian = Guardian.new(nil) guardian = Guardian.new(nil)
expect(Category.post_create_allowed(guardian).count).to be(0) 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 end