Skip to content

Commit fbc8a5e

Browse files
authored
Merge pull request #876 from code0-tech/851-prevent-role-deletion-if-no-member-has-a-different-admin-role
Prevent role deletion if no member has a different admin role
2 parents b36c028 + 04072e7 commit fbc8a5e

6 files changed

Lines changed: 52 additions & 2 deletions

File tree

app/services/namespaces/roles/assign_abilities_service.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ def check_admin_existing(t)
6363

6464
unless role.namespace.roles.where.not(id: role.id)
6565
.joins(:abilities)
66+
.joins(:member_roles)
6667
.exists?(abilities: { ability: :namespace_administrator }) ||
6768
abilities.include?(:namespace_administrator)
6869
t.rollback_and_return! ServiceResponse.error(

app/services/namespaces/roles/delete_service.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def execute
2020
if !namespace_role.namespace.has_owner? &&
2121
!namespace_role.namespace.roles.where.not(id: namespace_role.id)
2222
.joins(:abilities)
23+
.joins(:member_roles)
2324
.exists?(abilities: { ability: :namespace_administrator })
2425
return ServiceResponse.error(message: 'Cannot delete last administrator role',
2526
error_code: :cannot_delete_last_admin_role)

spec/requests/graphql/mutation/namespace/roles/assign_abilities_mutation_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
before do
3131
create(:namespace_role, namespace: namespace_role.namespace).tap do |role|
3232
create(:namespace_role_ability, namespace_role: role, ability: :namespace_administrator)
33+
create(:namespace_member_role, role: role, member: create(:namespace_member, namespace: role.namespace))
3334
end
3435
end
3536

spec/requests/graphql/mutation/namespace/roles/delete_mutation_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
before do
3939
create(:namespace_role, namespace: namespace).tap do |role|
4040
create(:namespace_role_ability, namespace_role: role, ability: :namespace_administrator)
41+
create(:namespace_member_role, role: role, member: create(:namespace_member, namespace: role.namespace))
4142
end
4243
end
4344

spec/services/namespaces/roles/assign_abilities_service_spec.rb

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,17 @@
99
let(:role) { create(:namespace_role) }
1010
let(:abilities) { [] }
1111

12-
let!(:admin_role) do
12+
let(:admin_role) do
1313
create(:namespace_role, namespace: role.namespace).tap do |role|
1414
create(:namespace_role_ability, namespace_role: role, ability: :namespace_administrator)
1515
end
1616
end
1717

18+
let!(:admin_role_member) do
19+
member = create(:namespace_member, namespace: admin_role.namespace, user: create(:user))
20+
create(:namespace_member_role, role: admin_role, member: member)
21+
end
22+
1823
context 'when user is nil' do
1924
let(:current_user) { nil }
2025

@@ -74,6 +79,24 @@
7479
expect { service_response }.not_to create_audit_event
7580
end
7681
end
82+
83+
context 'when another role has the namespace_administrator ability but no members' do
84+
let(:abilities) { [] }
85+
86+
before do
87+
stub_allowed_ability(NamespacePolicy, :assign_role_abilities, user: current_user, subject: role.namespace)
88+
create(:namespace_role_ability, namespace_role: role, ability: :namespace_administrator)
89+
admin_role_member.delete
90+
end
91+
92+
it { is_expected.not_to be_success }
93+
it { expect(service_response.payload[:error_code]).to eq(:cannot_remove_last_admin_ability) }
94+
it { expect { service_response }.not_to change { NamespaceRoleAbility.count } }
95+
96+
it do
97+
expect { service_response }.not_to create_audit_event
98+
end
99+
end
77100
end
78101

79102
context 'when adding an ability' do

spec/services/namespaces/roles/delete_service_spec.rb

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,41 @@
4848
end
4949

5050
it { is_expected.not_to be_success }
51+
it { expect(service_response.payload[:error_code]).to eq(:cannot_delete_last_admin_role) }
5152
it { expect { service_response }.not_to change { NamespaceRole.count } }
5253

5354
it do
5455
expect { service_response }.not_to create_audit_event
5556
end
5657
end
5758

58-
context 'when user is a member' do
59+
context 'when another role has the namespace_administrator ability but no members' do
5960
let(:current_user) { create(:user) }
6061

6162
before do
6263
create(:namespace_member, namespace: namespace_role.namespace, user: current_user)
64+
create(:namespace_role_ability, namespace_role: namespace_role, ability: :namespace_administrator)
65+
create(:namespace_member_role, member: create(:namespace_member, namespace: namespace_role.namespace),
66+
role: namespace_role)
67+
stub_allowed_ability(NamespacePolicy, :delete_namespace_role, user: current_user,
68+
subject: namespace_role.namespace)
69+
end
70+
71+
it { is_expected.not_to be_success }
72+
it { expect(service_response.payload[:error_code]).to eq(:cannot_delete_last_admin_role) }
73+
it { expect { service_response }.not_to change { NamespaceRole.count } }
74+
75+
it do
76+
expect { service_response }.not_to create_audit_event
77+
end
78+
end
79+
80+
context 'when user is a member' do
81+
let(:current_user) { create(:user) }
82+
83+
before do
84+
member = create(:namespace_member, namespace: namespace_role.namespace, user: current_user)
85+
create(:namespace_member_role, member: member, role: admin_role)
6386
stub_allowed_ability(NamespacePolicy, :delete_namespace_role, user: current_user,
6487
subject: namespace_role.namespace)
6588
end

0 commit comments

Comments
 (0)