Class: GraphQL::Schema::Warden

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

Overview

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

The mask is object that responds to #visible?(schema_member).

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.

Masks can be provided in #execute (or Query#initialize) with the mask: keyword.

Examples:

Hidding private fields

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

Custom mask 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)
    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)

Instance Method Summary collapse

Constructor Details

#initialize(schema, mask) ⇒ Warden


41
42
43
44
# File 'lib/graphql/schema/warden.rb', line 41

def initialize(schema, mask)
  @mask = mask
  @schema = schema
end

Instance Method Details

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


84
85
86
# File 'lib/graphql/schema/warden.rb', line 84

def arguments(argument_owner)
  argument_owner.arguments.each_value.select { |a| visible_field?(a) }
end

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


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

def enum_values(enum_defn)
  enum_defn.values.each_value.select { |enum_value_defn| visible?(enum_value_defn) }
end

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


78
79
80
# File 'lib/graphql/schema/warden.rb', line 78

def fields(type_defn)
  type_defn.all_fields.select { |f| visible_field?(f) }
end

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


62
63
64
65
66
67
68
69
# File 'lib/graphql/schema/warden.rb', line 62

def get_field(parent_type, field_name)
  field_defn = @schema.get_field(parent_type, field_name)
  if field_defn && visible_field?(field_defn)
    field_defn
  else
    nil
  end
end

#get_type(type_name) ⇒ GraphQL::BaseType?


52
53
54
55
56
57
58
59
# File 'lib/graphql/schema/warden.rb', line 52

def get_type(type_name)
  type_defn = @schema.types.fetch(type_name, nil)
  if type_defn && visible?(type_defn)
    type_defn
  else
    nil
  end
end

#input_fields(input_obj_type) ⇒ Array<GraphQL::Field>


99
100
101
# File 'lib/graphql/schema/warden.rb', line 99

def input_fields(input_obj_type)
  input_obj_type.arguments.each_value.select { |f| visible_field?(f) }
end

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


94
95
96
# File 'lib/graphql/schema/warden.rb', line 94

def interfaces(obj_type)
  obj_type.interfaces.select { |t| visible?(t) }
end

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


72
73
74
# File 'lib/graphql/schema/warden.rb', line 72

def possible_types(type_defn)
  @schema.possible_types(type_defn).select { |t| visible?(t) }
end

#typesArray<GraphQL::BaseType>


47
48
49
# File 'lib/graphql/schema/warden.rb', line 47

def types
  @schema.types.each_value.select { |t| visible?(t) }
end