From e6f73a1c802442715bc41cf8ce93d0ae44a06547 Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 14 May 2015 12:19:22 +1000 Subject: [PATCH] PERF: optimise front page category security lookup query --- app/models/category.rb | 36 ++++++++++++++++++++++-------------- spec/models/category_spec.rb | 4 ++++ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/app/models/category.rb b/app/models/category.rb index b5dca32e9..8b64d2b86 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -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 diff --git a/spec/models/category_spec.rb b/spec/models/category_spec.rb index 19746499c..a00529fb2 100644 --- a/spec/models/category_spec.rb +++ b/spec/models/category_spec.rb @@ -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