From 215a94a1bfe0e14286765d03a5ef3ffb7757b73a Mon Sep 17 00:00:00 2001 From: David Revelo Date: Sat, 8 Feb 2020 08:04:44 -0500 Subject: [PATCH] Add operation sanitizer class --- lib/graphql_devise.rb | 1 + .../rails/operation_sanitizer.rb | 37 ++++++++ spec/operation_sanitizer_spec.rb | 90 +++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 lib/graphql_devise/rails/operation_sanitizer.rb create mode 100644 spec/operation_sanitizer_spec.rb diff --git a/lib/graphql_devise.rb b/lib/graphql_devise.rb index 66dbffbd..bbb1332e 100644 --- a/lib/graphql_devise.rb +++ b/lib/graphql_devise.rb @@ -6,6 +6,7 @@ require 'graphql_devise/error_codes' require 'graphql_devise/user_error' require 'graphql_devise/detailed_user_error' +require 'graphql_devise/rails/operation_sanitizer' require 'graphql_devise/concerns/controller_methods' module GraphqlDevise diff --git a/lib/graphql_devise/rails/operation_sanitizer.rb b/lib/graphql_devise/rails/operation_sanitizer.rb new file mode 100644 index 00000000..ae784d4b --- /dev/null +++ b/lib/graphql_devise/rails/operation_sanitizer.rb @@ -0,0 +1,37 @@ +module GraphqlDevise + class OperationSanitizer + def self.call(resource:, default:, custom:, only:, skipped:) + new( + resource: resource, + default: default, + custom: custom, + only: only, + skipped: skipped + ).call + end + + def initialize(resource:, default:, custom:, only:, skipped:) + @resource = resource + @mapping = resource.underscore.tr('/', '_').to_sym + @default = default + @custom = custom + @only = only + @skipped = skipped + end + + def call + result = @default + result = result.merge(@custom.slice(*operations_whitelist)) + result = result.slice(*@only) if @only.present? + result = result.except(*@skipped) if @skipped.present? + + result.transform_keys { |k| "#{@mapping}_#{k}".to_sym } + end + + private + + def operations_whitelist + @default.keys + end + end +end diff --git a/spec/operation_sanitizer_spec.rb b/spec/operation_sanitizer_spec.rb new file mode 100644 index 00000000..94501640 --- /dev/null +++ b/spec/operation_sanitizer_spec.rb @@ -0,0 +1,90 @@ +require 'rails_helper' + +RSpec.describe GraphqlDevise::OperationSanitizer do + describe '.call' do + subject(:result) do + described_class.call( + resource: resource, + default: default, + custom: custom, + only: only, + skipped: skipped + ) + end + + context 'when the operations passed are mutations' do + let(:resource) { 'User' } + let(:custom) { {} } + let(:skipped) { [] } + let(:only) { [] } + let(:default) do + { + 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 + } + end + + context 'when no other option besides default is passed' do + it 'returns all the default operations appending mapping to the key' do + expect(result).to eq( + user_login: GraphqlDevise::Mutations::Login, + user_logout: GraphqlDevise::Mutations::Logout, + user_sign_up: GraphqlDevise::Mutations::SignUp, + user_update_password: GraphqlDevise::Mutations::UpdatePassword, + user_send_password_reset: GraphqlDevise::Mutations::SendPasswordReset, + user_resend_confirmation: GraphqlDevise::Mutations::ResendConfirmation + ) + end + end + + context 'when there are custom operations' do + let(:custom) do + { + login: Mutations::Login, + sign_up: Mutations::SignUp, + query: GraphQL::Schema::Resolver + } + end + + it 'returns the default ops replacing the custom ones appending mapping to the key' do + expect(result).to eq( + user_login: Mutations::Login, + user_logout: GraphqlDevise::Mutations::Logout, + user_sign_up: Mutations::SignUp, + user_update_password: GraphqlDevise::Mutations::UpdatePassword, + user_send_password_reset: GraphqlDevise::Mutations::SendPasswordReset, + user_resend_confirmation: GraphqlDevise::Mutations::ResendConfirmation + ) + end + end + + context 'when there are only operations' do + let(:only) { [:sign_up, :update_password] } + + it 'returns only those default ops appending mapping to the key' do + expect(result).to eq( + user_sign_up: GraphqlDevise::Mutations::SignUp, + user_update_password: GraphqlDevise::Mutations::UpdatePassword + ) + end + end + + context 'when there are skipped operations' do + let(:skipped) { [:sign_up, :update_password] } + + it 'returns the default ops but the skipped appending mapping to the key' do + expect(result).to eq( + user_login: GraphqlDevise::Mutations::Login, + user_logout: GraphqlDevise::Mutations::Logout, + user_send_password_reset: GraphqlDevise::Mutations::SendPasswordReset, + user_resend_confirmation: GraphqlDevise::Mutations::ResendConfirmation + ) + end + end + end + end +end