diff options
author | Eric Eastwood <contact@ericeastwood.com> | 2018-03-27 20:39:18 +0300 |
---|---|---|
committer | Eric Eastwood <contact@ericeastwood.com> | 2018-03-27 20:39:18 +0300 |
commit | de0c4730bb83b94195678e5ad4865ea648e6585f (patch) | |
tree | 3ea0fd48c5736b0f5b328f117c3db0508a371d22 /app/models/ability.rb | |
parent | dc5b5130d573a48fc34fa62862a1ad6da776b0d0 (diff) | |
parent | a1cde68d208437a470267e28ccff66fe8be88c2e (diff) |
Merge branch 'master' into add-canary-favicon
Diffstat (limited to 'app/models/ability.rb')
-rw-r--r-- | app/models/ability.rb | 94 |
1 files changed, 50 insertions, 44 deletions
diff --git a/app/models/ability.rb b/app/models/ability.rb index f3692a5a067..6dae49f38dc 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -1,35 +1,20 @@ +require_dependency 'declarative_policy' + class Ability class << self # Given a list of users and a project this method returns the users that can # read the given project. def users_that_can_read_project(users, project) - if project.public? - users - else - users.select do |user| - if user.admin? - true - elsif project.internal? && !user.external? - true - elsif project.owner == user - true - elsif project.team.members.include?(user) - true - else - false - end - end + DeclarativePolicy.subject_scope do + users.select { |u| allowed?(u, :read_project, project) } end end # Given a list of users and a snippet this method returns the users that can # read the given snippet. def users_that_can_read_personal_snippet(users, snippet) - case snippet.visibility_level - when Snippet::INTERNAL, Snippet::PUBLIC - users - when Snippet::PRIVATE - users.include?(snippet.author) ? [snippet.author] : [] + DeclarativePolicy.subject_scope do + users.select { |u| allowed?(u, :read_personal_snippet, snippet) } end end @@ -37,43 +22,64 @@ class Ability # # issues - The issues to reduce down to those readable by the user. # user - The User for which to check the issues - def issues_readable_by_user(issues, user = nil) - return issues if user && user.admin? + # filters - A hash of abilities and filters to apply if the user lacks this + # ability + def issues_readable_by_user(issues, user = nil, filters: {}) + issues = apply_filters_if_needed(issues, user, filters) - issues.select { |issue| issue.visible_to_user?(user) } + DeclarativePolicy.user_scope do + issues.select { |issue| issue.visible_to_user?(user) } + end end - # TODO: make this private and use the actual abilities stuff for this - def can_edit_note?(user, note) - return false if !note.editable? || !user.present? - return true if note.author == user || user.admin? + # Returns an Array of MergeRequests that can be read by the given user. + # + # merge_requests - MRs out of which to collect mr's readable by the user. + # user - The User for which to check the merge_requests + # filters - A hash of abilities and filters to apply if the user lacks this + # ability + def merge_requests_readable_by_user(merge_requests, user = nil, filters: {}) + merge_requests = apply_filters_if_needed(merge_requests, user, filters) - if note.project - max_access_level = note.project.team.max_member_access(user.id) - max_access_level >= Gitlab::Access::MASTER - else - false + DeclarativePolicy.user_scope do + merge_requests.select { |mr| allowed?(user, :read_merge_request, mr) } end end - def allowed?(user, action, subject = :global) - allowed(user, subject).include?(action) + def can_edit_note?(user, note) + allowed?(user, :edit_note, note) end - def allowed(user, subject = :global) - return BasePolicy::RuleSet.none if subject.nil? - return uncached_allowed(user, subject) unless RequestStore.active? + def allowed?(user, action, subject = :global, opts = {}) + if subject.is_a?(Hash) + opts, subject = subject, :global + end - user_key = user ? user.id : 'anonymous' - subject_key = subject == :global ? 'global' : "#{subject.class.name}/#{subject.id}" - key = "/ability/#{user_key}/#{subject_key}" - RequestStore[key] ||= uncached_allowed(user, subject).freeze + policy = policy_for(user, subject) + + case opts[:scope] + when :user + DeclarativePolicy.user_scope { policy.can?(action) } + when :subject + DeclarativePolicy.subject_scope { policy.can?(action) } + else + policy.can?(action) + end + end + + def policy_for(user, subject = :global) + cache = RequestStore.active? ? RequestStore : {} + DeclarativePolicy.policy_for(user, subject, cache: cache) end private - def uncached_allowed(user, subject) - BasePolicy.class_for(subject).abilities(user, subject) + def apply_filters_if_needed(elements, user, filters) + filters.each do |ability, filter| + elements = filter.call(elements) unless allowed?(user, ability) + end + + elements end end end |