Commit 3642c199 authored by Mario de la Ossa's avatar Mario de la Ossa

Move Related Issues controllers and serializers to FOSS

We're moving related issues to core but keeping blocked issues in EE
parent f495925f
......@@ -26,7 +26,6 @@ module EE
mount ::API::Geo
mount ::API::GeoReplication
mount ::API::GeoNodes
mount ::API::IssueLinks
mount ::API::Ldap
mount ::API::LdapGroupLinks
mount ::API::License
......
# frozen_string_literal: true
module EE
module API
module Entities
class IssueLink < Grape::Entity
expose :source, as: :source_issue, using: ::API::Entities::IssueBasic
expose :target, as: :target_issue, using: ::API::Entities::IssueBasic
expose :link_type
end
end
end
end
# frozen_string_literal: true
module EE
module API
module Entities
class RelatedIssue < ::API::Entities::Issue
expose :issue_link_id
expose :issue_link_type, as: :link_type
end
end
end
end
......@@ -25,7 +25,6 @@ RSpec.describe Projects::IssueLinksController do
end
before do
stub_licensed_features(blocked_issues: true)
project.add_developer(user)
end
......@@ -55,33 +54,30 @@ RSpec.describe Projects::IssueLinksController do
post :create, params: post_params, as: :json
end
context 'when related issues are available on the project' do
before do
project.add_developer(user)
stub_licensed_features(blocked_issues: true)
stub_feature_flags(link_types: true)
end
before do
project.add_developer(user)
end
it 'returns success response' do
create_link(user, issue1, issue2)
it 'returns success response' do
create_link(user, issue1, issue2)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to have_gitlab_http_status(:ok)
link = json_response['issuables'].first
expect(link['id']).to eq(issue2.id)
expect(link['link_type']).to eq('is_blocked_by')
end
link = json_response['issuables'].first
expect(link['id']).to eq(issue2.id)
expect(link['link_type']).to eq('is_blocked_by')
end
context 'when related issues are not available on the project' do
context 'when blocked issues is disabled' do
before do
stub_licensed_features(blocked_issues: false)
end
it 'returns 403' do
it 'returns failure response' do
create_link(user, issue1, issue2)
expect(response).to have_gitlab_http_status(:forbidden)
expect(json_response['message']).to eq('Blocked issues not available for current license')
end
end
end
......
......@@ -6,200 +6,35 @@ RSpec.describe API::IssueLinks do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:target_issue) { create(:issue, project: project) }
before do
project.add_guest(user)
end
describe 'GET /links' do
context 'when unauthenticated' do
it 'returns 401' do
get api("/projects/#{project.id}/issues/#{issue.iid}/links")
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
context 'when authenticated' do
it 'returns related issues' do
target_issue = create(:issue, project: project)
create(:issue_link, source: issue, target: target_issue)
get api("/projects/#{project.id}/issues/#{issue.iid}/links", user)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an Array
expect(json_response.length).to eq(1)
expect(response).to match_response_schema('public_api/v4/issue_links')
end
end
project.add_reporter(user)
end
describe 'POST /links' do
context 'when unauthenticated' do
it 'returns 401' do
target_issue = create(:issue)
post api("/projects/#{project.id}/issues/#{issue.iid}/links"),
params: { target_project_id: target_issue.project.id, target_issue_iid: target_issue.iid }
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
context 'when authenticated' do
context 'given target project not found' do
it 'returns 404' do
target_issue = create(:issue)
post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
params: { target_project_id: -1, target_issue_iid: target_issue.iid }
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Project Not Found')
end
end
context 'given target issue not found' do
it 'returns 404' do
target_project = create(:project, :public)
post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
params: { target_project_id: target_project.id, target_issue_iid: non_existing_record_iid }
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Not found')
end
end
context 'when user does not have write access to given issue' do
it 'returns 404' do
unauthorized_project = create(:project)
target_issue = create(:issue, project: unauthorized_project)
unauthorized_project.add_guest(user)
post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
params: { target_project_id: unauthorized_project.id, target_issue_iid: target_issue.iid }
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('No Issue found for given params')
end
end
context 'when trying to relate to a confidential issue' do
it 'returns 404' do
project = create(:project, :public)
target_issue = create(:issue, :confidential, project: project)
post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
params: { target_project_id: project.id, target_issue_iid: target_issue.iid }
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Not found')
end
end
context 'when trying to relate to a private project issue' do
it 'returns 404' do
project = create(:project, :private)
target_issue = create(:issue, project: project)
post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
params: { target_project_id: project.id, target_issue_iid: target_issue.iid }
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Project Not Found')
end
end
context 'when user has ability to create an issue link' do
let_it_be(:target_issue) { create(:issue, project: project) }
before do
project.add_reporter(user)
end
context 'when creating a blocked relationship' do
context 'when feature is enabled' do
it 'returns 201 status and contains the expected link response' do
post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
params: { target_project_id: project.id, target_issue_iid: target_issue.iid, link_type: 'blocks' }
expect_link_response(link_type: 'blocks')
end
it 'returns 201 when sending full path of target project' do
post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
params: { target_project_id: project.full_path, target_issue_iid: target_issue.iid }
expect_link_response
end
def expect_link_response(link_type: 'relates_to')
expect(response).to have_gitlab_http_status(:created)
expect(response).to match_response_schema('public_api/v4/issue_link')
expect(json_response['link_type']).to eq(link_type)
expect(json_response['link_type']).to eq('blocks')
end
end
end
end
describe 'DELETE /links/:issue_link_id' do
context 'when unauthenticated' do
it 'returns 401' do
issue_link = create(:issue_link)
delete api("/projects/#{project.id}/issues/#{issue.iid}/links/#{issue_link.id}")
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
context 'when authenticated' do
context 'when user does not have write access to given issue link' do
it 'returns 404' do
unauthorized_project = create(:project)
target_issue = create(:issue, project: unauthorized_project)
issue_link = create(:issue_link, source: issue, target: target_issue)
unauthorized_project.add_guest(user)
delete api("/projects/#{project.id}/issues/#{issue.iid}/links/#{issue_link.id}", user)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('No Issue Link found')
end
end
context 'issue link not found' do
it 'returns 404' do
delete api("/projects/#{project.id}/issues/#{issue.iid}/links/#{non_existing_record_id}", user)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Not found')
end
end
context 'when trying to delete a link with a private project issue' do
it 'returns 404' do
project = create(:project, :private)
target_issue = create(:issue, project: project)
issue_link = create(:issue_link, source: issue, target: target_issue)
delete api("/projects/#{project.id}/issues/#{issue.iid}/links/#{issue_link.id}", user)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Project Not Found')
context 'when feature is disabled' do
before do
stub_licensed_features(blocked_issues: false)
end
end
context 'when user has ability to delete the issue link' do
it 'returns 200' do
target_issue = create(:issue, project: project)
issue_link = create(:issue_link, source: issue, target: target_issue)
project.add_reporter(user)
delete api("/projects/#{project.id}/issues/#{issue.iid}/links/#{issue_link.id}", user)
it 'returns 403' do
post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
params: { target_project_id: project.id, target_issue_iid: target_issue.iid, link_type: 'blocks' }
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/issue_link')
expect(response).to have_gitlab_http_status(:forbidden)
end
end
end
......
......@@ -167,6 +167,7 @@ module API
mount ::API::GroupVariables
mount ::API::ImportBitbucketServer
mount ::API::ImportGithub
mount ::API::IssueLinks
mount ::API::Issues
mount ::API::JobArtifacts
mount ::API::Jobs
......
# frozen_string_literal: true
module API
module Entities
class IssueLink < Grape::Entity
expose :source, as: :source_issue, using: ::API::Entities::IssueBasic
expose :target, as: :target_issue, using: ::API::Entities::IssueBasic
expose :link_type
end
end
end
# frozen_string_literal: true
module API
module Entities
class RelatedIssue < ::API::Entities::Issue
expose :issue_link_id
expose :issue_link_type, as: :link_type
end
end
end
......@@ -12,20 +12,20 @@ module API
end
resource :projects, requirements: { id: %r{[^/]+} } do
desc 'Get related issues' do
success EE::API::Entities::RelatedIssue
success Entities::RelatedIssue
end
get ':id/issues/:issue_iid/links' do
source_issue = find_project_issue(params[:issue_iid])
related_issues = source_issue.related_issues(current_user)
present related_issues,
with: EE::API::Entities::RelatedIssue,
with: Entities::RelatedIssue,
current_user: current_user,
project: user_project
end
desc 'Relate issues' do
success EE::API::Entities::IssueLink
success Entities::IssueLink
end
params do
requires :target_project_id, type: String, desc: 'The ID of the target project'
......@@ -48,7 +48,7 @@ module API
if result[:status] == :success
issue_link = IssueLink.find_by!(source: source_issue, target: target_issue)
present issue_link, with: EE::API::Entities::IssueLink
present issue_link, with: Entities::IssueLink
else
render_api_error!(result[:message], result[:http_status])
end
......@@ -56,7 +56,7 @@ module API
# rubocop: enable CodeReuse/ActiveRecord
desc 'Remove issues relation' do
success EE::API::Entities::IssueLink
success Entities::IssueLink
end
params do
requires :issue_link_id, type: Integer, desc: 'The ID of an issue link'
......@@ -72,7 +72,7 @@ module API
.execute
if result[:status] == :success
present issue_link, with: EE::API::Entities::IssueLink
present issue_link, with: Entities::IssueLink
else
render_api_error!(result[:message], result[:http_status])
end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Projects::IssueLinksController do
let_it_be(:namespace) { create(:group, :public) }
let_it_be(:project) { create(:project, :public, namespace: namespace) }
let_it_be(:user) { create(:user) }
let_it_be(:issue1) { create(:issue, project: project) }
let_it_be(:issue2) { create(:issue, project: project) }
describe 'GET #index' do
let_it_be(:issue_link) { create(:issue_link, source: issue1, target: issue2, link_type: 'relates_to') }
def get_link(user, issue)
sign_in(user)
params = {
namespace_id: issue.project.namespace.to_param,
project_id: issue.project,
issue_id: issue.iid
}
get :index, params: params, as: :json
end
before do
project.add_developer(user)
end
it 'returns success response' do
get_link(user, issue1)
expect(response).to have_gitlab_http_status(:ok)
link = json_response.first
expect(link['id']).to eq(issue2.id)
expect(link['link_type']).to eq('relates_to')
end
end
describe 'POST #create' do
def create_link(user, issue, target)
sign_in(user)
post_params = {
namespace_id: issue.project.namespace.to_param,
project_id: issue.project,
issue_id: issue.iid,
issuable_references: [target.to_reference],
link_type: 'relates_to'
}
post :create, params: post_params, as: :json
end
before do
project.add_developer(user)
end
it 'returns success response' do
create_link(user, issue1, issue2)
expect(response).to have_gitlab_http_status(:ok)
link = json_response['issuables'].first
expect(link['id']).to eq(issue2.id)
expect(link['link_type']).to eq('relates_to')
end
end
end
......@@ -3,12 +3,12 @@
"properties" : {
"source_issue": {
"allOf": [
{ "$ref": "../../../../../../../spec/fixtures/api/schemas/public_api/v4/issue.json" }
{ "$ref": "../../../../../../spec/fixtures/api/schemas/public_api/v4/issue.json" }
]
},
"target_issue": {
"allOf": [
{ "$ref": "../../../../../../../spec/fixtures/api/schemas/public_api/v4/issue.json" }
{ "$ref": "../../../../../../spec/fixtures/api/schemas/public_api/v4/issue.json" }
]
},
"link_type": {
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe API::IssueLinks do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:issue) { create(:issue, project: project) }
before do
project.add_guest(user)
end
describe 'GET /links' do
context 'when unauthenticated' do
it 'returns 401' do
get api("/projects/#{project.id}/issues/#{issue.iid}/links")
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
context 'when authenticated' do
it 'returns related issues' do
target_issue = create(:issue, project: project)
create(:issue_link, source: issue, target: target_issue)
get api("/projects/#{project.id}/issues/#{issue.iid}/links", user)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an Array
expect(json_response.length).to eq(1)
expect(response).to match_response_schema('public_api/v4/issue_links')
end
end
end
describe 'POST /links' do
context 'when unauthenticated' do
it 'returns 401' do
target_issue = create(:issue)
post api("/projects/#{project.id}/issues/#{issue.iid}/links"),
params: { target_project_id: target_issue.project.id, target_issue_iid: target_issue.iid }
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
context 'when authenticated' do
context 'given target project not found' do
it 'returns 404' do
target_issue = create(:issue)
post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
params: { target_project_id: -1, target_issue_iid: target_issue.iid }
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Project Not Found')
end
end
context 'given target issue not found' do
it 'returns 404' do
target_project = create(:project, :public)
post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
params: { target_project_id: target_project.id, target_issue_iid: non_existing_record_iid }
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Not found')
end
end
context 'when user does not have write access to given issue' do
it 'returns 404' do
unauthorized_project = create(:project)
target_issue = create(:issue, project: unauthorized_project)
unauthorized_project.add_guest(user)
post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
params: { target_project_id: unauthorized_project.id, target_issue_iid: target_issue.iid }
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('No Issue found for given params')
end
end
context 'when trying to relate to a confidential issue' do
it 'returns 404' do
project = create(:project, :public)
target_issue = create(:issue, :confidential, project: project)
post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
params: { target_project_id: project.id, target_issue_iid: target_issue.iid }
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Not found')
end
end
context 'when trying to relate to a private project issue' do
it 'returns 404' do
project = create(:project, :private)
target_issue = create(:issue, project: project)
post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
params: { target_project_id: project.id, target_issue_iid: target_issue.iid }
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Project Not Found')
end
end
context 'when user has ability to create an issue link' do
let_it_be(:target_issue) { create(:issue, project: project) }
before do
project.add_reporter(user)
end
it 'returns 201 status and contains the expected link response' do
post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
params: { target_project_id: project.id, target_issue_iid: target_issue.iid, link_type: 'relates_to' }
expect_link_response(link_type: 'relates_to')
end
it 'returns 201 when sending full path of target project' do
post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
params: { target_project_id: project.full_path, target_issue_iid: target_issue.iid }
expect_link_response
end
def expect_link_response(link_type: 'relates_to')
expect(response).to have_gitlab_http_status(:created)
expect(response).to match_response_schema('public_api/v4/issue_link')
expect(json_response['link_type']).to eq(link_type)
end
end
end
end
describe 'DELETE /links/:issue_link_id' do
context 'when unauthenticated' do
it 'returns 401' do
issue_link = create(:issue_link)
delete api("/projects/#{project.id}/issues/#{issue.iid}/links/#{issue_link.id}")
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
context 'when authenticated' do
context 'when user does not have write access to given issue link' do
it 'returns 404' do
unauthorized_project = create(:project)
target_issue = create(:issue, project: unauthorized_project)
issue_link = create(:issue_link, source: issue, target: target_issue)
unauthorized_project.add_guest(user)
delete api("/projects/#{project.id}/issues/#{issue.iid}/links/#{issue_link.id}", user)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('No Issue Link found')
end
end
context 'issue link not found' do
it 'returns 404' do
delete api("/projects/#{project.id}/issues/#{issue.iid}/links/#{non_existing_record_id}", user)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Not found')
end
end
context 'when trying to delete a link with a private project issue' do
it 'returns 404' do
project = create(:project, :private)
target_issue = create(:issue, project: project)
issue_link = create(:issue_link, source: issue, target: target_issue)
delete api("/projects/#{project.id}/issues/#{issue.iid}/links/#{issue_link.id}", user)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Project Not Found')
end
end
context 'when user has ability to delete the issue link' do
it 'returns 200' do
target_issue = create(:issue, project: project)
issue_link = create(:issue_link, source: issue, target: target_issue)
project.add_reporter(user)
delete api("/projects/#{project.id}/issues/#{issue.iid}/links/#{issue_link.id}", user)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/issue_link')
end
end
end
end
end
......@@ -7,10 +7,6 @@ RSpec.describe Projects::IssueLinksController do
let(:project) { create(:project_empty_repo) }
let(:issue) { create :issue, project: project }
before do
stub_licensed_features(blocked_issues: true)
end
describe 'GET /*namespace_id/:project_id/issues/:issue_id/links' do
let(:issue_b) { create :issue, project: project }
let!(:issue_link) { create :issue_link, source: issue, target: issue_b }
......
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