diff options
author | Valery Sizov <valery@gitlab.com> | 2017-09-08 11:52:35 +0300 |
---|---|---|
committer | Valery Sizov <valery@gitlab.com> | 2017-09-08 11:52:35 +0300 |
commit | 2abf0532a634678ab1bf87bac2100d0d73192eec (patch) | |
tree | b4918945ade8090c72cf3f5ecc83b127e9f00917 /app/finders | |
parent | 71e2104ff26f7b180339576b06f3deb93b6bc8d8 (diff) | |
parent | bce1c50928e4885d54dd11221a9c8197a7fb1a7d (diff) |
Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce into rails5
Diffstat (limited to 'app/finders')
-rw-r--r-- | app/finders/admin/projects_finder.rb | 80 | ||||
-rw-r--r-- | app/finders/groups_finder.rb | 36 | ||||
-rw-r--r-- | app/finders/issuable_finder.rb | 43 | ||||
-rw-r--r-- | app/finders/issues_finder.rb | 39 | ||||
-rw-r--r-- | app/finders/merge_requests_finder.rb | 1 | ||||
-rw-r--r-- | app/finders/move_to_project_finder.rb | 1 | ||||
-rw-r--r-- | app/finders/projects_finder.rb | 19 | ||||
-rw-r--r-- | app/finders/todos_finder.rb | 2 |
8 files changed, 122 insertions, 99 deletions
diff --git a/app/finders/admin/projects_finder.rb b/app/finders/admin/projects_finder.rb index d3b04fa55b0..409a1758ae6 100644 --- a/app/finders/admin/projects_finder.rb +++ b/app/finders/admin/projects_finder.rb @@ -1,33 +1,67 @@ class Admin::ProjectsFinder - attr_reader :sort, :namespace_id, :visibility_level, :with_push, - :abandoned, :last_repository_check_failed, :archived, - :personal, :name, :page, :current_user + attr_reader :params, :current_user def initialize(params:, current_user:) + @params = params @current_user = current_user - @sort = params.fetch(:sort) { 'latest_activity_desc' } - @namespace_id = params[:namespace_id] - @visibility_level = params[:visibility_level] - @with_push = params[:with_push] - @abandoned = params[:abandoned] - @last_repository_check_failed = params[:last_repository_check_failed] - @archived = params[:archived] - @personal = params[:personal] - @name = params[:name] - @page = params[:page] end def execute items = Project.without_deleted.with_statistics - items = items.in_namespace(namespace_id) if namespace_id.present? - items = items.where(visibility_level: visibility_level) if visibility_level.present? - items = items.with_push if with_push.present? - items = items.abandoned if abandoned.present? - items = items.where(last_repository_check_failed: true) if last_repository_check_failed.present? - items = items.non_archived unless archived.present? - items = items.personal(current_user) if personal.present? - items = items.search(name) if name.present? - items = items.sort_by_attr(sort) - items.includes(:namespace).order("namespaces.path, projects.name ASC").page(page) + items = by_namespace_id(items) + items = by_visibilty_level(items) + items = by_with_push(items) + items = by_abandoned(items) + items = by_last_repository_check_failed(items) + items = by_archived(items) + items = by_personal(items) + items = by_name(items) + items = sort(items) + items.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]) + end + + private + + def by_namespace_id(items) + params[:namespace_id].present? ? items.in_namespace(params[:namespace_id]) : items + end + + def by_visibilty_level(items) + params[:visibility_level].present? ? items.where(visibility_level: params[:visibility_level]) : items + end + + def by_with_push(items) + params[:with_push].present? ? items.with_push : items + end + + def by_abandoned(items) + params[:abandoned].present? ? items.abandoned : items + end + + def by_last_repository_check_failed(items) + params[:last_repository_check_failed].present? ? items.where(last_repository_check_failed: true) : items + end + + def by_archived(items) + if params[:archived] == 'only' + items.archived + elsif params[:archived].blank? + items.non_archived + else + items + end + end + + def by_personal(items) + params[:personal].present? ? items.personal(current_user) : items + end + + def by_name(items) + params[:name].present? ? items.search(params[:name]) : items + end + + def sort(items) + sort = params.fetch(:sort) { 'latest_activity_desc' } + items.sort_by_attr(sort) end end diff --git a/app/finders/groups_finder.rb b/app/finders/groups_finder.rb index e6fb112e7f2..88d71b0a87b 100644 --- a/app/finders/groups_finder.rb +++ b/app/finders/groups_finder.rb @@ -1,3 +1,19 @@ +# GroupsFinder +# +# Used to filter Groups by a set of params +# +# Arguments: +# current_user - which user is requesting groups +# params: +# owned: boolean +# parent: Group +# all_available: boolean (defaults to true) +# +# Users with full private access can see all groups. The `owned` and `parent` +# params can be used to restrict the groups that are returned. +# +# Anonymous users will never return any `owned` groups. They will return all +# public groups instead, even if `all_available` is set to false. class GroupsFinder < UnionFinder def initialize(current_user = nil, params = {}) @current_user = current_user @@ -16,13 +32,13 @@ class GroupsFinder < UnionFinder attr_reader :current_user, :params def all_groups - groups = [] - - if current_user - groups << Gitlab::GroupHierarchy.new(groups_for_ancestors, groups_for_descendants).all_groups - end - groups << Group.unscoped.public_to_user(current_user) + return [owned_groups] if params[:owned] + return [Group.all] if current_user&.full_private_access? + groups = [] + groups << Gitlab::GroupHierarchy.new(groups_for_ancestors, groups_for_descendants).all_groups if current_user + groups << Group.unscoped.public_to_user(current_user) if include_public_groups? + groups << Group.none if groups.empty? groups end @@ -39,4 +55,12 @@ class GroupsFinder < UnionFinder groups.where(parent: params[:parent]) end + + def owned_groups + current_user&.groups || Group.none + end + + def include_public_groups? + current_user.nil? || params.fetch(:all_available, true) + end end diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index 8876dacb368..d8bce77a405 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -18,12 +18,12 @@ # sort: string # non_archived: boolean # iids: integer[] +# my_reaction_emoji: string # class IssuableFinder include CreatedAtFilter NONE = '0'.freeze - IRRELEVANT_PARAMS_FOR_CACHE_KEY = %i[utf8 sort page state].freeze attr_accessor :current_user, :params @@ -46,6 +46,7 @@ class IssuableFinder items = by_iids(items) items = by_milestone(items) items = by_label(items) + items = by_my_reaction_emoji(items) # Filtering by project HAS TO be the last because we use the project IDs yielded by the issuable query thus far items = by_project(items) @@ -60,13 +61,17 @@ class IssuableFinder execute.find_by(*params) end + def row_count + Gitlab::IssuablesCountForState.new(self).for_state_or_opened(params[:state]) + end + # We often get counts for each state by running a query per state, and # counting those results. This is typically slower than running one query # (even if that query is slower than any of the individual state queries) and # grouping and counting within that query. # def count_by_state - count_params = params.merge(state: nil, sort: nil, for_counting: true) + count_params = params.merge(state: nil, sort: nil) labels_count = label_names.any? ? label_names.count : 1 finder = self.class.new(current_user, count_params) counts = Hash.new(0) @@ -89,16 +94,6 @@ class IssuableFinder execute.find_by!(*params) end - def state_counter_cache_key - cache_key(state_counter_cache_key_components) - end - - def clear_caches! - state_counter_cache_key_components_permutations.each do |components| - Rails.cache.delete(cache_key(components)) - end - end - def group return @group if defined?(@group) @@ -371,6 +366,14 @@ class IssuableFinder items end + def by_my_reaction_emoji(items) + if params[:my_reaction_emoji].present? && current_user + items = items.awarded(current_user, params[:my_reaction_emoji]) + end + + items + end + def by_due_date(items) if due_date? if filter_by_no_due_date? @@ -422,20 +425,4 @@ class IssuableFinder def current_user_related? params[:scope] == 'created-by-me' || params[:scope] == 'authored' || params[:scope] == 'assigned-to-me' end - - def state_counter_cache_key_components - opts = params.to_h - opts.except!(*IRRELEVANT_PARAMS_FOR_CACHE_KEY) - opts.delete_if { |_, value| value.blank? } - - ['issuables_count', klass.to_ability_name, opts.sort] - end - - def state_counter_cache_key_components_permutations - [state_counter_cache_key_components] - end - - def cache_key(components) - Digest::SHA1.hexdigest(components.flatten.join('-')) - end end diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb index 0ec42a4e6eb..d2275139c42 100644 --- a/app/finders/issues_finder.rb +++ b/app/finders/issues_finder.rb @@ -14,6 +14,7 @@ # search: string # label_name: string # sort: string +# my_reaction_emoji: string # class IssuesFinder < IssuableFinder CONFIDENTIAL_ACCESS_LEVEL = Gitlab::Access::REPORTER @@ -54,44 +55,10 @@ class IssuesFinder < IssuableFinder project.team.max_member_access(current_user.id) >= CONFIDENTIAL_ACCESS_LEVEL end - # Anonymous users can't see any confidential issues. - # - # Users without access to see _all_ confidential issues (as in - # `user_can_see_all_confidential_issues?`) are more complicated, because they - # can see confidential issues where: - # 1. They are an assignee. - # 2. They are an author. - # - # That's fine for most cases, but if we're just counting, we need to cache - # effectively. If we cached this accurately, we'd have a cache key for every - # authenticated user without sufficient access to the project. Instead, when - # we are counting, we treat them as if they can't see any confidential issues. - # - # This does mean the counts may be wrong for those users, but avoids an - # explosion in cache keys. - def user_cannot_see_confidential_issues?(for_counting: false) + def user_cannot_see_confidential_issues? return false if user_can_see_all_confidential_issues? - current_user.blank? || for_counting || params[:for_counting] - end - - def state_counter_cache_key_components - extra_components = [ - user_can_see_all_confidential_issues?, - user_cannot_see_confidential_issues?(for_counting: true) - ] - - super + extra_components - end - - def state_counter_cache_key_components_permutations - # Ignore the last two, as we'll provide both options for them. - components = super.first[0..-3] - - [ - components + [false, true], - components + [true, false] - ] + current_user.blank? end def by_assignee(items) diff --git a/app/finders/merge_requests_finder.rb b/app/finders/merge_requests_finder.rb index 771da3d441d..d0687d28c21 100644 --- a/app/finders/merge_requests_finder.rb +++ b/app/finders/merge_requests_finder.rb @@ -16,6 +16,7 @@ # label_name: string # sort: string # non_archived: boolean +# my_reaction_emoji: string # class MergeRequestsFinder < IssuableFinder def klass diff --git a/app/finders/move_to_project_finder.rb b/app/finders/move_to_project_finder.rb index 79eb45568be..038d5565a1e 100644 --- a/app/finders/move_to_project_finder.rb +++ b/app/finders/move_to_project_finder.rb @@ -9,6 +9,7 @@ class MoveToProjectFinder projects = @user.projects_where_can_admin_issues projects = projects.search(search) if search.present? projects = projects.excluding_project(from_project) + projects = projects.order_id_desc # infinite scroll using offset projects = projects.where('projects.id < ?', offset_id) if offset_id.present? diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb index 3edb029cb66..2617c1cd4e2 100644 --- a/app/finders/projects_finder.rb +++ b/app/finders/projects_finder.rb @@ -121,13 +121,22 @@ class ProjectsFinder < UnionFinder end def sort(items) - params[:sort].present? ? items.sort_by_attr(params[:sort]) : items + params[:sort].present? ? items.sort_by_attr(params[:sort]) : items.order_id_desc end def by_archived(projects) - # Back-compatibility with the places where `params[:archived]` can be set explicitly to `false` - params[:non_archived] = !Gitlab::Utils.to_boolean(params[:archived]) if params.key?(:archived) - - params[:non_archived] ? projects.non_archived : projects + if params[:non_archived] + projects.non_archived + elsif params.key?(:archived) # Back-compatibility with the places where `params[:archived]` can be set explicitly to `false` + if params[:archived] == 'only' + projects.archived + elsif Gitlab::Utils.to_boolean(params[:archived]) + projects + else + projects.non_archived + end + else + projects + end end end diff --git a/app/finders/todos_finder.rb b/app/finders/todos_finder.rb index eec9fd4ca9c..6ad807867b7 100644 --- a/app/finders/todos_finder.rb +++ b/app/finders/todos_finder.rb @@ -118,7 +118,7 @@ class TodosFinder end def sort(items) - params[:sort] ? items.sort_by_attr(params[:sort]) : items.reorder(id: :desc) + params[:sort] ? items.sort_by_attr(params[:sort]) : items.order_id_desc end def by_action(items) |