Commit 4e36caa5 authored by Vitali Tatarintev's avatar Vitali Tatarintev

Merge branch 'ajk-base-edge' into 'master'

Add BaseEdge base class

See merge request gitlab-org/gitlab!71476
parents e8c59dbe 28e7d8c2
# frozen_string_literal: true
module Types
class BaseEdge < GraphQL::Types::Relay::BaseEdge
field_class Types::BaseField
end
end
...@@ -78,6 +78,8 @@ module Types ...@@ -78,6 +78,8 @@ module Types
attr_reader :feature_flag attr_reader :feature_flag
def field_authorized?(object, ctx) def field_authorized?(object, ctx)
object = object.node if object.is_a?(GraphQL::Pagination::Connection::Edge)
authorization.ok?(object, ctx[:current_user]) authorization.ok?(object, ctx[:current_user])
end end
......
...@@ -7,6 +7,7 @@ module Types ...@@ -7,6 +7,7 @@ module Types
prepend Gitlab::Graphql::MarkdownField prepend Gitlab::Graphql::MarkdownField
field_class Types::BaseField field_class Types::BaseField
edge_type_class Types::BaseEdge
def self.accepts(*types) def self.accepts(*types)
@accepts ||= [] @accepts ||= []
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
module Types module Types
module Ci module Ci
# rubocop: disable Graphql/AuthorizeTypes # rubocop: disable Graphql/AuthorizeTypes
class RunnerWebUrlEdge < GraphQL::Types::Relay::BaseEdge class RunnerWebUrlEdge < ::Types::BaseEdge
include FindClosest include FindClosest
field :web_url, GraphQL::Types::String, null: true, field :web_url, GraphQL::Types::String, null: true,
......
...@@ -85,7 +85,7 @@ RSpec.describe 'Query.project(fullPath).pipelines.dastProfile' do ...@@ -85,7 +85,7 @@ RSpec.describe 'Query.project(fullPath).pipelines.dastProfile' do
subject subject
expect(dast_profile_data).to be_empty expect(dast_profile_data).to contain_exactly(nil)
end end
end end
end end
......
...@@ -8,7 +8,7 @@ module RuboCop ...@@ -8,7 +8,7 @@ module RuboCop
'https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#type-authorization' 'https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#type-authorization'
# We want to exclude our own basetypes and scalars # We want to exclude our own basetypes and scalars
ALLOWED_TYPES = %w[BaseEnum BaseScalar BasePermissionType MutationType SubscriptionType ALLOWED_TYPES = %w[BaseEnum BaseEdge BaseScalar BasePermissionType MutationType SubscriptionType
QueryType GraphQL::Schema BaseUnion BaseInputObject].freeze QueryType GraphQL::Schema BaseUnion BaseInputObject].freeze
def_node_search :authorize?, <<~PATTERN def_node_search :authorize?, <<~PATTERN
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Types::BaseEdge do
include GraphqlHelpers
let_it_be(:test_schema) do
project_edge_type = Class.new(described_class) do
field :proof_of_admin_rights, String,
null: true, authorize: :admin_project
def proof_of_admin_rights
'ok'
end
end
project_type = Class.new(::Types::BaseObject) do
graphql_name 'Project'
authorize :read_project
edge_type_class project_edge_type
field :name, String, null: false
end
Class.new(GraphQL::Schema) do
lazy_resolve ::Gitlab::Graphql::Lazy, :force
use ::GraphQL::Pagination::Connections
use ::Gitlab::Graphql::Pagination::Connections
query(Class.new(::Types::BaseObject) do
graphql_name 'Query'
field :projects, project_type.connection_type, null: false
def projects
context[:projects]
end
end)
end
end
def document
GraphQL.parse(<<~GQL)
query {
projects {
edges {
proofOfAdminRights
node { name }
}
}
}
GQL
end
it 'supports field authorization on edge fields' do
user = create(:user)
private_project = create(:project, :private)
member_project = create(:project, :private)
maintainer_project = create(:project, :private)
public_project = create(:project, :public)
member_project.add_developer(user)
maintainer_project.add_maintainer(user)
projects = [private_project, member_project, maintainer_project, public_project]
data = { current_user: user, projects: projects }
query = GraphQL::Query.new(test_schema, document: document, context: data)
result = query.result.to_h
expect(graphql_dig_at(result, 'data', 'projects', 'edges', 'node', 'name'))
.to contain_exactly(member_project.name, maintainer_project.name, public_project.name)
expect(graphql_dig_at(result, 'data', 'projects', 'edges', 'proofOfAdminRights'))
.to contain_exactly(nil, 'ok', nil)
end
end
...@@ -68,7 +68,7 @@ RSpec.describe 'package details' do ...@@ -68,7 +68,7 @@ RSpec.describe 'package details' do
subject subject
expect(graphql_data_at(:package, :versions, :nodes, :version)).to be_present expect(graphql_data_at(:package, :versions, :nodes, :version)).to be_present
expect(graphql_data_at(:package, :versions, :nodes, :versions, :nodes)).to be_empty expect(graphql_data_at(:package, :versions, :nodes, :versions, :nodes)).to eq [nil, nil]
end end
end end
end end
......
...@@ -514,8 +514,13 @@ module GraphqlHelpers ...@@ -514,8 +514,13 @@ module GraphqlHelpers
# Allows for array indexing, like this # Allows for array indexing, like this
# ['project', 'boards', 'edges', 0, 'node', 'lists'] # ['project', 'boards', 'edges', 0, 'node', 'lists']
keys.reduce(data) do |memo, key| keys.reduce(data) do |memo, key|
if memo.is_a?(Array) if memo.is_a?(Array) && key.is_a?(Integer)
key.is_a?(Integer) ? memo[key] : memo.flat_map { |e| Array.wrap(e[key]) } memo[key]
elsif memo.is_a?(Array)
memo.compact.flat_map do |e|
x = e[key]
x.nil? ? [x] : Array.wrap(x)
end
else else
memo&.dig(key) memo&.dig(key)
end end
......
...@@ -55,7 +55,7 @@ RSpec.shared_examples 'group and project packages query' do ...@@ -55,7 +55,7 @@ RSpec.shared_examples 'group and project packages query' do
end end
it 'deals with metadata' do it 'deals with metadata' do
expect(target_shas).to contain_exactly(composer_metadatum.target_sha) expect(target_shas.compact).to contain_exactly(composer_metadatum.target_sha)
end end
it 'returns the count of the packages' do it 'returns the count of the packages' do
......
...@@ -43,6 +43,21 @@ RSpec.describe GraphqlHelpers do ...@@ -43,6 +43,21 @@ RSpec.describe GraphqlHelpers do
expect(graphql_dig_at(data, :foo, :nodes, :bar, :nodes, :id)).to eq([1, 2, 3, 4]) expect(graphql_dig_at(data, :foo, :nodes, :bar, :nodes, :id)).to eq([1, 2, 3, 4])
end end
it 'does not omit nils at the leaves' do
data = {
'foo' => {
'nodes' => [
{ 'bar' => { 'nodes' => [{ 'id' => nil }, { 'id' => 2 }] } },
{ 'bar' => { 'nodes' => [{ 'id' => 3 }, { 'id' => nil }] } },
{ 'bar' => nil }
]
},
'irrelevant' => 'the field is a red-herring'
}
expect(graphql_dig_at(data, :foo, :nodes, :bar, :nodes, :id)).to eq([nil, 2, 3, nil])
end
end end
describe 'var' do describe 'var' do
......
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