Commit 97c4b833 authored by Heinrich Lee Yu's avatar Heinrich Lee Yu

Merge branch 'issue_213078' into 'master'

Use EpicsFinder when fetching epics

See merge request gitlab-org/gitlab!30404
parents 64a9f6f6 5719a5a5
...@@ -50,7 +50,8 @@ class EpicsFinder < IssuableFinder ...@@ -50,7 +50,8 @@ class EpicsFinder < IssuableFinder
end end
def execute def execute
raise ArgumentError, 'group_id argument is missing' unless group raise ArgumentError, 'group_id argument is missing' unless params[:group_id]
return Epic.none unless Ability.allowed?(current_user, :read_epic, group)
items = init_collection items = init_collection
items = by_created_at(items) items = by_created_at(items)
...@@ -72,19 +73,6 @@ class EpicsFinder < IssuableFinder ...@@ -72,19 +73,6 @@ class EpicsFinder < IssuableFinder
sort(items) sort(items)
end end
def group
return unless params[:group_id]
return @group if defined?(@group)
group = Group.find(params[:group_id])
unless Ability.allowed?(current_user, :read_epic, group)
raise ActiveRecord::RecordNotFound.new("Could not find a Group with ID #{params[:group_id]}")
end
@group = group
end
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def init_collection def init_collection
groups = if params[:iids].present? groups = if params[:iids].present?
...@@ -104,6 +92,13 @@ class EpicsFinder < IssuableFinder ...@@ -104,6 +92,13 @@ class EpicsFinder < IssuableFinder
private private
def group
return unless params[:group_id]
return @group if defined?(@group)
@group = Group.find(params[:group_id])
end
def starts_with_iid(items) def starts_with_iid(items)
return items unless params[:iid_starts_with].present? return items unless params[:iid_starts_with].present?
......
...@@ -23,15 +23,11 @@ module Groups ...@@ -23,15 +23,11 @@ module Groups
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
def epics def epics
# TODO: change to EpicsFinder once frontend supports epics from external groups. # TODO: use include_descendant_groups: true optional parameter once frontend supports epics from external groups.
# See https://gitlab.com/gitlab-org/gitlab/issues/6837 # See https://gitlab.com/gitlab-org/gitlab/issues/6837
DeclarativePolicy.user_scope do EpicsFinder.new(current_user, group_id: group.id)
if Ability.allowed?(current_user, :read_epic, group) .execute
group.epics.select(:iid, :title) .select(:iid, :title)
else
[]
end
end
end end
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
......
...@@ -7,12 +7,18 @@ module EE ...@@ -7,12 +7,18 @@ module EE
extend ActiveSupport::Concern extend ActiveSupport::Concern
prepended do prepended do
with_options if: -> (issue, options) { ::Ability.allowed?(options[:current_user], :read_epic, issue.project&.group) } do with_options if: -> (issue, _) { issue.project.group&.feature_available?(:epics) } do
expose :epic_iid do |issue| expose :epic_iid do |issue|
issue.epic&.iid authorized_epic_for(issue)&.iid
end end
expose :epic, using: EpicBaseEntity expose :epic, using: EpicBaseEntity do |issue|
authorized_epic_for(issue)
end
def authorized_epic_for(issue)
issue.epic if ::Ability.allowed?(options[:current_user], :read_epic, issue.epic)
end
end end
end end
end end
......
...@@ -43,8 +43,8 @@ describe EpicsFinder do ...@@ -43,8 +43,8 @@ describe EpicsFinder do
end end
context 'when user can not read epics of a group' do context 'when user can not read epics of a group' do
it 'raises an error when group_id param is missing' do it 'returns empty collection' do
expect { epics }.to raise_error { ArgumentError } expect(epics).to be_empty
end end
end end
......
...@@ -44,19 +44,31 @@ describe API::Issues, :mailer do ...@@ -44,19 +44,31 @@ describe API::Issues, :mailer do
subject subject
expect(response).to have_gitlab_http_status(:success) expect(response).to have_gitlab_http_status(:success)
expect(epic_issue_response_for(epic_issue)['epic_iid']).to eq(epic.iid) expect(epic_issue_response_for(issue_with_epic)['epic_iid']).to eq(epic.iid)
end end
it 'contains epic in response' do it 'contains epic in response' do
subject subject
expect(response).to have_gitlab_http_status(:success) expect(response).to have_gitlab_http_status(:success)
expect(epic_issue_response_for(epic_issue)['epic']).to eq({ "id" => epic.id, expect(epic_issue_response_for(issue_with_epic)['epic']).to eq({ "id" => epic.id,
"iid" => epic.iid, "iid" => epic.iid,
"group_id" => epic.group_id, "group_id" => epic.group_id,
"title" => epic.title, "title" => epic.title,
"url" => group_epic_path(epic.group, epic) }) "url" => group_epic_path(epic.group, epic) })
end end
context 'and epic issue is not present' do
it 'exposes epic as nil' do
issue_with_epic.epic_issue.destroy
subject
response = epic_issue_response_for(issue_with_epic)
expect(response['epic']).to eq(nil)
expect(response['epic_id']).to eq(nil)
end
end
end end
context 'without epics feature' do context 'without epics feature' do
...@@ -68,14 +80,14 @@ describe API::Issues, :mailer do ...@@ -68,14 +80,14 @@ describe API::Issues, :mailer do
subject subject
expect(response).to have_gitlab_http_status(:success) expect(response).to have_gitlab_http_status(:success)
expect(epic_issue_response_for(epic_issue)).not_to have_key('epic_iid') expect(epic_issue_response_for(issue_with_epic)).not_to have_key('epic_iid')
end end
it 'does not contain epic_iid in response' do it 'does not contain epic_iid in response' do
subject subject
expect(response).to have_gitlab_http_status(:success) expect(response).to have_gitlab_http_status(:success)
expect(epic_issue_response_for(epic_issue)).not_to have_key('epic') expect(epic_issue_response_for(issue_with_epic)).not_to have_key('epic')
end end
end end
end end
...@@ -150,7 +162,7 @@ describe API::Issues, :mailer do ...@@ -150,7 +162,7 @@ describe API::Issues, :mailer do
end end
include_examples 'exposes epic' do include_examples 'exposes epic' do
let!(:epic_issue) { create(:issue, project: group_project, epic: epic) } let!(:issue_with_epic) { create(:issue, project: group_project, epic: epic) }
end end
end end
...@@ -176,7 +188,7 @@ describe API::Issues, :mailer do ...@@ -176,7 +188,7 @@ describe API::Issues, :mailer do
end end
context 'on personal project' do context 'on personal project' do
let!(:epic_issue) { create(:issue, project: project, epic: epic) } let!(:issue_with_epic) { create(:issue, project: project, epic: epic) }
before do before do
stub_licensed_features(epics: true) stub_licensed_features(epics: true)
...@@ -186,12 +198,12 @@ describe API::Issues, :mailer do ...@@ -186,12 +198,12 @@ describe API::Issues, :mailer do
subject subject
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(epic_issue_response_for(epic_issue)).not_to have_key('epic_iid') expect(epic_issue_response_for(issue_with_epic)).not_to have_key('epic_iid')
end end
end end
context 'on group project' do context 'on group project' do
let!(:epic_issue) { create(:issue, project: group_project, epic: epic) } let!(:issue_with_epic) { create(:issue, project: group_project, epic: epic) }
subject { get api("/projects/#{group_project.id}/issues", user) } subject { get api("/projects/#{group_project.id}/issues", user) }
...@@ -201,9 +213,9 @@ describe API::Issues, :mailer do ...@@ -201,9 +213,9 @@ describe API::Issues, :mailer do
describe 'GET /project/:id/issues/:issue_id' do describe 'GET /project/:id/issues/:issue_id' do
context 'on personal project' do context 'on personal project' do
let!(:epic_issue) { create(:issue, project: project, epic: epic) } let!(:issue_with_epic) { create(:issue, project: project, epic: epic) }
subject { get api("/projects/#{project.id}/issues/#{epic_issue.iid}", user) } subject { get api("/projects/#{project.id}/issues/#{issue_with_epic.iid}", user) }
before do before do
stub_licensed_features(epics: true) stub_licensed_features(epics: true)
...@@ -213,14 +225,14 @@ describe API::Issues, :mailer do ...@@ -213,14 +225,14 @@ describe API::Issues, :mailer do
subject subject
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(epic_issue_response_for(epic_issue)).not_to have_key('epic_iid') expect(epic_issue_response_for(issue_with_epic)).not_to have_key('epic_iid')
end end
end end
context 'on group project' do context 'on group project' do
let!(:epic_issue) { create(:issue, project: group_project, epic: epic) } let!(:issue_with_epic) { create(:issue, project: group_project, epic: epic) }
subject { get api("/projects/#{group_project.id}/issues/#{epic_issue.iid}", user) } subject { get api("/projects/#{group_project.id}/issues/#{issue_with_epic.iid}", user) }
include_examples 'exposes epic' include_examples 'exposes epic'
end end
...@@ -399,8 +411,8 @@ describe API::Issues, :mailer do ...@@ -399,8 +411,8 @@ describe API::Issues, :mailer do
describe 'PUT /projects/:id/issues/:issue_id to update epic' do describe 'PUT /projects/:id/issues/:issue_id to update epic' do
it_behaves_like 'with epic parameter' do it_behaves_like 'with epic parameter' do
let(:epic_issue) { create(:issue, project: target_project) } let(:issue_with_epic) { create(:issue, project: target_project) }
let(:request) { put api("/projects/#{target_project.id}/issues/#{epic_issue.iid}", user), params: params } let(:request) { put api("/projects/#{target_project.id}/issues/#{issue_with_epic.iid}", user), params: params }
end end
end end
......
...@@ -83,15 +83,19 @@ describe Groups::AutocompleteService do ...@@ -83,15 +83,19 @@ describe Groups::AutocompleteService do
end end
describe '#epics' do describe '#epics' do
before do
stub_licensed_features(epics: true)
end
it 'returns nothing if not allowed' do it 'returns nothing if not allowed' do
allow(Ability).to receive(:allowed?).with(user, :read_epic, group).and_return(false) guest = create(:user)
expect(subject.epics).to eq([]) epics = described_class.new(group, guest).epics
expect(epics).to be_empty
end end
it 'returns epics from group' do it 'returns epics from group' do
allow(Ability).to receive(:allowed?).with(user, :read_epic, group).and_return(true)
expect(subject.epics.map(&:iid)).to contain_exactly(epic.iid) expect(subject.epics.map(&:iid)).to contain_exactly(epic.iid)
end end
end end
......
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