Commit 2630a0f6 authored by Felipe Artur's avatar Felipe Artur Committed by Heinrich Lee Yu

Accept group path as ID when fetching notes from API

Allow to pass group full path as ID when fetching epic notes
from API.
parent bf5fcf7f
---
title: Accept group path as ID when fetching notes from API
merge_request: 23535
author:
type: fixed
...@@ -36,7 +36,7 @@ module API ...@@ -36,7 +36,7 @@ module API
forbidden!('Anonymous visual review feedback is disabled') forbidden!('Anonymous visual review feedback is disabled')
end end
merge_request = find_merge_request_without_permissions_check(params[:id], params[:merge_request_iid]) merge_request = find_merge_request_without_permissions_check(params[:merge_request_iid])
note = create_visual_review_note(merge_request, { note = create_visual_review_note(merge_request, {
note: params[:body], note: params[:body],
......
...@@ -15,17 +15,17 @@ module EE ...@@ -15,17 +15,17 @@ module EE
end end
end end
def add_parent_to_finder_params(finder_params, noteable_type, parent_id) def add_parent_to_finder_params(finder_params, noteable_type)
if noteable_type.name.underscore == 'epic' if noteable_type.name.underscore == 'epic'
finder_params[:group_id] = parent_id finder_params[:group_id] = user_group.id
else else
super super
end end
end end
# Used only for anonymous Visual Review Tools feedback # Used only for anonymous Visual Review Tools feedback
def find_merge_request_without_permissions_check(parent_id, noteable_id) def find_merge_request_without_permissions_check(noteable_id)
params = finder_params_by_noteable_type_and_id(::MergeRequest, noteable_id, parent_id) params = finder_params_by_noteable_type_and_id(::MergeRequest, noteable_id)
::NotesFinder.new(current_user, params).target || not_found!(noteable_type) ::NotesFinder.new(current_user, params).target || not_found!(noteable_type)
end end
......
...@@ -36,12 +36,18 @@ describe 'NotesHelpers' do ...@@ -36,12 +36,18 @@ describe 'NotesHelpers' do
stub_licensed_features(epics: true) stub_licensed_features(epics: true)
end end
context '#find_noteable' do
it 'returns the expected epic' do it 'returns the expected epic' do
expect(subject.find_noteable(Group, parent_id, noteable_type, epic.id)).to eq(epic) allow(subject).to receive(:user_group).and_return(group)
expect(subject.find_noteable(noteable_type, epic.id)).to eq(epic)
end end
it 'raises not found exception when epic does not belong to group' do it 'raises not found exception when epic does not belong to group' do
expect { subject.find_noteable(Group, other_group.id, noteable_type, epic.id) }.to raise_error(ActiveRecord::RecordNotFound) allow(subject).to receive(:user_group).and_return(other_group)
expect { subject.find_noteable(noteable_type, epic.id) }.to raise_error(ActiveRecord::RecordNotFound)
end
end end
end end
end end
...@@ -26,7 +26,7 @@ module API ...@@ -26,7 +26,7 @@ module API
end end
get ":id/#{noteables_path}/:noteable_id/discussions" do get ":id/#{noteables_path}/:noteable_id/discussions" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
notes = readable_discussion_notes(noteable) notes = readable_discussion_notes(noteable)
discussions = Kaminari.paginate_array(Discussion.build_collection(notes, noteable)) discussions = Kaminari.paginate_array(Discussion.build_collection(notes, noteable))
...@@ -42,7 +42,7 @@ module API ...@@ -42,7 +42,7 @@ module API
requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable' requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable'
end end
get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id" do get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
notes = readable_discussion_notes(noteable, params[:discussion_id]) notes = readable_discussion_notes(noteable, params[:discussion_id])
if notes.empty? if notes.empty?
...@@ -77,7 +77,7 @@ module API ...@@ -77,7 +77,7 @@ module API
end end
end end
post ":id/#{noteables_path}/:noteable_id/discussions" do post ":id/#{noteables_path}/:noteable_id/discussions" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
type = params[:position] ? 'DiffNote' : 'DiscussionNote' type = params[:position] ? 'DiffNote' : 'DiscussionNote'
id_key = noteable.is_a?(Commit) ? :commit_id : :noteable_id id_key = noteable.is_a?(Commit) ? :commit_id : :noteable_id
...@@ -107,7 +107,7 @@ module API ...@@ -107,7 +107,7 @@ module API
requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable' requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable'
end end
get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes" do get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
notes = readable_discussion_notes(noteable, params[:discussion_id]) notes = readable_discussion_notes(noteable, params[:discussion_id])
if notes.empty? if notes.empty?
...@@ -127,7 +127,7 @@ module API ...@@ -127,7 +127,7 @@ module API
optional :created_at, type: String, desc: 'The creation date of the note' optional :created_at, type: String, desc: 'The creation date of the note'
end end
post ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes" do post ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
notes = readable_discussion_notes(noteable, params[:discussion_id]) notes = readable_discussion_notes(noteable, params[:discussion_id])
first_note = notes.first first_note = notes.first
...@@ -161,7 +161,7 @@ module API ...@@ -161,7 +161,7 @@ module API
requires :note_id, type: Integer, desc: 'The ID of a note' requires :note_id, type: Integer, desc: 'The ID of a note'
end end
get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
get_note(noteable, params[:note_id]) get_note(noteable, params[:note_id])
end end
...@@ -178,7 +178,7 @@ module API ...@@ -178,7 +178,7 @@ module API
exactly_one_of :body, :resolved exactly_one_of :body, :resolved
end end
put ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do put ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
if params[:resolved].nil? if params[:resolved].nil?
update_note(noteable, params[:note_id]) update_note(noteable, params[:note_id])
...@@ -196,7 +196,7 @@ module API ...@@ -196,7 +196,7 @@ module API
requires :note_id, type: Integer, desc: 'The ID of a note' requires :note_id, type: Integer, desc: 'The ID of a note'
end end
delete ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do delete ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
delete_note(noteable, params[:note_id]) delete_note(noteable, params[:note_id])
end end
...@@ -211,7 +211,7 @@ module API ...@@ -211,7 +211,7 @@ module API
requires :resolved, type: Boolean, desc: 'Mark discussion resolved/unresolved' requires :resolved, type: Boolean, desc: 'Mark discussion resolved/unresolved'
end end
put ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id" do put ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
resolve_discussion(noteable, params[:discussion_id], params[:resolved]) resolve_discussion(noteable, params[:discussion_id], params[:resolved])
end end
......
...@@ -83,15 +83,15 @@ module API ...@@ -83,15 +83,15 @@ module API
end end
end end
def find_noteable(parent_type, parent_id, noteable_type, noteable_id) def find_noteable(noteable_type, noteable_id)
params = finder_params_by_noteable_type_and_id(noteable_type, noteable_id, parent_id) params = finder_params_by_noteable_type_and_id(noteable_type, noteable_id)
noteable = NotesFinder.new(current_user, params).target noteable = NotesFinder.new(current_user, params).target
noteable = nil unless can?(current_user, noteable_read_ability_name(noteable), noteable) noteable = nil unless can?(current_user, noteable_read_ability_name(noteable), noteable)
noteable || not_found!(noteable_type) noteable || not_found!(noteable_type)
end end
def finder_params_by_noteable_type_and_id(type, id, parent_id) def finder_params_by_noteable_type_and_id(type, id)
target_type = type.name.underscore target_type = type.name.underscore
{ target_type: target_type }.tap do |h| { target_type: target_type }.tap do |h|
if %w(issue merge_request).include?(target_type) if %w(issue merge_request).include?(target_type)
...@@ -100,11 +100,11 @@ module API ...@@ -100,11 +100,11 @@ module API
h[:target_id] = id h[:target_id] = id
end end
add_parent_to_finder_params(h, type, parent_id) add_parent_to_finder_params(h, type)
end end
end end
def add_parent_to_finder_params(finder_params, noteable_type, parent_id) def add_parent_to_finder_params(finder_params, noteable_type)
finder_params[:project] = user_project finder_params[:project] = user_project
end end
......
...@@ -30,7 +30,7 @@ module API ...@@ -30,7 +30,7 @@ module API
end end
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
get ":id/#{noteables_str}/:noteable_id/notes" do get ":id/#{noteables_str}/:noteable_id/notes" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
# We exclude notes that are cross-references and that cannot be viewed # We exclude notes that are cross-references and that cannot be viewed
# by the current user. By doing this exclusion at this level and not # by the current user. By doing this exclusion at this level and not
...@@ -58,7 +58,7 @@ module API ...@@ -58,7 +58,7 @@ module API
requires :noteable_id, type: Integer, desc: 'The ID of the noteable' requires :noteable_id, type: Integer, desc: 'The ID of the noteable'
end end
get ":id/#{noteables_str}/:noteable_id/notes/:note_id" do get ":id/#{noteables_str}/:noteable_id/notes/:note_id" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
get_note(noteable, params[:note_id]) get_note(noteable, params[:note_id])
end end
...@@ -71,7 +71,7 @@ module API ...@@ -71,7 +71,7 @@ module API
optional :created_at, type: String, desc: 'The creation date of the note' optional :created_at, type: String, desc: 'The creation date of the note'
end end
post ":id/#{noteables_str}/:noteable_id/notes" do post ":id/#{noteables_str}/:noteable_id/notes" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
opts = { opts = {
note: params[:body], note: params[:body],
...@@ -98,7 +98,7 @@ module API ...@@ -98,7 +98,7 @@ module API
requires :body, type: String, desc: 'The content of a note' requires :body, type: String, desc: 'The content of a note'
end end
put ":id/#{noteables_str}/:noteable_id/notes/:note_id" do put ":id/#{noteables_str}/:noteable_id/notes/:note_id" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
update_note(noteable, params[:note_id]) update_note(noteable, params[:note_id])
end end
...@@ -111,7 +111,7 @@ module API ...@@ -111,7 +111,7 @@ module API
requires :note_id, type: Integer, desc: 'The ID of a note' requires :note_id, type: Integer, desc: 'The ID of a note'
end end
delete ":id/#{noteables_str}/:noteable_id/notes/:note_id" do delete ":id/#{noteables_str}/:noteable_id/notes/:note_id" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
delete_note(noteable, params[:note_id]) delete_note(noteable, params[:note_id])
end end
......
...@@ -25,7 +25,7 @@ module API ...@@ -25,7 +25,7 @@ module API
end end
get ":id/#{eventables_str}/:eventable_id/resource_label_events" do get ":id/#{eventables_str}/:eventable_id/resource_label_events" do
eventable = find_noteable(parent_type, params[:id], eventable_type, params[:eventable_id]) eventable = find_noteable(eventable_type, params[:eventable_id])
opts = { page: params[:page], per_page: params[:per_page] } opts = { page: params[:page], per_page: params[:per_page] }
events = ResourceLabelEventFinder.new(current_user, eventable, opts).execute events = ResourceLabelEventFinder.new(current_user, eventable, opts).execute
...@@ -42,7 +42,8 @@ module API ...@@ -42,7 +42,8 @@ module API
requires :eventable_id, types: [Integer, String], desc: 'The ID of the eventable' requires :eventable_id, types: [Integer, String], desc: 'The ID of the eventable'
end end
get ":id/#{eventables_str}/:eventable_id/resource_label_events/:event_id" do get ":id/#{eventables_str}/:eventable_id/resource_label_events/:event_id" do
eventable = find_noteable(parent_type, params[:id], eventable_type, params[:eventable_id]) eventable = find_noteable(eventable_type, params[:eventable_id])
event = eventable.resource_label_events.find(params[:event_id]) event = eventable.resource_label_events.find(params[:event_id])
not_found!('ResourceLabelEvent') unless can?(current_user, :read_resource_label_event, event) not_found!('ResourceLabelEvent') unless can?(current_user, :read_resource_label_event, event)
......
...@@ -20,6 +20,14 @@ RSpec.shared_examples 'noteable API' do |parent_type, noteable_type, id_name| ...@@ -20,6 +20,14 @@ RSpec.shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
expect(response_dates).to eq(response_dates.sort.reverse) expect(response_dates).to eq(response_dates.sort.reverse)
end end
it 'fetches notes using parent path as id paremeter' do
parent_id = CGI.escape(parent.full_path)
get api("/#{parent_type}/#{parent_id}/#{noteable_type}/#{noteable[id_name]}/notes", user)
expect(response.status).to eq(200)
end
context '2 notes with equal created_at' do context '2 notes with equal created_at' do
before do before do
@first_note = Note.first @first_note = Note.first
......
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