Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ README.md.*
/spec/dummy/tmp/
/Gemfile.lock
*.gemfile.lock
/*.sqlite3
*.sqlite3
*.sqlite3-journal
/spec/dummy/db/development.sqlite3
/spec/dummy/db/test.sqlite3
/*.gem
Expand Down
9 changes: 4 additions & 5 deletions app/controllers/graphql_devise/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
module GraphqlDevise
class ApplicationController < DeviseTokenAuth::ApplicationController
private

def verify_authenticity_token
end
ApplicationController = if Rails::VERSION::MAJOR >= 5
Class.new(ActionController::API)
else
Class.new(ActionController::Base)
end
end
14 changes: 14 additions & 0 deletions app/controllers/graphql_devise/concerns/set_user_by_token.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
module GraphqlDevise
module Concerns
SetUserByToken = DeviseTokenAuth::Concerns::SetUserByToken

SetUserByToken.module_eval do
attr_accessor :client_id, :token, :resource

def build_redirect_headers(access_token, client, redirect_header_options = {})
{
DeviseTokenAuth.headers_names[:"access-token"] => access_token,
DeviseTokenAuth.headers_names[:client] => client,
:config => params[:config],
:client_id => client,
:token => access_token
}.merge(redirect_header_options)
end
end
end
end
2 changes: 2 additions & 0 deletions app/controllers/graphql_devise/graphql_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

module GraphqlDevise
class GraphqlController < ApplicationController
include GraphqlDevise::Concerns::SetUserByToken

def auth
result = if params[:_json]
GraphqlDevise::Schema.multiplex(
Expand Down
4 changes: 2 additions & 2 deletions app/helpers/graphql_devise/mailer_helper.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module GraphqlDevise
module MailerHelper
def confirmation_query(resource_name:, token:, redirect_url:)
name = "#{resource_name.camelize(:lower)}ConfirmAccount"
name = "#{resource_name.underscore.tr('/', '_').camelize(:lower)}ConfirmAccount"
raw = <<-GRAPHQL
query($token:String!,$redirectUrl:String!){
#{name}(confirmationToken:$token,redirectUrl:$redirectUrl){
Expand All @@ -17,7 +17,7 @@ def confirmation_query(resource_name:, token:, redirect_url:)
end

def password_reset_query(token:, redirect_url:, resource_name:)
name = "#{resource_name.camelize(:lower)}CheckPasswordToken"
name = "#{resource_name.underscore.tr('/', '_').camelize(:lower)}CheckPasswordToken"
raw = <<-GRAPHQL
query($token:String!,$redirectUrl:String!){
#{name}(resetPasswordToken:$token,redirectUrl:$redirectUrl){
Expand Down
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@
GraphqlDevise::Schema.query(GraphqlDevise::Types::QueryType)

GraphqlDevise.load_schema

Devise.mailer.helper(GraphqlDevise::MailerHelper)
end
end
20 changes: 16 additions & 4 deletions lib/graphql_devise.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,21 @@ def self.load_schema
@schema_loaded = true
end

def self.mount_resource(resource)
@mounted_resources << resource
def self.resource_mounted?(mapping_name)
@mounted_resources.include?(mapping_name)
end

def self.resource_mounted?(resource)
@mounted_resources.include?(resource)
def self.mount_resource(mapping_name)
@mounted_resources << mapping_name
end

def self.add_mapping(mapping_name, resource)
return if Devise.mappings.key?(mapping_name)

Devise.add_mapping(
mapping_name.to_s.pluralize.to_sym,
module: :devise, class_name: resource
)
end
end

Expand All @@ -47,3 +56,6 @@ def self.resource_mounted?(resource)
require 'graphql_devise/mount_method/options_validator'
require 'graphql_devise/mount_method/operation_preparer'
require 'graphql_devise/mount_method/operation_sanitizer'

require 'graphql_devise/resource_loader'
require 'graphql_devise/schema_plugin'
4 changes: 2 additions & 2 deletions lib/graphql_devise/mount_method/operation_preparer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
module GraphqlDevise
module MountMethod
class OperationPreparer
def initialize(resource:, selected_operations:, preparer:, custom:, additional_operations:)
def initialize(mapping_name:, selected_operations:, preparer:, custom:, additional_operations:)
@selected_operations = selected_operations
@preparer = preparer
@mapping_name = resource.underscore.tr('/', '_')
@mapping_name = mapping_name
@custom = custom
@additional_operations = additional_operations
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def initialize(name)
end

def call(operation)
operation.instance_variable_set(:@resource_name, @name.to_sym)
operation.instance_variable_set(:@resource_name, @name)

operation
end
Expand Down
6 changes: 1 addition & 5 deletions lib/graphql_devise/mutations/sign_up.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def resolve(confirm_success_url: nil, **attrs)

{ authenticatable: resource }
else
clean_up_passwords(resource)
resource.clean_up_passwords if resource.respond_to?(:clean_up_passwords)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since rails is a dependency, did you considered try ?

raise_user_error_list(
I18n.t('graphql_devise.registration_failed'),
errors: resource.errors.full_messages
Expand All @@ -48,10 +48,6 @@ def resolve(confirm_success_url: nil, **attrs)
def build_resource(attrs)
resource_class.new(attrs)
end

def clean_up_passwords(resource)
controller.send(:clean_up_passwords, resource)
end
end
end
end
77 changes: 5 additions & 72 deletions lib/graphql_devise/rails/routes.rb
Original file line number Diff line number Diff line change
@@ -1,80 +1,13 @@
module ActionDispatch::Routing
class Mapper
DEVISE_OPERATIONS = [
:sessions,
:registrations,
:passwords,
:confirmations,
:omniauth_callbacks,
:unlocks,
:invitations
].freeze

def mount_graphql_devise_for(resource, options = {})
default_operations = GraphqlDevise::DefaultOperations::MUTATIONS.merge(GraphqlDevise::DefaultOperations::QUERIES)

# clean_options responds to all keys defined in GraphqlDevise::MountMethod::SUPPORTED_OPTIONS
clean_options = GraphqlDevise::MountMethod::OptionSanitizer.new(options).call!

GraphqlDevise::MountMethod::OptionsValidator.new(
[
GraphqlDevise::MountMethod::OptionValidators::SkipOnlyValidator.new(options: clean_options),
GraphqlDevise::MountMethod::OptionValidators::ProvidedOperationsValidator.new(
options: clean_options, supported_operations: default_operations
)
]
).validate!

devise_for(
resource.pluralize.underscore.tr('/', '_').to_sym,
module: :devise,
class_name: resource,
skip: DEVISE_OPERATIONS
clean_options = GraphqlDevise::ResourceLoader.new(resource, options, true).call(
GraphqlDevise::Types::QueryType,
GraphqlDevise::Types::MutationType
)

devise_scope resource.underscore.tr('/', '_').to_sym do
post clean_options.at, to: 'graphql_devise/graphql#auth'
get clean_options.at, to: 'graphql_devise/graphql#auth'
end

# Avoid routes reload done by Devise
return if GraphqlDevise.resource_mounted?(resource)

authenticatable_type = clean_options.authenticatable_type.presence ||
"Types::#{resource}Type".safe_constantize ||
GraphqlDevise::Types::AuthenticatableType

prepared_mutations = GraphqlDevise::MountMethod::OperationPreparer.new(
resource: resource,
custom: clean_options.operations,
additional_operations: clean_options.additional_mutations,
preparer: GraphqlDevise::MountMethod::OperationPreparers::MutationFieldSetter.new(authenticatable_type),
selected_operations: GraphqlDevise::MountMethod::OperationSanitizer.call(
default: GraphqlDevise::DefaultOperations::MUTATIONS, only: clean_options.only, skipped: clean_options.skip
)
).call

prepared_mutations.each do |action, mutation|
GraphqlDevise::Types::MutationType.field(action, mutation: mutation)
end

prepared_queries = GraphqlDevise::MountMethod::OperationPreparer.new(
resource: resource,
custom: clean_options.operations,
additional_operations: clean_options.additional_queries,
preparer: GraphqlDevise::MountMethod::OperationPreparers::ResolverTypeSetter.new(authenticatable_type),
selected_operations: GraphqlDevise::MountMethod::OperationSanitizer.call(
default: GraphqlDevise::DefaultOperations::QUERIES, only: clean_options.only, skipped: clean_options.skip
)
).call

prepared_queries.each do |action, resolver|
GraphqlDevise::Types::QueryType.field(action, resolver: resolver)
end

Devise.mailer.helper(GraphqlDevise::MailerHelper)

GraphqlDevise.mount_resource(resource)
post clean_options.at, to: 'graphql_devise/graphql#auth'
get clean_options.at, to: 'graphql_devise/graphql#auth'
end
end
end
83 changes: 83 additions & 0 deletions lib/graphql_devise/resource_loader.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
module GraphqlDevise
class ResourceLoader
def initialize(resource, options, routing = false)
@resource = resource
@options = options
@routing = routing
@default_operations = GraphqlDevise::DefaultOperations::MUTATIONS.merge(GraphqlDevise::DefaultOperations::QUERIES)
end

def call(query, mutation)
mapping_name = @resource.to_s.underscore.tr('/', '_').to_sym

# clean_options responds to all keys defined in GraphqlDevise::MountMethod::SUPPORTED_OPTIONS
clean_options = GraphqlDevise::MountMethod::OptionSanitizer.new(@options).call!

return clean_options if GraphqlDevise.resource_mounted?(mapping_name) && @routing

validate_options!(clean_options)

authenticatable_type = clean_options.authenticatable_type.presence ||
"Types::#{@resource}Type".safe_constantize ||
GraphqlDevise::Types::AuthenticatableType

prepared_mutations = prepare_mutations(mapping_name, clean_options, authenticatable_type)

if prepared_mutations.any? && mutation.blank?
raise GraphqlDevise::Error, 'You need to provide a mutation type unless all mutations are skipped'
end

prepared_mutations.each do |action, prepared_mutation|
mutation.field(action, mutation: prepared_mutation, authenticate: false)
end

prepared_resolvers = prepare_resolvers(mapping_name, clean_options, authenticatable_type)

prepared_resolvers.each do |action, resolver|
query.field(action, resolver: resolver, authenticate: false)
end

GraphqlDevise.add_mapping(mapping_name, @resource)
GraphqlDevise.mount_resource(mapping_name) if @routing

clean_options
end

private

def prepare_resolvers(mapping_name, clean_options, authenticatable_type)
GraphqlDevise::MountMethod::OperationPreparer.new(
mapping_name: mapping_name,
custom: clean_options.operations,
additional_operations: clean_options.additional_queries,
preparer: GraphqlDevise::MountMethod::OperationPreparers::ResolverTypeSetter.new(authenticatable_type),
selected_operations: GraphqlDevise::MountMethod::OperationSanitizer.call(
default: GraphqlDevise::DefaultOperations::QUERIES, only: clean_options.only, skipped: clean_options.skip
)
).call
end

def prepare_mutations(mapping_name, clean_options, authenticatable_type)
GraphqlDevise::MountMethod::OperationPreparer.new(
mapping_name: mapping_name,
custom: clean_options.operations,
additional_operations: clean_options.additional_mutations,
preparer: GraphqlDevise::MountMethod::OperationPreparers::MutationFieldSetter.new(authenticatable_type),
selected_operations: GraphqlDevise::MountMethod::OperationSanitizer.call(
default: GraphqlDevise::DefaultOperations::MUTATIONS, only: clean_options.only, skipped: clean_options.skip
)
).call
end

def validate_options!(clean_options)
GraphqlDevise::MountMethod::OptionsValidator.new(
[
GraphqlDevise::MountMethod::OptionValidators::SkipOnlyValidator.new(options: clean_options),
GraphqlDevise::MountMethod::OptionValidators::ProvidedOperationsValidator.new(
options: clean_options, supported_operations: @default_operations
)
]
).validate!
end
end
end
Loading