Commit 3eb8773d authored by Stan Hu's avatar Stan Hu

Merge branch '5615-non-admins-only-archieve' into 'master'

Resolve "Only allow non-admins to archive projects, not delete them"

Closes #5615

See merge request gitlab-org/gitlab-ee!14002
parents 7961cf35 d3687fd1
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
.form-group .form-group
= f.label s_('ProjectCreationLevel|Default project creation protection'), class: 'label-bold' = f.label s_('ProjectCreationLevel|Default project creation protection'), class: 'label-bold'
= f.select :default_project_creation, options_for_select(Gitlab::Access.project_creation_options, @application_setting.default_project_creation), {}, class: 'form-control' = f.select :default_project_creation, options_for_select(Gitlab::Access.project_creation_options, @application_setting.default_project_creation), {}, class: 'form-control'
= render_if_exists 'admin/application_settings/default_project_deletion_protection_setting', form: f
.form-group.visibility-level-setting .form-group.visibility-level-setting
= f.label :default_project_visibility, class: 'label-bold' = f.label :default_project_visibility, class: 'label-bold'
= render('shared/visibility_radios', model_method: :default_project_visibility, form: f, selected_level: @application_setting.default_project_visibility, form_model: Project.new) = render('shared/visibility_radios', model_method: :default_project_visibility, form: f, selected_level: @application_setting.default_project_visibility, form_model: Project.new)
......
---
title: Add deletion protection setting column to application_settings table
merge_request: 29268
author:
type: other
...@@ -138,6 +138,7 @@ Settings['issues_tracker'] ||= {} ...@@ -138,6 +138,7 @@ Settings['issues_tracker'] ||= {}
# #
Settings['gitlab'] ||= Settingslogic.new({}) Settings['gitlab'] ||= Settingslogic.new({})
Settings.gitlab['default_project_creation'] ||= ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS Settings.gitlab['default_project_creation'] ||= ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS
Settings.gitlab['default_project_deletion_protection'] ||= false
Settings.gitlab['default_projects_limit'] ||= 100000 Settings.gitlab['default_projects_limit'] ||= 100000
Settings.gitlab['default_branch_protection'] ||= 2 Settings.gitlab['default_branch_protection'] ||= 2
Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil? Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil?
......
# frozen_string_literal: true
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddDefaultProjectDeletionProtectionToApplicationSettings < ActiveRecord::Migration[5.1]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_column_with_default :application_settings, :default_project_deletion_protection, :boolean, default: false, allow_null: false
end
def down
remove_column :application_settings, :default_project_deletion_protection
end
end
...@@ -226,6 +226,7 @@ ActiveRecord::Schema.define(version: 20190611161641) do ...@@ -226,6 +226,7 @@ ActiveRecord::Schema.define(version: 20190611161641) do
t.text "encrypted_lets_encrypt_private_key" t.text "encrypted_lets_encrypt_private_key"
t.text "encrypted_lets_encrypt_private_key_iv" t.text "encrypted_lets_encrypt_private_key_iv"
t.boolean "dns_rebinding_protection_enabled", default: true, null: false t.boolean "dns_rebinding_protection_enabled", default: true, null: false
t.boolean "default_project_deletion_protection", default: false, null: false
t.index ["custom_project_templates_group_id"], name: "index_application_settings_on_custom_project_templates_group_id", using: :btree t.index ["custom_project_templates_group_id"], name: "index_application_settings_on_custom_project_templates_group_id", using: :btree
t.index ["file_template_project_id"], name: "index_application_settings_on_file_template_project_id", using: :btree t.index ["file_template_project_id"], name: "index_application_settings_on_file_template_project_id", using: :btree
t.index ["usage_stats_set_by_user_id"], name: "index_application_settings_on_usage_stats_set_by_user_id", using: :btree t.index ["usage_stats_set_by_user_id"], name: "index_application_settings_on_usage_stats_set_by_user_id", using: :btree
......
...@@ -26,6 +26,10 @@ module EE ...@@ -26,6 +26,10 @@ module EE
attrs << :pseudonymizer_enabled attrs << :pseudonymizer_enabled
end end
if License.feature_available?(:default_project_deletion_protection)
attrs << :default_project_deletion_protection
end
attrs attrs
end end
end end
......
...@@ -75,6 +75,7 @@ module EE ...@@ -75,6 +75,7 @@ module EE
repository_mirror_attributes + %i[ repository_mirror_attributes + %i[
email_additional_text email_additional_text
file_template_project_id file_template_project_id
default_project_deletion_protection
] ]
end end
end end
......
...@@ -75,6 +75,7 @@ module EE ...@@ -75,6 +75,7 @@ module EE
def defaults def defaults
super.merge( super.merge(
allow_group_owners_to_manage_ldap: true, allow_group_owners_to_manage_ldap: true,
default_project_deletion_protection: false,
elasticsearch_aws: false, elasticsearch_aws: false,
elasticsearch_aws_region: ENV['ELASTIC_REGION'] || 'us-east-1', elasticsearch_aws_region: ENV['ELASTIC_REGION'] || 'us-east-1',
elasticsearch_replicas: 1, elasticsearch_replicas: 1,
......
...@@ -69,6 +69,7 @@ class License < ApplicationRecord ...@@ -69,6 +69,7 @@ class License < ApplicationRecord
reject_unsigned_commits reject_unsigned_commits
commit_committer_check commit_committer_check
ci_cd_projects ci_cd_projects
default_project_deletion_protection
protected_environments protected_environments
custom_project_templates custom_project_templates
group_project_templates group_project_templates
......
...@@ -210,6 +210,8 @@ module EE ...@@ -210,6 +210,8 @@ module EE
rule { owner | reporter }.enable :build_read_project rule { owner | reporter }.enable :build_read_project
rule { ~admin & owner & owner_cannot_destroy_project }.prevent :remove_project
rule { archived }.policy do rule { archived }.policy do
READONLY_FEATURES_WHEN_ARCHIVED.each do |feature| READONLY_FEATURES_WHEN_ARCHIVED.each do |feature|
prevent(*::ProjectPolicy.create_update_admin_destroy(feature)) prevent(*::ProjectPolicy.create_update_admin_destroy(feature))
...@@ -228,6 +230,11 @@ module EE ...@@ -228,6 +230,11 @@ module EE
::Gitlab::Auth::GroupSaml::SsoEnforcer.group_access_restricted?(subject.group) ::Gitlab::Auth::GroupSaml::SsoEnforcer.group_access_restricted?(subject.group)
end end
condition(:owner_cannot_destroy_project) do
::Gitlab::CurrentSettings.current_application_settings
.default_project_deletion_protection
end
rule { web_ide_terminal_available & can?(:create_pipeline) & can?(:maintainer_access) }.enable :create_web_ide_terminal rule { web_ide_terminal_available & can?(:create_pipeline) & can?(:maintainer_access) }.enable :create_web_ide_terminal
# Design abilities could also be prevented in the issue policy. # Design abilities could also be prevented in the issue policy.
......
- return unless License.feature_available?(:default_project_deletion_protection)
- f = local_assigns.fetch(:form)
.form-group
= f.label s_('Default project deletion protection'), class: 'label-bold'
.form-check
= f.check_box :default_project_deletion_protection, class: 'form-check-input'
= f.label :default_project_deletion_protection, class: 'form-check-label' do
= _('Only admins can delete project')
---
title: Add Admin settings to disable project deletion
merge_request: 14002
author:
type: added
...@@ -158,6 +158,7 @@ module EE ...@@ -158,6 +158,7 @@ module EE
end) end)
expose :email_additional_text, if: ->(_instance, _opts) { ::License.feature_available?(:email_additional_text) } expose :email_additional_text, if: ->(_instance, _opts) { ::License.feature_available?(:email_additional_text) }
expose :file_template_project_id, if: ->(_instance, _opts) { ::License.feature_available?(:custom_file_templates) } expose :file_template_project_id, if: ->(_instance, _opts) { ::License.feature_available?(:custom_file_templates) }
expose :default_project_deletion_protection, if: ->(_instance, _opts) { ::License.feature_available?(:default_project_deletion_protection) }
end end
end end
......
...@@ -30,6 +30,7 @@ module EE ...@@ -30,6 +30,7 @@ module EE
end end
optional :email_additional_text, type: String, desc: 'Additional text added to the bottom of every email for legal/auditing/compliance reasons' optional :email_additional_text, type: String, desc: 'Additional text added to the bottom of every email for legal/auditing/compliance reasons'
optional :default_project_deletion_protection, type: Grape::API::Boolean, desc: 'Disable project owners ability to delete project'
optional :help_text, type: String, desc: 'GitLab server administrator information' optional :help_text, type: String, desc: 'GitLab server administrator information'
optional :repository_size_limit, type: Integer, desc: 'Size limit per repository (MB)' optional :repository_size_limit, type: Integer, desc: 'Size limit per repository (MB)'
optional :file_template_project_id, type: Integer, desc: 'ID of project where instance-level file templates are stored.' optional :file_template_project_id, type: Integer, desc: 'ID of project where instance-level file templates are stored.'
......
...@@ -24,6 +24,10 @@ module EE ...@@ -24,6 +24,10 @@ module EE
attrs = attrs.except(:file_template_project_id) attrs = attrs.except(:file_template_project_id)
end end
unless ::License.feature_available?(:default_project_deletion_protection)
attrs = attrs.except(:default_project_deletion_protection)
end
attrs attrs
end end
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
......
...@@ -81,6 +81,13 @@ describe Admin::ApplicationSettingsController do ...@@ -81,6 +81,13 @@ describe Admin::ApplicationSettingsController do
it_behaves_like 'settings for licensed features' it_behaves_like 'settings for licensed features'
end end
context 'default project deletion protection' do
let(:settings) { { default_project_deletion_protection: true } }
let(:feature) { :default_project_deletion_protection }
it_behaves_like 'settings for licensed features'
end
context 'additional email footer' do context 'additional email footer' do
let(:settings) { { email_additional_text: 'scary legal footer' } } let(:settings) { { email_additional_text: 'scary legal footer' } }
let(:feature) { :email_additional_text } let(:feature) { :email_additional_text }
......
...@@ -451,6 +451,31 @@ describe ProjectPolicy do ...@@ -451,6 +451,31 @@ describe ProjectPolicy do
end end
end end
describe 'remove_project when default_project_deletion_protection is set to true' do
before do
allow(Gitlab::CurrentSettings.current_application_settings)
.to receive(:default_project_deletion_protection) { true }
end
context 'with admin' do
let(:current_user) { admin }
it { is_expected.to be_allowed(:remove_project) }
context 'who owns the project' do
let(:project) { create(:project, :public, namespace: admin.namespace) }
it { is_expected.to be_allowed(:remove_project) }
end
end
context 'with owner' do
let(:current_user) { owner }
it { is_expected.to be_disallowed(:remove_project) }
end
end
describe 'read_feature_flag' do describe 'read_feature_flag' do
context 'with admin' do context 'with admin' do
let(:current_user) { admin } let(:current_user) { admin }
......
...@@ -142,6 +142,13 @@ describe API::Settings, 'EE Settings' do ...@@ -142,6 +142,13 @@ describe API::Settings, 'EE Settings' do
it_behaves_like 'settings for licensed features' it_behaves_like 'settings for licensed features'
end end
context 'default project deletion protection' do
let(:settings) { { default_project_deletion_protection: true } }
let(:feature) { :default_project_deletion_protection }
it_behaves_like 'settings for licensed features'
end
context 'custom file template project' do context 'custom file template project' do
let(:settings) { { file_template_project_id: project.id } } let(:settings) { { file_template_project_id: project.id } }
let(:feature) { :custom_file_templates } let(:feature) { :custom_file_templates }
......
...@@ -3982,6 +3982,9 @@ msgstr "" ...@@ -3982,6 +3982,9 @@ msgstr ""
msgid "Default issue template" msgid "Default issue template"
msgstr "" msgstr ""
msgid "Default project deletion protection"
msgstr ""
msgid "Default: Directly import the Google Code email address or username" msgid "Default: Directly import the Google Code email address or username"
msgstr "" msgstr ""
...@@ -9059,6 +9062,9 @@ msgstr "" ...@@ -9059,6 +9062,9 @@ msgstr ""
msgid "Only admins" msgid "Only admins"
msgstr "" msgstr ""
msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches" msgid "Only mirror protected branches"
msgstr "" msgstr ""
......
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