From 4d904bf3521b4600db228c48214f3892e86ac72a Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Tue, 16 Aug 2016 11:10:34 -0700 Subject: [PATCH] port issues to Issu{able,e}Policy --- app/models/ability.rb | 6 ++++-- app/policies/base_policy.rb | 12 ++++++++++-- app/policies/issuable_policy.rb | 14 ++++++++++++++ app/policies/issue_policy.rb | 27 +++++++++++++++++++++++++++ app/policies/project_policy.rb | 3 +++ 5 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 app/policies/issuable_policy.rb create mode 100644 app/policies/issue_policy.rb diff --git a/app/models/ability.rb b/app/models/ability.rb index 5d2cbde4c0e..1ea97855e04 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -72,7 +72,7 @@ class Ability case subject when CommitStatus then commit_status_abilities(user, subject) when Project then ProjectPolicy.abilities(user, subject) - when Issue then issue_abilities(user, subject) + when Issue then IssuePolicy.abilities(user, subject) when Note then note_abilities(user, subject) when ProjectSnippet then project_snippet_abilities(user, subject) when PersonalSnippet then personal_snippet_abilities(user, subject) @@ -89,7 +89,7 @@ class Ability end # List of possible abilities for anonymous user - def anonymous_abilities(user, subject) + def anonymous_abilities(subject) if subject.is_a?(PersonalSnippet) anonymous_personal_snippet_abilities(subject) elsif subject.is_a?(ProjectSnippet) @@ -98,6 +98,8 @@ class Ability anonymous_commit_status_abilities(subject) elsif subject.is_a?(Project) ProjectPolicy.abilities(nil, subject) + elsif subject.is_a?(Issue) + IssuePolicy.abilities(nil, subject) elsif subject.respond_to?(:project) ProjectPolicy.abilities(nil, subject.project) elsif subject.is_a?(Group) || subject.respond_to?(:group) diff --git a/app/policies/base_policy.rb b/app/policies/base_policy.rb index 10ce38329c4..fd5d05a1bd1 100644 --- a/app/policies/base_policy.rb +++ b/app/policies/base_policy.rb @@ -3,6 +3,10 @@ class BasePolicy new(user, subject).abilities end + def self.class_for(subject) + "#{subject.class.name}Policy".constantize + end + attr_reader :user, :subject def initialize(user, subject) @user = user @@ -18,8 +22,12 @@ class BasePolicy collect_rules { anonymous_rules } end - def generate! - raise 'abstract' + def anonymous_rules + rules + end + + def delegate!(new_subject) + @can.merge(BasePolicy.class_for(new_subject).abilities(@user, new_subject)) end def can!(*rules) diff --git a/app/policies/issuable_policy.rb b/app/policies/issuable_policy.rb new file mode 100644 index 00000000000..c253f9a9399 --- /dev/null +++ b/app/policies/issuable_policy.rb @@ -0,0 +1,14 @@ +class IssuablePolicy < BasePolicy + def action_name + @subject.class.name.underscore + end + + def rules + if @user && (@subject.author == @user || @subject.assignee == @user) + can! :"read_#{action_name}" + can! :"update_#{action_name}" + end + + delegate! @subject.project + end +end diff --git a/app/policies/issue_policy.rb b/app/policies/issue_policy.rb new file mode 100644 index 00000000000..08538861364 --- /dev/null +++ b/app/policies/issue_policy.rb @@ -0,0 +1,27 @@ +class IssuePolicy < IssuablePolicy + def issue + @subject + end + + def rules + super + + if @subject.confidential? && !can_read_confidential? + cannot! :read_issue + cannot! :admin_issue + cannot! :update_issue + cannot! :read_issue + end + end + + private + + def can_read_confidential? + return false unless @user + return true if @user.admin? + return true if @subject.author == @user + return true if @subject.assignee == @user + return true if @subject.project.team.member?(@user, Gitlab::Access::REPORTER) + false + end +end diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index 95e8b71c102..4380b00d962 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -203,6 +203,9 @@ class ProjectPolicy < BasePolicy can! :read_container_image can! :download_code + # NB: may be overridden by IssuePolicy + can! :read_issue + # Allow to read builds by anonymous user if guests are allowed can! :read_build if project.public_builds?