summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhttp://jneen.net/ <jneen@jneen.net>2016-08-11 15:12:52 -0700
committerhttp://jneen.net/ <jneen@jneen.net>2016-08-30 11:35:06 -0700
commite208765a92748086cacbc56225e827c8463750a5 (patch)
treebe9bb5c39c1b88cb3bab21d05c7a6a07398b4f7e
parent5853c96b49010aaf33b85caeb94dfc18873d5656 (diff)
downloadgitlab-ce-e208765a92748086cacbc56225e827c8463750a5.tar.gz
add policies, and factor out ProjectPolicy
-rw-r--r--app/models/ability.rb35
-rw-r--r--app/policies/base_policy.rb25
-rw-r--r--app/policies/project_policy.rb202
3 files changed, 231 insertions, 31 deletions
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 891c5ba9276..4f0ffa09a1f 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -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)
diff --git a/app/policies/base_policy.rb b/app/policies/base_policy.rb
new file mode 100644
index 00000000000..3f52b0b005a
--- /dev/null
+++ b/app/policies/base_policy.rb
@@ -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
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
new file mode 100644
index 00000000000..1e82070e62a
--- /dev/null
+++ b/app/policies/project_policy.rb
@@ -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