Commit b9606f07 authored by Paul Slaughter's avatar Paul Slaughter

Merge branch '343872-remove-group-merge-request-approval-settings-feature-flag' into 'master'

Remove feature flag `group_merge_request_approval_settings_feature_flag`

See merge request gitlab-org/gitlab!81252
parents b1feb9ae ef2be582
......@@ -806,9 +806,7 @@ The group's new subgroups have push rules set for them based on either:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/285458) in GitLab 13.9. [Deployed behind the `group_merge_request_approval_settings_feature_flag` flag](../../administration/feature_flags.md), disabled by default.
> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/285410) in GitLab 14.5.
FLAG:
On self-managed GitLab, by default this feature is available. To hide the feature per group, ask an administrator to [disable the feature flag](../../administration/feature_flags.md) named `group_merge_request_approval_settings_feature_flag`. On GitLab.com, this feature is available.
> - [Feature flag `group_merge_request_approval_settings_feature_flag`](https://gitlab.com/gitlab-org/gitlab/-/issues/343872) removed in GitLab 14.9.
Group approval rules manage [project merge request approval rules](../project/merge_requests/approvals/index.md)
at the top-level group level. These rules [cascade to all projects](../project/merge_requests/approvals/settings.md#settings-cascading)
......
......@@ -140,9 +140,7 @@ To learn more, see [Coverage check approval rule](../../../../ci/pipelines/setti
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/285410) in GitLab 14.4. [Deployed behind the `group_merge_request_approval_settings_feature_flag` flag](../../../../administration/feature_flags.md), disabled by default.
> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/285410) in GitLab 14.5.
FLAG:
On self-managed GitLab, by default this feature is available. To hide the feature per group, ask an administrator to [disable the feature flag](../../../../administration/feature_flags.md) named `group_merge_request_approval_settings_feature_flag`. On GitLab.com, this feature is available.
> - [Feature flag `group_merge_request_approval_settings_feature_flag`](https://gitlab.com/gitlab-org/gitlab/-/issues/343872) removed in GitLab 14.9.
You can also enforce merge request approval settings:
......
......@@ -123,20 +123,3 @@ export const mergeRequestApprovalSettingsMappers = {
allow_committer_approval: !settings.preventCommittersApproval.value,
}),
};
export const projectApprovalsMappers = {
mapDataToState: (data) => ({
preventAuthorApproval: { value: !data.merge_requests_author_approval },
preventMrApprovalRuleEdit: { value: data.disable_overriding_approvers_per_merge_request },
requireUserPassword: { value: data.require_password_to_approve },
removeApprovalsOnPush: { value: data.reset_approvals_on_push },
preventCommittersApproval: { value: data.merge_requests_disable_committers_approval },
}),
mapStateToPayload: ({ settings }) => ({
merge_requests_author_approval: !settings.preventAuthorApproval.value,
disable_overriding_approvers_per_merge_request: settings.preventMrApprovalRuleEdit.value,
require_password_to_approve: settings.requireUserPassword.value,
reset_approvals_on_push: settings.removeApprovalsOnPush.value,
merge_requests_disable_committers_approval: settings.preventCommittersApproval.value,
}),
};
......@@ -2,7 +2,7 @@ import Vue from 'vue';
import { GlToast } from '@gitlab/ui';
import { parseBoolean } from '~/lib/utils/common_utils';
import ProjectSettingsApp from './components/project_settings/app.vue';
import { projectApprovalsMappers, mergeRequestApprovalSettingsMappers } from './mappers';
import { mergeRequestApprovalSettingsMappers } from './mappers';
import createStore from './stores';
import approvalSettingsModule from './stores/modules/approval_settings';
import projectSettingsModule from './stores/modules/project_settings';
......@@ -22,14 +22,7 @@ export default function mountProjectSettingsApprovals(el) {
approvals: projectSettingsModule(),
};
if (gon.features.groupMergeRequestApprovalSettingsFeatureFlag) {
modules.approvalSettings = approvalSettingsModule(mergeRequestApprovalSettingsMappers);
} else {
modules.approvalSettings = approvalSettingsModule({
updateMethod: 'post',
...projectApprovalsMappers,
});
}
modules.approvalSettings = approvalSettingsModule(mergeRequestApprovalSettingsMappers);
const store = createStore(modules, {
...el.dataset,
......
......@@ -13,7 +13,6 @@ module EE
before_action :log_unarchive_audit_event, only: [:unarchive]
before_action only: :edit do
push_frontend_feature_flag(:group_merge_request_approval_settings_feature_flag, project.root_ancestor, default_enabled: :yaml)
push_frontend_feature_flag(:permit_all_shared_groups_for_approval, project, default_enabled: :yaml)
end
......
......@@ -64,7 +64,7 @@ module EE
can_modify_commiter_settings: can_modify_commiter_settings.to_s,
project_path: expose_path(api_v4_projects_path(id: project.id)),
settings_path: expose_path(api_v4_projects_approval_settings_path(id: project.id)),
approvals_path: expose_path(api_v4_projects_approvals_path(id: project.id)),
approvals_path: expose_path(api_v4_projects_merge_request_approval_setting_path(id: project.id)),
rules_path: expose_path(api_v4_projects_approval_settings_rules_path(id: project.id)),
allow_multi_rule: project.multiple_approval_rules_available?.to_s,
eligible_approvers_docs_path: help_page_path('user/project/merge_requests/approvals/rules', anchor: 'eligible-approvers'),
......@@ -72,13 +72,9 @@ module EE
security_configuration_path: project_security_configuration_path(project),
vulnerability_check_help_page_path: help_page_path('user/application_security/index', anchor: 'security-approvals-in-merge-requests'),
license_check_help_page_path: help_page_path('user/application_security/index', anchor: 'enabling-license-approvals-within-a-project'),
coverage_check_help_page_path: help_page_path('ci/pipelines/settings', anchor: 'coverage-check-approval-rule')
}.tap do |data|
if ::Feature.enabled?(:group_merge_request_approval_settings_feature_flag, project.root_ancestor, default_enabled: :yaml)
data[:approvals_path] = expose_path(api_v4_projects_merge_request_approval_setting_path(id: project.id))
data[:group_name] = project.root_ancestor.name
end
end
coverage_check_help_page_path: help_page_path('ci/pipelines/settings', anchor: 'coverage-check-approval-rule'),
group_name: project.root_ancestor.name
}
end
def status_checks_app_data(project)
......
......@@ -3,8 +3,7 @@
module Groups
module MergeRequestApprovalSettingsHelper
def show_merge_request_approval_settings?(user, group)
Feature.enabled?(:group_merge_request_approval_settings_feature_flag, group, default_enabled: :yaml) &&
user.can?(:admin_merge_request_approval_settings, group)
user.can?(:admin_merge_request_approval_settings, group)
end
end
end
......@@ -543,13 +543,9 @@ module EE
end
def reset_approvals_on_push
if ::Feature.enabled?(:group_merge_request_approval_settings_feature_flag, self.group&.root_ancestor, default_enabled: :yaml)
!ComplianceManagement::MergeRequestApprovalSettings::Resolver.new(group, project: self)
.retain_approvals_on_push
.value && feature_available?(:merge_request_approvers)
else
super && feature_available?(:merge_request_approvers)
end
!ComplianceManagement::MergeRequestApprovalSettings::Resolver.new(group, project: self)
.retain_approvals_on_push
.value && feature_available?(:merge_request_approvers)
end
alias_method :reset_approvals_on_push?, :reset_approvals_on_push
......@@ -577,13 +573,9 @@ module EE
end
def require_password_to_approve
if ::Feature.enabled?(:group_merge_request_approval_settings_feature_flag, self&.group&.root_ancestor, default_enabled: :yaml)
ComplianceManagement::MergeRequestApprovalSettings::Resolver.new(group, project: self)
.require_password_to_approve
.value && password_authentication_enabled_for_web?
else
super && password_authentication_enabled_for_web?
end
ComplianceManagement::MergeRequestApprovalSettings::Resolver.new(group, project: self)
.require_password_to_approve
.value && password_authentication_enabled_for_web?
end
def require_password_to_approve?
......@@ -750,17 +742,11 @@ module EE
def disable_overriding_approvers_per_merge_request
strong_memoize(:disable_overriding_approvers_per_merge_request) do
if ::Feature.enabled?(:group_merge_request_approval_settings_feature_flag, self, default_enabled: :yaml)
super unless feature_available?(:admin_merge_request_approvers_rules)
super unless feature_available?(:admin_merge_request_approvers_rules)
!ComplianceManagement::MergeRequestApprovalSettings::Resolver.new(group&.root_ancestor, project: self)
.allow_overrides_to_approver_list_per_merge_request
.value
else
next super unless feature_available?(:admin_merge_request_approvers_rules)
::Gitlab::CurrentSettings.disable_overriding_approvers_per_merge_request? || super
end
!ComplianceManagement::MergeRequestApprovalSettings::Resolver.new(group&.root_ancestor, project: self)
.allow_overrides_to_approver_list_per_merge_request
.value
end
end
......@@ -770,18 +756,11 @@ module EE
def merge_requests_author_approval
strong_memoize(:merge_requests_author_approval) do
if ::Feature.enabled?(:group_merge_request_approval_settings_feature_flag, self, default_enabled: :yaml)
super unless feature_available?(:admin_merge_request_approvers_rules)
super unless feature_available?(:admin_merge_request_approvers_rules)
ComplianceManagement::MergeRequestApprovalSettings::Resolver.new(group&.root_ancestor, project: self)
.allow_author_approval
.value
else
next super unless License.feature_available?(:admin_merge_request_approvers_rules)
next false if ::Gitlab::CurrentSettings.prevent_merge_requests_author_approval?
!!read_attribute(:merge_requests_author_approval)
end
ComplianceManagement::MergeRequestApprovalSettings::Resolver.new(group&.root_ancestor, project: self)
.allow_author_approval
.value
end
end
......@@ -791,17 +770,11 @@ module EE
def merge_requests_disable_committers_approval
strong_memoize(:merge_requests_disable_committers_approval) do
if ::Feature.enabled?(:group_merge_request_approval_settings_feature_flag, self, default_enabled: :yaml)
super unless feature_available?(:admin_merge_request_approvers_rules)
super unless feature_available?(:admin_merge_request_approvers_rules)
!ComplianceManagement::MergeRequestApprovalSettings::Resolver.new(group&.root_ancestor, project: self)
.allow_committer_approval
.value
else
next super unless License.feature_available?(:admin_merge_request_approvers_rules)
::Gitlab::CurrentSettings.prevent_merge_requests_committers_approval? || super
end
!ComplianceManagement::MergeRequestApprovalSettings::Resolver.new(group&.root_ancestor, project: self)
.allow_committer_approval
.value
end
end
......
---
name: group_merge_request_approval_settings_feature_flag
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50256
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/247921
milestone: '13.8'
type: development
group: group::compliance
default_enabled: true
......@@ -35,19 +35,15 @@ module API
end
segment ':id/merge_request_approval_setting' do
desc 'Get project-level MR approval settings' do
detail 'This feature was introduced in 14.3 behind the :group_merge_request_approval_settings_feature_flag'
success EE::API::Entities::MergeRequestApprovalSettings
end
get '/', urgency: :medium do
not_found! unless ::Feature.enabled?(:group_merge_request_approval_settings_feature_flag, user_project.root_ancestor, default_enabled: :yaml)
group = user_project.group.present? ? user_project.root_ancestor : nil
setting = ComplianceManagement::MergeRequestApprovalSettings::Resolver.new(group, project: user_project).execute
present setting, with: ::API::Entities::MergeRequestApprovalSetting
end
desc 'Update existing merge request approval setting' do
detail 'This feature is gated by the :group_merge_request_approval_settings_feature_flag'
success ::API::Entities::MergeRequestApprovalSetting
end
params do
......@@ -77,13 +73,10 @@ module API
end
resource :groups, requirements: ::API::API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before do
not_found! unless ::Feature.enabled?(:group_merge_request_approval_settings_feature_flag, user_group, default_enabled: :yaml)
authorize! :admin_merge_request_approval_settings, user_group
end
segment ':id/merge_request_approval_setting' do
desc 'Get group merge request approval setting' do
detail 'This feature is gated by the :group_merge_request_approval_settings_feature_flag'
success ::API::Entities::MergeRequestApprovalSetting
end
get do
......@@ -93,7 +86,6 @@ module API
end
desc 'Update existing merge request approval setting' do
detail 'This feature is gated by the :group_merge_request_approval_settings_feature_flag'
success ::API::Entities::MergeRequestApprovalSetting
end
params do
......
......@@ -319,9 +319,8 @@ RSpec.describe 'Edit group settings' do
create(:group_merge_request_approval_setting, group: group, allow_author_approval: false)
end
context 'when feature flag is enabled and group is licensed' do
context 'when group is licensed' do
before do
stub_feature_flags(group_merge_request_approval_settings_feature_flag: true)
stub_licensed_features(merge_request_approvers: true)
end
......@@ -352,9 +351,8 @@ RSpec.describe 'Edit group settings' do
end
end
context 'when feature flag is disabled and group is not licensed' do
context 'when group is not licensed' do
before do
stub_feature_flags(group_merge_request_approval_settings_feature_flag: false)
stub_licensed_features(merge_request_approvers: false)
end
......
......@@ -133,45 +133,38 @@ RSpec.describe 'Projects > Audit Events', :js do
end
end
context 'with the group_merge_request_approval_settings feature' do
where(feature_enabled: [true, false])
with_them do
describe 'changing merge request approval permission for authors and reviewers' do
before do
stub_feature_flags(group_merge_request_approval_settings_feature_flag: feature_enabled)
stub_licensed_features(merge_request_approvers: true)
project.add_developer(pete)
end
describe 'changing merge request approval permission for authors and reviewers' do
before do
stub_licensed_features(merge_request_approvers: true)
project.add_developer(pete)
end
it "appears in the project's audit events", :js do
visit edit_project_path(project)
it "appears in the project's audit events", :js do
visit edit_project_path(project)
page.within('[data-testid="merge-request-approval-settings"]') do
find('[data-testid="prevent-author-approval"] > input').set(false)
find('[data-testid="prevent-committers-approval"] > input').set(true)
click_button 'Save changes'
end
page.within('[data-testid="merge-request-approval-settings"]') do
find('[data-testid="prevent-author-approval"] > input').set(false)
find('[data-testid="prevent-committers-approval"] > input').set(true)
click_button 'Save changes'
end
wait_for_all_requests
wait_for_all_requests
page.within('.sidebar-top-level-items') do
click_link 'Security & Compliance'
page.within('.sidebar-top-level-items') do
click_link 'Security & Compliance'
wait_for_all_requests
wait_for_all_requests
click_link 'Audit events'
end
click_link 'Audit events'
end
wait_for_all_requests
wait_for_all_requests
page.within('.audit-log-table') do
expect(page).to have_content(project.first_owner.name)
expect(page).to have_content('Changed prevent merge request approval from authors')
expect(page).to have_content('Changed prevent merge request approval from committers')
expect(page).to have_content(project.name)
end
end
page.within('.audit-log-table') do
expect(page).to have_content(project.first_owner.name)
expect(page).to have_content('Changed prevent merge request approval from authors')
expect(page).to have_content('Changed prevent merge request approval from committers')
expect(page).to have_content(project.name)
end
end
end
......
......@@ -4,7 +4,7 @@ import Vuex from 'vuex';
import ApprovalSettings from 'ee/approvals/components/approval_settings.vue';
import ProjectApprovalSettings from 'ee/approvals/components/project_settings/project_approval_settings.vue';
import { PROJECT_APPROVAL_SETTINGS_LABELS_I18N } from 'ee/approvals/constants';
import { projectApprovalsMappers } from 'ee/approvals/mappers';
import { mergeRequestApprovalSettingsMappers } from 'ee/approvals/mappers';
import createStore from 'ee/approvals/stores';
import approvalSettingsModule from 'ee/approvals/stores/modules/approval_settings';
......@@ -18,7 +18,7 @@ describe('ProjectApprovalSettings', () => {
const setupStore = (data = {}) => {
store = createStore({
approvalSettings: approvalSettingsModule(projectApprovalsMappers),
approvalSettings: approvalSettingsModule(mergeRequestApprovalSettingsMappers),
});
store.state.settings = data;
......
......@@ -430,43 +430,25 @@ RSpec.describe ProjectsHelper do
allow(helper).to receive(:can?).and_return(true)
end
context 'with group_merge_request_approval_settings_feature_flag disabled' do
before do
stub_feature_flags(group_merge_request_approval_settings_feature_flag: false)
end
it 'returns the correct data' do
expect(subject).to eq({
project_id: project.id,
can_edit: 'true',
can_modify_author_settings: 'true',
can_modify_commiter_settings: 'true',
approvals_path: expose_path(api_v4_projects_approvals_path(id: project.id)),
project_path: expose_path(api_v4_projects_path(id: project.id)),
settings_path: expose_path(api_v4_projects_approval_settings_path(id: project.id)),
rules_path: expose_path(api_v4_projects_approval_settings_rules_path(id: project.id)),
allow_multi_rule: project.multiple_approval_rules_available?.to_s,
eligible_approvers_docs_path: help_page_path('user/project/merge_requests/approvals/rules', anchor: 'eligible-approvers'),
security_approvals_help_page_path: help_page_path('user/application_security/index', anchor: 'security-approvals-in-merge-requests'),
security_configuration_path: project_security_configuration_path(project),
vulnerability_check_help_page_path: help_page_path('user/application_security/index', anchor: 'security-approvals-in-merge-requests'),
license_check_help_page_path: help_page_path('user/application_security/index', anchor: 'enabling-license-approvals-within-a-project'),
coverage_check_help_page_path: help_page_path('ci/pipelines/settings', anchor: 'coverage-check-approval-rule')
})
end
end
context 'with group_merge_request_approval_settings_feature_flag enabled' do
before do
stub_feature_flags(group_merge_request_approval_settings_feature_flag: true)
end
it 'returns the correct data' do
expect(subject).to include(
approvals_path: expose_path(api_v4_projects_merge_request_approval_setting_path(id: project.id)),
group_name: project.root_ancestor.name
)
end
it 'returns the correct data' do
expect(subject).to include(
project_id: project.id,
can_edit: 'true',
can_modify_author_settings: 'true',
can_modify_commiter_settings: 'true',
approvals_path: expose_path(api_v4_projects_merge_request_approval_setting_path(id: project.id)),
project_path: expose_path(api_v4_projects_path(id: project.id)),
settings_path: expose_path(api_v4_projects_approval_settings_path(id: project.id)),
rules_path: expose_path(api_v4_projects_approval_settings_rules_path(id: project.id)),
allow_multi_rule: project.multiple_approval_rules_available?.to_s,
eligible_approvers_docs_path: help_page_path('user/project/merge_requests/approvals/rules', anchor: 'eligible-approvers'),
security_approvals_help_page_path: help_page_path('user/application_security/index', anchor: 'security-approvals-in-merge-requests'),
security_configuration_path: project_security_configuration_path(project),
vulnerability_check_help_page_path: help_page_path('user/application_security/index', anchor: 'security-approvals-in-merge-requests'),
license_check_help_page_path: help_page_path('user/application_security/index', anchor: 'enabling-license-approvals-within-a-project'),
coverage_check_help_page_path: help_page_path('ci/pipelines/settings', anchor: 'coverage-check-approval-rule'),
group_name: project.root_ancestor.name
)
end
end
......
......@@ -819,121 +819,61 @@ RSpec.describe ApprovalState do
end
describe '#authors_can_approve?' do
context 'group_merge_request_approval_settings_feature_flag is enabled' do
context 'allow_author_approval is resolved to not be permitted' do
before do
stub_feature_flags(group_merge_request_approval_settings_feature_flag: true)
end
context 'allow_author_approval is resolved to not be permitted' do
before do
allow_next_instance_of ComplianceManagement::MergeRequestApprovalSettings::Resolver do |instance|
allow(instance).to receive(:allow_author_approval).and_return(
ComplianceManagement::MergeRequestApprovalSettings::Setting.new(value: false, locked: false, inherited_from: nil)
)
end
end
it 'returns false' do
expect(subject.authors_can_approve?).to be false
allow_next_instance_of ComplianceManagement::MergeRequestApprovalSettings::Resolver do |instance|
allow(instance).to receive(:allow_author_approval).and_return(
ComplianceManagement::MergeRequestApprovalSettings::Setting.new(value: false, locked: false, inherited_from: nil)
)
end
end
context 'allow_author_approval is resolved to be permitted' do
before do
allow_next_instance_of ComplianceManagement::MergeRequestApprovalSettings::Resolver do |instance|
allow(instance).to receive(:allow_author_approval).and_return(
ComplianceManagement::MergeRequestApprovalSettings::Setting.new(value: true, locked: false, inherited_from: nil)
)
end
end
it 'returns true' do
expect(subject.authors_can_approve?).to be true
end
it 'returns false' do
expect(subject.authors_can_approve?).to be false
end
end
context 'group_merge_request_approval_settings_feature_flag is disabled' do
context 'allow_author_approval is resolved to be permitted' do
before do
stub_feature_flags(group_merge_request_approval_settings_feature_flag: false)
end
context 'when project allows author approval' do
before do
project.update!(merge_requests_author_approval: true)
end
it 'returns true' do
expect(subject.authors_can_approve?).to eq(true)
allow_next_instance_of ComplianceManagement::MergeRequestApprovalSettings::Resolver do |instance|
allow(instance).to receive(:allow_author_approval).and_return(
ComplianceManagement::MergeRequestApprovalSettings::Setting.new(value: true, locked: false, inherited_from: nil)
)
end
end
context 'when project disallows author approval' do
before do
project.update!(merge_requests_author_approval: false)
end
it 'returns true' do
expect(subject.authors_can_approve?).to eq(false)
end
it 'returns true' do
expect(subject.authors_can_approve?).to be true
end
end
end
describe '#committers_can_approve?' do
context 'group_merge_request_approval_settings_feature_flag is enabled' do
context 'allow_committer_approval is resolved to not be permitted' do
before do
stub_feature_flags(group_merge_request_approval_settings_feature_flag: true)
end
context 'allow_committer_approval is resolved to not be permitted' do
before do
allow_next_instance_of ComplianceManagement::MergeRequestApprovalSettings::Resolver do |instance|
allow(instance).to receive(:allow_committer_approval).and_return(
ComplianceManagement::MergeRequestApprovalSettings::Setting.new(value: false, locked: false, inherited_from: nil)
)
end
end
it 'returns false' do
expect(subject.committers_can_approve?).to be false
allow_next_instance_of ComplianceManagement::MergeRequestApprovalSettings::Resolver do |instance|
allow(instance).to receive(:allow_committer_approval).and_return(
ComplianceManagement::MergeRequestApprovalSettings::Setting.new(value: false, locked: false, inherited_from: nil)
)
end
end
context 'allow_committer_approval is resolved to be permitted' do
before do
allow_next_instance_of ComplianceManagement::MergeRequestApprovalSettings::Resolver do |instance|
allow(instance).to receive(:allow_committer_approval).and_return(
ComplianceManagement::MergeRequestApprovalSettings::Setting.new(value: true, locked: false, inherited_from: nil)
)
end
end
it 'returns false' do
expect(subject.committers_can_approve?).to be true
end
it 'returns false' do
expect(subject.committers_can_approve?).to be false
end
end
context 'group_merge_request_approval_settings_feature_flag is disabled' do
context 'allow_committer_approval is resolved to be permitted' do
before do
stub_feature_flags(group_merge_request_approval_settings_feature_flag: false)
end
context 'when project allows committer approval' do
before do
project.update!(merge_requests_disable_committers_approval: false)
end
it 'returns true' do
expect(subject.committers_can_approve?).to eq(true)
allow_next_instance_of ComplianceManagement::MergeRequestApprovalSettings::Resolver do |instance|
allow(instance).to receive(:allow_committer_approval).and_return(
ComplianceManagement::MergeRequestApprovalSettings::Setting.new(value: true, locked: false, inherited_from: nil)
)
end
end
context 'when project disallows committer approval' do
before do
project.update!(merge_requests_disable_committers_approval: true)
end
it 'returns true' do
expect(subject.committers_can_approve?).to eq(false)
end
it 'returns false' do
expect(subject.committers_can_approve?).to be true
end
end
end
......
This diff is collapsed.
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