Commit 0b339785 authored by Jonathan Schafer's avatar Jonathan Schafer Committed by Stan Hu

Move counting logic to resolvers

Move `user_notes_count` and `user_discussions_count` from `IssueType`
into their own resolvers.
parent cef6eb7e
# frozen_string_literal: true
module Resolvers
class UserDiscussionsCountResolver < BaseResolver
include Gitlab::Graphql::Authorize::AuthorizeResource
type GraphQL::INT_TYPE, null: true
def resolve
authorize!(object)
BatchLoader::GraphQL.for(object.id).batch(key: :issue_user_discussions_count) do |ids, loader, args|
counts = Note.count_for_collection(ids, 'Issue', 'COUNT(DISTINCT discussion_id) as count').index_by(&:noteable_id)
ids.each do |id|
loader.call(id, counts[id]&.count || 0)
end
end
end
def authorized_resource?(object)
context[:current_user].present? && Ability.allowed?(context[:current_user], :read_issue, object)
end
end
end
# frozen_string_literal: true
module Resolvers
class UserNotesCountResolver < BaseResolver
include Gitlab::Graphql::Authorize::AuthorizeResource
type GraphQL::INT_TYPE, null: true
def resolve
authorize!(object)
BatchLoader::GraphQL.for(object.id).batch(key: :issue_user_notes_count) do |ids, loader, args|
counts = Note.count_for_collection(ids, 'Issue').index_by(&:noteable_id)
ids.each do |id|
loader.call(id, counts[id]&.count || 0)
end
end
end
def authorized_resource?(object)
context[:current_user].present? && Ability.allowed?(context[:current_user], :read_issue, object)
end
end
end
......@@ -61,9 +61,11 @@ module Types
field :downvotes, GraphQL::INT_TYPE, null: false,
description: 'Number of downvotes the issue has received'
field :user_notes_count, GraphQL::INT_TYPE, null: false,
description: 'Number of user notes of the issue'
description: 'Number of user notes of the issue',
resolver: Resolvers::UserNotesCountResolver
field :user_discussions_count, GraphQL::INT_TYPE, null: false,
description: 'Number of user discussions in the issue'
description: 'Number of user discussions in the issue',
resolver: Resolvers::UserDiscussionsCountResolver
field :web_path, GraphQL::STRING_TYPE, null: false, method: :issue_path,
description: 'Web path of the issue'
field :web_url, GraphQL::STRING_TYPE, null: false,
......@@ -119,26 +121,6 @@ module Types
field :moved_to, Types::IssueType, null: true,
description: 'Updated Issue after it got moved to another project'
def user_notes_count
BatchLoader::GraphQL.for(object.id).batch(key: :issue_user_notes_count) do |ids, loader, args|
counts = Note.count_for_collection(ids, 'Issue').index_by(&:noteable_id)
ids.each do |id|
loader.call(id, counts[id]&.count || 0)
end
end
end
def user_discussions_count
BatchLoader::GraphQL.for(object.id).batch(key: :issue_user_discussions_count) do |ids, loader, args|
counts = Note.count_for_collection(ids, 'Issue', 'COUNT(DISTINCT discussion_id) as count').index_by(&:noteable_id)
ids.each do |id|
loader.call(id, counts[id]&.count || 0)
end
end
end
def author
Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.author_id).find
end
......
---
title: Move IssueType notes and discussions count logic to resolvers
merge_request: 49160
author:
type: changed
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Resolvers::UserDiscussionsCountResolver do
include GraphqlHelpers
describe '#resolve' do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :public) }
let_it_be(:private_project) { create(:project, :private) }
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:private_issue) { create(:issue, project: private_project) }
let_it_be(:public_discussions) { create_list(:discussion_note_on_issue, 2, noteable: issue, project: project) }
let_it_be(:system_discussion) { create(:discussion_note_on_issue, system: true, noteable: issue, project: project) }
let_it_be(:private_discussion) { create_list(:discussion_note_on_issue, 3, noteable: private_issue, project: private_project) }
specify do
expect(described_class).to have_nullable_graphql_type(GraphQL::INT_TYPE)
end
context 'when counting discussions from a public issue' do
subject { batch_sync { resolve_user_discussions_count(issue) } }
it 'returns the number of discussions for the issue' do
expect(subject).to eq(2)
end
end
context 'when a user has permission to view discussions' do
before do
private_project.add_developer(user)
end
subject { batch_sync { resolve_user_discussions_count(private_issue) } }
it 'returns the number of non-system discussions for the issue' do
expect(subject).to eq(3)
end
end
context 'when a user does not have permission to view discussions' do
subject { batch_sync { resolve_user_discussions_count(private_issue) } }
it 'returns no discussions' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
end
def resolve_user_discussions_count(obj)
resolve(described_class, obj: obj, ctx: { current_user: user })
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Resolvers::UserNotesCountResolver do
include GraphqlHelpers
describe '#resolve' do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :public) }
let_it_be(:private_project) { create(:project, :private) }
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:private_issue) { create(:issue, project: private_project) }
let_it_be(:public_notes) { create_list(:note, 2, noteable: issue, project: project) }
let_it_be(:system_note) { create(:note, system: true, noteable: issue, project: project) }
let_it_be(:private_notes) { create_list(:note, 3, noteable: private_issue, project: private_project) }
specify do
expect(described_class).to have_nullable_graphql_type(GraphQL::INT_TYPE)
end
context 'when counting notes from a public issue' do
subject { batch_sync { resolve_user_notes_count(issue) } }
it 'returns the number of non-system notes for the issue' do
expect(subject).to eq(2)
end
end
context 'when a user has permission to view notes' do
before do
private_project.add_developer(user)
end
subject { batch_sync { resolve_user_notes_count(private_issue) } }
it 'returns the number of notes for the issue' do
expect(subject).to eq(3)
end
end
context 'when a user does not have permission to view discussions' do
subject { batch_sync { resolve_user_notes_count(private_issue) } }
it 'returns no notes' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
end
def resolve_user_notes_count(obj)
resolve(described_class, obj: obj, ctx: { current_user: user })
end
end
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