Class: GraphQL::Schema::Warden Private

Inherits:
Object
  • Object
show all
Defined in:
lib/graphql/schema/warden.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Restrict access to a GraphQL::Schema with a user-defined filter.

When validating and executing a query, all access to schema members should go through a warden. If you access the schema directly, you may show a client something that it shouldn’t be allowed to see.

Examples:

Hidding private fields

private_members = -> (member, ctx) { member.[:private] }
result = Schema.execute(query_string, except: private_members)

Custom filter implementation

# It must respond to `#call(member)`.
class MissingRequiredFlags
  def initialize(user)
    @user = user
  end

  # Return `false` if any required flags are missing
  def call(member, ctx)
    member.[:required_flags].any? do |flag|
      !@user.has_flag?(flag)
    end
  end
end

# Then, use the custom filter in query:
missing_required_flags = MissingRequiredFlags.new(current_user)

# This query can only access members which match the user's flags
result = Schema.execute(query_string, except: missing_required_flags)

Direct Known Subclasses

Query::NullContext::NullWarden

Instance Method Summary collapse

Constructor Details

#initialize(filter, context:, schema:) ⇒ Warden

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Warden.

Parameters:



43
44
45
46
47
48
49
50
51
# File 'lib/graphql/schema/warden.rb', line 43

def initialize(filter, context:, schema:)
  @schema = schema.interpreter? ? schema : schema.graphql_definition
  # Cache these to avoid repeated hits to the inheritance chain when one isn't present
  @query = @schema.query
  @mutation = @schema.mutation
  @subscription = @schema.subscription
  @context = context
  @visibility_cache = read_through { |m| filter.call(m, context) }
end

Instance Method Details

#arguments(argument_owner) ⇒ Array<GraphQL::Argument>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns Visible arguments on argument_owner.

Parameters:

Returns:



131
132
133
134
# File 'lib/graphql/schema/warden.rb', line 131

def arguments(argument_owner)
  @visible_arguments ||= read_through { |o| o.arguments.each_value.select { |a| visible_argument?(a) } }
  @visible_arguments[argument_owner]
end

#directivesObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



148
149
150
# File 'lib/graphql/schema/warden.rb', line 148

def directives
  @schema.directives.each_value.select { |d| visible?(d) }
end

#enum_values(enum_defn) ⇒ Array<GraphQL::EnumType::EnumValue>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns Visible members of enum_defn.

Returns:



137
138
139
140
# File 'lib/graphql/schema/warden.rb', line 137

def enum_values(enum_defn)
  @visible_enum_values ||= read_through { |e| e.values.each_value.select { |enum_value_defn| visible?(enum_value_defn) } }
  @visible_enum_values[enum_defn]
end

#fields(type_defn) ⇒ Array<GraphQL::Field>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns Fields on type_defn.

Parameters:

Returns:



124
125
126
127
# File 'lib/graphql/schema/warden.rb', line 124

def fields(type_defn)
  @visible_fields ||= read_through { |t| @schema.get_fields(t).each_value.select { |f| visible_field?(t, f) } }
  @visible_fields[type_defn]
end

#get_argument(parent_type, argument_name) ⇒ GraphQL::Argument?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns The argument named argument_name on parent_type, if it exists and is visible.

Returns:

  • (GraphQL::Argument, nil)

    The argument named argument_name on parent_type, if it exists and is visible



108
109
110
111
# File 'lib/graphql/schema/warden.rb', line 108

def get_argument(parent_type, argument_name)
  argument = parent_type.get_argument(argument_name)
  return argument if argument && visible_argument?(argument)
end

#get_field(parent_type, field_name) ⇒ GraphQL::Field?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns The field named field_name on parent_type, if it exists.

Returns:

  • (GraphQL::Field, nil)

    The field named field_name on parent_type, if it exists



92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/graphql/schema/warden.rb', line 92

def get_field(parent_type, field_name)
  @visible_parent_fields ||= read_through do |type|
    read_through do |f_name|
      field_defn = @schema.get_field(type, f_name)
      if field_defn && visible_field?(type, field_defn)
        field_defn
      else
        nil
      end
    end
  end

  @visible_parent_fields[parent_type][field_name]
end

#get_type(type_name) ⇒ GraphQL::BaseType?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns The type named type_name, if it exists (else nil).

Returns:



67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/graphql/schema/warden.rb', line 67

def get_type(type_name)
  @visible_types ||= read_through do |name|
    type_defn = @schema.get_type(name)
    if type_defn && visible_type?(type_defn)
      type_defn
    else
      nil
    end
  end

  @visible_types[type_name]
end

#interfaces(obj_type) ⇒ Array<GraphQL::InterfaceType>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns Visible interfaces implemented by obj_type.

Returns:



143
144
145
146
# File 'lib/graphql/schema/warden.rb', line 143

def interfaces(obj_type)
  @visible_interfaces ||= read_through { |t| t.interfaces(@context).select { |i| visible?(i) } }
  @visible_interfaces[obj_type]
end

#possible_types(type_defn) ⇒ Array<GraphQL::BaseType>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns The types which may be member of type_defn.

Returns:



114
115
116
117
118
119
120
# File 'lib/graphql/schema/warden.rb', line 114

def possible_types(type_defn)
  @visible_possible_types ||= read_through { |type_defn|
    pt = @schema.possible_types(type_defn, @context)
    pt.select { |t| visible_type?(t) }
  }
  @visible_possible_types[type_defn]
end

#reachable_type?(type_name) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns Boolean True if the type is visible and reachable in the schema.

Returns:

  • (Boolean)

    Boolean True if the type is visible and reachable in the schema



86
87
88
89
# File 'lib/graphql/schema/warden.rb', line 86

def reachable_type?(type_name)
  type = get_type(type_name)
  type && reachable_type_set.include?(type)
end

#reachable_typesArray<GraphQL::BaseType>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns Visible and reachable types in the schema.

Returns:



81
82
83
# File 'lib/graphql/schema/warden.rb', line 81

def reachable_types
  @reachable_types ||= reachable_type_set.to_a
end

#root_type_for_operation(op_name) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



152
153
154
155
156
157
158
159
# File 'lib/graphql/schema/warden.rb', line 152

def root_type_for_operation(op_name)
  root_type = @schema.root_type_for_operation(op_name)
  if root_type && visible?(root_type)
    root_type
  else
    nil
  end
end

#typesHash<String, GraphQL::BaseType>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns Visible types in the schema.

Returns:



54
55
56
57
58
59
60
61
62
63
64
# File 'lib/graphql/schema/warden.rb', line 54

def types
  @types ||= begin
    vis_types = {}
    @schema.types.each do |n, t|
      if visible_type?(t)
        vis_types[n] = t
      end
    end
    vis_types
  end
end