Skip to content

Commit

Permalink
Merge pull request #71 from graphql-devise/refactor-mount-method-opti…
Browse files Browse the repository at this point in the history
…on-validator

Refactor mount method option validator
  • Loading branch information
mcelicalderon committed Mar 29, 2020
2 parents 85086a0 + 879f9c5 commit c200065
Show file tree
Hide file tree
Showing 24 changed files with 448 additions and 299 deletions.
2 changes: 1 addition & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Style/MethodCalledOnDoEndBlock:
Enabled: false

Naming/VariableNumber:
Enabled: false
EnforcedColonStyle: normalcase

Style/StringLiterals:
ConsistentQuotesInMultiline: true
Expand Down
29 changes: 12 additions & 17 deletions lib/graphql_devise.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,28 @@
require 'graphql'
require 'devise_token_auth'

module GraphqlDevise
class Error < StandardError; end

class InvalidMountOptionsError < GraphqlDevise::Error; end
end

require 'graphql_devise/concerns/controller_methods'
require 'graphql_devise/types/authenticatable_type'
require 'graphql_devise/types/credential_type'
require 'graphql_devise/types/mutation_type'
require 'graphql_devise/types/query_type'
require 'graphql_devise/mutations/base'
require 'graphql_devise/mutations/login'
require 'graphql_devise/mutations/logout'
require 'graphql_devise/mutations/resend_confirmation'
require 'graphql_devise/mutations/send_password_reset'
require 'graphql_devise/mutations/sign_up'
require 'graphql_devise/mutations/update_password'
require 'graphql_devise/resolvers/base'
require 'graphql_devise/resolvers/check_password_token'
require 'graphql_devise/resolvers/confirm_account'
require 'graphql_devise/default_operations/mutations'
require 'graphql_devise/default_operations/resolvers'
require 'graphql_devise/resolvers/dummy'

require 'graphql_devise/engine'
require 'graphql_devise/version'
require 'graphql_devise/error_codes'
require 'graphql_devise/user_error'
require 'graphql_devise/detailed_user_error'
require 'graphql_devise/rails/queries_preparer'
require 'graphql_devise/rails/mutations_preparer'
require 'graphql_devise/rails/operation_checker'
require 'graphql_devise/rails/operation_sanitizer'

module GraphqlDevise
class Error < StandardError; end
end
require 'graphql_devise/mount_method/options_validator'
require 'graphql_devise/mount_method/queries_preparer'
require 'graphql_devise/mount_method/mutations_preparer'
require 'graphql_devise/mount_method/operation_sanitizer'
20 changes: 20 additions & 0 deletions lib/graphql_devise/default_operations/mutations.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require 'graphql_devise/mutations/base'
require 'graphql_devise/mutations/login'
require 'graphql_devise/mutations/logout'
require 'graphql_devise/mutations/resend_confirmation'
require 'graphql_devise/mutations/send_password_reset'
require 'graphql_devise/mutations/sign_up'
require 'graphql_devise/mutations/update_password'

module GraphqlDevise
module DefaultOperations
MUTATIONS = {
login: GraphqlDevise::Mutations::Login,
logout: GraphqlDevise::Mutations::Logout,
sign_up: GraphqlDevise::Mutations::SignUp,
update_password: GraphqlDevise::Mutations::UpdatePassword,
send_password_reset: GraphqlDevise::Mutations::SendPasswordReset,
resend_confirmation: GraphqlDevise::Mutations::ResendConfirmation
}.freeze
end
end
12 changes: 12 additions & 0 deletions lib/graphql_devise/default_operations/resolvers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require 'graphql_devise/resolvers/base'
require 'graphql_devise/resolvers/check_password_token'
require 'graphql_devise/resolvers/confirm_account'

module GraphqlDevise
module DefaultOperations
QUERIES = {
confirm_account: GraphqlDevise::Resolvers::ConfirmAccount,
check_password_token: GraphqlDevise::Resolvers::CheckPasswordToken
}.freeze
end
end
27 changes: 27 additions & 0 deletions lib/graphql_devise/mount_method/mutations_preparer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module GraphqlDevise
module MountMethod
class MutationsPreparer
def self.call(resource:, mutations:, authenticatable_type:)
new(resource: resource, mutations: mutations, authenticatable_type: authenticatable_type).call
end

def initialize(resource:, mutations:, authenticatable_type:)
@mapping_name = resource.underscore.tr('/', '_').to_sym
@mutations = mutations
@authenticatable_type = authenticatable_type
end

def call
@mutations.each_with_object({}) do |(action, mutation), result|
mapped_action = "#{@mapping_name}_#{action}".to_sym
new_mutation = Class.new(mutation)
new_mutation.graphql_name(mapped_action.to_s.camelize(:upper))
new_mutation.field(:authenticatable, @authenticatable_type, null: true)
new_mutation.instance_variable_set(:@resource_name, @mapping_name)

result[mapped_action] = new_mutation
end
end
end
end
end
35 changes: 35 additions & 0 deletions lib/graphql_devise/mount_method/operation_sanitizer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module GraphqlDevise
module MountMethod
class OperationSanitizer
def self.call(default:, custom:, only:, skipped:)
new(
default: default,
custom: custom,
only: only,
skipped: skipped
).call
end

def initialize(default:, custom:, only:, skipped:)
@default = default
@custom = custom
@only = only
@skipped = skipped
end

def call
result = @default.merge(@custom.slice(*operations_whitelist))
result = result.slice(*@only) if @only.present?
result = result.except(*@skipped) if @skipped.present?

result
end

private

def operations_whitelist
@default.keys
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
require_relative 'supported_operations_validator'

module GraphqlDevise
module MountMethod
module OptionValidators
class ProvidedOperationsValidator
def initialize(options: {}, supported_operations: {})
@options = options || {}
@supported_operations = supported_operations
end

def validate!
skipped = @options.fetch(:skip, [])
only = @options.fetch(:only, [])
operations = @options.fetch(:operations, {})
supported_keys = @supported_operations.keys

raise_on_invalid_option_type!(:skip, skipped, Array)
raise_on_invalid_option_type!(:only, only, Array)
raise_on_invalid_option_type!(:operations, operations, Hash)

custom = operations.keys

[
SupportedOperationsValidator.new(provided_operations: skipped, key: :skip, supported_operations: supported_keys),
SupportedOperationsValidator.new(provided_operations: only, key: :only, supported_operations: supported_keys),
SupportedOperationsValidator.new(provided_operations: custom, key: :operations, supported_operations: supported_keys)
].each(&:validate!)
end

private

def raise_on_invalid_option_type!(key, value, expected_class)
unless value.is_a?(expected_class)
raise(
GraphqlDevise::InvalidMountOptionsError,
"#{key} option contains value of invalid value. Value must be #{expected_class.name}."
)
end
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module GraphqlDevise
module MountMethod
module OptionValidators
class SkipOnlyValidator
def initialize(options: {})
@options = options || {}
end

def validate!
if [@options[:skip], @options[:only]].all?(&:present?)
raise(
GraphqlDevise::InvalidMountOptionsError,
"Can't specify both `skip` and `only` options when mounting the route."
)
end
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module GraphqlDevise
module MountMethod
module OptionValidators
class SupportedOperationsValidator
def initialize(provided_operations: [], supported_operations: [], key:)
@provided_operations = provided_operations
@supported_operations = supported_operations
@key = key
end

def validate!
unsupported_operations = @provided_operations - @supported_operations

if unsupported_operations.present?
raise(
GraphqlDevise::InvalidMountOptionsError,
"#{@key} option contains unsupported operations: \"#{unsupported_operations.join(', ')}\". Check for typos."
)
end
end
end
end
end
end
16 changes: 16 additions & 0 deletions lib/graphql_devise/mount_method/options_validator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require_relative 'option_validators/skip_only_validator'
require_relative 'option_validators/provided_operations_validator'

module GraphqlDevise
module MountMethod
class OptionsValidator
def initialize(validators = [])
@validators = validators
end

def validate!
@validators.each(&:validate!)
end
end
end
end
27 changes: 27 additions & 0 deletions lib/graphql_devise/mount_method/queries_preparer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module GraphqlDevise
module MountMethod
class QueriesPreparer
def self.call(resource:, queries:, authenticatable_type:)
new(resource: resource, queries: queries, authenticatable_type: authenticatable_type).call
end

def initialize(resource:, queries:, authenticatable_type:)
@mapping_name = resource.underscore.tr('/', '_').to_sym
@queries = queries
@authenticatable_type = authenticatable_type
end

def call
@queries.each_with_object({}) do |(action, query), result|
mapped_action = "#{@mapping_name}_#{action}".to_sym
new_query = Class.new(query)
new_query.graphql_name(mapped_action.to_s.camelize(:upper))
new_query.type(@authenticatable_type, null: true)
new_query.instance_variable_set(:@resource_name, @mapping_name)

result[mapped_action] = new_query
end
end
end
end
end
34 changes: 0 additions & 34 deletions lib/graphql_devise/rails/mutations_preparer.rb

This file was deleted.

59 changes: 0 additions & 59 deletions lib/graphql_devise/rails/operation_checker.rb

This file was deleted.

Loading

0 comments on commit c200065

Please sign in to comment.