sorcery 0.9.1 → 0.16.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/FUNDING.yml +1 -0
- data/.github/ISSUE_TEMPLATE.md +24 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +7 -0
- data/.github/workflows/ruby.yml +70 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +55 -0
- data/.rubocop_todo.yml +163 -0
- data/CHANGELOG.md +132 -34
- data/CODE_OF_CONDUCT.md +14 -0
- data/Gemfile +3 -17
- data/{LICENSE.txt → LICENSE.md} +1 -1
- data/MAINTAINING.md +64 -0
- data/README.md +146 -269
- data/Rakefile +4 -2
- data/SECURITY.md +19 -0
- data/gemfiles/rails_52.gemfile +7 -0
- data/gemfiles/rails_60.gemfile +7 -0
- data/gemfiles/rails_61.gemfile +7 -0
- data/gemfiles/rails_70.gemfile +7 -0
- data/lib/generators/sorcery/USAGE +1 -1
- data/lib/generators/sorcery/helpers.rb +8 -4
- data/lib/generators/sorcery/install_generator.rb +41 -35
- data/lib/generators/sorcery/templates/initializer.rb +216 -112
- data/lib/generators/sorcery/templates/migration/activity_logging.rb +7 -7
- data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +5 -5
- data/lib/generators/sorcery/templates/migration/core.rb +5 -7
- data/lib/generators/sorcery/templates/migration/external.rb +4 -4
- data/lib/generators/sorcery/templates/migration/magic_login.rb +9 -0
- data/lib/generators/sorcery/templates/migration/remember_me.rb +5 -5
- data/lib/generators/sorcery/templates/migration/reset_password.rb +7 -6
- data/lib/generators/sorcery/templates/migration/user_activation.rb +6 -6
- data/lib/sorcery/adapters/active_record_adapter.rb +11 -21
- data/lib/sorcery/adapters/mongoid_adapter.rb +23 -11
- data/lib/sorcery/controller/config.rb +27 -23
- data/lib/sorcery/controller/submodules/activity_logging.rb +16 -18
- data/lib/sorcery/controller/submodules/brute_force_protection.rb +1 -2
- data/lib/sorcery/controller/submodules/external.rb +69 -44
- data/lib/sorcery/controller/submodules/http_basic_auth.rb +18 -19
- data/lib/sorcery/controller/submodules/remember_me.rb +16 -16
- data/lib/sorcery/controller/submodules/session_timeout.rb +33 -11
- data/lib/sorcery/controller.rb +50 -35
- data/lib/sorcery/crypto_providers/aes256.rb +17 -16
- data/lib/sorcery/crypto_providers/bcrypt.rb +26 -22
- data/lib/sorcery/crypto_providers/common.rb +1 -1
- data/lib/sorcery/crypto_providers/md5.rb +5 -5
- data/lib/sorcery/crypto_providers/sha1.rb +5 -5
- data/lib/sorcery/crypto_providers/sha256.rb +2 -2
- data/lib/sorcery/crypto_providers/sha512.rb +3 -3
- data/lib/sorcery/engine.rb +19 -11
- data/lib/sorcery/model/config.rb +73 -50
- data/lib/sorcery/model/submodules/activity_logging.rb +31 -12
- data/lib/sorcery/model/submodules/brute_force_protection.rb +38 -31
- data/lib/sorcery/model/submodules/external.rb +22 -10
- data/lib/sorcery/model/submodules/magic_login.rb +130 -0
- data/lib/sorcery/model/submodules/remember_me.rb +19 -7
- data/lib/sorcery/model/submodules/reset_password.rb +64 -42
- data/lib/sorcery/model/submodules/user_activation.rb +52 -54
- data/lib/sorcery/model/temporary_token.rb +30 -7
- data/lib/sorcery/model.rb +65 -40
- data/lib/sorcery/protocols/oauth.rb +4 -9
- data/lib/sorcery/protocols/oauth2.rb +0 -2
- data/lib/sorcery/providers/auth0.rb +46 -0
- data/lib/sorcery/providers/base.rb +4 -4
- data/lib/sorcery/providers/battlenet.rb +51 -0
- data/lib/sorcery/providers/discord.rb +52 -0
- data/lib/sorcery/providers/facebook.rb +8 -11
- data/lib/sorcery/providers/github.rb +5 -7
- data/lib/sorcery/providers/google.rb +3 -5
- data/lib/sorcery/providers/heroku.rb +7 -8
- data/lib/sorcery/providers/instagram.rb +73 -0
- data/lib/sorcery/providers/jira.rb +12 -17
- data/lib/sorcery/providers/line.rb +63 -0
- data/lib/sorcery/providers/linkedin.rb +44 -35
- data/lib/sorcery/providers/liveid.rb +4 -7
- data/lib/sorcery/providers/microsoft.rb +59 -0
- data/lib/sorcery/providers/paypal.rb +60 -0
- data/lib/sorcery/providers/salesforce.rb +3 -5
- data/lib/sorcery/providers/slack.rb +45 -0
- data/lib/sorcery/providers/twitter.rb +4 -6
- data/lib/sorcery/providers/vk.rb +8 -9
- data/lib/sorcery/providers/wechat.rb +81 -0
- data/lib/sorcery/providers/xing.rb +7 -10
- data/lib/sorcery/test_helpers/internal/rails.rb +25 -17
- data/lib/sorcery/test_helpers/internal.rb +15 -14
- data/lib/sorcery/test_helpers/rails/controller.rb +1 -1
- data/lib/sorcery/test_helpers/rails/integration.rb +5 -6
- data/lib/sorcery/test_helpers/rails/request.rb +20 -0
- data/lib/sorcery/version.rb +1 -1
- data/lib/sorcery.rb +4 -17
- data/sorcery.gemspec +43 -28
- data/spec/active_record/user_activation_spec.rb +4 -5
- data/spec/active_record/user_activity_logging_spec.rb +4 -6
- data/spec/active_record/user_brute_force_protection_spec.rb +5 -6
- data/spec/active_record/user_magic_login_spec.rb +15 -0
- data/spec/active_record/user_oauth_spec.rb +5 -6
- data/spec/active_record/user_remember_me_spec.rb +5 -6
- data/spec/active_record/user_reset_password_spec.rb +4 -5
- data/spec/active_record/user_spec.rb +7 -17
- data/spec/controllers/controller_activity_logging_spec.rb +13 -24
- data/spec/controllers/controller_brute_force_protection_spec.rb +8 -10
- data/spec/controllers/controller_http_basic_auth_spec.rb +20 -21
- data/spec/controllers/controller_oauth2_spec.rb +297 -158
- data/spec/controllers/controller_oauth_spec.rb +97 -71
- data/spec/controllers/controller_remember_me_spec.rb +49 -36
- data/spec/controllers/controller_session_timeout_spec.rb +106 -20
- data/spec/controllers/controller_spec.rb +87 -111
- data/spec/orm/active_record.rb +3 -3
- data/spec/providers/example_provider_spec.rb +17 -0
- data/spec/providers/example_spec.rb +17 -0
- data/spec/providers/examples_spec.rb +17 -0
- data/spec/providers/vk_spec.rb +42 -0
- data/spec/rails_app/app/active_record/authentication.rb +1 -1
- data/spec/rails_app/app/active_record/user.rb +2 -2
- data/spec/rails_app/app/assets/config/manifest.js +1 -0
- data/spec/rails_app/app/controllers/application_controller.rb +2 -0
- data/spec/rails_app/app/controllers/sorcery_controller.rb +250 -46
- data/spec/rails_app/app/mailers/sorcery_mailer.rb +23 -17
- data/spec/rails_app/app/views/sorcery_mailer/magic_login_email.html.erb +13 -0
- data/spec/rails_app/app/views/sorcery_mailer/magic_login_email.text.erb +6 -0
- data/spec/rails_app/config/application.rb +14 -9
- data/spec/rails_app/config/boot.rb +2 -2
- data/spec/rails_app/config/environment.rb +1 -1
- data/spec/rails_app/config/environments/test.rb +1 -1
- data/spec/rails_app/config/initializers/compatible_legacy_migration.rb +11 -0
- data/spec/rails_app/config/initializers/session_store.rb +3 -3
- data/spec/rails_app/config/routes.rb +31 -1
- data/spec/rails_app/config/secrets.yml +4 -0
- data/spec/rails_app/config.ru +1 -1
- data/spec/rails_app/db/migrate/activation/20101224223622_add_activation_to_users.rb +4 -4
- data/spec/rails_app/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +10 -10
- data/spec/rails_app/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +5 -5
- data/spec/rails_app/db/migrate/core/20101224223620_create_users.rb +5 -5
- data/spec/rails_app/db/migrate/external/20101224223628_create_authentications_and_user_providers.rb +3 -3
- data/spec/rails_app/db/migrate/invalidate_active_sessions/20180221093235_add_invalidate_active_sessions_before_to_users.rb +9 -0
- data/spec/rails_app/db/migrate/magic_login/20170924151831_add_magic_login_to_users.rb +17 -0
- data/spec/rails_app/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +6 -6
- data/spec/rails_app/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +7 -5
- data/spec/rails_app/db/schema.rb +7 -9
- data/spec/shared_examples/user_activation_shared_examples.rb +177 -58
- data/spec/shared_examples/user_activity_logging_shared_examples.rb +47 -41
- data/spec/shared_examples/user_brute_force_protection_shared_examples.rb +19 -24
- data/spec/shared_examples/user_magic_login_shared_examples.rb +150 -0
- data/spec/shared_examples/user_oauth_shared_examples.rb +7 -10
- data/spec/shared_examples/user_remember_me_shared_examples.rb +91 -22
- data/spec/shared_examples/user_reset_password_shared_examples.rb +153 -58
- data/spec/shared_examples/user_shared_examples.rb +328 -145
- data/spec/sorcery_crypto_providers_spec.rb +122 -75
- data/spec/sorcery_temporary_token_spec.rb +27 -0
- data/spec/spec.opts +1 -1
- data/spec/spec_helper.rb +19 -14
- data/spec/support/migration_helper.rb +29 -0
- data/spec/support/providers/example.rb +11 -0
- data/spec/support/providers/example_provider.rb +11 -0
- data/spec/support/providers/examples.rb +11 -0
- metadata +119 -89
- data/.travis.yml +0 -132
- data/gemfiles/active_record-rails40.gemfile +0 -7
- data/gemfiles/active_record-rails41.gemfile +0 -7
- data/gemfiles/mongo_mapper-rails40.gemfile +0 -9
- data/gemfiles/mongo_mapper-rails41.gemfile +0 -9
- data/gemfiles/mongoid-rails40.gemfile +0 -9
- data/gemfiles/mongoid-rails41.gemfile +0 -9
- data/gemfiles/mongoid3-rails32.gemfile +0 -9
- data/lib/sorcery/adapters/data_mapper_adapter.rb +0 -176
- data/lib/sorcery/adapters/mongo_mapper_adapter.rb +0 -110
- data/lib/sorcery/railties/tasks.rake +0 -6
- data/spec/data_mapper/user_activation_spec.rb +0 -10
- data/spec/data_mapper/user_activity_logging_spec.rb +0 -14
- data/spec/data_mapper/user_brute_force_protection_spec.rb +0 -9
- data/spec/data_mapper/user_oauth_spec.rb +0 -9
- data/spec/data_mapper/user_remember_me_spec.rb +0 -8
- data/spec/data_mapper/user_reset_password_spec.rb +0 -8
- data/spec/data_mapper/user_spec.rb +0 -27
- data/spec/mongo_mapper/user_activation_spec.rb +0 -9
- data/spec/mongo_mapper/user_activity_logging_spec.rb +0 -8
- data/spec/mongo_mapper/user_brute_force_protection_spec.rb +0 -8
- data/spec/mongo_mapper/user_oauth_spec.rb +0 -8
- data/spec/mongo_mapper/user_remember_me_spec.rb +0 -8
- data/spec/mongo_mapper/user_reset_password_spec.rb +0 -8
- data/spec/mongo_mapper/user_spec.rb +0 -37
- data/spec/mongoid/user_activation_spec.rb +0 -9
- data/spec/mongoid/user_activity_logging_spec.rb +0 -8
- data/spec/mongoid/user_brute_force_protection_spec.rb +0 -8
- data/spec/mongoid/user_oauth_spec.rb +0 -8
- data/spec/mongoid/user_remember_me_spec.rb +0 -8
- data/spec/mongoid/user_reset_password_spec.rb +0 -8
- data/spec/mongoid/user_spec.rb +0 -51
- data/spec/orm/data_mapper.rb +0 -48
- data/spec/orm/mongo_mapper.rb +0 -10
- data/spec/orm/mongoid.rb +0 -22
- data/spec/rails_app/app/data_mapper/authentication.rb +0 -8
- data/spec/rails_app/app/data_mapper/user.rb +0 -7
- data/spec/rails_app/app/mongo_mapper/authentication.rb +0 -6
- data/spec/rails_app/app/mongo_mapper/user.rb +0 -7
- data/spec/rails_app/app/mongoid/authentication.rb +0 -7
- data/spec/rails_app/app/mongoid/user.rb +0 -7
- data/spec/rails_app/config/initializers/secret_token.rb +0 -7
- data/spec/rails_app/log/development.log +0 -1791
@@ -0,0 +1,81 @@
|
|
1
|
+
module Sorcery
|
2
|
+
module Providers
|
3
|
+
# This class adds support for OAuth with open.wx.qq.com.
|
4
|
+
#
|
5
|
+
# config.wechat.key = <key>
|
6
|
+
# config.wechat.secret = <secret>
|
7
|
+
# ...
|
8
|
+
#
|
9
|
+
class Wechat < Base
|
10
|
+
include Protocols::Oauth2
|
11
|
+
|
12
|
+
attr_reader :mode, :param_name, :parse
|
13
|
+
attr_accessor :auth_url, :scope, :token_url, :user_info_path
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
super
|
17
|
+
|
18
|
+
@scope = 'snsapi_login'
|
19
|
+
@auth_url = 'https://open.weixin.qq.com/connect/qrconnect'
|
20
|
+
@user_info_path = 'https://api.weixin.qq.com/sns/userinfo'
|
21
|
+
@token_url = 'https://api.weixin.qq.com/sns/oauth2/access_token'
|
22
|
+
@state = SecureRandom.hex(16)
|
23
|
+
@mode = :body
|
24
|
+
@parse = :json
|
25
|
+
@param_name = 'access_token'
|
26
|
+
end
|
27
|
+
|
28
|
+
def authorize_url(options = {})
|
29
|
+
oauth_params = {
|
30
|
+
appid: @key,
|
31
|
+
redirect_uri: @callback_url,
|
32
|
+
response_type: 'code',
|
33
|
+
scope: scope,
|
34
|
+
state: @state
|
35
|
+
}
|
36
|
+
"#{options[:authorize_url]}?#{oauth_params.to_query}#wechat_redirect"
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_user_hash(access_token)
|
40
|
+
response = access_token.get(
|
41
|
+
user_info_path,
|
42
|
+
params: {
|
43
|
+
access_token: access_token.token,
|
44
|
+
openid: access_token.params['openid']
|
45
|
+
}
|
46
|
+
)
|
47
|
+
|
48
|
+
{}.tap do |h|
|
49
|
+
h[:user_info] = JSON.parse(response.body)
|
50
|
+
h[:uid] = h[:user_info]['unionid']
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_access_token(args, options = {})
|
55
|
+
client = build_client(options)
|
56
|
+
client.auth_code.get_token(
|
57
|
+
args[:code],
|
58
|
+
{ appid: @key, secret: @secret, parse: parse },
|
59
|
+
options
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
def login_url(_params, _session)
|
64
|
+
authorize_url authorize_url: auth_url
|
65
|
+
end
|
66
|
+
|
67
|
+
def process_callback(params, _session)
|
68
|
+
args = {}.tap do |a|
|
69
|
+
a[:code] = params[:code] if params[:code]
|
70
|
+
end
|
71
|
+
|
72
|
+
get_access_token(
|
73
|
+
args,
|
74
|
+
token_url: token_url,
|
75
|
+
mode: mode,
|
76
|
+
param_name: param_name
|
77
|
+
)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -7,19 +7,17 @@ module Sorcery
|
|
7
7
|
# ...
|
8
8
|
#
|
9
9
|
class Xing < Base
|
10
|
-
|
11
10
|
include Protocols::Oauth
|
12
11
|
|
13
12
|
attr_accessor :access_token_path, :authorize_path, :request_token_path,
|
14
13
|
:user_info_path
|
15
14
|
|
16
|
-
|
17
15
|
def initialize
|
18
16
|
@configuration = {
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
17
|
+
site: 'https://api.xing.com/v1',
|
18
|
+
authorize_path: '/authorize',
|
19
|
+
request_token_path: '/request_token',
|
20
|
+
access_token_path: '/access_token'
|
23
21
|
}
|
24
22
|
@user_info_path = '/users/me'
|
25
23
|
end
|
@@ -40,11 +38,11 @@ module Sorcery
|
|
40
38
|
|
41
39
|
# calculates and returns the url to which the user should be redirected,
|
42
40
|
# to get authenticated at the external provider's site.
|
43
|
-
def login_url(
|
41
|
+
def login_url(_params, session)
|
44
42
|
req_token = get_request_token
|
45
43
|
session[:request_token] = req_token.token
|
46
44
|
session[:request_token_secret] = req_token.secret
|
47
|
-
authorize_url(
|
45
|
+
authorize_url(request_token: req_token.token, request_token_secret: req_token.secret)
|
48
46
|
end
|
49
47
|
|
50
48
|
# tries to login the user from access token
|
@@ -55,10 +53,9 @@ module Sorcery
|
|
55
53
|
request_token_secret: session[:request_token_secret]
|
56
54
|
}
|
57
55
|
|
58
|
-
args
|
56
|
+
args[:code] = params[:code] if params[:code]
|
59
57
|
get_access_token(args)
|
60
58
|
end
|
61
|
-
|
62
59
|
end
|
63
60
|
end
|
64
61
|
end
|
@@ -4,11 +4,11 @@ module Sorcery
|
|
4
4
|
module Rails
|
5
5
|
include ::Sorcery::TestHelpers::Rails::Controller
|
6
6
|
|
7
|
-
SUBMODULES_AUTO_ADDED_CONTROLLER_FILTERS = [
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
]
|
7
|
+
SUBMODULES_AUTO_ADDED_CONTROLLER_FILTERS = %i[
|
8
|
+
register_last_activity_time_to_db
|
9
|
+
deny_banned_user
|
10
|
+
validate_session
|
11
|
+
].freeze
|
12
12
|
|
13
13
|
def sorcery_reload!(submodules = [], options = {})
|
14
14
|
reload_user_class
|
@@ -17,34 +17,34 @@ module Sorcery
|
|
17
17
|
::Sorcery::Controller::Config.init!
|
18
18
|
::Sorcery::Controller::Config.reset!
|
19
19
|
|
20
|
-
# remove all plugin
|
20
|
+
# remove all plugin before_actions so they won't fail other tests.
|
21
21
|
# I don't like this way, but I didn't find another.
|
22
22
|
# hopefully it won't break until Rails 4.
|
23
|
-
chain = if Gem::Version.new(::Rails::VERSION::STRING) >= Gem::Version.new(
|
23
|
+
chain = if Gem::Version.new(::Rails::VERSION::STRING) >= Gem::Version.new('4.1.0')
|
24
24
|
SorceryController._process_action_callbacks.send :chain
|
25
25
|
else
|
26
26
|
SorceryController._process_action_callbacks
|
27
27
|
end
|
28
28
|
|
29
|
-
chain.delete_if {|c| SUBMODULES_AUTO_ADDED_CONTROLLER_FILTERS.include?(c.filter) }
|
29
|
+
chain.delete_if { |c| SUBMODULES_AUTO_ADDED_CONTROLLER_FILTERS.include?(c.filter) }
|
30
30
|
|
31
31
|
# configure
|
32
32
|
::Sorcery::Controller::Config.submodules = submodules
|
33
33
|
::Sorcery::Controller::Config.user_class = nil
|
34
|
-
ActionController::Base.send(:include
|
35
|
-
::Sorcery::Controller::Config.user_class =
|
34
|
+
ActionController::Base.send(:include, ::Sorcery::Controller)
|
35
|
+
::Sorcery::Controller::Config.user_class = 'User'
|
36
36
|
|
37
37
|
::Sorcery::Controller::Config.user_config do |user|
|
38
|
-
options.each do |property,value|
|
38
|
+
options.each do |property, value|
|
39
39
|
user.send(:"#{property}=", value)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
User.authenticates_with_sorcery!
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
43
|
+
return unless defined?(DataMapper) && User.ancestors.include?(DataMapper::Resource)
|
44
|
+
|
45
|
+
DataMapper.auto_migrate!
|
46
|
+
User.finalize
|
47
|
+
Authentication.finalize
|
48
48
|
end
|
49
49
|
|
50
50
|
def sorcery_controller_property_set(property, value)
|
@@ -60,7 +60,15 @@ module Sorcery
|
|
60
60
|
# all this without calling the :logout action explicitly.
|
61
61
|
# A dirty dirty hack.
|
62
62
|
def clear_user_without_logout
|
63
|
-
subject.instance_variable_set(:@current_user,nil)
|
63
|
+
subject.instance_variable_set(:@current_user, nil)
|
64
|
+
end
|
65
|
+
|
66
|
+
if ::Rails.version < '5.0.0'
|
67
|
+
%w[get post put].each do |method|
|
68
|
+
define_method(method) do |action, options = {}|
|
69
|
+
super action, options[:params] || {}, options[:session]
|
70
|
+
end
|
71
|
+
end
|
64
72
|
end
|
65
73
|
end
|
66
74
|
end
|
@@ -3,7 +3,7 @@ module Sorcery
|
|
3
3
|
# Internal TestHelpers are used to test the gem, internally, and should not be used to test apps *using* sorcery.
|
4
4
|
# This file will be included in the spec_helper file.
|
5
5
|
module Internal
|
6
|
-
def self.included(
|
6
|
+
def self.included(_base)
|
7
7
|
# reducing default cost for specs speed
|
8
8
|
CryptoProviders::BCrypt.class_eval do
|
9
9
|
class << self
|
@@ -17,38 +17,38 @@ module Sorcery
|
|
17
17
|
# a patch to fix a bug in testing that happens when you 'destroy' a session twice.
|
18
18
|
# After the first destroy, the session is an ordinary hash, and then when destroy
|
19
19
|
# is called again there's an exception.
|
20
|
-
class ::Hash
|
20
|
+
class ::Hash # rubocop:disable Style/ClassAndModuleChildren
|
21
21
|
def destroy
|
22
22
|
clear
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
26
|
def build_new_user(attributes_hash = nil)
|
27
|
-
user_attributes_hash = attributes_hash || {:
|
27
|
+
user_attributes_hash = attributes_hash || { username: 'gizmo', email: 'bla@bla.com', password: 'secret' }
|
28
28
|
@user = User.new(user_attributes_hash)
|
29
29
|
end
|
30
30
|
|
31
31
|
def create_new_user(attributes_hash = nil)
|
32
32
|
@user = build_new_user(attributes_hash)
|
33
|
-
@user.sorcery_adapter.save(:
|
33
|
+
@user.sorcery_adapter.save(raise_on_failure: true)
|
34
34
|
@user
|
35
35
|
end
|
36
36
|
|
37
37
|
def create_new_external_user(provider, attributes_hash = nil)
|
38
|
-
user_attributes_hash = attributes_hash || {:
|
38
|
+
user_attributes_hash = attributes_hash || { username: 'gizmo' }
|
39
39
|
@user = User.new(user_attributes_hash)
|
40
|
-
@user.sorcery_adapter.save(:
|
41
|
-
@user.authentications.create!(
|
40
|
+
@user.sorcery_adapter.save(raise_on_failure: true)
|
41
|
+
@user.authentications.create!(provider: provider, uid: 123)
|
42
42
|
@user
|
43
43
|
end
|
44
44
|
|
45
45
|
def custom_create_new_external_user(provider, authentication_class, attributes_hash = nil)
|
46
46
|
authentication_association = authentication_class.name.underscore.pluralize
|
47
47
|
|
48
|
-
user_attributes_hash = attributes_hash || {:
|
48
|
+
user_attributes_hash = attributes_hash || { username: 'gizmo' }
|
49
49
|
@user = User.new(user_attributes_hash)
|
50
|
-
@user.sorcery_adapter.save(:
|
51
|
-
@user.send(authentication_association).create!(
|
50
|
+
@user.sorcery_adapter.save(raise_on_failure: true)
|
51
|
+
@user.send(authentication_association).create!(provider: provider, uid: 123)
|
52
52
|
@user
|
53
53
|
end
|
54
54
|
|
@@ -67,11 +67,12 @@ module Sorcery
|
|
67
67
|
# reload user class between specs
|
68
68
|
# so it will be possible to test the different submodules in isolation
|
69
69
|
def reload_user_class
|
70
|
-
Object.send(:remove_const,
|
70
|
+
User && Object.send(:remove_const, 'User')
|
71
71
|
load 'user.rb'
|
72
|
-
|
73
|
-
|
74
|
-
|
72
|
+
|
73
|
+
return unless User.respond_to?(:reset_column_information)
|
74
|
+
|
75
|
+
User.reset_column_information
|
75
76
|
end
|
76
77
|
end
|
77
78
|
end
|
@@ -2,7 +2,7 @@ module Sorcery
|
|
2
2
|
module TestHelpers
|
3
3
|
module Rails
|
4
4
|
module Controller
|
5
|
-
def login_user(user = nil,
|
5
|
+
def login_user(user = nil, _test_context = {})
|
6
6
|
user ||= @user
|
7
7
|
@controller.send(:auto_login, user)
|
8
8
|
@controller.send(:after_login!, user, [user.send(user.sorcery_config.username_attribute_names.first), 'secret'])
|
@@ -2,20 +2,19 @@ module Sorcery
|
|
2
2
|
module TestHelpers
|
3
3
|
module Rails
|
4
4
|
module Integration
|
5
|
-
|
6
|
-
#
|
7
|
-
#Defaults - @user, 'sessions_url' and POST
|
5
|
+
# Accepts arguments for user to login, route to use and HTTP method
|
6
|
+
# Defaults - @user, 'sessions_url' and POST
|
8
7
|
def login_user(user = nil, route = nil, http_method = :post)
|
9
8
|
user ||= @user
|
10
9
|
route ||= sessions_url
|
11
10
|
|
12
11
|
username_attr = user.sorcery_config.username_attribute_names.first
|
13
12
|
username = user.send(username_attr)
|
14
|
-
page.driver.send(http_method, route,
|
13
|
+
page.driver.send(http_method, route, :"#{username_attr}" => username, :password => 'secret')
|
15
14
|
end
|
16
15
|
|
17
|
-
#Accepts route and HTTP method arguments
|
18
|
-
#Default - 'logout_url' and GET
|
16
|
+
# Accepts route and HTTP method arguments
|
17
|
+
# Default - 'logout_url' and GET
|
19
18
|
def logout_user(route = nil, http_method = :get)
|
20
19
|
route ||= logout_url
|
21
20
|
page.driver.send(http_method, route)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Sorcery
|
2
|
+
module TestHelpers
|
3
|
+
module Rails
|
4
|
+
module Request
|
5
|
+
# Accepts arguments for user to login, the password, route to use and HTTP method
|
6
|
+
# Defaults - @user, 'secret', 'user_sessions_url' and http_method: POST
|
7
|
+
def login_user(user = nil, password = 'secret', route = nil, http_method = :post)
|
8
|
+
user ||= @user
|
9
|
+
route ||= user_sessions_url
|
10
|
+
|
11
|
+
username_attr = user.sorcery_config.username_attribute_names.first
|
12
|
+
username = user.send(username_attr)
|
13
|
+
password_attr = user.sorcery_config.password_attribute_name
|
14
|
+
|
15
|
+
send(http_method, route, params: { "#{username_attr}": username, "#{password_attr}": password })
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/sorcery/version.rb
CHANGED
data/lib/sorcery.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'sorcery/version'
|
2
2
|
|
3
3
|
module Sorcery
|
4
|
-
|
5
4
|
require 'sorcery/model'
|
6
5
|
|
7
6
|
module Adapters
|
@@ -12,7 +11,6 @@ module Sorcery
|
|
12
11
|
require 'sorcery/model/temporary_token'
|
13
12
|
require 'sorcery/model/config'
|
14
13
|
|
15
|
-
|
16
14
|
module Submodules
|
17
15
|
require 'sorcery/model/submodules/user_activation'
|
18
16
|
require 'sorcery/model/submodules/reset_password'
|
@@ -20,6 +18,7 @@ module Sorcery
|
|
20
18
|
require 'sorcery/model/submodules/activity_logging'
|
21
19
|
require 'sorcery/model/submodules/brute_force_protection'
|
22
20
|
require 'sorcery/model/submodules/external'
|
21
|
+
require 'sorcery/model/submodules/magic_login'
|
23
22
|
end
|
24
23
|
end
|
25
24
|
|
@@ -58,17 +57,17 @@ module Sorcery
|
|
58
57
|
module Rails
|
59
58
|
require 'sorcery/test_helpers/rails/controller'
|
60
59
|
require 'sorcery/test_helpers/rails/integration'
|
60
|
+
require 'sorcery/test_helpers/rails/request'
|
61
61
|
end
|
62
62
|
|
63
63
|
module Internal
|
64
64
|
require 'sorcery/test_helpers/internal/rails'
|
65
65
|
end
|
66
|
-
|
67
66
|
end
|
68
67
|
|
69
68
|
require 'sorcery/adapters/base_adapter'
|
70
69
|
|
71
|
-
if defined?(ActiveRecord)
|
70
|
+
if defined?(ActiveRecord::Base)
|
72
71
|
require 'sorcery/adapters/active_record_adapter'
|
73
72
|
ActiveRecord::Base.extend Sorcery::Model
|
74
73
|
|
@@ -81,7 +80,7 @@ module Sorcery
|
|
81
80
|
end
|
82
81
|
end
|
83
82
|
|
84
|
-
if defined?(Mongoid)
|
83
|
+
if defined?(Mongoid::Document)
|
85
84
|
require 'sorcery/adapters/mongoid_adapter'
|
86
85
|
Mongoid::Document::ClassMethods.send :include, Sorcery::Model
|
87
86
|
|
@@ -94,17 +93,5 @@ module Sorcery
|
|
94
93
|
end
|
95
94
|
end
|
96
95
|
|
97
|
-
if defined?(MongoMapper)
|
98
|
-
require 'sorcery/adapters/mongo_mapper_adapter'
|
99
|
-
MongoMapper::Document.send(:plugin, Sorcery::Adapters::MongoMapperAdapter::Wrapper)
|
100
|
-
end
|
101
|
-
|
102
|
-
if defined?(DataMapper)
|
103
|
-
require 'sorcery/adapters/data_mapper_adapter'
|
104
|
-
DataMapper::Model.append_extensions(Sorcery::Model)
|
105
|
-
|
106
|
-
DataMapper::Model.append_inclusions(Sorcery::Adapters::DataMapperAdapter::Wrapper)
|
107
|
-
end
|
108
|
-
|
109
96
|
require 'sorcery/engine' if defined?(Rails)
|
110
97
|
end
|
data/sorcery.gemspec
CHANGED
@@ -1,34 +1,49 @@
|
|
1
|
-
lib = File.expand_path('
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
3
|
require 'sorcery/version'
|
4
4
|
|
5
|
+
# rubocop:disable Metrics/BlockLength
|
5
6
|
Gem::Specification.new do |s|
|
6
|
-
s.name =
|
7
|
+
s.name = 'sorcery'
|
7
8
|
s.version = Sorcery::VERSION
|
8
|
-
s.authors = [
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
s.
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
s.
|
22
|
-
s.
|
23
|
-
s.
|
24
|
-
|
25
|
-
s.
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
s.
|
30
|
-
|
31
|
-
s.
|
32
|
-
|
9
|
+
s.authors = [
|
10
|
+
'Noam Ben Ari',
|
11
|
+
'Kir Shatrov',
|
12
|
+
'Grzegorz Witek',
|
13
|
+
'Chase Gilliam',
|
14
|
+
'Josh Buker'
|
15
|
+
]
|
16
|
+
s.email = [
|
17
|
+
'crypto@joshbuker.com'
|
18
|
+
]
|
19
|
+
|
20
|
+
# TODO: Cleanup formatting.
|
21
|
+
# rubocop:disable Layout/LineLength
|
22
|
+
s.description = 'Provides common authentication needs such as signing in/out, activating by email and resetting password.'
|
23
|
+
s.summary = 'Magical authentication for Rails applications'
|
24
|
+
s.homepage = 'https://github.com/Sorcery/sorcery'
|
25
|
+
s.post_install_message = "As of version 1.0 oauth/oauth2 won't be automatically bundled so you may need to add those dependencies to your Gemfile.\n"
|
26
|
+
s.post_install_message += 'You may need oauth2 if you use external providers such as any of these: https://github.com/Sorcery/sorcery/tree/master/lib/sorcery/providers'
|
27
|
+
# rubocop:enable Layout/LineLength
|
28
|
+
|
29
|
+
s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
30
|
+
s.require_paths = ['lib']
|
31
|
+
|
32
|
+
s.licenses = ['MIT']
|
33
|
+
|
34
|
+
s.required_ruby_version = '>= 2.4.9'
|
35
|
+
|
36
|
+
s.add_dependency 'bcrypt', '~> 3.1'
|
37
|
+
s.add_dependency 'oauth', '~> 0.5', '>= 0.5.5'
|
38
|
+
s.add_dependency 'oauth2', '~> 1.0', '>= 0.8.0'
|
39
|
+
|
40
|
+
s.add_development_dependency 'byebug', '~> 10.0.0'
|
41
|
+
s.add_development_dependency 'rspec-rails', '~> 3.7.0'
|
42
|
+
s.add_development_dependency 'rubocop'
|
43
|
+
s.add_development_dependency 'simplecov', '>= 0.3.8'
|
44
|
+
s.add_development_dependency 'test-unit', '~> 3.2.0'
|
45
|
+
s.add_development_dependency 'timecop'
|
46
|
+
s.add_development_dependency 'webmock', '~> 3.3.0'
|
47
|
+
s.add_development_dependency 'yard', '~> 0.9.0', '>= 0.9.12'
|
33
48
|
end
|
34
|
-
|
49
|
+
# rubocop:enable Metrics/BlockLength
|
@@ -3,16 +3,15 @@ require 'spec_helper'
|
|
3
3
|
require 'rails_app/app/mailers/sorcery_mailer'
|
4
4
|
require 'shared_examples/user_activation_shared_examples'
|
5
5
|
|
6
|
-
describe User,
|
6
|
+
describe User, 'with activation submodule', active_record: true do
|
7
7
|
before(:all) do
|
8
|
-
|
8
|
+
MigrationHelper.migrate("#{Rails.root}/db/migrate/activation")
|
9
9
|
User.reset_column_information
|
10
10
|
end
|
11
11
|
|
12
12
|
after(:all) do
|
13
|
-
|
13
|
+
MigrationHelper.rollback("#{Rails.root}/db/migrate/activation")
|
14
14
|
end
|
15
15
|
|
16
|
-
it_behaves_like
|
17
|
-
|
16
|
+
it_behaves_like 'rails_3_activation_model'
|
18
17
|
end
|
@@ -1,17 +1,15 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'shared_examples/user_activity_logging_shared_examples'
|
3
3
|
|
4
|
-
describe User,
|
5
|
-
|
4
|
+
describe User, 'with activity logging submodule', active_record: true do
|
6
5
|
before(:all) do
|
7
|
-
|
6
|
+
MigrationHelper.migrate("#{Rails.root}/db/migrate/activity_logging")
|
8
7
|
User.reset_column_information
|
9
8
|
end
|
10
9
|
|
11
10
|
after(:all) do
|
12
|
-
|
11
|
+
MigrationHelper.rollback("#{Rails.root}/db/migrate/activity_logging")
|
13
12
|
end
|
14
13
|
|
15
|
-
it_behaves_like
|
16
|
-
|
14
|
+
it_behaves_like 'rails_3_activity_logging_model'
|
17
15
|
end
|
@@ -1,16 +1,15 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'shared_examples/user_brute_force_protection_shared_examples'
|
3
3
|
|
4
|
-
describe User,
|
4
|
+
describe User, 'with brute_force_protection submodule', active_record: true do
|
5
5
|
before(:all) do
|
6
|
-
|
6
|
+
MigrationHelper.migrate("#{Rails.root}/db/migrate/brute_force_protection")
|
7
7
|
User.reset_column_information
|
8
8
|
end
|
9
9
|
|
10
10
|
after(:all) do
|
11
|
-
|
11
|
+
MigrationHelper.rollback("#{Rails.root}/db/migrate/brute_force_protection")
|
12
12
|
end
|
13
13
|
|
14
|
-
it_behaves_like
|
15
|
-
|
16
|
-
end
|
14
|
+
it_behaves_like 'rails_3_brute_force_protection_model'
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'shared_examples/user_magic_login_shared_examples'
|
3
|
+
|
4
|
+
describe User, 'with magic_login submodule', active_record: true do
|
5
|
+
before(:all) do
|
6
|
+
MigrationHelper.migrate("#{Rails.root}/db/migrate/magic_login")
|
7
|
+
User.reset_column_information
|
8
|
+
end
|
9
|
+
|
10
|
+
after(:all) do
|
11
|
+
MigrationHelper.rollback("#{Rails.root}/db/migrate/magic_login")
|
12
|
+
end
|
13
|
+
|
14
|
+
it_behaves_like 'magic_login_model'
|
15
|
+
end
|
@@ -1,16 +1,15 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'shared_examples/user_oauth_shared_examples'
|
3
3
|
|
4
|
-
describe User,
|
4
|
+
describe User, 'with oauth submodule', active_record: true do
|
5
5
|
before(:all) do
|
6
|
-
|
6
|
+
MigrationHelper.migrate("#{Rails.root}/db/migrate/external")
|
7
7
|
User.reset_column_information
|
8
8
|
end
|
9
9
|
|
10
10
|
after(:all) do
|
11
|
-
|
11
|
+
MigrationHelper.rollback("#{Rails.root}/db/migrate/external")
|
12
12
|
end
|
13
13
|
|
14
|
-
it_behaves_like
|
15
|
-
|
16
|
-
end
|
14
|
+
it_behaves_like 'rails_3_oauth_model'
|
15
|
+
end
|
@@ -1,16 +1,15 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'shared_examples/user_remember_me_shared_examples'
|
3
3
|
|
4
|
-
describe User,
|
4
|
+
describe User, 'with remember_me submodule', active_record: true do
|
5
5
|
before(:all) do
|
6
|
-
|
6
|
+
MigrationHelper.migrate("#{Rails.root}/db/migrate/remember_me")
|
7
7
|
User.reset_column_information
|
8
8
|
end
|
9
9
|
|
10
10
|
after(:all) do
|
11
|
-
|
11
|
+
MigrationHelper.rollback("#{Rails.root}/db/migrate/remember_me")
|
12
12
|
end
|
13
13
|
|
14
|
-
it_behaves_like
|
15
|
-
|
16
|
-
end
|
14
|
+
it_behaves_like 'rails_3_remember_me_model'
|
15
|
+
end
|
@@ -1,16 +1,15 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'shared_examples/user_reset_password_shared_examples'
|
3
3
|
|
4
|
-
describe User,
|
4
|
+
describe User, 'with reset_password submodule', active_record: true do
|
5
5
|
before(:all) do
|
6
|
-
|
6
|
+
MigrationHelper.migrate("#{Rails.root}/db/migrate/reset_password")
|
7
7
|
User.reset_column_information
|
8
8
|
end
|
9
9
|
|
10
10
|
after(:all) do
|
11
|
-
|
11
|
+
MigrationHelper.rollback("#{Rails.root}/db/migrate/reset_password")
|
12
12
|
end
|
13
13
|
|
14
|
-
it_behaves_like
|
15
|
-
|
14
|
+
it_behaves_like 'rails_3_reset_password_model'
|
16
15
|
end
|