Commit de3e6712 authored by Heinrich Lee Yu's avatar Heinrich Lee Yu

Merge branch 'issue_195791' into 'master'

Accept group path as ID when fetching notes from API

See merge request gitlab-org/gitlab!23535
parents bf5fcf7f 2630a0f6
---
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