Commit acb5376b authored by Jan Provaznik's avatar Jan Provaznik

Merge branch 'fix-epic-link-create-perm' into 'master'

Check user permissions correctly

See merge request gitlab-org/gitlab!24946
parents 2dd90ff5 d533b4f8
...@@ -346,7 +346,7 @@ module EE ...@@ -346,7 +346,7 @@ module EE
elsif parent.has_ancestor?(self) elsif parent.has_ancestor?(self)
errors.add :parent, "This epic can't be added as it is already assigned to this epic's ancestor" errors.add :parent, "This epic can't be added as it is already assigned to this epic's ancestor"
elsif !preloaded_parent_group_and_descendants.include?(group) elsif !preloaded_parent_group_and_descendants.include?(group)
errors.add :parent, "This epic can't be added because parent and child epics must belong to the same group" errors.add :parent, "This epic can't be added because it must belong to the same group as the parent, or subgroup of the parent epic’s group"
elsif level_depth_exceeded?(parent) elsif level_depth_exceeded?(parent)
errors.add :parent, "This epic can't be added as the maximum depth of nested epics would be exceeded" errors.add :parent, "This epic can't be added as the maximum depth of nested epics would be exceeded"
end end
......
...@@ -3,6 +3,10 @@ ...@@ -3,6 +3,10 @@
module EpicLinks module EpicLinks
class CreateService < IssuableLinks::CreateService class CreateService < IssuableLinks::CreateService
def execute def execute
unless can?(current_user, :admin_epic, issuable.group)
return error(issuables_not_found_message, 404)
end
if issuable.max_hierarchy_depth_achieved? if issuable.max_hierarchy_depth_achieved?
return error("This epic can't be added because the parent is already at the maximum depth from its most distant ancestor", 409) return error("This epic can't be added because the parent is already at the maximum depth from its most distant ancestor", 409)
end end
...@@ -54,8 +58,6 @@ module EpicLinks ...@@ -54,8 +58,6 @@ module EpicLinks
def linkable_issuables(epics) def linkable_issuables(epics)
@linkable_issuables ||= begin @linkable_issuables ||= begin
return [] unless can?(current_user, :admin_epic, issuable.group)
epics.select do |epic| epics.select do |epic|
linkable_epic?(epic) linkable_epic?(epic)
end end
......
...@@ -70,98 +70,108 @@ describe EpicLinks::CreateService do ...@@ -70,98 +70,108 @@ describe EpicLinks::CreateService do
context 'when a single epic is given' do context 'when a single epic is given' do
subject { add_epic([valid_reference]) } subject { add_epic([valid_reference]) }
context 'when an epic from a another group is given' do context 'when a user does not have permissions to add an epic' do
let(:other_group) { create(:group) } include_examples 'returns an error'
let(:expected_error) { "This epic can't be added because parent and child epics must belong to the same group" } end
let(:expected_code) { 409 }
context 'when a user has permissions to add an epic' do
before do before do
epic_to_add.update!(group: other_group) group.add_developer(user)
end end
include_examples 'returns an error' context 'when an epic from another group is given' do
end let(:other_group) { create(:group) }
let(:expected_error) { "This epic can't be added because it must belong to the same group as the parent, or subgroup of the parent epic’s group" }
context 'when hierarchy is cyclic' do
context 'when given child epic is the same as given parent' do
let(:expected_error) { 'Cannot add an epic as a child of itself' }
let(:expected_code) { 409 } let(:expected_code) { 409 }
subject { add_epic([epic.to_reference(full: true)]) } before do
epic_to_add.update!(group: other_group)
end
include_examples 'returns an error' include_examples 'returns an error'
end end
context 'when given child epic is parent of the given parent' do context 'when hierarchy is cyclic' do
let(:expected_error) { "This epic can't be added as it is already assigned to this epic's ancestor" } context 'when given child epic is the same as given parent' do
let(:expected_code) { 409 } let(:expected_error) { 'Cannot add an epic as a child of itself' }
let(:expected_code) { 409 }
before do subject { add_epic([epic.to_reference(full: true)]) }
epic.update(parent: epic_to_add)
include_examples 'returns an error'
end end
include_examples 'returns an error' context 'when given child epic is parent of the given parent' do
end let(:expected_error) { "This epic can't be added as it is already assigned to this epic's ancestor" }
let(:expected_code) { 409 }
context 'when new child epic is an ancestor of the given parent' do before do
let(:expected_error) { "This epic can't be added as it is already assigned to this epic's ancestor" } epic.update(parent: epic_to_add)
let(:expected_code) { 409 } end
before do include_examples 'returns an error'
# epic_to_add -> epic1 -> epic2 -> epic
epic1 = create(:epic, group: group, parent: epic_to_add)
epic2 = create(:epic, group: group, parent: epic1)
epic.update(parent: epic2)
end end
include_examples 'returns an error' context 'when new child epic is an ancestor of the given parent' do
let(:expected_error) { "This epic can't be added as it is already assigned to this epic's ancestor" }
let(:expected_code) { 409 }
before do
# epic_to_add -> epic1 -> epic2 -> epic
epic1 = create(:epic, group: group, parent: epic_to_add)
epic2 = create(:epic, group: group, parent: epic1)
epic.update(parent: epic2)
end
include_examples 'returns an error'
end
end end
end
context 'when adding an epic that is already a child of the parent epic' do context 'when adding an epic that is already a child of the parent epic' do
before do before do
epic_to_add.update(parent: epic) epic_to_add.update(parent: epic)
end
let(:expected_error) { "This epic can't be added as it is already assigned to the parent" }
let(:expected_code) { 409 }
include_examples 'returns an error'
end end
let(:expected_error) { "This epic can't be added as it is already assigned to the parent" } context 'when adding to an Epic that is already at maximum depth' do
let(:expected_code) { 409 } before do
epic1 = create(:epic, group: group)
epic2 = create(:epic, group: group, parent: epic1)
epic3 = create(:epic, group: group, parent: epic2)
epic4 = create(:epic, group: group, parent: epic3)
include_examples 'returns an error' epic.update(parent: epic4)
end end
context 'when adding to an Epic that is already at maximum depth' do let(:expected_error) { "This epic can't be added because the parent is already at the maximum depth from its most distant ancestor" }
before do let(:expected_code) { 409 }
epic1 = create(:epic, group: group)
epic2 = create(:epic, group: group, parent: epic1)
epic3 = create(:epic, group: group, parent: epic2)
epic4 = create(:epic, group: group, parent: epic3)
epic.update(parent: epic4) include_examples 'returns an error'
end end
let(:expected_error) { "This epic can't be added because the parent is already at the maximum depth from its most distant ancestor" } context 'when total depth after adding would exceed depth limit' do
let(:expected_code) { 409 } let(:expected_error) { "This epic can't be added as the maximum depth of nested epics would be exceeded" }
let(:expected_code) { 409 }
include_examples 'returns an error'
end
context 'when total depth after adding would exceed limit' do before do
let(:expected_error) { "This epic can't be added as the maximum depth of nested epics would be exceeded" } epic1 = create(:epic, group: group)
let(:expected_code) { 409 }
before do epic.update(parent: epic1) # epic is on level 2
epic1 = create(:epic, group: group)
epic.update(parent: epic1) # epic is on level 2 # epic_to_add has 3 children (level 4 including epic_to_add)
# that would mean level 6 after relating epic_to_add on epic
epic2 = create(:epic, group: group, parent: epic_to_add)
epic3 = create(:epic, group: group, parent: epic2)
create(:epic, group: group, parent: epic3)
end
# epic_to_add has 3 children (level 4 including epic_to_add) include_examples 'returns an error'
# that would mean level 6 after relating epic_to_add on epic
epic2 = create(:epic, group: group, parent: epic_to_add)
epic3 = create(:epic, group: group, parent: epic2)
create(:epic, group: group, parent: epic3)
end end
include_examples 'returns an error'
end end
end end
...@@ -174,75 +184,85 @@ describe EpicLinks::CreateService do ...@@ -174,75 +184,85 @@ describe EpicLinks::CreateService do
) )
end end
context 'when adding epics that are already a child of the parent epic' do context 'when a user dos not have permissions to add an epic' do
let(:expected_error) { 'Epic(s) already assigned' }
let(:expected_code) { 409 }
before do
epic_to_add.update(parent: epic)
another_epic.update(parent: epic)
end
include_examples 'returns an error' include_examples 'returns an error'
end end
context 'when total depth after adding would exceed limit' do context 'when a user has permissions to add an epic' do
before do before do
epic1 = create(:epic, group: group) group.add_developer(user)
end
epic.update(parent: epic1) # epic is on level 2 context 'when adding epics that are already a child of the parent epic' do
let(:expected_error) { 'Epic(s) already assigned' }
let(:expected_code) { 409 }
# epic_to_add has 3 children (level 4 including epic_to_add) before do
# that would mean level 6 after relating epic_to_add on epic epic_to_add.update(parent: epic)
epic2 = create(:epic, group: group, parent: epic_to_add) another_epic.update(parent: epic)
epic3 = create(:epic, group: group, parent: epic2) end
create(:epic, group: group, parent: epic3)
include_examples 'returns an error'
end end
let(:another_epic) { create(:epic) } context 'when total depth after adding would exceed limit' do
before do
epic1 = create(:epic, group: group)
include_examples 'returns an error' epic.update(parent: epic1) # epic is on level 2
end
context 'when an epic from a another group is given' do # epic_to_add has 3 children (level 4 including epic_to_add)
let(:other_group) { create(:group) } # that would mean level 6 after relating epic_to_add on epic
epic2 = create(:epic, group: group, parent: epic_to_add)
epic3 = create(:epic, group: group, parent: epic2)
create(:epic, group: group, parent: epic3)
end
before do let(:another_epic) { create(:epic) }
epic_to_add.update!(group: other_group)
include_examples 'returns an error'
end end
include_examples 'returns an error' context 'when an epic from a another group is given' do
end let(:other_group) { create(:group) }
context 'when hierarchy is cyclic' do before do
context 'when given child epic is the same as given parent' do epic_to_add.update!(group: other_group)
subject { add_epic([epic.to_reference(full: true), another_epic.to_reference(full: true)]) } end
include_examples 'returns an error' include_examples 'returns an error'
end end
context 'when given child epic is parent of the given parent' do context 'when hierarchy is cyclic' do
before do context 'when given child epic is the same as given parent' do
epic.update(parent: epic_to_add) subject { add_epic([epic.to_reference(full: true), another_epic.to_reference(full: true)]) }
include_examples 'returns an error'
end end
context 'when given child epic is parent of the given parent' do
before do
epic.update(parent: epic_to_add)
end
include_examples 'returns an error'
end
end
context 'when the reference list is empty' do
subject { add_epic([]) }
include_examples 'returns an error' include_examples 'returns an error'
end end
end end
end end
end end
context 'when user has permissions to link the epic' do context 'when everything is ok' do
before do before do
group.add_developer(user) group.add_developer(user)
end end
context 'when the reference list is empty' do
subject { add_epic([]) }
include_examples 'returns an error'
end
context 'when a correct reference is given' do context 'when a correct reference is given' do
subject { add_epic([valid_reference]) } subject { add_epic([valid_reference]) }
......
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