graphql_devise 0.11.2 → 0.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.rspec +1 -0
- data/.travis.yml +9 -3
- data/CHANGELOG.md +50 -1
- data/README.md +185 -32
- data/app/controllers/graphql_devise/application_controller.rb +4 -1
- data/app/controllers/graphql_devise/concerns/set_user_by_token.rb +25 -0
- data/app/controllers/graphql_devise/graphql_controller.rb +2 -0
- data/app/helpers/graphql_devise/mailer_helper.rb +2 -2
- data/app/views/graphql_devise/mailer/confirmation_instructions.html.erb +1 -1
- data/app/views/graphql_devise/mailer/reset_password_instructions.html.erb +1 -1
- data/config/locales/en.yml +1 -0
- data/config/routes.rb +2 -0
- data/graphql_devise.gemspec +6 -4
- data/lib/generators/graphql_devise/install_generator.rb +63 -30
- data/lib/graphql_devise.rb +24 -10
- data/lib/graphql_devise/default_operations/mutations.rb +6 -6
- data/lib/graphql_devise/default_operations/resolvers.rb +2 -2
- data/lib/graphql_devise/errors/authentication_error.rb +7 -0
- data/lib/graphql_devise/{detailed_user_error.rb → errors/detailed_user_error.rb} +1 -1
- data/lib/graphql_devise/errors/error_codes.rb +6 -0
- data/lib/graphql_devise/errors/execution_error.rb +4 -0
- data/lib/graphql_devise/{user_error.rb → errors/user_error.rb} +1 -1
- data/lib/graphql_devise/mount_method/operation_preparer.rb +2 -2
- data/lib/graphql_devise/mount_method/operation_preparers/default_operation_preparer.rb +6 -2
- data/lib/graphql_devise/mount_method/operation_preparers/gql_name_setter.rb +1 -1
- data/lib/graphql_devise/mount_method/operation_preparers/mutation_field_setter.rb +3 -2
- data/lib/graphql_devise/mount_method/operation_preparers/resolver_type_setter.rb +1 -1
- data/lib/graphql_devise/mount_method/operation_preparers/resource_name_setter.rb +2 -2
- data/lib/graphql_devise/mutations/resend_confirmation.rb +3 -5
- data/lib/graphql_devise/mutations/send_password_reset.rb +5 -2
- data/lib/graphql_devise/mutations/sign_up.rb +3 -6
- data/lib/graphql_devise/rails/routes.rb +5 -72
- data/lib/graphql_devise/resource_loader.rb +87 -0
- data/lib/graphql_devise/schema_plugin.rb +106 -0
- data/lib/graphql_devise/version.rb +1 -1
- data/spec/dummy/app/controllers/api/v1/graphql_controller.rb +41 -3
- data/spec/dummy/app/controllers/application_controller.rb +1 -0
- data/spec/dummy/app/graphql/dummy_schema.rb +18 -0
- data/spec/dummy/app/graphql/interpreter_schema.rb +9 -0
- data/spec/dummy/app/graphql/types/mutation_type.rb +1 -1
- data/spec/dummy/app/graphql/types/query_type.rb +10 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/generators/graphql_devise/install_generator_spec.rb +62 -30
- data/spec/rails_helper.rb +4 -1
- data/spec/requests/graphql_controller_spec.rb +80 -0
- data/spec/requests/mutations/resend_confirmation_spec.rb +44 -29
- data/spec/requests/mutations/send_password_reset_spec.rb +40 -12
- data/spec/requests/queries/confirm_account_spec.rb +7 -1
- data/spec/requests/user_controller_spec.rb +189 -24
- data/spec/services/mount_method/operation_preparer_spec.rb +8 -3
- data/spec/services/mount_method/operation_preparers/custom_operation_preparer_spec.rb +1 -1
- data/spec/services/mount_method/operation_preparers/default_operation_preparer_spec.rb +15 -8
- data/spec/services/mount_method/operation_preparers/mutation_field_setter_spec.rb +18 -4
- data/spec/services/mount_method/operation_preparers/resource_name_setter_spec.rb +1 -1
- data/spec/services/resource_loader_spec.rb +82 -0
- data/spec/services/schema_plugin_spec.rb +26 -0
- data/spec/spec_helper.rb +1 -1
- metadata +107 -89
- data/lib/graphql_devise/error_codes.rb +0 -5
- data/spec/support/generators/file_helpers.rb +0 -12
@@ -4,6 +4,8 @@ module GraphqlDevise
|
|
4
4
|
argument :email, String, required: true
|
5
5
|
argument :redirect_url, String, required: true
|
6
6
|
|
7
|
+
field :message, String, null: false
|
8
|
+
|
7
9
|
def resolve(email:, redirect_url:)
|
8
10
|
resource = find_resource(:email, get_case_insensitive_field(:email, email))
|
9
11
|
|
@@ -14,11 +16,12 @@ module GraphqlDevise
|
|
14
16
|
email: email,
|
15
17
|
provider: 'email',
|
16
18
|
redirect_url: redirect_url,
|
17
|
-
template_path: ['graphql_devise/mailer']
|
19
|
+
template_path: ['graphql_devise/mailer'],
|
20
|
+
**controller.params.permit('controller', 'action').to_h.symbolize_keys
|
18
21
|
)
|
19
22
|
|
20
23
|
if resource.errors.empty?
|
21
|
-
{
|
24
|
+
{ message: I18n.t('graphql_devise.passwords.send_instructions') }
|
22
25
|
else
|
23
26
|
raise_user_error_list(I18n.t('graphql_devise.invalid_resource'), errors: resource.errors.full_messages)
|
24
27
|
end
|
@@ -27,7 +27,8 @@ module GraphqlDevise
|
|
27
27
|
unless resource.confirmed?
|
28
28
|
resource.send_confirmation_instructions(
|
29
29
|
redirect_url: confirm_success_url,
|
30
|
-
template_path: ['graphql_devise/mailer']
|
30
|
+
template_path: ['graphql_devise/mailer'],
|
31
|
+
**controller.params.permit('controller', 'action').to_h.symbolize_keys
|
31
32
|
)
|
32
33
|
end
|
33
34
|
|
@@ -35,7 +36,7 @@ module GraphqlDevise
|
|
35
36
|
|
36
37
|
{ authenticatable: resource }
|
37
38
|
else
|
38
|
-
clean_up_passwords
|
39
|
+
resource.try(:clean_up_passwords)
|
39
40
|
raise_user_error_list(
|
40
41
|
I18n.t('graphql_devise.registration_failed'),
|
41
42
|
errors: resource.errors.full_messages
|
@@ -48,10 +49,6 @@ module GraphqlDevise
|
|
48
49
|
def build_resource(attrs)
|
49
50
|
resource_class.new(attrs)
|
50
51
|
end
|
51
|
-
|
52
|
-
def clean_up_passwords(resource)
|
53
|
-
controller.send(:clean_up_passwords, resource)
|
54
|
-
end
|
55
52
|
end
|
56
53
|
end
|
57
54
|
end
|
@@ -1,80 +1,13 @@
|
|
1
1
|
module ActionDispatch::Routing
|
2
2
|
class Mapper
|
3
|
-
DEVISE_OPERATIONS = [
|
4
|
-
:sessions,
|
5
|
-
:registrations,
|
6
|
-
:passwords,
|
7
|
-
:confirmations,
|
8
|
-
:omniauth_callbacks,
|
9
|
-
:unlocks,
|
10
|
-
:invitations
|
11
|
-
].freeze
|
12
|
-
|
13
3
|
def mount_graphql_devise_for(resource, options = {})
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
clean_options = GraphqlDevise::MountMethod::OptionSanitizer.new(options).call!
|
18
|
-
|
19
|
-
GraphqlDevise::MountMethod::OptionsValidator.new(
|
20
|
-
[
|
21
|
-
GraphqlDevise::MountMethod::OptionValidators::SkipOnlyValidator.new(options: clean_options),
|
22
|
-
GraphqlDevise::MountMethod::OptionValidators::ProvidedOperationsValidator.new(
|
23
|
-
options: clean_options, supported_operations: default_operations
|
24
|
-
)
|
25
|
-
]
|
26
|
-
).validate!
|
27
|
-
|
28
|
-
devise_for(
|
29
|
-
resource.pluralize.underscore.tr('/', '_').to_sym,
|
30
|
-
module: :devise,
|
31
|
-
class_name: resource,
|
32
|
-
skip: DEVISE_OPERATIONS
|
4
|
+
clean_options = GraphqlDevise::ResourceLoader.new(resource, options, true).call(
|
5
|
+
GraphqlDevise::Types::QueryType,
|
6
|
+
GraphqlDevise::Types::MutationType
|
33
7
|
)
|
34
8
|
|
35
|
-
|
36
|
-
|
37
|
-
get clean_options.at, to: 'graphql_devise/graphql#auth'
|
38
|
-
end
|
39
|
-
|
40
|
-
# Avoid routes reload done by Devise
|
41
|
-
return if GraphqlDevise.resource_mounted?(resource)
|
42
|
-
|
43
|
-
authenticatable_type = clean_options.authenticatable_type.presence ||
|
44
|
-
"Types::#{resource}Type".safe_constantize ||
|
45
|
-
GraphqlDevise::Types::AuthenticatableType
|
46
|
-
|
47
|
-
prepared_mutations = GraphqlDevise::MountMethod::OperationPreparer.new(
|
48
|
-
resource: resource,
|
49
|
-
custom: clean_options.operations,
|
50
|
-
additional_operations: clean_options.additional_mutations,
|
51
|
-
preparer: GraphqlDevise::MountMethod::OperationPreparers::MutationFieldSetter.new(authenticatable_type),
|
52
|
-
selected_operations: GraphqlDevise::MountMethod::OperationSanitizer.call(
|
53
|
-
default: GraphqlDevise::DefaultOperations::MUTATIONS, only: clean_options.only, skipped: clean_options.skip
|
54
|
-
)
|
55
|
-
).call
|
56
|
-
|
57
|
-
prepared_mutations.each do |action, mutation|
|
58
|
-
GraphqlDevise::Types::MutationType.field(action, mutation: mutation)
|
59
|
-
end
|
60
|
-
|
61
|
-
prepared_queries = GraphqlDevise::MountMethod::OperationPreparer.new(
|
62
|
-
resource: resource,
|
63
|
-
custom: clean_options.operations,
|
64
|
-
additional_operations: clean_options.additional_queries,
|
65
|
-
preparer: GraphqlDevise::MountMethod::OperationPreparers::ResolverTypeSetter.new(authenticatable_type),
|
66
|
-
selected_operations: GraphqlDevise::MountMethod::OperationSanitizer.call(
|
67
|
-
default: GraphqlDevise::DefaultOperations::QUERIES, only: clean_options.only, skipped: clean_options.skip
|
68
|
-
)
|
69
|
-
).call
|
70
|
-
|
71
|
-
prepared_queries.each do |action, resolver|
|
72
|
-
GraphqlDevise::Types::QueryType.field(action, resolver: resolver)
|
73
|
-
end
|
74
|
-
|
75
|
-
Devise.mailer.helper(GraphqlDevise::MailerHelper)
|
76
|
-
|
77
|
-
GraphqlDevise.mount_resource(resource)
|
9
|
+
post clean_options.at, to: 'graphql_devise/graphql#auth'
|
10
|
+
get clean_options.at, to: 'graphql_devise/graphql#auth'
|
78
11
|
end
|
79
12
|
end
|
80
13
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module GraphqlDevise
|
2
|
+
class ResourceLoader
|
3
|
+
def initialize(resource, options = {}, routing = false)
|
4
|
+
@resource = resource
|
5
|
+
@options = options
|
6
|
+
@routing = routing
|
7
|
+
@default_operations = GraphqlDevise::DefaultOperations::MUTATIONS.merge(GraphqlDevise::DefaultOperations::QUERIES)
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(query, mutation)
|
11
|
+
mapping_name = @resource.to_s.underscore.tr('/', '_').to_sym
|
12
|
+
|
13
|
+
# clean_options responds to all keys defined in GraphqlDevise::MountMethod::SUPPORTED_OPTIONS
|
14
|
+
clean_options = GraphqlDevise::MountMethod::OptionSanitizer.new(@options).call!
|
15
|
+
|
16
|
+
return clean_options if GraphqlDevise.resource_mounted?(mapping_name) && @routing
|
17
|
+
|
18
|
+
validate_options!(clean_options)
|
19
|
+
|
20
|
+
authenticatable_type = clean_options.authenticatable_type.presence ||
|
21
|
+
"Types::#{@resource}Type".safe_constantize ||
|
22
|
+
GraphqlDevise::Types::AuthenticatableType
|
23
|
+
|
24
|
+
prepared_mutations = prepare_mutations(mapping_name, clean_options, authenticatable_type)
|
25
|
+
|
26
|
+
if prepared_mutations.any? && mutation.blank?
|
27
|
+
raise GraphqlDevise::Error, 'You need to provide a mutation type unless all mutations are skipped'
|
28
|
+
end
|
29
|
+
|
30
|
+
prepared_mutations.each do |action, prepared_mutation|
|
31
|
+
mutation.field(action, mutation: prepared_mutation, authenticate: false)
|
32
|
+
end
|
33
|
+
|
34
|
+
prepared_resolvers = prepare_resolvers(mapping_name, clean_options, authenticatable_type)
|
35
|
+
|
36
|
+
if prepared_resolvers.any? && query.blank?
|
37
|
+
raise GraphqlDevise::Error, 'You need to provide a query type unless all queries are skipped'
|
38
|
+
end
|
39
|
+
|
40
|
+
prepared_resolvers.each do |action, resolver|
|
41
|
+
query.field(action, resolver: resolver, authenticate: false)
|
42
|
+
end
|
43
|
+
|
44
|
+
GraphqlDevise.add_mapping(mapping_name, @resource)
|
45
|
+
GraphqlDevise.mount_resource(mapping_name) if @routing
|
46
|
+
|
47
|
+
clean_options
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def prepare_resolvers(mapping_name, clean_options, authenticatable_type)
|
53
|
+
GraphqlDevise::MountMethod::OperationPreparer.new(
|
54
|
+
mapping_name: mapping_name,
|
55
|
+
custom: clean_options.operations,
|
56
|
+
additional_operations: clean_options.additional_queries,
|
57
|
+
preparer: GraphqlDevise::MountMethod::OperationPreparers::ResolverTypeSetter.new(authenticatable_type),
|
58
|
+
selected_operations: GraphqlDevise::MountMethod::OperationSanitizer.call(
|
59
|
+
default: GraphqlDevise::DefaultOperations::QUERIES, only: clean_options.only, skipped: clean_options.skip
|
60
|
+
)
|
61
|
+
).call
|
62
|
+
end
|
63
|
+
|
64
|
+
def prepare_mutations(mapping_name, clean_options, authenticatable_type)
|
65
|
+
GraphqlDevise::MountMethod::OperationPreparer.new(
|
66
|
+
mapping_name: mapping_name,
|
67
|
+
custom: clean_options.operations,
|
68
|
+
additional_operations: clean_options.additional_mutations,
|
69
|
+
preparer: GraphqlDevise::MountMethod::OperationPreparers::MutationFieldSetter.new(authenticatable_type),
|
70
|
+
selected_operations: GraphqlDevise::MountMethod::OperationSanitizer.call(
|
71
|
+
default: GraphqlDevise::DefaultOperations::MUTATIONS, only: clean_options.only, skipped: clean_options.skip
|
72
|
+
)
|
73
|
+
).call
|
74
|
+
end
|
75
|
+
|
76
|
+
def validate_options!(clean_options)
|
77
|
+
GraphqlDevise::MountMethod::OptionsValidator.new(
|
78
|
+
[
|
79
|
+
GraphqlDevise::MountMethod::OptionValidators::SkipOnlyValidator.new(options: clean_options),
|
80
|
+
GraphqlDevise::MountMethod::OptionValidators::ProvidedOperationsValidator.new(
|
81
|
+
options: clean_options, supported_operations: @default_operations
|
82
|
+
)
|
83
|
+
]
|
84
|
+
).validate!
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module GraphqlDevise
|
2
|
+
class SchemaPlugin
|
3
|
+
DEFAULT_NOT_AUTHENTICATED = ->(field) { raise GraphqlDevise::AuthenticationError, "#{field} field requires authentication" }
|
4
|
+
|
5
|
+
def initialize(query: nil, mutation: nil, authenticate_default: true, resource_loaders: [], unauthenticated_proc: DEFAULT_NOT_AUTHENTICATED)
|
6
|
+
@query = query
|
7
|
+
@mutation = mutation
|
8
|
+
@resource_loaders = resource_loaders
|
9
|
+
@authenticate_default = authenticate_default
|
10
|
+
@unauthenticated_proc = unauthenticated_proc
|
11
|
+
|
12
|
+
# Must happen on initialize so operations are loaded before the types are added to the schema on GQL < 1.10
|
13
|
+
load_fields
|
14
|
+
end
|
15
|
+
|
16
|
+
def use(schema_definition)
|
17
|
+
schema_definition.tracer(self)
|
18
|
+
end
|
19
|
+
|
20
|
+
def trace(event, trace_data)
|
21
|
+
# Authenticate only root level queries
|
22
|
+
return yield unless event == 'execute_field' && path(trace_data).count == 1
|
23
|
+
|
24
|
+
field = traced_field(trace_data)
|
25
|
+
provided_value = authenticate_option(field, trace_data)
|
26
|
+
context = set_current_resource(context_from_data(trace_data))
|
27
|
+
|
28
|
+
if !provided_value.nil?
|
29
|
+
raise_on_missing_resource(context, field) if provided_value
|
30
|
+
elsif @authenticate_default
|
31
|
+
raise_on_missing_resource(context, field)
|
32
|
+
end
|
33
|
+
|
34
|
+
yield
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def set_current_resource(context)
|
40
|
+
controller = context[:controller]
|
41
|
+
resource_names = Array(context[:resource_name])
|
42
|
+
context[:current_resource] = resource_names.find do |resource_name|
|
43
|
+
unless Devise.mappings.key?(resource_name)
|
44
|
+
raise(
|
45
|
+
GraphqlDevise::Error,
|
46
|
+
"Invalid resource_name `#{resource_name}` provided to `graphql_context`. Possible values are: #{Devise.mappings.keys}."
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
found = controller.set_resource_by_token(resource_name)
|
51
|
+
break found if found
|
52
|
+
end
|
53
|
+
|
54
|
+
context
|
55
|
+
end
|
56
|
+
|
57
|
+
def raise_on_missing_resource(context, field)
|
58
|
+
@unauthenticated_proc.call(field.name) if context[:current_resource].blank?
|
59
|
+
end
|
60
|
+
|
61
|
+
def context_from_data(trace_data)
|
62
|
+
query = if trace_data[:context]
|
63
|
+
trace_data[:context].query
|
64
|
+
else
|
65
|
+
trace_data[:query]
|
66
|
+
end
|
67
|
+
|
68
|
+
query.context
|
69
|
+
end
|
70
|
+
|
71
|
+
def path(trace_data)
|
72
|
+
if trace_data[:context]
|
73
|
+
trace_data[:context].path
|
74
|
+
else
|
75
|
+
trace_data[:path]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def traced_field(trace_data)
|
80
|
+
if trace_data[:context]
|
81
|
+
trace_data[:context].field
|
82
|
+
else
|
83
|
+
trace_data[:field]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def authenticate_option(field, trace_data)
|
88
|
+
if trace_data[:context]
|
89
|
+
field.metadata[:authenticate]
|
90
|
+
else
|
91
|
+
field.graphql_definition.metadata[:authenticate]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def load_fields
|
96
|
+
@resource_loaders.each do |resource_loader|
|
97
|
+
raise Error, 'Invalid resource loader instance' unless resource_loader.instance_of?(GraphqlDevise::ResourceLoader)
|
98
|
+
|
99
|
+
resource_loader.call(@query, @mutation)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
GraphQL::Field.accepts_definitions(authenticate: GraphQL::Define.assign_metadata_key(:authenticate))
|
106
|
+
GraphQL::Schema::Field.accepts_definition(:authenticate)
|
@@ -3,10 +3,48 @@ module Api
|
|
3
3
|
class GraphqlController < ApplicationController
|
4
4
|
include GraphqlDevise::Concerns::SetUserByToken
|
5
5
|
|
6
|
-
before_action :authenticate_user!
|
7
|
-
|
8
6
|
def graphql
|
9
|
-
|
7
|
+
result = DummySchema.execute(params[:query], execute_params(params))
|
8
|
+
|
9
|
+
render json: result unless performed?
|
10
|
+
end
|
11
|
+
|
12
|
+
def interpreter
|
13
|
+
render json: InterpreterSchema.execute(params[:query], execute_params(params))
|
14
|
+
end
|
15
|
+
|
16
|
+
def failing_resource_name
|
17
|
+
render json: DummySchema.execute(params[:query], context: graphql_context([:user, :fail]))
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def execute_params(item)
|
23
|
+
{
|
24
|
+
operation_name: item[:operationName],
|
25
|
+
variables: ensure_hash(item[:variables]),
|
26
|
+
context: graphql_context(:user)
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def ensure_hash(ambiguous_param)
|
31
|
+
case ambiguous_param
|
32
|
+
when String
|
33
|
+
if ambiguous_param.present?
|
34
|
+
ensure_hash(JSON.parse(ambiguous_param))
|
35
|
+
else
|
36
|
+
{}
|
37
|
+
end
|
38
|
+
when Hash, ActionController::Parameters
|
39
|
+
ambiguous_param
|
40
|
+
when nil
|
41
|
+
{}
|
42
|
+
else
|
43
|
+
raise ArgumentError, "Unexpected parameter: #{ambiguous_param}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def verify_authenticity_token
|
10
48
|
end
|
11
49
|
end
|
12
50
|
end
|
@@ -1,4 +1,22 @@
|
|
1
1
|
class DummySchema < GraphQL::Schema
|
2
|
+
use GraphqlDevise::SchemaPlugin.new(
|
3
|
+
query: Types::QueryType,
|
4
|
+
mutation: Types::MutationType,
|
5
|
+
resource_loaders: [
|
6
|
+
GraphqlDevise::ResourceLoader.new(
|
7
|
+
'User',
|
8
|
+
only: [
|
9
|
+
:login,
|
10
|
+
:confirm_account,
|
11
|
+
:send_password_reset,
|
12
|
+
:resend_confirmation,
|
13
|
+
:check_password_token
|
14
|
+
]
|
15
|
+
),
|
16
|
+
GraphqlDevise::ResourceLoader.new('Guest', only: [:logout])
|
17
|
+
]
|
18
|
+
)
|
19
|
+
|
2
20
|
mutation(Types::MutationType)
|
3
21
|
query(Types::QueryType)
|
4
22
|
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class InterpreterSchema < GraphQL::Schema
|
2
|
+
use GraphQL::Execution::Interpreter if Gem::Version.new(GraphQL::VERSION) >= Gem::Version.new('1.9.0')
|
3
|
+
use GraphQL::Analysis::AST if Gem::Version.new(GraphQL::VERSION) >= Gem::Version.new('1.10.0')
|
4
|
+
|
5
|
+
use GraphqlDevise::SchemaPlugin.new(query: Types::QueryType, authenticate_default: false)
|
6
|
+
|
7
|
+
mutation(Types::MutationType)
|
8
|
+
query(Types::QueryType)
|
9
|
+
end
|
@@ -1,5 +1,15 @@
|
|
1
1
|
module Types
|
2
2
|
class QueryType < Types::BaseObject
|
3
3
|
field :user, resolver: Resolvers::UserShow
|
4
|
+
field :public_field, String, null: false, authenticate: false
|
5
|
+
field :private_field, String, null: false, authenticate: true
|
6
|
+
|
7
|
+
def public_field
|
8
|
+
'Field does not require authentication'
|
9
|
+
end
|
10
|
+
|
11
|
+
def private_field
|
12
|
+
'Field will always require authentication'
|
13
|
+
end
|
4
14
|
end
|
5
15
|
end
|