Skip to content
Snippets Groups Projects
Commit 382bb108 authored by Luke Duncalfe's avatar Luke Duncalfe :red_circle: Committed by Natalia Tepluhina
Browse files

GraphQL support for Notes created in discussions

A new `discussion_id` argument on the `createNote` mutation allows
people to create a note within that discussion.

The ability to lazy-load Discussions has been added, so
GraphQL.object_from_id can treat Discussions the same as AR objects and
batch load them.

https://gitlab.com/gitlab-org/gitlab-ce/issues/62826
https://gitlab.com/gitlab-org/gitlab-ee/issues/9489
parent 8e2596e8
No related branches found
No related tags found
No related merge requests found
......@@ -66,8 +66,8 @@ def object_from_id(global_id)
if gid.model_class < ApplicationRecord
Gitlab::Graphql::Loaders::BatchModelLoader.new(gid.model_class, gid.model_id).find
elsif gid.model_class.in?([Discussion, IndividualNoteDiscussion])
Note.lazy_find_discussion(gid.model_id)
elsif gid.model_class.respond_to?(:lazy_find)
gid.model_class.lazy_find(gid.model_id)
else
gid.find
end
......
......@@ -5,6 +5,35 @@ module Notes
module Create
class Note < Base
graphql_name 'CreateNote'
argument :discussion_id,
GraphQL::ID_TYPE,
required: false,
description: 'The global id of the discussion this note is in reply to'
private
def create_note_params(noteable, args)
discussion_id = nil
if args[:discussion_id]
discussion = GitlabSchema.object_from_id(args[:discussion_id])
authorize_discussion!(discussion)
discussion_id = discussion.id
end
super(noteable, args).merge({
in_reply_to_discussion_id: discussion_id
})
end
def authorize_discussion!(discussion)
unless Ability.allowed?(current_user, :read_note, discussion, scope: :user)
raise Gitlab::Graphql::Errors::ResourceNotAvailable,
"The discussion does not exist or you don't have permission to perform this action"
end
end
end
end
end
......
......@@ -14,9 +14,9 @@ class DiscussionType < BaseObject
# The gem we use to generate Global IDs is hard-coded to work with
# `id` properties. To generate a GID for the `reply_id` property,
# we must use the low-level .build method.
# we must use the ::Gitlab::GlobalId module.
def reply_id
::URI::GID.build(app: GlobalID.app, model_name: object.class.name, model_id: object.reply_id)
::Gitlab::GlobalId.build(object, id: object.reply_id)
end
end
end
......
......@@ -143,7 +143,7 @@
end
end
context 'for `Discussion` and `IndividualNoteDiscussion` classes' do
context 'for classes that are not ActiveRecord subclasses and have implemented .lazy_find' do
it 'returns the correct record' do
note = create(:discussion_note_on_merge_request)
......
......@@ -7,10 +7,12 @@
set(:current_user) { create(:user) }
let(:noteable) { create(:merge_request, source_project: project, target_project: project) }
let(:project) { create(:project, :repository) }
let(:project) { create(:project) }
let(:discussion) { nil }
let(:mutation) do
variables = {
noteable_id: GitlabSchema.id_from_object(noteable).to_s,
discussion_id: (GitlabSchema.id_from_object(discussion).to_s if discussion),
body: 'Body text'
}
......@@ -39,5 +41,24 @@ def mutation_response
expect(mutation_response['note']['body']).to eq('Body text')
end
describe 'creating Notes in reply to a discussion' do
context 'when the user does not have permission to create notes on the discussion' do
let(:discussion) { create(:discussion_note).to_discussion }
it_behaves_like 'a mutation that returns top-level errors',
errors: ["The discussion does not exist or you don't have permission to perform this action"]
end
context 'when the user has permission to create notes on the discussion' do
let(:discussion) { create(:discussion_note, project: project).to_discussion }
it 'creates a Note in a discussion' do
post_graphql_mutation(mutation, current_user: current_user)
expect(mutation_response['note']['discussion']['id']).to eq(discussion.to_global_id.to_s)
end
end
end
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment