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

add policies, and factor out ProjectPolicy

parent 5853c96b
...@@ -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 project_abilities(user, subject) when Project then ProjectPolicy.new(user, subject).abilities
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)
...@@ -85,7 +85,7 @@ class Ability ...@@ -85,7 +85,7 @@ class Ability
when ExternalIssue, Deployment, Environment then project_abilities(user, subject.project) when ExternalIssue, Deployment, Environment then project_abilities(user, subject.project)
when Ci::Runner then runner_abilities(user, subject) when Ci::Runner then runner_abilities(user, subject)
else [] else []
end.concat(global_abilities(user)) end + global_abilities(user)
end end
# List of possible abilities for anonymous user # List of possible abilities for anonymous user
...@@ -193,35 +193,8 @@ class Ability ...@@ -193,35 +193,8 @@ class Ability
end end
def project_abilities(user, project) def project_abilities(user, project)
rules = [] # temporary patch, deleteme before merge
ProjectPolicy.new(user, project).abilities.to_a
# Push abilities on the users team role
rules.push(*project_team_rules(project.team, user))
owner = user.admin? ||
project.owner == user ||
(project.group && project.group.has_owner?(user))
if owner
rules.push(*project_owner_rules)
end
if project.public? || (project.internal? && !user.external?)
rules.push(*public_project_rules)
# Allow to read builds for internal projects
rules << :read_build if project.public_builds?
unless owner || project.team.member?(user) || project_group_member?(project, user)
rules << :request_access if project.request_access_enabled
end
end
if project.archived?
rules -= project_archived_rules
end
rules - project_disabled_features_rules(project)
end end
def project_team_rules(team, user) def project_team_rules(team, user)
......
class BasePolicy
def initialize(user, subject)
@user = user
@subject = subject
end
def abilities
@can = Set.new
@cannot = Set.new
generate!
@can - @cannot
end
def generate!
raise 'abstract'
end
def can!(*rules)
@can.merge(rules)
end
def cannot!(*rules)
@cannot.merge(rules)
end
end
class ProjectPolicy < BasePolicy
def project
@subject
end
def guest_access!
can! :read_project
can! :read_board
can! :read_list
can! :read_wiki
can! :read_issue
can! :read_label
can! :read_milestone
can! :read_project_snippet
can! :read_project_member
can! :read_merge_request
can! :read_note
can! :create_project
can! :create_issue
can! :create_note
can! :upload_file
end
def reporter_access!
can! :download_code
can! :fork_project
can! :create_project_snippet
can! :update_issue
can! :admin_issue
can! :admin_label
can! :read_commit_status
can! :read_build
can! :read_container_image
can! :read_pipeline
can! :read_environment
can! :read_deployment
end
def developer_access!
can! :admin_merge_request
can! :update_merge_request
can! :create_commit_status
can! :update_commit_status
can! :create_build
can! :update_build
can! :create_pipeline
can! :update_pipeline
can! :create_merge_request
can! :create_wiki
can! :push_code
can! :create_container_image
can! :update_container_image
can! :create_environment
can! :create_deployment
end
def master_access!
can! :push_code_to_protected_branches
can! :update_project_snippet
can! :update_environment
can! :update_deployment
can! :admin_milestone
can! :admin_project_snippet
can! :admin_project_member
can! :admin_merge_request
can! :admin_note
can! :admin_wiki
can! :admin_project
can! :admin_commit_status
can! :admin_build
can! :admin_container_image
can! :admin_pipeline
can! :admin_environment
can! :admin_deployment
end
def public_access!
can! :download_code
can! :fork_project
can! :read_commit_status
can! :read_pipeline
can! :read_container_image
end
def owner_access!
guest_access!
reporter_access!
developer_access!
master_access!
can! :change_namespace
can! :change_visibility_level
can! :rename_project
can! :remove_project
can! :archive_project
can! :remove_fork_project
can! :destroy_merge_request
can! :destroy_issue
end
# Push abilities on the users team role
def team_access!
access = project.team.max_member_access(@user.id)
return if access < Gitlab::Access::GUEST
guest_access!
return if access < Gitlab::Access::REPORTER
reporter_access!
return if access < Gitlab::Access::DEVELOPER
developer_access!
return if access < Gitlab::Access::MASTER
master_access!
end
def archived_access!
cannot! :create_merge_request
cannot! :push_code
cannot! :push_code_to_protected_branches
cannot! :update_merge_request
cannot! :admin_merge_request
end
def disabled_features!
unless project.issues_enabled
cannot!(*named_abilities(:issue))
end
unless project.merge_requests_enabled
cannot!(*named_abilities(:merge_request))
end
unless project.issues_enabled or project.merge_requests_enabled
cannot!(*named_abilities(:label))
cannot!(*named_abilities(:milestone))
end
unless project.snippets_enabled
cannot!(*named_abilities(:project_snippet))
end
unless project.wiki_enabled
cannot!(*named_abilities(:wiki))
end
unless project.builds_enabled
cannot!(*named_abilities(:build))
cannot!(*named_abilities(:pipeline))
cannot!(*named_abilities(:environment))
cannot!(*named_abilities(:deployment))
end
unless project.container_registry_enabled
cannot!(*named_abilities(:container_image))
end
end
def generate!
team_access!
owner = @user.admin? ||
project.owner == @user ||
(project.group && project.group.has_owner?(@user))
owner_access! if owner
if project.public? || (project.internal? && !@user.external?)
guest_access!
public_access!
# Allow to read builds for internal projects
can! :read_build if project.public_builds?
if project.request_access_enabled &&
!(owner || project.team.member?(@user) || project_group_member?)
can! :request_access
end
end
archived_access! if project.archived?
disabled_features!
end
def project_group_member?
project.group &&
(
project.group.members.exists?(user_id: @user.id) ||
project.group.requesters.exists?(user_id: @user.id)
)
end
def named_abilities(name)
[
:"read_#{name}",
:"create_#{name}",
:"update_#{name}",
:"admin_#{name}"
]
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