Commit 3ecbbe3a authored by Dylan Griffith's avatar Dylan Griffith

Merge branch '221259-move-package-permissions-to-core' into 'master'

Move package permission declarations to core [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!36386
parents 8fc065bc b32f8ffb
...@@ -65,6 +65,7 @@ class Project < ApplicationRecord ...@@ -65,6 +65,7 @@ class Project < ApplicationRecord
cache_markdown_field :description, pipeline: :description cache_markdown_field :description, pipeline: :description
default_value_for :packages_enabled, true
default_value_for :archived, false default_value_for :archived, false
default_value_for :resolve_outdated_diff_discussions, false default_value_for :resolve_outdated_diff_discussions, false
default_value_for :container_registry_enabled, gitlab_config_features.container_registry default_value_for :container_registry_enabled, gitlab_config_features.container_registry
...@@ -446,6 +447,7 @@ class Project < ApplicationRecord ...@@ -446,6 +447,7 @@ class Project < ApplicationRecord
# Sometimes queries (e.g. using CTEs) require explicit disambiguation with table name # Sometimes queries (e.g. using CTEs) require explicit disambiguation with table name
scope :projects_order_id_desc, -> { reorder(self.arel_table['id'].desc) } scope :projects_order_id_desc, -> { reorder(self.arel_table['id'].desc) }
scope :with_packages, -> { joins(:packages) }
scope :in_namespace, ->(namespace_ids) { where(namespace_id: namespace_ids) } scope :in_namespace, ->(namespace_ids) { where(namespace_id: namespace_ids) }
scope :personal, ->(user) { where(namespace_id: user.namespace_id) } scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
scope :joined, ->(user) { where('namespace_id != ?', user.namespace_id) } scope :joined, ->(user) { where('namespace_id != ?', user.namespace_id) }
...@@ -866,6 +868,15 @@ class Project < ApplicationRecord ...@@ -866,6 +868,15 @@ class Project < ApplicationRecord
end end
end end
# Because we use default_value_for we need to be sure
# packages_enabled= method does exist even if we rollback migration.
# Otherwise many tests from spec/migrations will fail.
def packages_enabled=(value)
if has_attribute?(:packages_enabled)
write_attribute(:packages_enabled, value)
end
end
def cleanup def cleanup
@repository = nil @repository = nil
end end
......
...@@ -154,6 +154,9 @@ class ProjectPolicy < BasePolicy ...@@ -154,6 +154,9 @@ class ProjectPolicy < BasePolicy
::Feature.enabled?(:build_service_proxy, @subject) ::Feature.enabled?(:build_service_proxy, @subject)
end end
with_scope :subject
condition(:packages_disabled) { !@subject.packages_enabled }
features = %w[ features = %w[
merge_requests merge_requests
issues issues
...@@ -296,12 +299,17 @@ class ProjectPolicy < BasePolicy ...@@ -296,12 +299,17 @@ class ProjectPolicy < BasePolicy
enable :read_metrics_user_starred_dashboard enable :read_metrics_user_starred_dashboard
end end
rule { packages_disabled | repository_disabled }.policy do
prevent(*create_read_update_admin_destroy(:package))
end
rule { owner | admin | guest | group_member }.prevent :request_access rule { owner | admin | guest | group_member }.prevent :request_access
rule { ~request_access_enabled }.prevent :request_access rule { ~request_access_enabled }.prevent :request_access
rule { can?(:developer_access) & can?(:create_issue) }.enable :import_issues rule { can?(:developer_access) & can?(:create_issue) }.enable :import_issues
rule { can?(:developer_access) }.policy do rule { can?(:developer_access) }.policy do
enable :create_package
enable :admin_board enable :admin_board
enable :admin_merge_request enable :admin_merge_request
enable :admin_milestone enable :admin_milestone
...@@ -342,6 +350,7 @@ class ProjectPolicy < BasePolicy ...@@ -342,6 +350,7 @@ class ProjectPolicy < BasePolicy
end end
rule { can?(:maintainer_access) }.policy do rule { can?(:maintainer_access) }.policy do
enable :destroy_package
enable :admin_board enable :admin_board
enable :push_to_delete_protected_branch enable :push_to_delete_protected_branch
enable :update_snippet enable :update_snippet
......
...@@ -130,7 +130,6 @@ module EE ...@@ -130,7 +130,6 @@ module EE
scope :with_active_prometheus_service, -> { joins(:prometheus_service).merge(PrometheusService.active) } scope :with_active_prometheus_service, -> { joins(:prometheus_service).merge(PrometheusService.active) }
scope :with_enabled_error_tracking, -> { joins(:error_tracking_setting).where(project_error_tracking_settings: { enabled: true }) } scope :with_enabled_error_tracking, -> { joins(:error_tracking_setting).where(project_error_tracking_settings: { enabled: true }) }
scope :with_tracing_enabled, -> { joins(:tracing_setting) } scope :with_tracing_enabled, -> { joins(:tracing_setting) }
scope :with_packages, -> { joins(:packages) }
scope :mirrored_with_enabled_pipelines, -> do scope :mirrored_with_enabled_pipelines, -> do
joins(:project_feature).mirror.where(mirror_trigger_builds: true, joins(:project_feature).mirror.where(mirror_trigger_builds: true,
project_features: { builds_access_level: ::ProjectFeature::ENABLED }) project_features: { builds_access_level: ::ProjectFeature::ENABLED })
...@@ -179,8 +178,6 @@ module EE ...@@ -179,8 +178,6 @@ module EE
validates :mirror_user, presence: true validates :mirror_user, presence: true
end end
default_value_for :packages_enabled, true
accepts_nested_attributes_for :tracing_setting, update_only: true, allow_destroy: true accepts_nested_attributes_for :tracing_setting, update_only: true, allow_destroy: true
accepts_nested_attributes_for :status_page_setting, update_only: true, allow_destroy: true accepts_nested_attributes_for :status_page_setting, update_only: true, allow_destroy: true
accepts_nested_attributes_for :compliance_framework_setting, update_only: true, allow_destroy: true accepts_nested_attributes_for :compliance_framework_setting, update_only: true, allow_destroy: true
...@@ -590,15 +587,6 @@ module EE ...@@ -590,15 +587,6 @@ module EE
feature_available?(:protected_environments) feature_available?(:protected_environments)
end end
# Because we use default_value_for we need to be sure
# packages_enabled= method does exist even if we rollback migration.
# Otherwise many tests from spec/migrations will fail.
def packages_enabled=(value)
if has_attribute?(:packages_enabled)
write_attribute(:packages_enabled, value)
end
end
# Update the default branch querying the remote to determine its HEAD # Update the default branch querying the remote to determine its HEAD
def update_root_ref(remote_name) def update_root_ref(remote_name)
root_ref = repository.find_remote_root_ref(remote_name) root_ref = repository.find_remote_root_ref(remote_name)
......
...@@ -27,9 +27,6 @@ module EE ...@@ -27,9 +27,6 @@ module EE
with_scope :subject with_scope :subject
condition(:deploy_board_disabled) { !@subject.feature_available?(:deploy_board) } condition(:deploy_board_disabled) { !@subject.feature_available?(:deploy_board) }
with_scope :subject
condition(:packages_disabled) { !@subject.packages_enabled }
with_scope :subject with_scope :subject
condition(:iterations_available) { @subject.feature_available?(:iterations) } condition(:iterations_available) { @subject.feature_available?(:iterations) }
...@@ -236,7 +233,6 @@ module EE ...@@ -236,7 +233,6 @@ module EE
enable :create_vulnerability_feedback enable :create_vulnerability_feedback
enable :destroy_vulnerability_feedback enable :destroy_vulnerability_feedback
enable :update_vulnerability_feedback enable :update_vulnerability_feedback
enable :create_package
enable :read_feature_flag enable :read_feature_flag
enable :create_feature_flag enable :create_feature_flag
enable :update_feature_flag enable :update_feature_flag
...@@ -287,10 +283,6 @@ module EE ...@@ -287,10 +283,6 @@ module EE
rule { deploy_board_disabled & ~is_development }.prevent :read_deploy_board rule { deploy_board_disabled & ~is_development }.prevent :read_deploy_board
rule { packages_disabled | repository_disabled }.policy do
prevent(*create_read_update_admin_destroy(:package))
end
rule { feature_flags_disabled | repository_disabled }.policy do rule { feature_flags_disabled | repository_disabled }.policy do
prevent(*create_read_update_admin_destroy(:feature_flag)) prevent(*create_read_update_admin_destroy(:feature_flag))
prevent(:admin_feature_flags_user_lists) prevent(:admin_feature_flags_user_lists)
...@@ -300,7 +292,6 @@ module EE ...@@ -300,7 +292,6 @@ module EE
enable :push_code_to_protected_branches enable :push_code_to_protected_branches
enable :admin_path_locks enable :admin_path_locks
enable :update_approvers enable :update_approvers
enable :destroy_package
enable :admin_feature_flags_client enable :admin_feature_flags_client
enable :modify_approvers_rules enable :modify_approvers_rules
enable :modify_approvers_list enable :modify_approvers_list
......
...@@ -39,8 +39,6 @@ RSpec.describe Project do ...@@ -39,8 +39,6 @@ RSpec.describe Project do
it { is_expected.to have_many(:approvers).dependent(:destroy) } it { is_expected.to have_many(:approvers).dependent(:destroy) }
it { is_expected.to have_many(:approver_users).through(:approvers) } it { is_expected.to have_many(:approver_users).through(:approvers) }
it { is_expected.to have_many(:approver_groups).dependent(:destroy) } it { is_expected.to have_many(:approver_groups).dependent(:destroy) }
it { is_expected.to have_many(:packages).class_name('Packages::Package') }
it { is_expected.to have_many(:package_files).class_name('Packages::PackageFile') }
it { is_expected.to have_many(:upstream_project_subscriptions) } it { is_expected.to have_many(:upstream_project_subscriptions) }
it { is_expected.to have_many(:upstream_projects) } it { is_expected.to have_many(:upstream_projects) }
it { is_expected.to have_many(:downstream_project_subscriptions) } it { is_expected.to have_many(:downstream_project_subscriptions) }
...@@ -1926,12 +1924,6 @@ RSpec.describe Project do ...@@ -1926,12 +1924,6 @@ RSpec.describe Project do
end end
end end
describe '#packages_enabled' do
subject { create(:project).packages_enabled }
it { is_expected.to be true }
end
describe '#update_root_ref' do describe '#update_root_ref' do
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
...@@ -2383,33 +2375,6 @@ RSpec.describe Project do ...@@ -2383,33 +2375,6 @@ RSpec.describe Project do
.and_return(host: host) .and_return(host: host)
end end
describe '#package_already_taken?' do
let(:namespace) { create(:namespace) }
let(:project) { create(:project, :public, namespace: namespace) }
let!(:package) { create(:npm_package, project: project, name: "@#{namespace.path}/foo") }
context 'no package exists with the same name' do
it 'returns false' do
result = project.package_already_taken?("@#{namespace.path}/bar")
expect(result).to be false
end
it 'returns false if it is the project that the package belongs to' do
result = project.package_already_taken?("@#{namespace.path}/foo")
expect(result).to be false
end
end
context 'a package already exists with the same name' do
let(:alt_project) { create(:project, :public, namespace: namespace) }
it 'returns true' do
result = alt_project.package_already_taken?("@#{namespace.path}/foo")
expect(result).to be true
end
end
end
describe '#ancestor_marked_for_deletion' do describe '#ancestor_marked_for_deletion' do
context 'adjourned deletion feature is not available' do context 'adjourned deletion feature is not available' do
before do before do
......
...@@ -611,64 +611,6 @@ RSpec.describe ProjectPolicy do ...@@ -611,64 +611,6 @@ RSpec.describe ProjectPolicy do
end end
end end
describe 'read_package' do
context 'with admin' do
let(:current_user) { admin }
it { is_expected.to be_allowed(:read_package) }
context 'when repository is disabled' do
before do
project.project_feature.update(repository_access_level: ProjectFeature::DISABLED)
end
it { is_expected.to be_disallowed(:read_package) }
end
end
context 'with owner' do
let(:current_user) { owner }
it { is_expected.to be_allowed(:read_package) }
end
context 'with maintainer' do
let(:current_user) { maintainer }
it { is_expected.to be_allowed(:read_package) }
end
context 'with developer' do
let(:current_user) { developer }
it { is_expected.to be_allowed(:read_package) }
end
context 'with reporter' do
let(:current_user) { reporter }
it { is_expected.to be_allowed(:read_package) }
end
context 'with guest' do
let(:current_user) { guest }
it { is_expected.to be_allowed(:read_package) }
end
context 'with non member' do
let(:current_user) { create(:user) }
it { is_expected.to be_allowed(:read_package) }
end
context 'with anonymous' do
let(:current_user) { nil }
it { is_expected.to be_allowed(:read_package) }
end
end
describe 'remove_project when default_project_deletion_protection is set to true' do describe 'remove_project when default_project_deletion_protection is set to true' do
before do before do
allow(Gitlab::CurrentSettings.current_application_settings) allow(Gitlab::CurrentSettings.current_application_settings)
......
...@@ -119,6 +119,8 @@ RSpec.describe Project do ...@@ -119,6 +119,8 @@ RSpec.describe Project do
it { is_expected.to have_many(:metrics_users_starred_dashboards).inverse_of(:project) } it { is_expected.to have_many(:metrics_users_starred_dashboards).inverse_of(:project) }
it { is_expected.to have_many(:repository_storage_moves) } it { is_expected.to have_many(:repository_storage_moves) }
it { is_expected.to have_many(:reviews).inverse_of(:project) } it { is_expected.to have_many(:reviews).inverse_of(:project) }
it { is_expected.to have_many(:packages).class_name('Packages::Package') }
it { is_expected.to have_many(:package_files).class_name('Packages::PackageFile') }
it_behaves_like 'model with repository' do it_behaves_like 'model with repository' do
let_it_be(:container) { create(:project, :repository, path: 'somewhere') } let_it_be(:container) { create(:project, :repository, path: 'somewhere') }
...@@ -6167,6 +6169,39 @@ RSpec.describe Project do ...@@ -6167,6 +6169,39 @@ RSpec.describe Project do
end end
end end
describe '#packages_enabled' do
subject { create(:project).packages_enabled }
it { is_expected.to be true }
end
describe '#package_already_taken?' do
let(:namespace) { create(:namespace) }
let(:project) { create(:project, :public, namespace: namespace) }
let!(:package) { create(:npm_package, project: project, name: "@#{namespace.path}/foo") }
context 'no package exists with the same name' do
it 'returns false' do
result = project.package_already_taken?("@#{namespace.path}/bar")
expect(result).to be false
end
it 'returns false if it is the project that the package belongs to' do
result = project.package_already_taken?("@#{namespace.path}/foo")
expect(result).to be false
end
end
context 'a package already exists with the same name' do
let(:alt_project) { create(:project, :public, namespace: namespace) }
it 'returns true' do
result = alt_project.package_already_taken?("@#{namespace.path}/foo")
expect(result).to be true
end
end
end
describe '#design_management_enabled?' do describe '#design_management_enabled?' do
let(:project) { build(:project) } let(:project) { build(:project) }
......
...@@ -941,4 +941,64 @@ RSpec.describe ProjectPolicy do ...@@ -941,4 +941,64 @@ RSpec.describe ProjectPolicy do
it { is_expected.to be_disallowed(:read_build_report_results) } it { is_expected.to be_disallowed(:read_build_report_results) }
end end
end end
describe 'read_package' do
subject { described_class.new(current_user, project) }
context 'with admin' do
let(:current_user) { admin }
it { is_expected.to be_allowed(:read_package) }
context 'when repository is disabled' do
before do
project.project_feature.update(repository_access_level: ProjectFeature::DISABLED)
end
it { is_expected.to be_disallowed(:read_package) }
end
end
context 'with owner' do
let(:current_user) { owner }
it { is_expected.to be_allowed(:read_package) }
end
context 'with maintainer' do
let(:current_user) { maintainer }
it { is_expected.to be_allowed(:read_package) }
end
context 'with developer' do
let(:current_user) { developer }
it { is_expected.to be_allowed(:read_package) }
end
context 'with reporter' do
let(:current_user) { reporter }
it { is_expected.to be_allowed(:read_package) }
end
context 'with guest' do
let(:current_user) { guest }
it { is_expected.to be_allowed(:read_package) }
end
context 'with non member' do
let(:current_user) { create(:user) }
it { is_expected.to be_allowed(:read_package) }
end
context 'with anonymous' do
let(:current_user) { nil }
it { is_expected.to be_allowed(:read_package) }
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