sorcery 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/Dockerfile +10 -0
  3. data/.devcontainer/devcontainer.json +29 -0
  4. data/.devcontainer/postcreate.sh +4 -0
  5. data/.github/FUNDING.yml +1 -0
  6. data/.github/ISSUE_TEMPLATE.md +8 -4
  7. data/.github/PULL_REQUEST_TEMPLATE.md +7 -0
  8. data/.github/workflows/ruby.yml +54 -0
  9. data/.gitignore +2 -1
  10. data/.rubocop_todo.yml +44 -26
  11. data/CHANGELOG.md +48 -0
  12. data/CODE_OF_CONDUCT.md +14 -0
  13. data/Gemfile +2 -2
  14. data/MAINTAINING.md +64 -0
  15. data/README.md +3 -6
  16. data/Rakefile +3 -1
  17. data/SECURITY.md +19 -0
  18. data/gemfiles/rails_61.gemfile +7 -0
  19. data/gemfiles/rails_70.gemfile +7 -0
  20. data/gemfiles/rails_71.gemfile +7 -0
  21. data/lib/generators/sorcery/helpers.rb +4 -0
  22. data/lib/generators/sorcery/install_generator.rb +9 -2
  23. data/lib/generators/sorcery/templates/initializer.rb +23 -1
  24. data/lib/generators/sorcery/templates/migration/activity_logging.rb +5 -5
  25. data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +4 -4
  26. data/lib/generators/sorcery/templates/migration/core.rb +2 -4
  27. data/lib/generators/sorcery/templates/migration/external.rb +1 -1
  28. data/lib/generators/sorcery/templates/migration/magic_login.rb +4 -4
  29. data/lib/generators/sorcery/templates/migration/remember_me.rb +3 -3
  30. data/lib/generators/sorcery/templates/migration/reset_password.rb +5 -5
  31. data/lib/generators/sorcery/templates/migration/user_activation.rb +4 -4
  32. data/lib/sorcery/adapters/active_record_adapter.rb +2 -2
  33. data/lib/sorcery/adapters/mongoid_adapter.rb +1 -1
  34. data/lib/sorcery/controller/config.rb +6 -6
  35. data/lib/sorcery/controller/submodules/activity_logging.rb +5 -10
  36. data/lib/sorcery/controller/submodules/brute_force_protection.rb +3 -7
  37. data/lib/sorcery/controller/submodules/external.rb +3 -2
  38. data/lib/sorcery/controller/submodules/http_basic_auth.rb +2 -4
  39. data/lib/sorcery/controller/submodules/remember_me.rb +3 -7
  40. data/lib/sorcery/controller/submodules/session_timeout.rb +4 -7
  41. data/lib/sorcery/controller.rb +1 -1
  42. data/lib/sorcery/model/submodules/reset_password.rb +2 -0
  43. data/lib/sorcery/model.rb +11 -6
  44. data/lib/sorcery/protocols/oauth2.rb +1 -0
  45. data/lib/sorcery/providers/battlenet.rb +51 -0
  46. data/lib/sorcery/providers/line.rb +20 -4
  47. data/lib/sorcery/providers/slack.rb +1 -1
  48. data/lib/sorcery/version.rb +1 -1
  49. data/sorcery.gemspec +4 -5
  50. data/spec/controllers/controller_oauth2_spec.rb +27 -9
  51. data/spec/controllers/controller_oauth_spec.rb +10 -4
  52. data/spec/controllers/controller_session_timeout_spec.rb +3 -1
  53. data/spec/controllers/controller_spec.rb +6 -0
  54. data/spec/providers/examples_spec.rb +17 -0
  55. data/spec/rails_app/app/controllers/application_controller.rb +2 -0
  56. data/spec/rails_app/app/controllers/sorcery_controller.rb +21 -1
  57. data/spec/rails_app/config/routes.rb +3 -0
  58. data/spec/shared_examples/user_reset_password_shared_examples.rb +12 -0
  59. data/spec/shared_examples/user_shared_examples.rb +2 -2
  60. data/spec/support/migration_helper.rb +12 -2
  61. data/spec/support/providers/examples.rb +11 -0
  62. metadata +28 -26
  63. data/.travis.yml +0 -8
@@ -84,11 +84,17 @@ describe SorceryController, type: :controller do
84
84
  end
85
85
 
86
86
  context 'when callback_url begin with http://' do
87
+ before do
88
+ sorcery_controller_external_property_set(:twitter, :callback_url, '/oauth/twitter/callback')
89
+ end
87
90
  it 'login_at redirects correctly', pending: true do
88
91
  get :login_at_test
89
92
  expect(response).to be_a_redirect
90
93
  expect(response).to redirect_to('http://myapi.com/oauth/authorize?oauth_callback=http%3A%2F%2Fblabla.com&oauth_token=')
91
94
  end
95
+ after do
96
+ sorcery_controller_external_property_set(:twitter, :callback_url, 'http://blabla.com')
97
+ end
92
98
  end
93
99
 
94
100
  it 'logins if user exists' do
@@ -130,7 +136,7 @@ describe SorceryController, type: :controller do
130
136
  it 'creates a new user' do
131
137
  sorcery_controller_external_property_set(:twitter, :user_info_mapping, username: 'screen_name')
132
138
  expect(User).to receive(:load_from_provider).with('twitter', '123').and_return(nil)
133
- expect(User).to receive(:create_from_provider).with('twitter', '123', username: 'nbenari').and_return(user)
139
+ expect(User).to receive(:create_from_provider).with('twitter', '123', { username: 'nbenari' }).and_return(user)
134
140
 
135
141
  get :test_create_from_provider, params: { provider: 'twitter' }
136
142
  end
@@ -138,7 +144,7 @@ describe SorceryController, type: :controller do
138
144
  it 'supports nested attributes' do
139
145
  sorcery_controller_external_property_set(:twitter, :user_info_mapping, username: 'status/text')
140
146
  expect(User).to receive(:load_from_provider).with('twitter', '123').and_return(nil)
141
- expect(User).to receive(:create_from_provider).with('twitter', '123', username: 'coming soon to sorcery gem: twitter and facebook authentication support.').and_return(user)
147
+ expect(User).to receive(:create_from_provider).with('twitter', '123', { username: 'coming soon to sorcery gem: twitter and facebook authentication support.' }).and_return(user)
142
148
 
143
149
  get :test_create_from_provider, params: { provider: 'twitter' }
144
150
  end
@@ -146,7 +152,7 @@ describe SorceryController, type: :controller do
146
152
  it 'does not crash on missing nested attributes' do
147
153
  sorcery_controller_external_property_set(:twitter, :user_info_mapping, username: 'status/text', created_at: 'does/not/exist')
148
154
  expect(User).to receive(:load_from_provider).with('twitter', '123').and_return(nil)
149
- expect(User).to receive(:create_from_provider).with('twitter', '123', username: 'coming soon to sorcery gem: twitter and facebook authentication support.').and_return(user)
155
+ expect(User).to receive(:create_from_provider).with('twitter', '123', { username: 'coming soon to sorcery gem: twitter and facebook authentication support.' }).and_return(user)
150
156
 
151
157
  get :test_create_from_provider, params: { provider: 'twitter' }
152
158
  end
@@ -169,7 +175,7 @@ describe SorceryController, type: :controller do
169
175
 
170
176
  u = double('user')
171
177
  expect(User).to receive(:load_from_provider).with('twitter', '123').and_return(nil)
172
- expect(User).to receive(:create_from_provider).with('twitter', '123', username: 'nbenari').and_return(u).and_yield(u)
178
+ expect(User).to receive(:create_from_provider).with('twitter', '123', { username: 'nbenari' }).and_return(u).and_yield(u)
173
179
 
174
180
  get :test_create_from_provider_with_block, params: { provider: 'twitter' }
175
181
  end
@@ -129,9 +129,11 @@ describe SorceryController, type: :controller do
129
129
  end
130
130
 
131
131
  context "with 'session_timeout_from_last_action'" do
132
+ before { create_new_user }
133
+ after { User.delete_all }
134
+
132
135
  it 'does not logout if there was activity' do
133
136
  sorcery_controller_property_set(:session_timeout_from_last_action, true)
134
- expect(User).to receive(:authenticate).with('bla@bla.com', 'secret') { |&block| block.call(user, nil) }
135
137
 
136
138
  get :test_login, params: { email: 'bla@bla.com', password: 'secret' }
137
139
  Timecop.travel(Time.now.in_time_zone + 0.3)
@@ -64,7 +64,13 @@ describe SorceryController, type: :controller do
64
64
  expect(session[:user_id]).to eq user.id.to_s
65
65
  end
66
66
 
67
+ # NOTE: The lack of a CSRF token may mean that sessions will break
68
+ # horribly for Sorcery when using Rails 7.1+. We shall see.
67
69
  it 'sets csrf token in session' do
70
+ if Gem::Version.new(Rails.version) >= Gem::Version.new('7.1')
71
+ pending 'Rails 7.1 is not including the csrf token in the session for unknown reasons'
72
+ end
73
+
68
74
  expect(session[:_csrf_token]).not_to be_nil
69
75
  end
70
76
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'sorcery/providers/base'
5
+
6
+ describe Sorcery::Providers::Examples do
7
+ before(:all) do
8
+ sorcery_reload!([:external])
9
+ sorcery_controller_property_set(:external_providers, [:examples])
10
+ end
11
+
12
+ context 'fetching a plural custom provider' do
13
+ it 'returns the provider' do
14
+ expect(Sorcery::Controller::Config.examples).to be_a(Sorcery::Providers::Examples)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,2 @@
1
+ class ApplicationController < ActionController::Base
2
+ end
@@ -1,6 +1,6 @@
1
1
  require 'oauth'
2
2
 
3
- class SorceryController < ActionController::Base
3
+ class SorceryController < ApplicationController
4
4
  protect_from_forgery
5
5
 
6
6
  before_action :require_login_from_http_basic, only: [:test_http_basic_auth]
@@ -170,6 +170,10 @@ class SorceryController < ActionController::Base
170
170
  login_at(:discord)
171
171
  end
172
172
 
173
+ def login_at_test_battlenet
174
+ login_at(:battlenet)
175
+ end
176
+
173
177
  def test_login_from_twitter
174
178
  if (@user = login_from(:twitter))
175
179
  redirect_to 'bla', notice: 'Success!'
@@ -300,6 +304,14 @@ class SorceryController < ActionController::Base
300
304
  end
301
305
  end
302
306
 
307
+ def test_login_from_battlenet
308
+ if (@user = login_from(:battlenet))
309
+ redirect_to 'bla', notice: 'Success!'
310
+ else
311
+ redirect_to 'blu', alert: 'Failed!'
312
+ end
313
+ end
314
+
303
315
  def test_return_to_with_external_twitter
304
316
  if (@user = login_from(:twitter))
305
317
  redirect_back_or_to 'bla', notice: 'Success!'
@@ -430,6 +442,14 @@ class SorceryController < ActionController::Base
430
442
  end
431
443
  end
432
444
 
445
+ def test_return_to_with_external_battlenet
446
+ if (@user = login_from(:battlenet))
447
+ redirect_back_or_to 'bla', notice: 'Success!'
448
+ else
449
+ redirect_to 'blu', alert: 'Failed!'
450
+ end
451
+ end
452
+
433
453
  def test_create_from_provider
434
454
  provider = params[:provider]
435
455
  login_from(provider)
@@ -35,6 +35,7 @@ AppRoot::Application.routes.draw do
35
35
  get :test_login_from_auth0
36
36
  get :test_login_from_line
37
37
  get :test_login_from_discord
38
+ get :test_login_from_battlenet
38
39
  get :login_at_test
39
40
  get :login_at_test_twitter
40
41
  get :login_at_test_facebook
@@ -52,6 +53,7 @@ AppRoot::Application.routes.draw do
52
53
  get :login_at_test_auth0
53
54
  get :login_at_test_line
54
55
  get :login_at_test_discord
56
+ get :login_at_test_battlenet
55
57
  get :test_return_to_with_external
56
58
  get :test_return_to_with_external_twitter
57
59
  get :test_return_to_with_external_facebook
@@ -69,6 +71,7 @@ AppRoot::Application.routes.draw do
69
71
  get :test_return_to_with_external_auth0
70
72
  get :test_return_to_with_external_line
71
73
  get :test_return_to_with_external_discord
74
+ get :test_return_to_with_external_battlenet
72
75
  get :test_http_basic_auth
73
76
  get :some_action_making_a_non_persisted_change_to_the_user
74
77
  post :test_login_with_remember
@@ -328,6 +328,18 @@ shared_examples_for 'rails_3_reset_password_model' do
328
328
  expect(user.reset_password_token).to be_nil
329
329
  end
330
330
 
331
+ it 'when change_password! is called with empty argument, raise an exception' do
332
+ expect {
333
+ user.change_password!('')
334
+ }.to raise_error(ArgumentError, 'Blank password passed to change_password!')
335
+ end
336
+
337
+ it 'when change_password! is called with nil argument, raise an exception' do
338
+ expect {
339
+ user.change_password!(nil)
340
+ }.to raise_error(ArgumentError, 'Blank password passed to change_password!')
341
+ end
342
+
331
343
  it 'when change_password is called, deletes reset_password_token and calls #save' do
332
344
  new_password = 'blabulsdf'
333
345
 
@@ -511,7 +511,7 @@ shared_examples_for 'rails_3_core_model' do
511
511
 
512
512
  # password comparison is done using BCrypt::Password#==(raw_token), not String#==
513
513
  bcrypt_password = BCrypt::Password.new(user.crypted_password)
514
- allow(::BCrypt::Password).to receive(:create) do |token, cost:|
514
+ allow(::BCrypt::Password).to receive(:create) do |token, options = {}|
515
515
  # need to use common BCrypt's salt when genarating BCrypt::Password objects
516
516
  # so that any generated password hashes can be compared each other
517
517
  ::BCrypt::Engine.hash_secret(token, bcrypt_password.salt)
@@ -535,7 +535,7 @@ shared_examples_for 'rails_3_core_model' do
535
535
 
536
536
  # password comparison is done using BCrypt::Password#==(raw_token), not String#==
537
537
  bcrypt_password = BCrypt::Password.new(user.crypted_password)
538
- allow(::BCrypt::Password).to receive(:create) do |token, cost:|
538
+ allow(::BCrypt::Password).to receive(:create) do |token, options = {}|
539
539
  # need to use common BCrypt's salt when genarating BCrypt::Password objects
540
540
  # so that any generated password hashes can be compared each other
541
541
  ::BCrypt::Engine.hash_secret(token, bcrypt_password.salt)
@@ -1,7 +1,9 @@
1
1
  class MigrationHelper
2
2
  class << self
3
3
  def migrate(path)
4
- if ActiveRecord.version >= Gem::Version.new('5.2.0')
4
+ if ActiveRecord.version >= Gem::Version.new('6.0.0')
5
+ ActiveRecord::MigrationContext.new(path, schema_migration).migrate
6
+ elsif ActiveRecord.version >= Gem::Version.new('5.2.0')
5
7
  ActiveRecord::MigrationContext.new(path).migrate
6
8
  else
7
9
  ActiveRecord::Migrator.migrate(path)
@@ -9,11 +11,19 @@ class MigrationHelper
9
11
  end
10
12
 
11
13
  def rollback(path)
12
- if ActiveRecord.version >= Gem::Version.new('5.2.0')
14
+ if ActiveRecord.version >= Gem::Version.new('6.0.0')
15
+ ActiveRecord::MigrationContext.new(path, schema_migration).rollback
16
+ elsif ActiveRecord.version >= Gem::Version.new('5.2.0')
13
17
  ActiveRecord::MigrationContext.new(path).rollback
14
18
  else
15
19
  ActiveRecord::Migrator.rollback(path)
16
20
  end
17
21
  end
22
+
23
+ private
24
+
25
+ def schema_migration
26
+ ActiveRecord::Base.connection.schema_migration
27
+ end
18
28
  end
19
29
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sorcery/providers/base'
4
+
5
+ module Sorcery
6
+ module Providers
7
+ class Examples < Base
8
+ include Protocols::Oauth2
9
+ end
10
+ end
11
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sorcery
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.0
4
+ version: 0.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Noam Ben Ari
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2020-05-02 00:00:00.000000000 Z
15
+ date: 2024-03-08 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: bcrypt
@@ -32,42 +32,30 @@ dependencies:
32
32
  name: oauth
33
33
  requirement: !ruby/object:Gem::Requirement
34
34
  requirements:
35
- - - "~>"
36
- - !ruby/object:Gem::Version
37
- version: '0.4'
38
35
  - - ">="
39
36
  - !ruby/object:Gem::Version
40
- version: 0.4.4
37
+ version: '0.6'
41
38
  type: :runtime
42
39
  prerelease: false
43
40
  version_requirements: !ruby/object:Gem::Requirement
44
41
  requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '0.4'
48
42
  - - ">="
49
43
  - !ruby/object:Gem::Version
50
- version: 0.4.4
44
+ version: '0.6'
51
45
  - !ruby/object:Gem::Dependency
52
46
  name: oauth2
53
47
  requirement: !ruby/object:Gem::Requirement
54
48
  requirements:
55
- - - ">="
56
- - !ruby/object:Gem::Version
57
- version: 0.8.0
58
49
  - - "~>"
59
50
  - !ruby/object:Gem::Version
60
- version: '1.0'
51
+ version: '2.0'
61
52
  type: :runtime
62
53
  prerelease: false
63
54
  version_requirements: !ruby/object:Gem::Requirement
64
55
  requirements:
65
- - - ">="
66
- - !ruby/object:Gem::Version
67
- version: 0.8.0
68
56
  - - "~>"
69
57
  - !ruby/object:Gem::Version
70
- version: '1.0'
58
+ version: '2.0'
71
59
  - !ruby/object:Gem::Dependency
72
60
  name: byebug
73
61
  requirement: !ruby/object:Gem::Requirement
@@ -86,16 +74,16 @@ dependencies:
86
74
  name: rspec-rails
87
75
  requirement: !ruby/object:Gem::Requirement
88
76
  requirements:
89
- - - "~>"
77
+ - - ">="
90
78
  - !ruby/object:Gem::Version
91
- version: 3.7.0
79
+ version: '0'
92
80
  type: :development
93
81
  prerelease: false
94
82
  version_requirements: !ruby/object:Gem::Requirement
95
83
  requirements:
96
- - - "~>"
84
+ - - ">="
97
85
  - !ruby/object:Gem::Version
98
- version: 3.7.0
86
+ version: '0'
99
87
  - !ruby/object:Gem::Dependency
100
88
  name: rubocop
101
89
  requirement: !ruby/object:Gem::Requirement
@@ -189,24 +177,34 @@ dependencies:
189
177
  description: Provides common authentication needs such as signing in/out, activating
190
178
  by email and resetting password.
191
179
  email:
192
- - chase.gilliam@gmail.com
193
- - contact@joshbuker.com
180
+ - crypto@joshbuker.com
194
181
  executables: []
195
182
  extensions: []
196
183
  extra_rdoc_files: []
197
184
  files:
185
+ - ".devcontainer/Dockerfile"
186
+ - ".devcontainer/devcontainer.json"
187
+ - ".devcontainer/postcreate.sh"
198
188
  - ".document"
189
+ - ".github/FUNDING.yml"
199
190
  - ".github/ISSUE_TEMPLATE.md"
191
+ - ".github/PULL_REQUEST_TEMPLATE.md"
192
+ - ".github/workflows/ruby.yml"
200
193
  - ".gitignore"
201
194
  - ".rspec"
202
195
  - ".rubocop.yml"
203
196
  - ".rubocop_todo.yml"
204
- - ".travis.yml"
205
197
  - CHANGELOG.md
198
+ - CODE_OF_CONDUCT.md
206
199
  - Gemfile
207
200
  - LICENSE.md
201
+ - MAINTAINING.md
208
202
  - README.md
209
203
  - Rakefile
204
+ - SECURITY.md
205
+ - gemfiles/rails_61.gemfile
206
+ - gemfiles/rails_70.gemfile
207
+ - gemfiles/rails_71.gemfile
210
208
  - lib/generators/sorcery/USAGE
211
209
  - lib/generators/sorcery/helpers.rb
212
210
  - lib/generators/sorcery/install_generator.rb
@@ -254,6 +252,7 @@ files:
254
252
  - lib/sorcery/protocols/oauth2.rb
255
253
  - lib/sorcery/providers/auth0.rb
256
254
  - lib/sorcery/providers/base.rb
255
+ - lib/sorcery/providers/battlenet.rb
257
256
  - lib/sorcery/providers/discord.rb
258
257
  - lib/sorcery/providers/facebook.rb
259
258
  - lib/sorcery/providers/github.rb
@@ -298,11 +297,13 @@ files:
298
297
  - spec/orm/active_record.rb
299
298
  - spec/providers/example_provider_spec.rb
300
299
  - spec/providers/example_spec.rb
300
+ - spec/providers/examples_spec.rb
301
301
  - spec/providers/vk_spec.rb
302
302
  - spec/rails_app/app/active_record/authentication.rb
303
303
  - spec/rails_app/app/active_record/user.rb
304
304
  - spec/rails_app/app/active_record/user_provider.rb
305
305
  - spec/rails_app/app/assets/config/manifest.js
306
+ - spec/rails_app/app/controllers/application_controller.rb
306
307
  - spec/rails_app/app/controllers/sorcery_controller.rb
307
308
  - spec/rails_app/app/helpers/application_helper.rb
308
309
  - spec/rails_app/app/mailers/sorcery_mailer.rb
@@ -358,6 +359,7 @@ files:
358
359
  - spec/support/migration_helper.rb
359
360
  - spec/support/providers/example.rb
360
361
  - spec/support/providers/example_provider.rb
362
+ - spec/support/providers/examples.rb
361
363
  homepage: https://github.com/Sorcery/sorcery
362
364
  licenses:
363
365
  - MIT
@@ -379,7 +381,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
379
381
  - !ruby/object:Gem::Version
380
382
  version: '0'
381
383
  requirements: []
382
- rubygems_version: 3.0.8
384
+ rubygems_version: 3.3.5
383
385
  signing_key:
384
386
  specification_version: 4
385
387
  summary: Magical authentication for Rails applications
data/.travis.yml DELETED
@@ -1,8 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.4.9
4
- - 2.5.7
5
- - 2.6.5
6
-
7
- gemfile:
8
- - Gemfile