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
forbidden!('Anonymous visual review feedback is disabled')
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: params[:body],
......
......@@ -15,17 +15,17 @@ module EE
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'
finder_params[:group_id] = parent_id
finder_params[:group_id] = user_group.id
else
super
end
end
# Used only for anonymous Visual Review Tools feedback
def find_merge_request_without_permissions_check(parent_id, noteable_id)
params = finder_params_by_noteable_type_and_id(::MergeRequest, noteable_id, parent_id)
def find_merge_request_without_permissions_check(noteable_id)
params = finder_params_by_noteable_type_and_id(::MergeRequest, noteable_id)
::NotesFinder.new(current_user, params).target || not_found!(noteable_type)
end
......
......@@ -36,12 +36,18 @@ describe 'NotesHelpers' do
stub_licensed_features(epics: true)
end
context '#find_noteable' 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
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
......@@ -26,7 +26,7 @@ module API
end
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)
discussions = Kaminari.paginate_array(Discussion.build_collection(notes, noteable))
......@@ -42,7 +42,7 @@ module API
requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable'
end
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])
if notes.empty?
......@@ -77,7 +77,7 @@ module API
end
end
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'
id_key = noteable.is_a?(Commit) ? :commit_id : :noteable_id
......@@ -107,7 +107,7 @@ module API
requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable'
end
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])
if notes.empty?
......@@ -127,7 +127,7 @@ module API
optional :created_at, type: String, desc: 'The creation date of the note'
end
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])
first_note = notes.first
......@@ -161,7 +161,7 @@ module API
requires :note_id, type: Integer, desc: 'The ID of a note'
end
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])
end
......@@ -178,7 +178,7 @@ module API
exactly_one_of :body, :resolved
end
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?
update_note(noteable, params[:note_id])
......@@ -196,7 +196,7 @@ module API
requires :note_id, type: Integer, desc: 'The ID of a note'
end
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])
end
......@@ -211,7 +211,7 @@ module API
requires :resolved, type: Boolean, desc: 'Mark discussion resolved/unresolved'
end
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])
end
......
......@@ -83,15 +83,15 @@ module API
end
end
def find_noteable(parent_type, parent_id, noteable_type, noteable_id)
params = finder_params_by_noteable_type_and_id(noteable_type, noteable_id, parent_id)
def find_noteable(noteable_type, noteable_id)
params = finder_params_by_noteable_type_and_id(noteable_type, noteable_id)
noteable = NotesFinder.new(current_user, params).target
noteable = nil unless can?(current_user, noteable_read_ability_name(noteable), noteable)
noteable || not_found!(noteable_type)
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: target_type }.tap do |h|
if %w(issue merge_request).include?(target_type)
......@@ -100,11 +100,11 @@ module API
h[:target_id] = id
end
add_parent_to_finder_params(h, type, parent_id)
add_parent_to_finder_params(h, type)
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
end
......
......@@ -30,7 +30,7 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
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
# by the current user. By doing this exclusion at this level and not
......@@ -58,7 +58,7 @@ module API
requires :noteable_id, type: Integer, desc: 'The ID of the noteable'
end
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])
end
......@@ -71,7 +71,7 @@ module API
optional :created_at, type: String, desc: 'The creation date of the note'
end
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 = {
note: params[:body],
......@@ -98,7 +98,7 @@ module API
requires :body, type: String, desc: 'The content of a note'
end
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])
end
......@@ -111,7 +111,7 @@ module API
requires :note_id, type: Integer, desc: 'The ID of a note'
end
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])
end
......
......@@ -25,7 +25,7 @@ module API
end
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] }
events = ResourceLabelEventFinder.new(current_user, eventable, opts).execute
......@@ -42,7 +42,8 @@ module API
requires :eventable_id, types: [Integer, String], desc: 'The ID of the eventable'
end
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])
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|
expect(response_dates).to eq(response_dates.sort.reverse)
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
before do
@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