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:



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

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:



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

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.



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

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:



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

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:



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

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



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

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



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

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:



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

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:



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

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:



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

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



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

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:



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

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.



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

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

#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 types in the schema.

Returns:



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

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