Skip to content

Commit a5e2107

Browse files
Merge pull request #3 from graphql-device/cleanup-sign-in
Cleanup login mutation
2 parents c77457e + 8b5d553 commit a5e2107

29 files changed

Lines changed: 504 additions & 182 deletions

File tree

.rubocop.yml

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
require: rubocop-rspec
2+
require: rubocop-performance
3+
4+
Rails:
5+
Enabled: true
6+
7+
AllCops:
8+
TargetRubyVersion: 2.5
9+
DisplayCopNames: true
10+
Exclude:
11+
- bin/**/*
12+
- db/**/*
13+
- vendor/**/*
14+
- tmp/**/*
15+
16+
Rails/HasAndBelongsToMany:
17+
Enabled: false
18+
19+
Rails/HasManyOrHasOneDependent:
20+
Enabled: false
21+
22+
Rails/OutputSafety:
23+
Enabled: false
24+
25+
RSpec/MultipleExpectations:
26+
Enabled: false
27+
28+
RSpec/ExampleLength:
29+
Enabled: false
30+
31+
RSpec/RepeatedDescription:
32+
Enabled: false
33+
34+
RSpec/MessageSpies:
35+
EnforcedStyle: receive
36+
37+
Style/AndOr:
38+
Enabled: false
39+
40+
Style/Documentation:
41+
Enabled: false
42+
43+
Style/MethodCalledOnDoEndBlock:
44+
Enabled: true
45+
46+
Style/CollectionMethods:
47+
Enabled: true
48+
49+
Style/SymbolArray:
50+
Enabled: false
51+
52+
Naming/AccessorMethodName:
53+
Enabled: false
54+
55+
Style/MethodCalledOnDoEndBlock:
56+
Enabled: false
57+
58+
Naming/VariableNumber:
59+
Enabled: false
60+
61+
Style/StringLiterals:
62+
ConsistentQuotesInMultiline: true
63+
64+
Style/ClassAndModuleChildren:
65+
Enabled: false
66+
67+
Style/GuardClause:
68+
Enabled: false
69+
70+
Style/EmptyMethod:
71+
EnforcedStyle: expanded
72+
SupportedStyles:
73+
- compact
74+
- expanded
75+
76+
Style/FrozenStringLiteralComment:
77+
Enabled: false
78+
79+
Style/StringMethods:
80+
Enabled: true
81+
82+
Metrics/LineLength:
83+
Max: 120
84+
85+
Metrics/MethodLength:
86+
Max: 15
87+
88+
Metrics/BlockLength:
89+
Enabled: false
90+
91+
Layout/AlignHash:
92+
EnforcedColonStyle: table
93+
94+
Layout/AlignParameters:
95+
EnforcedStyle: with_fixed_indentation
96+
SupportedStyles:
97+
- with_first_parameter
98+
- with_fixed_indentation
99+
100+
Lint/EndAlignment:
101+
EnforcedStyleAlignWith: variable
102+
SupportedStylesAlignWith:
103+
- keyword
104+
- variable
105+
106+
Lint/MissingCopEnableDirective:
107+
Enabled: false
108+
109+
RSpec/NestedGroups:
110+
Max: 7
111+
112+
RSpec/ContextWording:
113+
Prefixes:
114+
- when
115+
- with
116+
- without
117+
- and

Gemfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,4 @@ source 'https://rubygems.org'
22

33
gemspec
44

5-
gem 'bootsnap', require: false
65
gem 'listen'

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# GraphqlDevise
2+
[![Build Status](https://travis-ci.org/graphql-device/graphql_devise.svg?branch=master)](https://travis-ci.org/graphql-device/graphql_devise)
23

34
## Installation
45

Rakefile

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,28 @@
1-
require "bundler/gem_tasks"
2-
require "rspec/core/rake_task"
1+
begin
2+
require 'bundler/setup'
3+
rescue LoadError
4+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5+
end
6+
7+
require 'rdoc/task'
8+
9+
RDoc::Task.new(:rdoc) do |rdoc|
10+
rdoc.rdoc_dir = 'rdoc'
11+
rdoc.title = 'GraphqlDevise'
12+
rdoc.options << '--line-numbers'
13+
rdoc.rdoc_files.include('README.md')
14+
rdoc.rdoc_files.include('lib/**/*.rb')
15+
end
16+
17+
APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__)
18+
load 'rails/tasks/engine.rake'
19+
20+
load 'rails/tasks/statistics.rake'
21+
22+
require 'bundler/gem_tasks'
23+
24+
require 'rspec/core/rake_task'
325

426
RSpec::Core::RakeTask.new(:spec)
527

6-
task :default => :spec
28+
task default: :spec

app/controllers/graphql_devise/graphql_controller.rb

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
module GraphqlDevise
44
class GraphqlController < ApplicationController
5+
before_action :set_user_by_token
6+
57
def auth
68
result = if params[:_json]
79
GraphqlDevise::Schema.multiplex(
@@ -18,15 +20,14 @@ def auth
1820

1921
private
2022

21-
def execute_params(item, user = current_user)
23+
def execute_params(item)
2224
{
2325
operation_name: item[:operationName],
2426
variables: ensure_hash(item[:variables]),
2527
context: {
26-
current_user: user,
27-
request: request,
28-
response: response,
29-
resource_class: resource_class
28+
current_resource: @resource,
29+
controller: self,
30+
resource_class: resource_class
3031
}
3132
}
3233
end
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
module GraphqlDevise
2+
module Mutations
3+
class Base < GraphQL::Schema::Mutation
4+
private
5+
6+
def single_error_object(error)
7+
{ success: false, errors: [error] }
8+
end
9+
10+
def request
11+
context[:controller].request
12+
end
13+
14+
def response
15+
context[:controller].response
16+
end
17+
18+
def controller
19+
context[:controller]
20+
end
21+
22+
def resource_class
23+
context[:resource_class]
24+
end
25+
26+
def current_resource
27+
context[:current_resource]
28+
end
29+
end
30+
end
31+
end
Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,59 @@
11
module GraphqlDevise
22
module Mutations
3-
class Login < GraphQL::Schema::Mutation
3+
class Login < Base
44
argument :email, String, required: true
55
argument :password, String, required: true
66

77
field :authenticable, GraphqlDevise::Types::AuthenticableType, null: true
8+
field :success, Boolean, null: false
9+
field :errors, [String], null: false
810

911
def resolve(email:, password:)
10-
resource = context[:resource_class].find_by(email: email)
12+
resource = resource_class.find_by(email: email)
1113

12-
if resource && (!resource.respond_to?(:active_for_authentication?) || resource.active_for_authentication?)
13-
valid_password = resource.valid_password?(password)
14-
if (resource.respond_to?(:valid_for_authentication?) && !resource.valid_for_authentication? { valid_password }) || !valid_password
15-
return {}
14+
if resource && active_for_authentication?(resource)
15+
if invalid_for_authentication?(resource, password)
16+
return single_error_object(I18n.t('graphql_devise.sessions.bad_credentials'))
1617
end
1718

18-
auth_headers = resource.create_new_auth_token
19-
context[:response].headers.merge!(auth_headers)
19+
set_auth_headers(resource)
20+
controller.sign_in(:user, resource, store: false, bypass: false)
2021

21-
{ authenticable: resource }
22-
elsif resource && !(!resource.respond_to?(:active_for_authentication?) || resource.active_for_authentication?)
23-
if resource.respond_to?(:locked_at) && resource.locked_at
24-
return {}
22+
yield resource if block_given?
23+
24+
{ success: true, authenticable: resource, errors: [] }
25+
elsif resource && !active_for_authentication?(resource)
26+
if locked?(resource)
27+
single_error_object(I18n.t('graphql_devise.mailer.unlock_instructions.account_lock_msg'))
2528
else
26-
return {}
29+
single_error_object(I18n.t('devise_token_auth.sessions.not_confirmed', email: resource.email))
2730
end
2831
else
29-
return {}
32+
single_error_object(I18n.t('graphql_devise.sessions.bad_credentials'))
3033
end
3134
end
35+
36+
private
37+
38+
def set_auth_headers(resource)
39+
auth_headers = resource.create_new_auth_token
40+
response.headers.merge!(auth_headers)
41+
end
42+
43+
def invalid_for_authentication?(resource, password)
44+
valid_password = resource.valid_password?(password)
45+
46+
(resource.respond_to?(:valid_for_authentication?) && !resource.valid_for_authentication? { valid_password }) ||
47+
!valid_password
48+
end
49+
50+
def active_for_authentication?(resource)
51+
!resource.respond_to?(:active_for_authentication?) || resource.active_for_authentication?
52+
end
53+
54+
def locked?(resource)
55+
resource.respond_to?(:locked_at) && resource.locked_at
56+
end
3257
end
3358
end
3459
end

bin/rails

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
ENGINE_ROOT = File.expand_path('..', __dir__)
66
ENGINE_PATH = File.expand_path('../lib/graphql_devise/engine', __dir__)
7-
APP_PATH = File.expand_path('../test/dummy/config/application', __dir__)
7+
APP_PATH = File.expand_path('../spec/dummy/config/application', __dir__)
88

99
# Set up gems listed in the Gemfile.
1010
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)

config/locales/en.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
en:
2+
graphql_devise:
3+
sessions:
4+
bad_credentials: "Invalid login credentials. Please try again."
5+
not_confirmed: "A confirmation email was sent to your account at '%{email}'. You must follow the instructions in the email before your account can be activated"
6+
mailer:
7+
unlock_instructions:
8+
account_lock_msg: "Your account has been locked due to an excessive number of unsuccessful sign in attempts."

graphql_devise.gemspec

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,13 @@ Gem::Specification.new do |spec|
2828
spec.add_dependency 'rails', '~> 5.0'
2929

3030
spec.add_development_dependency 'bundler', '~> 2.0'
31+
spec.add_development_dependency 'factory_bot'
32+
spec.add_development_dependency 'faker'
33+
spec.add_development_dependency 'pry'
3134
spec.add_development_dependency 'rake', '~> 10.0'
3235
spec.add_development_dependency 'rspec-rails'
36+
spec.add_development_dependency 'rubocop'
37+
spec.add_development_dependency 'rubocop-performance'
38+
spec.add_development_dependency 'rubocop-rspec'
3339
spec.add_development_dependency 'sqlite3'
3440
end

0 commit comments

Comments
 (0)