debian-mirror-gitlab/lib/api/discussions.rb

248 lines
10 KiB
Ruby
Raw Normal View History

2018-12-05 23:21:45 +05:30
# frozen_string_literal: true
2018-03-27 19:54:05 +05:30
module API
class Discussions < Grape::API
include PaginationParams
helpers ::API::Helpers::NotesHelpers
2019-10-12 21:52:04 +05:30
helpers ::RendersNotes
2018-03-27 19:54:05 +05:30
before { authenticate! }
2019-07-07 11:18:12 +05:30
Helpers::DiscussionsHelpers.noteable_types.each do |noteable_type|
2018-03-27 19:54:05 +05:30
parent_type = noteable_type.parent_class.to_s.underscore
noteables_str = noteable_type.to_s.underscore.pluralize
2018-10-15 14:42:47 +05:30
noteables_path = noteable_type == Commit ? "repository/#{noteables_str}" : noteables_str
2018-03-27 19:54:05 +05:30
params do
requires :id, type: String, desc: "The ID of a #{parent_type}"
end
2019-02-15 15:39:39 +05:30
resource parent_type.pluralize.to_sym, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
2018-03-27 19:54:05 +05:30
desc "Get a list of #{noteable_type.to_s.downcase} discussions" do
success Entities::Discussion
end
params do
2018-10-15 14:42:47 +05:30
requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable'
2018-03-27 19:54:05 +05:30
use :pagination
end
2019-10-12 21:52:04 +05:30
2018-10-15 14:42:47 +05:30
get ":id/#{noteables_path}/:noteable_id/discussions" do
2019-09-30 21:07:59 +05:30
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id])
2018-03-27 19:54:05 +05:30
2019-10-12 21:52:04 +05:30
notes = readable_discussion_notes(noteable)
2018-03-27 19:54:05 +05:30
discussions = Kaminari.paginate_array(Discussion.build_collection(notes, noteable))
present paginate(discussions), with: Entities::Discussion
end
desc "Get a single #{noteable_type.to_s.downcase} discussion" do
success Entities::Discussion
end
params do
requires :discussion_id, type: String, desc: 'The ID of a discussion'
2018-10-15 14:42:47 +05:30
requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable'
2018-03-27 19:54:05 +05:30
end
2018-10-15 14:42:47 +05:30
get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id" do
2019-09-30 21:07:59 +05:30
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id])
2018-03-27 19:54:05 +05:30
notes = readable_discussion_notes(noteable, params[:discussion_id])
2018-10-15 14:42:47 +05:30
if notes.empty?
break not_found!("Discussion")
2018-03-27 19:54:05 +05:30
end
discussion = Discussion.build(notes, noteable)
present discussion, with: Entities::Discussion
end
desc "Create a new #{noteable_type.to_s.downcase} discussion" do
success Entities::Discussion
end
params do
2018-10-15 14:42:47 +05:30
requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable'
2018-03-27 19:54:05 +05:30
requires :body, type: String, desc: 'The content of a note'
optional :created_at, type: String, desc: 'The creation date of the note'
2018-10-15 14:42:47 +05:30
optional :position, type: Hash do
requires :base_sha, type: String, desc: 'Base commit SHA in the source branch'
requires :start_sha, type: String, desc: 'SHA referencing commit in target branch'
requires :head_sha, type: String, desc: 'SHA referencing HEAD of this merge request'
requires :position_type, type: String, desc: 'Type of the position reference', values: %w(text image)
optional :new_path, type: String, desc: 'File path after change'
optional :new_line, type: Integer, desc: 'Line number after change'
optional :old_path, type: String, desc: 'File path before change'
optional :old_line, type: Integer, desc: 'Line number before change'
optional :width, type: Integer, desc: 'Width of the image'
optional :height, type: Integer, desc: 'Height of the image'
optional :x, type: Integer, desc: 'X coordinate in the image'
optional :y, type: Integer, desc: 'Y coordinate in the image'
end
2018-03-27 19:54:05 +05:30
end
2018-10-15 14:42:47 +05:30
post ":id/#{noteables_path}/:noteable_id/discussions" do
2019-09-30 21:07:59 +05:30
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id])
2018-10-15 14:42:47 +05:30
type = params[:position] ? 'DiffNote' : 'DiscussionNote'
id_key = noteable.is_a?(Commit) ? :commit_id : :noteable_id
2018-03-27 19:54:05 +05:30
opts = {
note: params[:body],
created_at: params[:created_at],
2018-10-15 14:42:47 +05:30
type: type,
2018-03-27 19:54:05 +05:30
noteable_type: noteables_str.classify,
2018-10-15 14:42:47 +05:30
position: params[:position],
id_key => noteable.id
2018-03-27 19:54:05 +05:30
}
note = create_note(noteable, opts)
if note.valid?
present note.discussion, with: Entities::Discussion
else
bad_request!("Note #{note.errors.messages}")
end
end
desc "Get comments in a single #{noteable_type.to_s.downcase} discussion" do
success Entities::Discussion
end
params do
requires :discussion_id, type: String, desc: 'The ID of a discussion'
2018-10-15 14:42:47 +05:30
requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable'
2018-03-27 19:54:05 +05:30
end
2018-10-15 14:42:47 +05:30
get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes" do
2019-09-30 21:07:59 +05:30
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id])
2018-03-27 19:54:05 +05:30
notes = readable_discussion_notes(noteable, params[:discussion_id])
2018-10-15 14:42:47 +05:30
if notes.empty?
break not_found!("Notes")
2018-03-27 19:54:05 +05:30
end
present notes, with: Entities::Note
end
desc "Add a comment to a #{noteable_type.to_s.downcase} discussion" do
success Entities::Note
end
params do
2018-10-15 14:42:47 +05:30
requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable'
2018-03-27 19:54:05 +05:30
requires :discussion_id, type: String, desc: 'The ID of a discussion'
requires :body, type: String, desc: 'The content of a note'
optional :created_at, type: String, desc: 'The creation date of the note'
end
2018-10-15 14:42:47 +05:30
post ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes" do
2019-09-30 21:07:59 +05:30
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id])
2018-03-27 19:54:05 +05:30
notes = readable_discussion_notes(noteable, params[:discussion_id])
2019-07-31 22:56:46 +05:30
first_note = notes.first
2018-03-27 19:54:05 +05:30
2018-10-15 14:42:47 +05:30
break not_found!("Discussion") if notes.empty?
2019-07-31 22:56:46 +05:30
unless first_note.part_of_discussion? || first_note.to_discussion.can_convert_to_discussion?
break bad_request!("Discussion can not be replied to.")
end
2018-03-27 19:54:05 +05:30
opts = {
note: params[:body],
type: 'DiscussionNote',
in_reply_to_discussion_id: params[:discussion_id],
created_at: params[:created_at]
}
note = create_note(noteable, opts)
if note.valid?
present note, with: Entities::Note
else
bad_request!("Note #{note.errors.messages}")
end
end
desc "Get a comment in a #{noteable_type.to_s.downcase} discussion" do
success Entities::Note
end
params do
2018-10-15 14:42:47 +05:30
requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable'
2018-03-27 19:54:05 +05:30
requires :discussion_id, type: String, desc: 'The ID of a discussion'
requires :note_id, type: Integer, desc: 'The ID of a note'
end
2018-10-15 14:42:47 +05:30
get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do
2019-09-30 21:07:59 +05:30
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id])
2018-03-27 19:54:05 +05:30
get_note(noteable, params[:note_id])
end
desc "Edit a comment in a #{noteable_type.to_s.downcase} discussion" do
success Entities::Note
end
params do
2018-10-15 14:42:47 +05:30
requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable'
2018-03-27 19:54:05 +05:30
requires :discussion_id, type: String, desc: 'The ID of a discussion'
requires :note_id, type: Integer, desc: 'The ID of a note'
2018-10-15 14:42:47 +05:30
optional :body, type: String, desc: 'The content of a note'
optional :resolved, type: Boolean, desc: 'Mark note resolved/unresolved'
exactly_one_of :body, :resolved
2018-03-27 19:54:05 +05:30
end
2018-10-15 14:42:47 +05:30
put ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do
2019-09-30 21:07:59 +05:30
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id])
2018-03-27 19:54:05 +05:30
2018-10-15 14:42:47 +05:30
if params[:resolved].nil?
update_note(noteable, params[:note_id])
else
resolve_note(noteable, params[:note_id], params[:resolved])
end
2018-03-27 19:54:05 +05:30
end
desc "Delete a comment in a #{noteable_type.to_s.downcase} discussion" do
success Entities::Note
end
params do
2018-10-15 14:42:47 +05:30
requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable'
2018-03-27 19:54:05 +05:30
requires :discussion_id, type: String, desc: 'The ID of a discussion'
requires :note_id, type: Integer, desc: 'The ID of a note'
end
2018-10-15 14:42:47 +05:30
delete ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do
2019-09-30 21:07:59 +05:30
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id])
2018-03-27 19:54:05 +05:30
delete_note(noteable, params[:note_id])
end
2018-10-15 14:42:47 +05:30
2019-09-04 21:01:54 +05:30
if Noteable.resolvable_types.include?(noteable_type.to_s)
2018-10-15 14:42:47 +05:30
desc "Resolve/unresolve an existing #{noteable_type.to_s.downcase} discussion" do
success Entities::Discussion
end
params do
requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable'
requires :discussion_id, type: String, desc: 'The ID of a discussion'
requires :resolved, type: Boolean, desc: 'Mark discussion resolved/unresolved'
end
put ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id" do
2019-09-30 21:07:59 +05:30
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id])
2018-10-15 14:42:47 +05:30
resolve_discussion(noteable, params[:discussion_id], params[:resolved])
end
end
2018-03-27 19:54:05 +05:30
end
end
helpers do
2018-12-05 23:21:45 +05:30
# rubocop: disable CodeReuse/ActiveRecord
2019-10-12 21:52:04 +05:30
def readable_discussion_notes(noteable, discussion_id = nil)
2018-03-27 19:54:05 +05:30
notes = noteable.notes
2019-10-12 21:52:04 +05:30
notes = notes.where(discussion_id: discussion_id) if discussion_id
notes = notes
2018-03-27 19:54:05 +05:30
.inc_relations_for_view
.includes(:noteable)
.fresh
2019-10-12 21:52:04 +05:30
# Without RendersActions#prepare_notes_for_rendering,
# Note#cross_reference_not_visible_for? will attempt to render
# Markdown references mentioned in the note to see whether they
# should be redacted. For notes that reference a commit, this
# would also incur a Gitaly call to verify the commit exists.
#
# With prepare_notes_for_rendering, we can avoid Gitaly calls
# because notes are redacted if they point to projects that
# cannot be accessed by the user.
notes = prepare_notes_for_rendering(notes)
2019-09-04 21:01:54 +05:30
notes.select { |n| n.visible_for?(current_user) }
2018-03-27 19:54:05 +05:30
end
2018-12-05 23:21:45 +05:30
# rubocop: enable CodeReuse/ActiveRecord
2018-03-27 19:54:05 +05:30
end
end
end