Commit 5e02ef43 authored by Alex Kalderimis's avatar Alex Kalderimis

Add BaseEdge base class

See https://gitlab.com/gitlab-org/gitlab/-/issues/341911

This adds a new base class for edges that uses our custom `BaseField`
as the standard field class.

We do not need to customize authorization for edges, since nodes are
redacted by our connections before edges are constructed from them.

All our edges should inherit from this base class in order to use field
customizations.

Changelog: changed
parent 0b83283a
# frozen_string_literal: true
module Types
class BaseEdge < GraphQL::Types::Relay::BaseEdge
field_class Types::BaseField
end
end
......@@ -78,6 +78,8 @@ module Types
attr_reader :feature_flag
def field_authorized?(object, ctx)
object = object.node if object.is_a?(GraphQL::Pagination::Connection::Edge)
authorization.ok?(object, ctx[:current_user])
end
......
......@@ -8,7 +8,7 @@ module RuboCop
'https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#type-authorization'
# 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
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('ok')
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