Commit f1dcfe8e authored by Mario de la Ossa's avatar Mario de la Ossa

Include ancestors in Iteration query

We have to include Iterations belonging to the parent groups if any
parent f6a5eae4
......@@ -5099,6 +5099,11 @@ type Group {
"""
iid: ID
"""
Whether to include ancestor Iterations. Defaults to true
"""
includeAncestors: Boolean
"""
Returns the last _n_ elements from the list.
"""
......
......@@ -14110,6 +14110,16 @@
},
"defaultValue": null
},
{
"name": "includeAncestors",
"description": "Whether to include ancestor Iterations. Defaults to true",
"type": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
},
"defaultValue": null
},
{
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
......@@ -17,6 +17,9 @@ module Resolvers
argument :iid, GraphQL::ID_TYPE,
required: false,
description: 'The internal ID of the Iteration to look up'
argument :include_ancestors, GraphQL::BOOLEAN_TYPE,
required: false,
description: 'Whether to include ancestor Iterations. Defaults to true'
type Types::IterationType, null: true
......@@ -25,6 +28,8 @@ module Resolvers
authorize!
args[:include_ancestors] = true if args[:include_ancestors].nil?
iterations = IterationsFinder.new(context[:current_user], iterations_finder_params(args)).execute
Gitlab::Graphql::Pagination::OffsetActiveRecordRelationConnection.new(iterations)
......@@ -40,23 +45,29 @@ module Resolvers
start_date: args[:start_date],
end_date: args[:end_date],
search_title: args[:title]
}.merge(parent_id_parameter)
}.merge(parent_id_parameter(args[:include_ancestors]))
end
def parent
@parent ||= object.respond_to?(:sync) ? object.sync : object
end
def parent_id_parameter
def parent_id_parameter(include_ancestors)
if parent.is_a?(Group)
{ group_ids: parent.id }
if include_ancestors
{ group_ids: parent.self_and_ancestors.select(:id) }
else
{ group_ids: parent.id }
end
elsif parent.is_a?(Project)
{ project_ids: parent.id }
if include_ancestors && parent.parent_id.present?
{ group_ids: parent.parent.self_and_ancestors.select(:id), project_ids: parent.id }
else
{ project_ids: parent.id }
end
end
end
# IterationsFinder does not check for current_user permissions,
# so for now we need to keep it here.
def authorize!
Ability.allowed?(context[:current_user], :read_iteration, parent) || raise_resource_not_available_error!
end
......
---
title: Include ancestors in Iteration query
merge_request: 36766
author:
type: added
......@@ -12,8 +12,8 @@ RSpec.describe Resolvers::IterationsResolver do
let_it_be(:now) { Time.now }
let_it_be(:group) { create(:group, :private) }
def resolve_group_iterations(args = {}, context = { current_user: current_user })
resolve(described_class, obj: group, args: args, ctx: context)
def resolve_group_iterations(args = {}, obj = group, context = { current_user: current_user })
resolve(described_class, obj: obj, args: args, ctx: context)
end
before do
......@@ -30,7 +30,7 @@ RSpec.describe Resolvers::IterationsResolver do
context 'without parameters' do
it 'calls IterationsFinder to retrieve all iterations' do
params = { id: nil, iid: nil, group_ids: group.id, state: 'all', start_date: nil, end_date: nil, search_title: nil }
params = { id: nil, iid: nil, group_ids: Group.where(id: group.id).select(:id), state: 'all', start_date: nil, end_date: nil, search_title: nil }
expect(IterationsFinder).to receive(:new).with(current_user, params).and_call_original
......@@ -45,7 +45,7 @@ RSpec.describe Resolvers::IterationsResolver do
search = 'wow'
id = 1
iid = 2
params = { id: id, iid: iid, group_ids: group.id, state: 'closed', start_date: start_date, end_date: end_date, search_title: search }
params = { id: id, iid: iid, group_ids: Group.where(id: group.id).select(:id), state: 'closed', start_date: start_date, end_date: end_date, search_title: search }
expect(IterationsFinder).to receive(:new).with(current_user, params).and_call_original
......@@ -53,6 +53,26 @@ RSpec.describe Resolvers::IterationsResolver do
end
end
context 'with subgroup' do
let_it_be(:subgroup) { create(:group, :private, parent: group) }
it 'defaults to include_ancestors' do
params = { id: nil, iid: nil, group_ids: subgroup.self_and_ancestors.select(:id), state: 'all', start_date: nil, end_date: nil, search_title: nil }
expect(IterationsFinder).to receive(:new).with(current_user, params).and_call_original
resolve_group_iterations({}, subgroup)
end
it 'accepts include_ancestors false' do
params = { id: nil, iid: nil, group_ids: subgroup.id, state: 'all', start_date: nil, end_date: nil, search_title: nil }
expect(IterationsFinder).to receive(:new).with(current_user, params).and_call_original
resolve_group_iterations({ include_ancestors: false }, subgroup)
end
end
context 'by timeframe' do
context 'when start_date and end_date are present' do
context 'when start date is after end_date' do
......@@ -86,7 +106,7 @@ RSpec.describe Resolvers::IterationsResolver do
unauthorized_user = create(:user)
expect do
resolve_group_iterations({}, { current_user: unauthorized_user })
resolve_group_iterations({}, group, { current_user: unauthorized_user })
end.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
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