2020-06-23 00:09:42 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
class Projects::MergeRequests::DraftsController < Projects::MergeRequests::ApplicationController
|
|
|
|
include Gitlab::Utils::StrongMemoize
|
|
|
|
|
|
|
|
respond_to :json
|
|
|
|
|
|
|
|
before_action :authorize_create_note!, only: [:create, :publish]
|
|
|
|
before_action :authorize_admin_draft!, only: [:update, :destroy]
|
|
|
|
before_action :authorize_admin_draft!, if: -> { action_name == 'publish' && params[:id].present? }
|
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
urgency :low, [
|
|
|
|
:create,
|
|
|
|
:update,
|
|
|
|
:destroy,
|
|
|
|
:publish
|
|
|
|
]
|
|
|
|
|
2020-06-23 00:09:42 +05:30
|
|
|
def index
|
|
|
|
drafts = prepare_notes_for_rendering(draft_notes)
|
|
|
|
render json: DraftNoteSerializer.new(current_user: current_user).represent(drafts)
|
|
|
|
end
|
|
|
|
|
|
|
|
def create
|
|
|
|
create_params = draft_note_params.merge(in_reply_to_discussion_id: params[:in_reply_to_discussion_id])
|
|
|
|
create_service = DraftNotes::CreateService.new(merge_request, current_user, create_params)
|
|
|
|
|
|
|
|
draft_note = create_service.execute
|
|
|
|
|
|
|
|
prepare_notes_for_rendering(draft_note)
|
|
|
|
|
|
|
|
render json: DraftNoteSerializer.new(current_user: current_user).represent(draft_note)
|
|
|
|
end
|
|
|
|
|
|
|
|
def update
|
|
|
|
draft_note.update!(draft_note_params)
|
|
|
|
|
|
|
|
prepare_notes_for_rendering(draft_note)
|
|
|
|
|
|
|
|
render json: DraftNoteSerializer.new(current_user: current_user).represent(draft_note)
|
|
|
|
end
|
|
|
|
|
|
|
|
def destroy
|
|
|
|
DraftNotes::DestroyService.new(merge_request, current_user).execute(draft_note)
|
|
|
|
|
|
|
|
head :ok
|
|
|
|
end
|
|
|
|
|
|
|
|
def publish
|
|
|
|
result = DraftNotes::PublishService.new(merge_request, current_user).execute(draft_note(allow_nil: true))
|
|
|
|
|
2022-07-23 23:45:48 +05:30
|
|
|
if Feature.enabled?(:mr_review_submit_comment, @project) && create_note_params[:note]
|
|
|
|
Notes::CreateService.new(@project, current_user, create_note_params).execute
|
|
|
|
end
|
|
|
|
|
2020-06-23 00:09:42 +05:30
|
|
|
if result[:status] == :success
|
|
|
|
head :ok
|
|
|
|
else
|
2021-01-03 14:25:43 +05:30
|
|
|
render json: { message: result[:message] }, status: :internal_server_error
|
2020-06-23 00:09:42 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def discard
|
|
|
|
DraftNotes::DestroyService.new(merge_request, current_user).execute
|
|
|
|
|
|
|
|
head :ok
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def draft_note(allow_nil: false)
|
|
|
|
strong_memoize(:draft_note) do
|
|
|
|
draft_notes.find(params[:id])
|
|
|
|
end
|
|
|
|
rescue ActiveRecord::RecordNotFound => ex
|
|
|
|
# draft_note is allowed to be nil in #publish
|
|
|
|
raise ex unless allow_nil
|
|
|
|
end
|
|
|
|
|
|
|
|
def draft_notes
|
|
|
|
return unless current_user
|
|
|
|
|
|
|
|
strong_memoize(:draft_notes) do
|
|
|
|
merge_request.draft_notes.authored_by(current_user)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
|
|
|
def merge_request
|
|
|
|
@merge_request ||= MergeRequestsFinder.new(current_user, project_id: @project.id).find_by!(iid: params[:merge_request_id])
|
|
|
|
end
|
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
|
|
|
|
|
|
|
def draft_note_params
|
|
|
|
params.require(:draft_note).permit(
|
|
|
|
:commit_id,
|
|
|
|
:note,
|
|
|
|
:position,
|
2022-04-04 11:22:00 +05:30
|
|
|
:resolve_discussion,
|
|
|
|
:line_code
|
2020-06-23 00:09:42 +05:30
|
|
|
).tap do |h|
|
|
|
|
# Old FE version will still be sending `draft_note[commit_id]` as 'undefined'.
|
|
|
|
# That can result to having a note linked to a commit with 'undefined' ID
|
|
|
|
# which is non-existent.
|
|
|
|
h[:commit_id] = nil if h[:commit_id] == 'undefined'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-07-23 23:45:48 +05:30
|
|
|
def create_note_params
|
|
|
|
params.permit(
|
|
|
|
:note
|
|
|
|
).tap do |create_params|
|
|
|
|
create_params[:noteable_type] = merge_request.class.name
|
|
|
|
create_params[:noteable_id] = merge_request.id
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-06-23 00:09:42 +05:30
|
|
|
def prepare_notes_for_rendering(notes)
|
|
|
|
return [] unless notes
|
|
|
|
|
|
|
|
notes = Array.wrap(notes)
|
|
|
|
|
|
|
|
# Preload author and access-level information
|
|
|
|
DraftNote.preload_author(notes)
|
|
|
|
user_ids = notes.map(&:author_id)
|
|
|
|
project.team.max_member_access_for_user_ids(user_ids)
|
|
|
|
|
|
|
|
notes.map(&method(:render_draft_note))
|
|
|
|
end
|
|
|
|
|
|
|
|
def render_draft_note(note)
|
|
|
|
params = { target_id: merge_request.id, target_type: 'MergeRequest', text: note.note }
|
|
|
|
result = PreviewMarkdownService.new(@project, current_user, params).execute
|
2022-01-26 12:08:38 +05:30
|
|
|
markdown_params = { markdown_engine: result[:markdown_engine], issuable_reference_expansion_enabled: true }
|
2020-06-23 00:09:42 +05:30
|
|
|
|
|
|
|
note.rendered_note = view_context.markdown(result[:text], markdown_params)
|
|
|
|
note.users_referenced = result[:users]
|
|
|
|
note.commands_changes = view_context.markdown(result[:commands])
|
|
|
|
|
|
|
|
note
|
|
|
|
end
|
|
|
|
|
|
|
|
def authorize_admin_draft!
|
|
|
|
access_denied! unless can?(current_user, :admin_note, draft_note)
|
|
|
|
end
|
|
|
|
|
|
|
|
def authorize_create_note!
|
|
|
|
access_denied! unless can?(current_user, :create_note, merge_request)
|
|
|
|
end
|
|
|
|
end
|