Commit ef6ded68 authored by Max Woolf's avatar Max Woolf

Merge branch...

Merge branch '208425-user-without-parent-group-permission-cannot-assign-epic-to-issue' into 'master'

Change permissions to set epic of an issue

See merge request gitlab-org/gitlab!66865
parents 89d0caa1 72154b41
...@@ -16,11 +16,13 @@ module Mutations ...@@ -16,11 +16,13 @@ module Mutations
issue = authorized_find!(project_path: project_path, iid: iid) issue = authorized_find!(project_path: project_path, iid: iid)
project = issue.project project = issue.project
authorize_admin_rights!(epic) authorize_read_rights!(epic)
begin begin
::Issues::UpdateService.new(project: project, current_user: current_user, params: { epic: epic }) ::Issues::UpdateService.new(project: project, current_user: current_user, params: { epic: epic })
.execute(issue) .execute(issue)
rescue ::Gitlab::Access::AccessDeniedError
raise_resource_not_available_error!
rescue EE::Issues::BaseService::EpicAssignmentError => error rescue EE::Issues::BaseService::EpicAssignmentError => error
issue.errors.add(:base, error.message) issue.errors.add(:base, error.message)
end end
...@@ -33,10 +35,10 @@ module Mutations ...@@ -33,10 +35,10 @@ module Mutations
private private
def authorize_admin_rights!(epic) def authorize_read_rights!(epic)
return unless epic.present? return unless epic.present?
raise_resource_not_available_error! unless Ability.allowed?(current_user, :admin_epic, epic.group) raise_resource_not_available_error! unless Ability.allowed?(current_user, :read_epic, epic.group)
end end
end end
end end
......
...@@ -150,7 +150,7 @@ module EE ...@@ -150,7 +150,7 @@ module EE
end end
def can_assign_epic?(user) def can_assign_epic?(user)
user&.can?(:admin_epic, project.group) user&.can?(:read_epic, project.group) && user&.can?(:admin_issue, project)
end end
def can_be_promoted_to_epic?(user, group = nil) def can_be_promoted_to_epic?(user, group = nil)
......
...@@ -52,7 +52,7 @@ module EE ...@@ -52,7 +52,7 @@ module EE
return unless epic return unless epic
unless can?(current_user, :admin_epic, epic) unless can?(current_user, :read_epic, epic) && can?(current_user, :admin_issue, issue)
raise ::Gitlab::Access::AccessDeniedError raise ::Gitlab::Access::AccessDeniedError
end end
......
...@@ -35,16 +35,25 @@ module EpicIssues ...@@ -35,16 +35,25 @@ module EpicIssues
def linkable_issuables(issues) def linkable_issuables(issues)
@linkable_issues ||= begin @linkable_issues ||= begin
return [] unless can?(current_user, :admin_epic, issuable.group) return [] unless can?(current_user, :read_epic, issuable.group)
Preloaders::UserMaxAccessLevelInProjectsPreloader
.new(issues.map(&:project).compact, current_user)
.execute
issues.select do |issue| issues.select do |issue|
issue.supports_epic? && linkable_issue?(issue)
issuable_group_descendants.include?(issue.project.group) &&
!previous_related_issuables.include?(issue)
end end
end end
end end
def linkable_issue?(issue)
issue.supports_epic? &&
can?(current_user, :admin_issue, issue.project) &&
issuable_group_descendants.include?(issue.project.group) &&
!previous_related_issuables.include?(issue)
end
def previous_related_issuables def previous_related_issuables
@related_issues ||= issuable.issues.to_a @related_issues ||= issuable.issues.to_a
end end
......
...@@ -27,7 +27,7 @@ module EpicIssues ...@@ -27,7 +27,7 @@ module EpicIssues
end end
def permission_to_remove_relation? def permission_to_remove_relation?
can?(current_user, :admin_epic_issue, target) && can?(current_user, :admin_epic, source) can?(current_user, :admin_epic_issue, target) && can?(current_user, :read_epic, source)
end end
def create_notes def create_notes
......
...@@ -23,6 +23,10 @@ module API ...@@ -23,6 +23,10 @@ module API
.with_api_entity_associations .with_api_entity_associations
.sorted_by_epic_position .sorted_by_epic_position
end end
def authorize_can_assign_to_epic!(issue)
forbidden! unless can?(current_user, :read_epic, epic) && can?(current_user, :admin_issue, issue)
end
end end
params do params do
...@@ -40,7 +44,7 @@ module API ...@@ -40,7 +44,7 @@ module API
use :pagination use :pagination
end end
put ':id/(-/)epics/:epic_iid/issues/:epic_issue_id' do put ':id/(-/)epics/:epic_iid/issues/:epic_issue_id' do
authorize_can_admin_epic! authorize_can_assign_to_epic!(link.issue)
update_params = { update_params = {
move_before_id: params[:move_before_id], move_before_id: params[:move_before_id],
...@@ -84,9 +88,9 @@ module API ...@@ -84,9 +88,9 @@ module API
end end
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
post ':id/(-/)epics/:epic_iid/issues/:issue_id' do post ':id/(-/)epics/:epic_iid/issues/:issue_id' do
authorize_can_admin_epic! authorize_can_read!
issue = Issue.find(params[:issue_id]) issue = Issue.find(params[:issue_id])
authorize!(:admin_issue, issue)
create_params = { target_issuable: issue } create_params = { target_issuable: issue }
...@@ -110,8 +114,7 @@ module API ...@@ -110,8 +114,7 @@ module API
requires :epic_issue_id, type: Integer, desc: 'The ID of the association' requires :epic_issue_id, type: Integer, desc: 'The ID of the association'
end end
delete ':id/(-/)epics/:epic_iid/issues/:epic_issue_id' do delete ':id/(-/)epics/:epic_iid/issues/:epic_issue_id' do
authorize_can_admin_epic! authorize_can_assign_to_epic!(link.issue)
result = ::EpicIssues::DestroyService.new(link, current_user).execute result = ::EpicIssues::DestroyService.new(link, current_user).execute
if result[:status] == :success if result[:status] == :success
......
...@@ -24,7 +24,7 @@ RSpec.describe Mutations::Boards::Issues::IssueMoveList do ...@@ -24,7 +24,7 @@ RSpec.describe Mutations::Boards::Issues::IssueMoveList do
before do before do
stub_licensed_features(epics: true) stub_licensed_features(epics: true)
project.add_maintainer(user) project.add_reporter(user)
end end
subject do subject do
...@@ -34,7 +34,7 @@ RSpec.describe Mutations::Boards::Issues::IssueMoveList do ...@@ -34,7 +34,7 @@ RSpec.describe Mutations::Boards::Issues::IssueMoveList do
describe '#resolve' do describe '#resolve' do
context 'when user has access to the epic' do context 'when user has access to the epic' do
before do before do
group.add_developer(user) group.add_guest(user)
end end
it 'moves and repositions issue' do it 'moves and repositions issue' do
...@@ -47,6 +47,8 @@ RSpec.describe Mutations::Boards::Issues::IssueMoveList do ...@@ -47,6 +47,8 @@ RSpec.describe Mutations::Boards::Issues::IssueMoveList do
end end
context 'when user does not have access to the epic' do context 'when user does not have access to the epic' do
let(:epic) { create(:epic, :confidential, group: group) }
it 'does not update issue' do it 'does not update issue' do
subject subject
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Mutations::Issues::SetEpic do RSpec.describe Mutations::Issues::SetEpic do
let_it_be(:group) { create(:group) } let_it_be(:group) { create(:group, :public) }
let_it_be(:project) { create(:project, group: group) } let_it_be(:project) { create(:project, group: group) }
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be_with_reload(:issue) { create(:issue, project: project) } let_it_be_with_reload(:issue) { create(:issue, project: project) }
...@@ -12,6 +12,7 @@ RSpec.describe Mutations::Issues::SetEpic do ...@@ -12,6 +12,7 @@ RSpec.describe Mutations::Issues::SetEpic do
describe '#resolve' do describe '#resolve' do
let_it_be_with_reload(:epic) { create(:epic, group: group) } let_it_be_with_reload(:epic) { create(:epic, group: group) }
let_it_be_with_reload(:confidential_epic) { create(:epic, group: group, confidential: true) }
let(:mutated_issue) { subject[:issue] } let(:mutated_issue) { subject[:issue] }
...@@ -22,18 +23,11 @@ RSpec.describe Mutations::Issues::SetEpic do ...@@ -22,18 +23,11 @@ RSpec.describe Mutations::Issues::SetEpic do
context 'when the user can update the issue' do context 'when the user can update the issue' do
before do before do
stub_licensed_features(epics: true) stub_licensed_features(epics: true)
project.add_developer(user) project.add_reporter(user)
group.add_guest(user)
end end
it 'raises an error if the epic is not accessible to the user' do context 'when user can read epic' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
context 'when user can admin epic' do
before do
group.add_owner(user)
end
it 'returns the issue with the epic' do it 'returns the issue with the epic' do
expect(mutated_issue).to eq(issue) expect(mutated_issue).to eq(issue)
expect(mutated_issue.epic).to eq(epic) expect(mutated_issue.epic).to eq(epic)
...@@ -61,12 +55,32 @@ RSpec.describe Mutations::Issues::SetEpic do ...@@ -61,12 +55,32 @@ RSpec.describe Mutations::Issues::SetEpic do
end end
context 'when epic is confidential but issue is public' do context 'when epic is confidential but issue is public' do
let(:epic) { create(:epic, group: group, confidential: true) } let(:epic) { confidential_epic }
it 'returns an error with appropriate message' do it 'returns an error with appropriate message' do
group.add_reporter(user)
expect(subject[:errors].first).to include("Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again") expect(subject[:errors].first).to include("Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again")
end end
end end
context 'with assigning epic error' do
let(:mock_service) { double('service', execute: { status: :error, message: 'failed to assign epic' }) }
it 'returns an error with appropriate message' do
expect(EpicIssues::CreateService).to receive(:new).and_return(mock_service)
expect(subject[:errors].first).to include('failed to assign epic')
end
end
end
context 'when user can not read epic' do
let(:epic) { confidential_epic }
it 'raises an error' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end end
end end
end end
......
...@@ -39,13 +39,12 @@ RSpec.describe Mutations::Issues::Update do ...@@ -39,13 +39,12 @@ RSpec.describe Mutations::Issues::Update do
before do before do
group.clear_memoization(:feature_available) group.clear_memoization(:feature_available)
group.add_developer(user) project.add_reporter(user)
group.add_guest(user)
end end
context 'when epics feature is disabled' do context 'when epics feature is disabled' do
it 'raises an error' do it 'raises an error' do
group.add_developer(user)
expect { subject }.to raise_error(::Gitlab::Graphql::Errors::ResourceNotAvailable) expect { subject }.to raise_error(::Gitlab::Graphql::Errors::ResourceNotAvailable)
end end
end end
...@@ -56,7 +55,7 @@ RSpec.describe Mutations::Issues::Update do ...@@ -56,7 +55,7 @@ RSpec.describe Mutations::Issues::Update do
end end
context 'for user without permissions' do context 'for user without permissions' do
let(:current_user) { create(:user) } let(:epic) { create(:epic, :confidential, group: group) }
it 'raises an error' do it 'raises an error' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
......
...@@ -813,19 +813,11 @@ RSpec.describe Issue do ...@@ -813,19 +813,11 @@ RSpec.describe Issue do
end end
context 'when a user is a project member' do context 'when a user is a project member' do
it 'returns false' do before do
project.add_developer(user) project.add_reporter(user)
expect(subject).to be_falsey
end end
end
context 'when a user is a group member' do it { is_expected.to be_truthy }
it 'returns true' do
group.add_developer(user)
expect(subject).to be_truthy
end
end end
end end
......
...@@ -102,6 +102,7 @@ RSpec.describe API::EpicIssues do ...@@ -102,6 +102,7 @@ RSpec.describe API::EpicIssues do
context 'when epics feature is enabled' do context 'when epics feature is enabled' do
before do before do
stub_licensed_features(epics: true) stub_licensed_features(epics: true)
group.add_guest(user)
end end
context 'when an error occurs' do context 'when an error occurs' do
...@@ -117,13 +118,33 @@ RSpec.describe API::EpicIssues do ...@@ -117,13 +118,33 @@ RSpec.describe API::EpicIssues do
post api(url, user) post api(url, user)
expect(response).to have_gitlab_http_status(:not_found) expect(response).to have_gitlab_http_status(:forbidden)
end end
it 'returns 403 forbidden error for a user without permissions to admin the epic' do context 'without permissions to admin the issue' do
post api(url, user) before do
project.add_guest(user)
end
expect(response).to have_gitlab_http_status(:forbidden) it 'returns 403 forbidden error' do
post api(url, user)
expect(response).to have_gitlab_http_status(:forbidden)
end
end
context 'without permissions to read the epic' do
let(:epic) { create(:epic, :confidential, group: create(:group, :private)) }
before do
project.add_reporter(user)
end
it 'returns 403 forbidden error' do
post api(url, user)
expect(response).to have_gitlab_http_status(:forbidden)
end
end end
context 'when issue project is not under the epic group' do context 'when issue project is not under the epic group' do
...@@ -146,7 +167,7 @@ RSpec.describe API::EpicIssues do ...@@ -146,7 +167,7 @@ RSpec.describe API::EpicIssues do
context 'when the request is correct' do context 'when the request is correct' do
before do before do
group.add_developer(user) project.add_reporter(user)
post api(url, user) post api(url, user)
end end
...@@ -205,10 +226,29 @@ RSpec.describe API::EpicIssues do ...@@ -205,10 +226,29 @@ RSpec.describe API::EpicIssues do
expect(response).to have_gitlab_http_status(:not_found) expect(response).to have_gitlab_http_status(:not_found)
end end
it 'returns 403 forbidden error for a user without permissions to admin the epic' do context 'With user without permissions to admin the issue' do
delete api(url, user) before do
project.add_guest(user)
end
expect(response).to have_gitlab_http_status(:forbidden) it 'returns 403 forbidden error' do
delete api(url, user)
expect(response).to have_gitlab_http_status(:forbidden)
end
end
context 'without permissions to read the epic' do
before do
[issue, epic].map { |issuable| issuable.update!(confidential: true) }
project.add_reporter(user)
end
it 'returns 403 forbidden error' do
delete api(url, user)
expect(response).to have_gitlab_http_status(:forbidden)
end
end end
context 'when epic_issue association does not include the epic in the url' do context 'when epic_issue association does not include the epic in the url' do
......
...@@ -33,38 +33,19 @@ RSpec.describe 'Reposition and move issue within board lists' do ...@@ -33,38 +33,19 @@ RSpec.describe 'Reposition and move issue within board lists' do
before do before do
stub_licensed_features(epics: true) stub_licensed_features(epics: true)
project.add_maintainer(user)
end end
context 'when user can admin epic' do context 'when user can admin issue' do
before do before do
group.add_maintainer(user) project.add_reporter(user)
end end
it 'updates issue position and epic' do context 'when user can read epic' do
post_graphql_mutation(mutation(params), current_user: user) before do
group.add_guest(user)
expect(response).to have_gitlab_http_status(:success)
response_issue = graphql_mutation_response(:issue_move_list)['issue']
expect(response_issue['iid']).to eq(issue1.iid.to_s)
expect(response_issue['relativePosition']).to be > existing_issue1.relative_position
expect(response_issue['relativePosition']).to be < existing_issue2.relative_position
expect(response_issue['epic']['id']).to eq(epic.to_global_id.to_s)
expect(response_issue['labels']['nodes'].first['title']).to eq(testing.title)
end
context 'when user sets nil epic' do
let_it_be(:epic_issue) { create(:epic_issue, issue: issue1, epic: epic) }
let(:issue_move_params) do
{
epic_id: nil,
move_before_id: existing_issue2.id,
move_after_id: existing_issue1.id
}
end end
it 'updates issue position and epic is unassigned' do it 'updates issue position and epic' do
post_graphql_mutation(mutation(params), current_user: user) post_graphql_mutation(mutation(params), current_user: user)
expect(response).to have_gitlab_http_status(:success) expect(response).to have_gitlab_http_status(:success)
...@@ -72,19 +53,46 @@ RSpec.describe 'Reposition and move issue within board lists' do ...@@ -72,19 +53,46 @@ RSpec.describe 'Reposition and move issue within board lists' do
expect(response_issue['iid']).to eq(issue1.iid.to_s) expect(response_issue['iid']).to eq(issue1.iid.to_s)
expect(response_issue['relativePosition']).to be > existing_issue1.relative_position expect(response_issue['relativePosition']).to be > existing_issue1.relative_position
expect(response_issue['relativePosition']).to be < existing_issue2.relative_position expect(response_issue['relativePosition']).to be < existing_issue2.relative_position
expect(response_issue['epic']).to be_nil expect(response_issue['epic']['id']).to eq(epic.to_global_id.to_s)
expect(response_issue['labels']['nodes'].first['title']).to eq(testing.title)
end
context 'when user sets nil epic' do
let_it_be(:epic_issue) { create(:epic_issue, issue: issue1, epic: epic) }
let(:issue_move_params) do
{
epic_id: nil,
move_before_id: existing_issue2.id,
move_after_id: existing_issue1.id
}
end
it 'updates issue position and epic is unassigned' do
post_graphql_mutation(mutation(params), current_user: user)
expect(response).to have_gitlab_http_status(:success)
response_issue = graphql_mutation_response(:issue_move_list)['issue']
expect(response_issue['iid']).to eq(issue1.iid.to_s)
expect(response_issue['relativePosition']).to be > existing_issue1.relative_position
expect(response_issue['relativePosition']).to be < existing_issue2.relative_position
expect(response_issue['epic']).to be_nil
end
end end
end end
end
context 'when user can not admin epic' do context 'when user can not read epic' do
it 'fails with error' do let(:confidential_epic) { create(:epic, :confidential, group: group) }
post_graphql_mutation(mutation(params), current_user: user)
it 'does not set epic' do
params[:epic_id] = confidential_epic.to_global_id.to_s
post_graphql_mutation(mutation(params), current_user: user)
mutation_response = graphql_mutation_response(:issue_move_list) response_issue = graphql_mutation_response(:issue_move_list)['issue']
expect(mutation_response['errors']).to eq(['You are not allowed to move the issue']) expect(response_issue['epic']).to be_nil
expect(mutation_response['issue']['epic']).to eq(nil) expect(response_issue['relativePosition']).to eq(3)
expect(mutation_response['issue']['relativePosition']).to eq(3) expect(graphql_mutation_response(:issue_move_list)['errors']).to include('Resource not found')
end
end end
end end
......
...@@ -23,7 +23,7 @@ RSpec.describe 'Update of an existing issue' do ...@@ -23,7 +23,7 @@ RSpec.describe 'Update of an existing issue' do
before do before do
stub_licensed_features(issuable_health_status: true) stub_licensed_features(issuable_health_status: true)
project.add_developer(current_user) project.add_reporter(current_user)
end end
it 'updates the issue' do it 'updates the issue' do
...@@ -42,7 +42,7 @@ RSpec.describe 'Update of an existing issue' do ...@@ -42,7 +42,7 @@ RSpec.describe 'Update of an existing issue' do
before do before do
stub_licensed_features(epics: true) stub_licensed_features(epics: true)
group.add_developer(current_user) group.add_guest(current_user)
end end
it 'sets the epic' do it 'sets the epic' do
...@@ -56,7 +56,7 @@ RSpec.describe 'Update of an existing issue' do ...@@ -56,7 +56,7 @@ RSpec.describe 'Update of an existing issue' do
end end
context 'the epic is not readable to the current user' do context 'the epic is not readable to the current user' do
let(:epic) { create(:epic) } let(:epic) { create(:epic, :confidential, group: group) }
it 'does not set the epic' do it 'does not set the epic' do
post_graphql_mutation(mutation, current_user: current_user) post_graphql_mutation(mutation, current_user: current_user)
...@@ -117,7 +117,7 @@ RSpec.describe 'Update of an existing issue' do ...@@ -117,7 +117,7 @@ RSpec.describe 'Update of an existing issue' do
before do before do
stub_licensed_features(epics: true) stub_licensed_features(epics: true)
group.add_developer(current_user) group.add_guest(current_user)
issue.update!(epic: epic) issue.update!(epic: epic)
end end
......
...@@ -252,6 +252,10 @@ RSpec.describe Issues::UpdateService do ...@@ -252,6 +252,10 @@ RSpec.describe Issues::UpdateService do
subject { update_issue(params) } subject { update_issue(params) }
context 'when a user does not have permissions to assign an epic' do context 'when a user does not have permissions to assign an epic' do
before do
project.add_guest(author)
end
it 'raises an exception' do it 'raises an exception' do
expect { subject }.to raise_error(Gitlab::Access::AccessDeniedError) expect { subject }.to raise_error(Gitlab::Access::AccessDeniedError)
end end
...@@ -259,7 +263,7 @@ RSpec.describe Issues::UpdateService do ...@@ -259,7 +263,7 @@ RSpec.describe Issues::UpdateService do
context 'when a user has permissions to assign an epic' do context 'when a user has permissions to assign an epic' do
before do before do
group.add_maintainer(user) group.add_guest(user)
end end
context 'when EpicIssues::CreateService returns failure', :aggregate_failures do context 'when EpicIssues::CreateService returns failure', :aggregate_failures do
......
...@@ -89,6 +89,11 @@ RSpec.describe EpicIssues::CreateService do ...@@ -89,6 +89,11 @@ RSpec.describe EpicIssues::CreateService do
context 'when epics feature is disabled' do context 'when epics feature is disabled' do
subject { assign_issue([valid_reference]) } subject { assign_issue([valid_reference]) }
before do
group.add_guest(user)
project.add_reporter(user)
end
include_examples 'returns an error' include_examples 'returns an error'
end end
...@@ -99,7 +104,8 @@ RSpec.describe EpicIssues::CreateService do ...@@ -99,7 +104,8 @@ RSpec.describe EpicIssues::CreateService do
context 'when user has permissions to link the issue' do context 'when user has permissions to link the issue' do
before do before do
group.add_developer(user) group.add_guest(user)
project.add_reporter(user)
end end
context 'when the reference list is empty' do context 'when the reference list is empty' do
...@@ -124,7 +130,7 @@ RSpec.describe EpicIssues::CreateService do ...@@ -124,7 +130,7 @@ RSpec.describe EpicIssues::CreateService do
include_examples 'returns success' include_examples 'returns success'
it 'does not perform N + 1 queries' do it 'does not perform N + 1 queries', :request_store do
allow(SystemNoteService).to receive(:epic_issue) allow(SystemNoteService).to receive(:epic_issue)
allow(SystemNoteService).to receive(:issue_on_epic) allow(SystemNoteService).to receive(:issue_on_epic)
...@@ -146,7 +152,7 @@ RSpec.describe EpicIssues::CreateService do ...@@ -146,7 +152,7 @@ RSpec.describe EpicIssues::CreateService do
project = create(:project, group: group) project = create(:project, group: group)
issues = create_list(:issue, 5, project: project) issues = create_list(:issue, 5, project: project)
epic = create(:epic, group: group) epic = create(:epic, group: group)
group.add_developer(user) group.add_reporter(user)
allow(extractor).to receive(:issues).and_return(issues) allow(extractor).to receive(:issues).and_return(issues)
params = { issuable_references: issues.map { |i| i.to_reference(full: true) } } params = { issuable_references: issues.map { |i| i.to_reference(full: true) } }
...@@ -173,6 +179,10 @@ RSpec.describe EpicIssues::CreateService do ...@@ -173,6 +179,10 @@ RSpec.describe EpicIssues::CreateService do
subject { assign_issue([Gitlab::Routing.url_helpers.namespace_project_issue_url(namespace_id: issue.project.namespace, project_id: issue.project, id: issue.iid)])} subject { assign_issue([Gitlab::Routing.url_helpers.namespace_project_issue_url(namespace_id: issue.project.namespace, project_id: issue.project, id: issue.iid)])}
before do
project2.add_reporter(user)
end
include_examples 'returns success' include_examples 'returns success'
end end
...@@ -196,6 +206,7 @@ RSpec.describe EpicIssues::CreateService do ...@@ -196,6 +206,7 @@ RSpec.describe EpicIssues::CreateService do
expect(created_link2.relative_position).to be < created_link1.relative_position expect(created_link2.relative_position).to be < created_link1.relative_position
end end
it 'orders the epic issues to the first place and moves the existing ones down' do it 'orders the epic issues to the first place and moves the existing ones down' do
existing_link = create(:epic_issue, epic: epic, issue: issue3) existing_link = create(:epic_issue, epic: epic, issue: issue3)
...@@ -258,7 +269,8 @@ RSpec.describe EpicIssues::CreateService do ...@@ -258,7 +269,8 @@ RSpec.describe EpicIssues::CreateService do
context 'when assigning issue(s) to the same epic' do context 'when assigning issue(s) to the same epic' do
before do before do
group.add_developer(user) group.add_guest(user)
project.add_reporter(user)
assign_issue([valid_reference]) assign_issue([valid_reference])
epic.reload epic.reload
end end
...@@ -288,7 +300,8 @@ RSpec.describe EpicIssues::CreateService do ...@@ -288,7 +300,8 @@ RSpec.describe EpicIssues::CreateService do
context 'when an issue is already assigned to another epic', :sidekiq_inline do context 'when an issue is already assigned to another epic', :sidekiq_inline do
before do before do
group.add_developer(user) group.add_guest(user)
project.add_reporter(user)
create(:epic_issue, epic: epic, issue: issue) create(:epic_issue, epic: epic, issue: issue)
issue.reload issue.reload
end end
...@@ -361,8 +374,8 @@ RSpec.describe EpicIssues::CreateService do ...@@ -361,8 +374,8 @@ RSpec.describe EpicIssues::CreateService do
let_it_be(:another_issue) { create :issue } let_it_be(:another_issue) { create :issue }
before do before do
group.add_developer(user) group.add_guest(user)
another_issue.project.add_developer(user) another_issue.project.add_reporter(user)
end end
include_examples 'returns an error' include_examples 'returns an error'
......
...@@ -15,7 +15,8 @@ RSpec.describe EpicIssues::DestroyService do ...@@ -15,7 +15,8 @@ RSpec.describe EpicIssues::DestroyService do
context 'when epics feature is disabled' do context 'when epics feature is disabled' do
before do before do
group.add_reporter(user) project.add_reporter(user)
group.add_guest(user)
end end
it 'returns an error' do it 'returns an error' do
...@@ -30,7 +31,8 @@ RSpec.describe EpicIssues::DestroyService do ...@@ -30,7 +31,8 @@ RSpec.describe EpicIssues::DestroyService do
context 'when user has permissions to remove associations' do context 'when user has permissions to remove associations' do
before do before do
group.add_reporter(user) project.add_reporter(user)
group.add_guest(user)
end end
it 'removes related issue' do it 'removes related issue' do
...@@ -73,6 +75,14 @@ RSpec.describe EpicIssues::DestroyService do ...@@ -73,6 +75,14 @@ RSpec.describe EpicIssues::DestroyService do
subject subject
end end
context 'refresh epic dates' do
it 'calls UpdateDatesService' do
expect(Epics::UpdateDatesService).to receive(:new).with([epic_issue.epic]).and_call_original
subject
end
end
end end
context 'user does not have permissions to remove associations' do context 'user does not have permissions to remove associations' do
...@@ -90,16 +100,6 @@ RSpec.describe EpicIssues::DestroyService do ...@@ -90,16 +100,6 @@ RSpec.describe EpicIssues::DestroyService do
subject subject
end end
end end
context 'refresh epic dates' do
it 'calls UpdateDatesService' do
group.add_reporter(user)
expect(Epics::UpdateDatesService).to receive(:new).with([epic_issue.epic]).and_call_original
subject
end
end
end end
end end
end end
...@@ -26,7 +26,7 @@ RSpec.shared_examples 'issue with epic_id parameter' do ...@@ -26,7 +26,7 @@ RSpec.shared_examples 'issue with epic_id parameter' do
context 'when user can not add issues to the epic' do context 'when user can not add issues to the epic' do
before do before do
project.add_maintainer(user) project.add_guest(user)
end end
let(:params) { { title: 'issue1', epic_id: epic.id } } let(:params) { { title: 'issue1', epic_id: epic.id } }
......
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