add policies, and factor out ProjectPolicy
This commit is contained in:
parent
5853c96b49
commit
e208765a92
|
@ -71,7 +71,7 @@ class Ability
|
|||
def abilities_by_subject_class(user:, subject:)
|
||||
case 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 Note then note_abilities(user, subject)
|
||||
when ProjectSnippet then project_snippet_abilities(user, subject)
|
||||
|
@ -85,7 +85,7 @@ class Ability
|
|||
when ExternalIssue, Deployment, Environment then project_abilities(user, subject.project)
|
||||
when Ci::Runner then runner_abilities(user, subject)
|
||||
else []
|
||||
end.concat(global_abilities(user))
|
||||
end + global_abilities(user)
|
||||
end
|
||||
|
||||
# List of possible abilities for anonymous user
|
||||
|
@ -193,35 +193,8 @@ class Ability
|
|||
end
|
||||
|
||||
def project_abilities(user, project)
|
||||
rules = []
|
||||
|
||||
# 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)
|
||||
# temporary patch, deleteme before merge
|
||||
ProjectPolicy.new(user, project).abilities.to_a
|
||||
end
|
||||
|
||||
def project_team_rules(team, user)
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
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
|
|
@ -0,0 +1,202 @@
|
|||
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
|
Loading…
Reference in New Issue