Commit 8272ec9a authored by Douwe Maan's avatar Douwe Maan Committed by Bob Van Landuyt

Update policies to make archived projects completely read-only

parent 267a9096
...@@ -11,7 +11,7 @@ module Ci ...@@ -11,7 +11,7 @@ module Ci
end end
condition(:owner_of_job) do condition(:owner_of_job) do
can?(:developer_access) && @subject.triggered_by?(@user) @subject.triggered_by?(@user)
end end
rule { protected_ref }.policy do rule { protected_ref }.policy do
...@@ -19,6 +19,6 @@ module Ci ...@@ -19,6 +19,6 @@ module Ci
prevent :erase_build prevent :erase_build
end end
rule { can?(:master_access) | owner_of_job }.enable :erase_build rule { can?(:admin_build) | (can?(:update_build) & owner_of_job) }.enable :erase_build
end end
end end
...@@ -7,23 +7,17 @@ module Ci ...@@ -7,23 +7,17 @@ module Ci
end end
condition(:owner_of_schedule) do condition(:owner_of_schedule) do
can?(:developer_access) && pipeline_schedule.owned_by?(@user) pipeline_schedule.owned_by?(@user)
end end
condition(:non_owner_of_schedule) do rule { can?(:create_pipeline) }.enable :play_pipeline_schedule
!pipeline_schedule.owned_by?(@user)
end
rule { can?(:developer_access) }.policy do
enable :play_pipeline_schedule
end
rule { can?(:master_access) | owner_of_schedule }.policy do rule { can?(:admin_pipeline) | (can?(:update_build) & owner_of_schedule) }.policy do
enable :update_pipeline_schedule enable :update_pipeline_schedule
enable :admin_pipeline_schedule enable :admin_pipeline_schedule
end end
rule { can?(:master_access) & non_owner_of_schedule }.policy do rule { can?(:admin_pipeline_schedule) & ~owner_of_schedule }.policy do
enable :take_ownership_pipeline_schedule enable :take_ownership_pipeline_schedule
end end
......
...@@ -3,7 +3,6 @@ class NotePolicy < BasePolicy ...@@ -3,7 +3,6 @@ class NotePolicy < BasePolicy
delegate { @subject.noteable if @subject.noteable.lockable? } delegate { @subject.noteable if @subject.noteable.lockable? }
condition(:is_author) { @user && @subject.author == @user } condition(:is_author) { @user && @subject.author == @user }
condition(:for_merge_request, scope: :subject) { @subject.for_merge_request? }
condition(:is_noteable_author) { @user && @subject.noteable.author_id == @user.id } condition(:is_noteable_author) { @user && @subject.noteable.author_id == @user.id }
condition(:editable, scope: :subject) { @subject.editable? } condition(:editable, scope: :subject) { @subject.editable? }
...@@ -16,7 +15,7 @@ class NotePolicy < BasePolicy ...@@ -16,7 +15,7 @@ class NotePolicy < BasePolicy
enable :resolve_note enable :resolve_note
end end
rule { for_merge_request & is_noteable_author }.policy do rule { is_noteable_author }.policy do
enable :resolve_note enable :resolve_note
end end
end end
class ProjectPolicy < BasePolicy class ProjectPolicy < BasePolicy
def self.create_read_update_admin(name) READONLY_FEATURES_WHEN_ARCHIVED = %i[
issue
list
merge_request
label
milestone
project_snippet
wiki
note
pipeline
pipeline_schedule
build
trigger
environment
deployment
commit_status
container_image
pages
cluster
].freeze
def self.create_read_update_admin_destroy(name)
[ [
:"create_#{name}",
:"read_#{name}", :"read_#{name}",
*create_update_admin_destroy(name)
]
end
def self.create_update_admin_destroy(name)
[
:"create_#{name}",
:"update_#{name}", :"update_#{name}",
:"admin_#{name}" :"admin_#{name}",
:"destroy_#{name}"
] ]
end end
...@@ -15,7 +43,7 @@ class ProjectPolicy < BasePolicy ...@@ -15,7 +43,7 @@ class ProjectPolicy < BasePolicy
end end
desc "Project has public builds enabled" desc "Project has public builds enabled"
condition(:public_builds, scope: :subject) { project.public_builds? } condition(:public_builds, scope: :subject, score: 0) { project.public_builds? }
# For guest access we use #team_member? so we can use # For guest access we use #team_member? so we can use
# project.members, which gets cached in subject scope. # project.members, which gets cached in subject scope.
...@@ -35,7 +63,7 @@ class ProjectPolicy < BasePolicy ...@@ -35,7 +63,7 @@ class ProjectPolicy < BasePolicy
condition(:master) { team_access_level >= Gitlab::Access::MASTER } condition(:master) { team_access_level >= Gitlab::Access::MASTER }
desc "Project is public" desc "Project is public"
condition(:public_project, scope: :subject) { project.public? } condition(:public_project, scope: :subject, score: 0) { project.public? }
desc "Project is visible to internal users" desc "Project is visible to internal users"
condition(:internal_access) do condition(:internal_access) do
...@@ -46,7 +74,7 @@ class ProjectPolicy < BasePolicy ...@@ -46,7 +74,7 @@ class ProjectPolicy < BasePolicy
condition(:group_member, scope: :subject) { project_group_member? } condition(:group_member, scope: :subject) { project_group_member? }
desc "Project is archived" desc "Project is archived"
condition(:archived, scope: :subject) { project.archived? } condition(:archived, scope: :subject, score: 0) { project.archived? }
condition(:default_issues_tracker, scope: :subject) { project.default_issues_tracker? } condition(:default_issues_tracker, scope: :subject) { project.default_issues_tracker? }
...@@ -56,10 +84,10 @@ class ProjectPolicy < BasePolicy ...@@ -56,10 +84,10 @@ class ProjectPolicy < BasePolicy
end end
desc "Project has an external wiki" desc "Project has an external wiki"
condition(:has_external_wiki, scope: :subject) { project.has_external_wiki? } condition(:has_external_wiki, scope: :subject, score: 0) { project.has_external_wiki? }
desc "Project has request access enabled" desc "Project has request access enabled"
condition(:request_access_enabled, scope: :subject) { project.request_access_enabled } condition(:request_access_enabled, scope: :subject, score: 0) { project.request_access_enabled }
desc "Has merge requests allowing pushes to user" desc "Has merge requests allowing pushes to user"
condition(:has_merge_requests_allowing_pushes, scope: :subject) do condition(:has_merge_requests_allowing_pushes, scope: :subject) do
...@@ -231,37 +259,45 @@ class ProjectPolicy < BasePolicy ...@@ -231,37 +259,45 @@ class ProjectPolicy < BasePolicy
end end
rule { archived }.policy do rule { archived }.policy do
prevent :create_merge_request
prevent :push_to_delete_protected_branch
prevent :push_code prevent :push_code
prevent :update_merge_request prevent :push_to_delete_protected_branch
prevent :admin_merge_request prevent :request_access
prevent :upload_file
prevent :resolve_note
READONLY_FEATURES_WHEN_ARCHIVED.each do |feature|
prevent(*create_update_admin_destroy(feature))
end
end
rule { issues_disabled }.policy do
prevent(*create_read_update_admin_destroy(:issue))
end end
rule { merge_requests_disabled | repository_disabled }.policy do rule { merge_requests_disabled | repository_disabled }.policy do
prevent(*create_read_update_admin(:merge_request)) prevent(*create_read_update_admin_destroy(:merge_request))
end end
rule { issues_disabled & merge_requests_disabled }.policy do rule { issues_disabled & merge_requests_disabled }.policy do
prevent(*create_read_update_admin(:label)) prevent(*create_read_update_admin_destroy(:label))
prevent(*create_read_update_admin(:milestone)) prevent(*create_read_update_admin_destroy(:milestone))
end end
rule { snippets_disabled }.policy do rule { snippets_disabled }.policy do
prevent(*create_read_update_admin(:project_snippet)) prevent(*create_read_update_admin_destroy(:project_snippet))
end end
rule { wiki_disabled & ~has_external_wiki }.policy do rule { wiki_disabled & ~has_external_wiki }.policy do
prevent(*create_read_update_admin(:wiki)) prevent(*create_read_update_admin_destroy(:wiki))
prevent(:download_wiki_code) prevent(:download_wiki_code)
end end
rule { builds_disabled | repository_disabled }.policy do rule { builds_disabled | repository_disabled }.policy do
prevent(*create_read_update_admin(:build)) prevent(*create_update_admin_destroy(:pipeline))
prevent(*(create_read_update_admin(:pipeline) - [:read_pipeline])) prevent(*create_read_update_admin_destroy(:build))
prevent(*create_read_update_admin(:pipeline_schedule)) prevent(*create_read_update_admin_destroy(:pipeline_schedule))
prevent(*create_read_update_admin(:environment)) prevent(*create_read_update_admin_destroy(:environment))
prevent(*create_read_update_admin(:deployment)) prevent(*create_read_update_admin_destroy(:deployment))
end end
rule { repository_disabled }.policy do rule { repository_disabled }.policy do
...@@ -272,7 +308,7 @@ class ProjectPolicy < BasePolicy ...@@ -272,7 +308,7 @@ class ProjectPolicy < BasePolicy
end end
rule { container_registry_disabled }.policy do rule { container_registry_disabled }.policy do
prevent(*create_read_update_admin(:container_image)) prevent(*create_read_update_admin_destroy(:container_image))
end end
rule { anonymous & ~public_project }.prevent_all rule { anonymous & ~public_project }.prevent_all
...@@ -314,13 +350,6 @@ class ProjectPolicy < BasePolicy ...@@ -314,13 +350,6 @@ class ProjectPolicy < BasePolicy
enable :read_pipeline_schedule enable :read_pipeline_schedule
end end
rule { issues_disabled }.policy do
prevent :create_issue
prevent :update_issue
prevent :admin_issue
prevent :read_issue
end
# These rules are included to allow maintainers of projects to push to certain # These rules are included to allow maintainers of projects to push to certain
# to run pipelines for the branches they have access to. # to run pipelines for the branches they have access to.
rule { can?(:public_access) & has_merge_requests_allowing_pushes }.policy do rule { can?(:public_access) & has_merge_requests_allowing_pushes }.policy do
......
...@@ -136,13 +136,49 @@ describe ProjectPolicy do ...@@ -136,13 +136,49 @@ describe ProjectPolicy do
end end
end end
shared_examples 'archived project policies' do
let(:feature_write_abilities) do
described_class::READONLY_FEATURES_WHEN_ARCHIVED.flat_map do |feature|
described_class.create_update_admin_destroy(feature)
end
end
let(:other_write_abilities) do
%i[
push_to_delete_protected_branch
push_code
request_access
upload_file
resolve_note
]
end
context 'when the project is archived' do
before do
project.archived = true
end
it 'disables write actions on all relevant project features' do
expect_disallowed(*feature_write_abilities)
end
it 'disables some other important write actions' do
expect_disallowed(*other_write_abilities)
end
it 'does not disable other other abilities' do
expect_allowed(*(regular_abilities - feature_write_abilities - other_write_abilities))
end
end
end
shared_examples 'project policies as anonymous' do shared_examples 'project policies as anonymous' do
context 'abilities for public projects' do context 'abilities for public projects' do
context 'when a project has pending invites' do context 'when a project has pending invites' do
let(:group) { create(:group, :public) } let(:group) { create(:group, :public) }
let(:project) { create(:project, :public, namespace: group) } let(:project) { create(:project, :public, namespace: group) }
let(:user_permissions) { [:create_project, :create_issue, :create_note, :upload_file] } let(:user_permissions) { [:create_project, :create_issue, :create_note, :upload_file] }
let(:anonymous_permissions) { guest_permissions - user_permissions } let(:anonymous_permissions) { guest_permissions - user_permissions }
subject { described_class.new(nil, project) } subject { described_class.new(nil, project) }
...@@ -154,6 +190,10 @@ describe ProjectPolicy do ...@@ -154,6 +190,10 @@ describe ProjectPolicy do
expect_allowed(*anonymous_permissions) expect_allowed(*anonymous_permissions)
expect_disallowed(*user_permissions) expect_disallowed(*user_permissions)
end end
it_behaves_like 'archived project policies' do
let(:regular_abilities) { anonymous_permissions }
end
end end
end end
...@@ -184,6 +224,10 @@ describe ProjectPolicy do ...@@ -184,6 +224,10 @@ describe ProjectPolicy do
expect_disallowed(*owner_permissions) expect_disallowed(*owner_permissions)
end end
it_behaves_like 'archived project policies' do
let(:regular_abilities) { guest_permissions }
end
context 'public builds enabled' do context 'public builds enabled' do
it do it do
expect_allowed(*guest_permissions) expect_allowed(*guest_permissions)
...@@ -224,12 +268,15 @@ describe ProjectPolicy do ...@@ -224,12 +268,15 @@ describe ProjectPolicy do
it do it do
expect_allowed(*guest_permissions) expect_allowed(*guest_permissions)
expect_allowed(*reporter_permissions) expect_allowed(*reporter_permissions)
expect_allowed(*reporter_permissions)
expect_allowed(*team_member_reporter_permissions) expect_allowed(*team_member_reporter_permissions)
expect_disallowed(*developer_permissions) expect_disallowed(*developer_permissions)
expect_disallowed(*master_permissions) expect_disallowed(*master_permissions)
expect_disallowed(*owner_permissions) expect_disallowed(*owner_permissions)
end end
it_behaves_like 'archived project policies' do
let(:regular_abilities) { reporter_permissions }
end
end end
end end
...@@ -247,6 +294,10 @@ describe ProjectPolicy do ...@@ -247,6 +294,10 @@ describe ProjectPolicy do
expect_disallowed(*master_permissions) expect_disallowed(*master_permissions)
expect_disallowed(*owner_permissions) expect_disallowed(*owner_permissions)
end end
it_behaves_like 'archived project policies' do
let(:regular_abilities) { developer_permissions }
end
end end
end end
...@@ -264,6 +315,10 @@ describe ProjectPolicy do ...@@ -264,6 +315,10 @@ describe ProjectPolicy do
expect_allowed(*master_permissions) expect_allowed(*master_permissions)
expect_disallowed(*owner_permissions) expect_disallowed(*owner_permissions)
end end
it_behaves_like 'archived project policies' do
let(:regular_abilities) { master_permissions }
end
end end
end end
...@@ -281,6 +336,10 @@ describe ProjectPolicy do ...@@ -281,6 +336,10 @@ describe ProjectPolicy do
expect_allowed(*master_permissions) expect_allowed(*master_permissions)
expect_allowed(*owner_permissions) expect_allowed(*owner_permissions)
end end
it_behaves_like 'archived project policies' do
let(:regular_abilities) { owner_permissions }
end
end end
end end
...@@ -298,6 +357,10 @@ describe ProjectPolicy do ...@@ -298,6 +357,10 @@ describe ProjectPolicy do
expect_allowed(*master_permissions) expect_allowed(*master_permissions)
expect_allowed(*owner_permissions) expect_allowed(*owner_permissions)
end end
it_behaves_like 'archived project policies' do
let(:regular_abilities) { owner_permissions }
end
end end
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