Class: GraphQL::Schema::Visibility

Inherits:
Object
  • Object
show all
Defined in:
lib/graphql/schema/visibility.rb,
lib/graphql/schema/visibility/visit.rb,
lib/graphql/schema/visibility/profile.rb,
lib/graphql/schema/visibility/migration.rb

Overview

Use this plugin to make some parts of your schema hidden from some viewers.

Defined Under Namespace

Classes: Migration, Profile, TypeConfigurationError, Visit

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(schema, dynamic:, preload:, profiles:, migration_errors:, configuration_inherited: false) ⇒ Visibility

Returns a new instance of Visibility.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/graphql/schema/visibility.rb', line 29

def initialize(schema, dynamic:, preload:, profiles:, migration_errors:, configuration_inherited: false)
  @schema = schema
  schema.use_visibility_profile = true
  schema.visibility_profile_class = if migration_errors
    Visibility::Migration
  else
    Visibility::Profile
  end
  @preload = preload
  @profiles = profiles
  @cached_profiles = {}
  @dynamic = dynamic
  @migration_errors = migration_errors
  # Top-level type caches:
  @visit = nil
  @interface_type_memberships = nil
  @directives = nil
  @types = nil
  @all_references = nil
  @loaded_all = false
  @configuration_inherited = configuration_inherited
  if preload
    self.preload
  end
end

Instance Attribute Details

#cached_profilesObject (readonly)

Returns the value of attribute cached_profiles.



154
155
156
# File 'lib/graphql/schema/visibility.rb', line 154

def cached_profiles
  @cached_profiles
end

#top_levelObject (readonly)

Returns the value of attribute top_level.



180
181
182
# File 'lib/graphql/schema/visibility.rb', line 180

def top_level
  @top_level
end

#typesObject

Returns the value of attribute types.



83
84
85
# File 'lib/graphql/schema/visibility.rb', line 83

def types
  @types
end

#unfiltered_interface_type_membershipsObject (readonly)

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.



183
184
185
# File 'lib/graphql/schema/visibility.rb', line 183

def unfiltered_interface_type_memberships
  @unfiltered_interface_type_memberships
end

Class Method Details

.use(schema, dynamic: false, profiles: EmptyObjects::EMPTY_HASH, preload: (Rails.env) ? (Rails.env.production? || Rails.env.staging? || nil) : false), migration_errors: false) ⇒ Object

Parameters:

  • schema (Class<GraphQL::Schema>)
  • profiles (Hash<Symbol => Hash>) (defaults to: EmptyObjects::EMPTY_HASH)

    A hash of name => context pairs for preloading visibility profiles

  • preload (Boolean) (defaults to: (Rails.env) ? (Rails.env.production? || Rails.env.staging? || nil) : false))

    if true, load the default schema profile and all named profiles immediately (defaults to true for Rails.env.production? and Rails.env.staging?)

  • migration_errors (Boolean) (defaults to: false)

    if true, raise an error when Visibility and Warden return different results



21
22
23
24
25
26
27
# File 'lib/graphql/schema/visibility.rb', line 21

def self.use(schema, dynamic: false, profiles: EmptyObjects::EMPTY_HASH, preload: (defined?(Rails.env) ? (Rails.env.production? || Rails.env.staging? || nil) : false), migration_errors: false)
  profiles&.each { |name, ctx|
    ctx[:visibility_profile] = name
    ctx.freeze
  }
  schema.visibility = self.new(schema, dynamic: dynamic, preload: preload, profiles: profiles, migration_errors: migration_errors)
end

Instance Method Details

#all_directivesObject



63
64
65
66
# File 'lib/graphql/schema/visibility.rb', line 63

def all_directives
  load_all
  @directives
end

#all_interface_type_membershipsObject



68
69
70
71
# File 'lib/graphql/schema/visibility.rb', line 68

def all_interface_type_memberships
  load_all
  @interface_type_memberships
end

#all_referencesObject



73
74
75
76
# File 'lib/graphql/schema/visibility.rb', line 73

def all_references
  load_all
  @all_references
end

#dup_for(other_schema) ⇒ Visibility

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.

Make another Visibility for schema based on this one

Returns:



139
140
141
142
143
144
145
146
147
148
# File 'lib/graphql/schema/visibility.rb', line 139

def dup_for(other_schema)
  self.class.new(
    other_schema,
    dynamic: @dynamic,
    preload: @preload,
    profiles: @profiles,
    migration_errors: @migration_errors,
    configuration_inherited: true,
  )
end

#freezeObject



55
56
57
58
59
60
61
# File 'lib/graphql/schema/visibility.rb', line 55

def freeze
  load_all
  @visit = true
  @interface_type_memberships.default_proc = nil
  @all_references.default_proc = nil
  super
end

#get_type(type_name) ⇒ Object



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

def get_type(type_name)
  load_all
  @types[type_name]
end

#introspection_system_configured(introspection_system) ⇒ 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.



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

def introspection_system_configured(introspection_system)
  require_if_preloaded("custom introspection was", "introspection(...)")
end

#migration_errors?Boolean

Returns:

  • (Boolean)


150
151
152
# File 'lib/graphql/schema/visibility.rb', line 150

def migration_errors?
  @migration_errors
end

#mutation_configured(mutation_type) ⇒ 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.



117
118
119
# File 'lib/graphql/schema/visibility.rb', line 117

def mutation_configured(mutation_type)
  require_if_preloaded("a mutation type was", "mutation(...)")
end

#orphan_types_configured(orphan_types) ⇒ 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.



127
128
129
# File 'lib/graphql/schema/visibility.rb', line 127

def orphan_types_configured(orphan_types)
  require_if_preloaded("orphan types were", "orphan_types(...)")
end

#preloadObject



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/graphql/schema/visibility.rb', line 89

def preload
  # Traverse the schema now (and in the *_configured hooks below)
  # To make sure things are loaded during boot
  @preloaded_types = Set.new
  types_to_visit = [
    @schema.query,
    @schema.mutation,
    @schema.subscription,
    *@schema.introspection_system.types.values,
    *@schema.introspection_system.entry_points.map { |ep| ep.type.unwrap },
    *@schema.orphan_types,
  ]
  # Root types may have been nil:
  types_to_visit.compact!
  ensure_all_loaded(types_to_visit)
  @cached_profiles.clear
  @profiles.each do |profile_name, example_ctx|
    prof = profile_for(example_ctx)
    prof.preload
  end
end

#preload?Boolean

Returns:

  • (Boolean)


85
86
87
# File 'lib/graphql/schema/visibility.rb', line 85

def preload?
  @preload
end

#profile_for(context) ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/graphql/schema/visibility.rb', line 156

def profile_for(context)
  if !@profiles.empty?
    visibility_profile = context[:visibility_profile]
    if @profiles.include?(visibility_profile)
      profile_ctx = @profiles[visibility_profile]
      @cached_profiles[visibility_profile] ||= @schema.visibility_profile_class.new(name: visibility_profile, context: profile_ctx, schema: @schema, visibility: self)
    elsif @dynamic
      if context.is_a?(Query::NullContext)
        top_level_profile
      else
        @schema.visibility_profile_class.new(context: context, schema: @schema, visibility: self)
      end
    elsif !context.key?(:visibility_profile)
      raise ArgumentError, "#{@schema} expects a visibility profile, but `visibility_profile:` wasn't passed. Provide a `visibility_profile:` value or add `dynamic: true` to your visibility configuration."
    else
      raise ArgumentError, "`#{visibility_profile.inspect}` isn't allowed for `visibility_profile:` (must be one of #{@profiles.keys.map(&:inspect).join(", ")}). Or, add `#{visibility_profile.inspect}` to the list of profiles in the schema definition."
    end
  elsif context.is_a?(Query::NullContext)
    top_level_profile
  else
    @schema.visibility_profile_class.new(context: context, schema: @schema, visibility: self)
  end
end

#query_configured(query_type) ⇒ 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.



112
113
114
# File 'lib/graphql/schema/visibility.rb', line 112

def query_configured(query_type)
  require_if_preloaded("a query type was", "query(...)")
end

#subscription_configured(subscription_type) ⇒ 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.



122
123
124
# File 'lib/graphql/schema/visibility.rb', line 122

def subscription_configured(subscription_type)
  require_if_preloaded("a mutation type was", "subscription(...)")
end

#top_level_profile(refresh: false) ⇒ Object



185
186
187
188
189
190
# File 'lib/graphql/schema/visibility.rb', line 185

def top_level_profile(refresh: false)
  if refresh
    @top_level_profile = nil
  end
  @top_level_profile ||= @schema.visibility_profile_class.new(context: @schema.null_context, schema: @schema, visibility: self)
end