Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# frozen_string_literal: true

module GraphqlDevise
module Concerns
module AdditionalControllerMethods
extend ActiveSupport::Concern

included do
attr_accessor :client_id, :token, :resource
end

def gql_devise_context(models)
{
current_resource: authenticate_model(models),
controller: self
}
end

def authenticate_model(models)
Array(models).each do |model|
set_resource_by_token(model)
return @resource if @resource.present?
end

nil
end

def resource_class(resource = nil)
# Return the resource class instead of looking for a Devise mapping if resource is already a resource class
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.

I think this comment should mention find_by is meant to use duck typing to indentify AR and Mongo ID models.

return resource if resource.respond_to?(:find_by)
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.

In which cases will this not be an AR or Mongo Id model?


super
end

def full_url_without_params
request.base_url + request.path
end

def set_resource_by_token(resource)
set_user_by_token(resource)
end

def graphql_context(resource_name)
{
resource_name: resource_name,
controller: self
}
end

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
32 changes: 5 additions & 27 deletions app/controllers/graphql_devise/concerns/set_user_by_token.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,12 @@

module GraphqlDevise
module Concerns
SetUserByToken = DeviseTokenAuth::Concerns::SetUserByToken
module SetUserByToken
extend ActiveSupport::Concern

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

def full_url_without_params
request.base_url + request.path
end

def set_resource_by_token(resource)
set_user_by_token(resource)
end

def graphql_context(resource_name)
{
resource_name: resource_name,
controller: self
}
end

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)
included do
include DeviseTokenAuth::Concerns::SetUserByToken
include GraphqlDevise::Concerns::AdditionalControllerMethods
end
end
end
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
Expand Up @@ -3,7 +3,7 @@
module GraphqlDevise
module MailerHelper
def confirmation_query(resource_name:, token:, redirect_url:)
name = "#{resource_name.underscore.tr('/', '_').camelize(:lower)}ConfirmAccount"
name = "#{GraphqlDevise.to_mapping_name(resource_name).camelize(:lower)}ConfirmAccount"
raw = <<-GRAPHQL
query($token:String!,$redirectUrl:String!){
#{name}(confirmationToken:$token,redirectUrl:$redirectUrl){
Expand All @@ -19,7 +19,7 @@ def confirmation_query(resource_name:, token:, redirect_url:)
end

def password_reset_query(token:, redirect_url:, resource_name:)
name = "#{resource_name.underscore.tr('/', '_').camelize(:lower)}CheckPasswordToken"
name = "#{GraphqlDevise.to_mapping_name(resource_name).camelize(:lower)}CheckPasswordToken"
raw = <<-GRAPHQL
query($token:String!,$redirectUrl:String!){
#{name}(resetPasswordToken:$token,redirectUrl:$redirectUrl){
Expand Down
21 changes: 21 additions & 0 deletions app/models/graphql_devise/concerns/additional_model_methods.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

require 'graphql_devise/model/with_email_updater'

module GraphqlDevise
module Concerns
module AdditionalModelMethods
extend ActiveSupport::Concern

class_methods do
def reconfirmable
devise_modules.include?(:confirmable) && column_names.include?('unconfirmed_email')
end
end

def update_with_email(attributes = {})
GraphqlDevise::Model::WithEmailUpdater.new(self, attributes).call
end
end
end
end
15 changes: 6 additions & 9 deletions app/models/graphql_devise/concerns/model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,14 @@

module GraphqlDevise
module Concerns
Model = DeviseTokenAuth::Concerns::User
module Model
extend ActiveSupport::Concern

Model.module_eval do
class_methods do
def reconfirmable
devise_modules.include?(:confirmable) && column_names.include?('unconfirmed_email')
end
end
included do
include DeviseTokenAuth::Concerns::User
include GraphqlDevise::Concerns::AdditionalModelMethods

def update_with_email(attributes = {})
GraphqlDevise::Model::WithEmailUpdater.new(self, attributes).call
GraphqlDevise.configure_warden_serializer_for_model(self)
end
end
end
Expand Down
24 changes: 19 additions & 5 deletions lib/graphql_devise.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,36 @@ def self.load_schema
@schema_loaded = true
end

def self.resource_mounted?(mapping_name)
@mounted_resources.include?(mapping_name)
def self.resource_mounted?(model)
@mounted_resources.include?(model)
end

def self.mount_resource(mapping_name)
@mounted_resources << mapping_name
def self.mount_resource(model)
@mounted_resources << model
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.

Should we check the resource is not already there before adding?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

we do on the resource_loader

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.

I think it would less error prone if the check is closer to the assignation, like with add_mapping bellow where the key is looked among the devise mapping before adding

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

With add_mapping it is important to prevent adding a new Devise mapping as it has mnay implications, with this one, no real problem if we ever mount the same model more than once. I think it would just add unnecessary overhead to check the list each time we mount a resource. This array is only used to later check the model is or not already on the list.

end

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

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

def self.to_mapping_name(resource)
resource.to_s.underscore.tr('/', '_')
end

def self.configure_warden_serializer_for_model(model)
Devise.warden_config.serialize_into_session(to_mapping_name(model)) do |record|
model.serialize_into_session(record)
end

Devise.warden_config.serialize_from_session(to_mapping_name(model)) do |args|
model.serialize_from_session(*args)
end
end
end

require 'graphql_devise/engine'
Expand Down
6 changes: 3 additions & 3 deletions lib/graphql_devise/concerns/controller_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ def controller
end

def resource_name
self.class.instance_variable_get(:@resource_name)
GraphqlDevise.to_mapping_name(resource_class)
end

def resource_class
controller.send(:resource_class, resource_name)
self.class.instance_variable_get(:@resource_klass)
end

def recoverable_enabled?
Expand All @@ -60,7 +60,7 @@ def blacklisted_redirect_url?(redirect_url)
end

def current_resource
@current_resource ||= controller.send(:set_user_by_token, resource_name)
@current_resource ||= controller.send(:set_resource_by_token, resource_class)
end

def client
Expand Down
12 changes: 6 additions & 6 deletions lib/graphql_devise/mount_method/operation_preparer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
require_relative 'operation_preparers/gql_name_setter'
require_relative 'operation_preparers/mutation_field_setter'
require_relative 'operation_preparers/resolver_type_setter'
require_relative 'operation_preparers/resource_name_setter'
require_relative 'operation_preparers/resource_klass_setter'
require_relative 'operation_preparers/default_operation_preparer'
require_relative 'operation_preparers/custom_operation_preparer'

module GraphqlDevise
module MountMethod
class OperationPreparer
def initialize(mapping_name:, selected_operations:, preparer:, custom:, additional_operations:)
def initialize(model:, selected_operations:, preparer:, custom:, additional_operations:)
@selected_operations = selected_operations
@preparer = preparer
@mapping_name = mapping_name
@model = model
@custom = custom
@additional_operations = additional_operations
end
Expand All @@ -22,18 +22,18 @@ def call
default_operations = OperationPreparers::DefaultOperationPreparer.new(
selected_operations: @selected_operations,
custom_keys: @custom.keys,
mapping_name: @mapping_name,
model: @model,
preparer: @preparer
).call

custom_operations = OperationPreparers::CustomOperationPreparer.new(
selected_keys: @selected_operations.keys,
custom_operations: @custom,
mapping_name: @mapping_name
model: @model
).call

additional_operations = @additional_operations.each_with_object({}) do |(action, operation), result|
result[action] = OperationPreparers::ResourceNameSetter.new(@mapping_name).call(operation)
result[action] = OperationPreparers::ResourceKlassSetter.new(@model).call(operation)
end

default_operations.merge(custom_operations).merge(additional_operations)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,21 @@ module GraphqlDevise
module MountMethod
module OperationPreparers
class CustomOperationPreparer
def initialize(selected_keys:, custom_operations:, mapping_name:)
def initialize(selected_keys:, custom_operations:, model:)
@selected_keys = selected_keys
@custom_operations = custom_operations
@mapping_name = mapping_name
@model = model
end

def call
mapping_name = GraphqlDevise.to_mapping_name(@model)

@custom_operations.slice(*@selected_keys).each_with_object({}) do |(action, operation), result|
mapped_action = "#{@mapping_name}_#{action}"
mapped_action = "#{mapping_name}_#{action}"

result[mapped_action.to_sym] = [
OperationPreparers::GqlNameSetter.new(mapped_action),
OperationPreparers::ResourceNameSetter.new(@mapping_name)
OperationPreparers::ResourceKlassSetter.new(@model)
].reduce(operation) { |prepared_operation, preparer| preparer.call(prepared_operation) }
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,25 @@ module GraphqlDevise
module MountMethod
module OperationPreparers
class DefaultOperationPreparer
def initialize(selected_operations:, custom_keys:, mapping_name:, preparer:)
def initialize(selected_operations:, custom_keys:, model:, preparer:)
@selected_operations = selected_operations
@custom_keys = custom_keys
@mapping_name = mapping_name
@model = model
@preparer = preparer
end

def call
mapping_name = GraphqlDevise.to_mapping_name(@model)

@selected_operations.except(*@custom_keys).each_with_object({}) do |(action, operation_info), result|
mapped_action = "#{@mapping_name}_#{action}"
mapped_action = "#{mapping_name}_#{action}"
operation = operation_info[:klass]
options = operation_info.except(:klass)

result[mapped_action.to_sym] = [
OperationPreparers::GqlNameSetter.new(mapped_action),
@preparer,
OperationPreparers::ResourceNameSetter.new(@mapping_name)
OperationPreparers::ResourceKlassSetter.new(@model)
].reduce(child_class(operation)) do |prepared_operation, preparer|
preparer.call(prepared_operation, **options)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
module GraphqlDevise
module MountMethod
module OperationPreparers
class ResourceNameSetter
def initialize(name)
@name = name
class ResourceKlassSetter
def initialize(klass)
@klass = klass
end

def call(operation, **)
operation.instance_variable_set(:@resource_name, @name)
operation.instance_variable_set(:@resource_klass, @klass)

operation
end
Expand Down
Loading