Commit 1ca9b335 authored by http://jneen.net/'s avatar http://jneen.net/

add support for anonymous abilities

parent 29b1623a
...@@ -71,7 +71,7 @@ class Ability ...@@ -71,7 +71,7 @@ class Ability
def abilities_by_subject_class(user:, subject:) def abilities_by_subject_class(user:, subject:)
case subject case subject
when CommitStatus then commit_status_abilities(user, subject) when CommitStatus then commit_status_abilities(user, subject)
when Project then ProjectPolicy.new(user, subject).abilities when Project then ProjectPolicy.abilities(user, subject)
when Issue then issue_abilities(user, subject) when Issue then issue_abilities(user, subject)
when Note then note_abilities(user, subject) when Note then note_abilities(user, subject)
when ProjectSnippet then project_snippet_abilities(user, subject) when ProjectSnippet then project_snippet_abilities(user, subject)
...@@ -96,8 +96,10 @@ class Ability ...@@ -96,8 +96,10 @@ class Ability
anonymous_project_snippet_abilities(subject) anonymous_project_snippet_abilities(subject)
elsif subject.is_a?(CommitStatus) elsif subject.is_a?(CommitStatus)
anonymous_commit_status_abilities(subject) anonymous_commit_status_abilities(subject)
elsif subject.is_a?(Project) || subject.respond_to?(:project) elsif subject.is_a?(Project)
anonymous_project_abilities(subject) ProjectPolicy.abilities(nil, subject)
elsif subject.respond_to?(:project)
ProjectPolicy.abilities(nil, subject.project)
elsif subject.is_a?(Group) || subject.respond_to?(:group) elsif subject.is_a?(Group) || subject.respond_to?(:group)
anonymous_group_abilities(subject) anonymous_group_abilities(subject)
elsif subject.is_a?(User) elsif subject.is_a?(User)
...@@ -194,174 +196,7 @@ class Ability ...@@ -194,174 +196,7 @@ class Ability
def project_abilities(user, project) def project_abilities(user, project)
# temporary patch, deleteme before merge # temporary patch, deleteme before merge
ProjectPolicy.new(user, project).abilities.to_a ProjectPolicy.abilities(user, project).to_a
end
def project_team_rules(team, user)
# Rules based on role in project
if team.master?(user)
project_master_rules
elsif team.developer?(user)
project_dev_rules
elsif team.reporter?(user)
project_report_rules
elsif team.guest?(user)
project_guest_rules
else
[]
end
end
def public_project_rules
@public_project_rules ||= project_guest_rules + [
:download_code,
:fork_project,
:read_commit_status,
:read_pipeline,
:read_container_image
]
end
def project_guest_rules
@project_guest_rules ||= [
:read_project,
:read_wiki,
:read_issue,
:read_board,
:read_list,
:read_label,
:read_milestone,
:read_project_snippet,
:read_project_member,
:read_merge_request,
:read_note,
:create_project,
:create_issue,
:create_note,
:upload_file
]
end
def project_report_rules
@project_report_rules ||= project_guest_rules + [
:download_code,
:fork_project,
:create_project_snippet,
:update_issue,
:admin_issue,
:admin_label,
:admin_list,
:read_commit_status,
:read_build,
:read_container_image,
:read_pipeline,
:read_environment,
:read_deployment
]
end
def project_dev_rules
@project_dev_rules ||= project_report_rules + [
:admin_merge_request,
:update_merge_request,
:create_commit_status,
:update_commit_status,
:create_build,
:update_build,
:create_pipeline,
:update_pipeline,
:create_merge_request,
:create_wiki,
:push_code,
:resolve_note,
:create_container_image,
:update_container_image,
:create_environment,
:create_deployment
]
end
def project_archived_rules
@project_archived_rules ||= [
:create_merge_request,
:push_code,
:push_code_to_protected_branches,
:update_merge_request,
:admin_merge_request
]
end
def project_master_rules
@project_master_rules ||= project_dev_rules + [
:push_code_to_protected_branches,
:update_project_snippet,
:update_environment,
:update_deployment,
:admin_milestone,
:admin_project_snippet,
:admin_project_member,
:admin_merge_request,
:admin_note,
:admin_wiki,
:admin_project,
:admin_commit_status,
:admin_build,
:admin_container_image,
:admin_pipeline,
:admin_environment,
:admin_deployment
]
end
def project_owner_rules
@project_owner_rules ||= project_master_rules + [
:change_namespace,
:change_visibility_level,
:rename_project,
:remove_project,
:archive_project,
:remove_fork_project,
:destroy_merge_request,
:destroy_issue
]
end
def project_disabled_features_rules(project)
rules = []
unless project.issues_enabled
rules += named_abilities('issue')
end
unless project.merge_requests_enabled
rules += named_abilities('merge_request')
end
unless project.issues_enabled or project.merge_requests_enabled
rules += named_abilities('label')
rules += named_abilities('milestone')
end
unless project.snippets_enabled
rules += named_abilities('project_snippet')
end
unless project.has_wiki?
rules += named_abilities('wiki')
end
unless project.builds_enabled
rules += named_abilities('build')
rules += named_abilities('pipeline')
rules += named_abilities('environment')
rules += named_abilities('deployment')
end
unless project.container_registry_enabled
rules += named_abilities('container_image')
end
rules
end end
def group_abilities(user, group) def group_abilities(user, group)
...@@ -569,15 +404,6 @@ class Ability ...@@ -569,15 +404,6 @@ class Ability
current_application_settings.restricted_visibility_levels.include?(Gitlab::VisibilityLevel::PUBLIC) current_application_settings.restricted_visibility_levels.include?(Gitlab::VisibilityLevel::PUBLIC)
end end
def named_abilities(name)
[
:"read_#{name}",
:"create_#{name}",
:"update_#{name}",
:"admin_#{name}"
]
end
def filter_confidential_issues_abilities(user, issue, rules) def filter_confidential_issues_abilities(user, issue, rules)
return rules if user.admin? || !issue.confidential? return rules if user.admin? || !issue.confidential?
...@@ -589,13 +415,5 @@ class Ability ...@@ -589,13 +415,5 @@ class Ability
rules rules
end end
def project_group_member?(project, user)
project.group &&
(
project.group.members.exists?(user_id: user.id) ||
project.group.requesters.exists?(user_id: user.id)
)
end
end end
end end
class BasePolicy class BasePolicy
def self.abilities(user, subject)
new(user, subject).abilities
end
attr_reader :user, :subject
def initialize(user, subject) def initialize(user, subject)
@user = user @user = user
@subject = subject @subject = subject
end end
def abilities def abilities
@can = Set.new return anonymous_abilities if @user.nil?
@cannot = Set.new collect_rules { rules }
generate! end
@can - @cannot
def anonymous_abilities
collect_rules { anonymous_rules }
end end
def generate! def generate!
...@@ -22,4 +29,15 @@ class BasePolicy ...@@ -22,4 +29,15 @@ class BasePolicy
def cannot!(*rules) def cannot!(*rules)
@cannot.merge(rules) @cannot.merge(rules)
end end
private
def collect_rules(&b)
return Set.new if @subject.nil?
@can = Set.new
@cannot = Set.new
yield
@can - @cannot
end
end end
...@@ -28,6 +28,7 @@ class ProjectPolicy < BasePolicy ...@@ -28,6 +28,7 @@ class ProjectPolicy < BasePolicy
can! :update_issue can! :update_issue
can! :admin_issue can! :admin_issue
can! :admin_label can! :admin_label
can! :admin_list
can! :read_commit_status can! :read_commit_status
can! :read_build can! :read_build
can! :read_container_image can! :read_container_image
...@@ -48,6 +49,7 @@ class ProjectPolicy < BasePolicy ...@@ -48,6 +49,7 @@ class ProjectPolicy < BasePolicy
can! :create_merge_request can! :create_merge_request
can! :create_wiki can! :create_wiki
can! :push_code can! :push_code
can! :resolve_note
can! :create_container_image can! :create_container_image
can! :update_container_image can! :update_container_image
can! :create_environment can! :create_environment
...@@ -98,8 +100,8 @@ class ProjectPolicy < BasePolicy ...@@ -98,8 +100,8 @@ class ProjectPolicy < BasePolicy
end end
# Push abilities on the users team role # Push abilities on the users team role
def team_access! def team_access!(user)
access = project.team.max_member_access(@user.id) access = project.team.max_member_access(user.id)
return if access < Gitlab::Access::GUEST return if access < Gitlab::Access::GUEST
guest_access! guest_access!
...@@ -140,7 +142,7 @@ class ProjectPolicy < BasePolicy ...@@ -140,7 +142,7 @@ class ProjectPolicy < BasePolicy
cannot!(*named_abilities(:project_snippet)) cannot!(*named_abilities(:project_snippet))
end end
unless project.wiki_enabled unless project.has_wiki?
cannot!(*named_abilities(:wiki)) cannot!(*named_abilities(:wiki))
end end
...@@ -156,16 +158,16 @@ class ProjectPolicy < BasePolicy ...@@ -156,16 +158,16 @@ class ProjectPolicy < BasePolicy
end end
end end
def generate! def rules
team_access! team_access!(user)
owner = @user.admin? || owner = user.admin? ||
project.owner == @user || project.owner == user ||
(project.group && project.group.has_owner?(@user)) (project.group && project.group.has_owner?(user))
owner_access! if owner owner_access! if owner
if project.public? || (project.internal? && !@user.external?) if project.public? || (project.internal? && !user.external?)
guest_access! guest_access!
public_access! public_access!
...@@ -173,7 +175,7 @@ class ProjectPolicy < BasePolicy ...@@ -173,7 +175,7 @@ class ProjectPolicy < BasePolicy
can! :read_build if project.public_builds? can! :read_build if project.public_builds?
if project.request_access_enabled && if project.request_access_enabled &&
!(owner || project.team.member?(@user) || project_group_member?) !(owner || project.team.member?(user) || project_group_member?(user))
can! :request_access can! :request_access
end end
end end
...@@ -183,11 +185,35 @@ class ProjectPolicy < BasePolicy ...@@ -183,11 +185,35 @@ class ProjectPolicy < BasePolicy
disabled_features! disabled_features!
end end
def project_group_member? def anonymous_rules
return unless project.public?
can! :read_project
can! :read_board
can! :read_list
can! :read_wiki
can! :read_label
can! :read_milestone
can! :read_project_snippet
can! :read_project_member
can! :read_merge_request
can! :read_note
can! :read_pipeline
can! :read_commit_status
can! :read_container_image
can! :download_code
# Allow to read builds by anonymous user if guests are allowed
can! :read_build if project.public_builds?
disabled_features!
end
def project_group_member?(user)
project.group && project.group &&
( (
project.group.members.exists?(user_id: @user.id) || project.group.members.exists?(user_id: user.id) ||
project.group.requesters.exists?(user_id: @user.id) project.group.requesters.exists?(user_id: user.id)
) )
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment