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
@@ -1,13 +1,11 @@
|
|
1
|
-
class SorceryCore <
|
1
|
+
class SorceryCore < <%= migration_class_name %>
|
2
2
|
def change
|
3
|
-
create_table :<%=
|
4
|
-
t.string :email, :
|
3
|
+
create_table :<%= tableized_model_class %> do |t|
|
4
|
+
t.string :email, null: false, index: { unique: true }
|
5
5
|
t.string :crypted_password
|
6
6
|
t.string :salt
|
7
7
|
|
8
|
-
t.timestamps
|
8
|
+
t.timestamps null: false
|
9
9
|
end
|
10
|
-
|
11
|
-
add_index :<%= model_class_name.tableize %>, :email, unique: true
|
12
10
|
end
|
13
|
-
end
|
11
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
|
-
class SorceryExternal <
|
1
|
+
class SorceryExternal < <%= migration_class_name %>
|
2
2
|
def change
|
3
3
|
create_table :authentications do |t|
|
4
|
-
t.integer :<%=
|
5
|
-
t.string :provider, :uid, :
|
4
|
+
t.integer :<%= tableized_model_class.singularize %>_id, null: false
|
5
|
+
t.string :provider, :uid, null: false
|
6
6
|
|
7
|
-
t.timestamps
|
7
|
+
t.timestamps null: false
|
8
8
|
end
|
9
9
|
|
10
10
|
add_index :authentications, [:provider, :uid]
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class SorceryMagicLogin < <%= migration_class_name %>
|
2
|
+
def change
|
3
|
+
add_column :<%= tableized_model_class %>, :magic_login_token, :string, default: nil
|
4
|
+
add_column :<%= tableized_model_class %>, :magic_login_token_expires_at, :datetime, default: nil
|
5
|
+
add_column :<%= tableized_model_class %>, :magic_login_email_sent_at, :datetime, default: nil
|
6
|
+
|
7
|
+
add_index :<%= tableized_model_class %>, :magic_login_token
|
8
|
+
end
|
9
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
|
-
class SorceryRememberMe <
|
1
|
+
class SorceryRememberMe < <%= migration_class_name %>
|
2
2
|
def change
|
3
|
-
add_column :<%=
|
4
|
-
add_column :<%=
|
3
|
+
add_column :<%= tableized_model_class %>, :remember_me_token, :string, default: nil
|
4
|
+
add_column :<%= tableized_model_class %>, :remember_me_token_expires_at, :datetime, default: nil
|
5
5
|
|
6
|
-
add_index :<%=
|
6
|
+
add_index :<%= tableized_model_class %>, :remember_me_token
|
7
7
|
end
|
8
|
-
end
|
8
|
+
end
|
@@ -1,9 +1,10 @@
|
|
1
|
-
class SorceryResetPassword <
|
1
|
+
class SorceryResetPassword < <%= migration_class_name %>
|
2
2
|
def change
|
3
|
-
add_column :<%=
|
4
|
-
add_column :<%=
|
5
|
-
add_column :<%=
|
3
|
+
add_column :<%= tableized_model_class %>, :reset_password_token, :string, default: nil
|
4
|
+
add_column :<%= tableized_model_class %>, :reset_password_token_expires_at, :datetime, default: nil
|
5
|
+
add_column :<%= tableized_model_class %>, :reset_password_email_sent_at, :datetime, default: nil
|
6
|
+
add_column :<%= tableized_model_class %>, :access_count_to_reset_password_page, :integer, default: 0
|
6
7
|
|
7
|
-
add_index :<%=
|
8
|
+
add_index :<%= tableized_model_class %>, :reset_password_token
|
8
9
|
end
|
9
|
-
end
|
10
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
|
-
class SorceryUserActivation <
|
1
|
+
class SorceryUserActivation < <%= migration_class_name %>
|
2
2
|
def change
|
3
|
-
add_column :<%=
|
4
|
-
add_column :<%=
|
5
|
-
add_column :<%=
|
3
|
+
add_column :<%= tableized_model_class %>, :activation_state, :string, default: nil
|
4
|
+
add_column :<%= tableized_model_class %>, :activation_token, :string, default: nil
|
5
|
+
add_column :<%= tableized_model_class %>, :activation_token_expires_at, :datetime, default: nil
|
6
6
|
|
7
|
-
add_index :<%=
|
7
|
+
add_index :<%= tableized_model_class %>, :activation_token
|
8
8
|
end
|
9
|
-
end
|
9
|
+
end
|
@@ -6,12 +6,13 @@ module Sorcery
|
|
6
6
|
@model.send(:"#{name}=", value)
|
7
7
|
end
|
8
8
|
primary_key = @model.class.primary_key
|
9
|
-
@model.class.where(:"#{primary_key}" => @model.send(:"#{primary_key}")).update_all(attrs)
|
9
|
+
updated_count = @model.class.where(:"#{primary_key}" => @model.send(:"#{primary_key}")).update_all(attrs)
|
10
|
+
updated_count == 1
|
10
11
|
end
|
11
12
|
|
12
13
|
def save(options = {})
|
13
14
|
mthd = options.delete(:raise_on_failure) ? :save! : :save
|
14
|
-
@model.send(mthd, options)
|
15
|
+
@model.send(mthd, **options)
|
15
16
|
end
|
16
17
|
|
17
18
|
def increment(field)
|
@@ -29,12 +30,12 @@ module Sorcery
|
|
29
30
|
end
|
30
31
|
|
31
32
|
class << self
|
32
|
-
def define_field(name, type, options={})
|
33
|
+
def define_field(name, type, options = {})
|
33
34
|
# AR fields are defined through migrations, only validator here
|
34
35
|
end
|
35
36
|
|
36
|
-
def define_callback(time, event, method_name, options={})
|
37
|
-
@klass.send "#{time}_#{event}", method_name, options.slice(:if)
|
37
|
+
def define_callback(time, event, method_name, options = {})
|
38
|
+
@klass.send "#{time}_#{event}", method_name, **options.slice(:if, :on)
|
38
39
|
end
|
39
40
|
|
40
41
|
def find_by_oauth_credentials(provider, uid)
|
@@ -61,11 +62,11 @@ module Sorcery
|
|
61
62
|
condition = @klass.arel_table[attribute].eq(credentials[0])
|
62
63
|
end
|
63
64
|
|
64
|
-
if relation.nil?
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
65
|
+
relation = if relation.nil?
|
66
|
+
condition
|
67
|
+
else
|
68
|
+
relation.or(condition)
|
69
|
+
end
|
69
70
|
end
|
70
71
|
|
71
72
|
@klass.where(relation).first
|
@@ -100,21 +101,10 @@ module Sorcery
|
|
100
101
|
@klass.where(@klass.sorcery_config.email_attribute_name => email).first
|
101
102
|
end
|
102
103
|
|
103
|
-
def get_current_users
|
104
|
-
config = @klass.sorcery_config
|
105
|
-
|
106
|
-
@klass
|
107
|
-
.where("#{config.last_activity_at_attribute_name} IS NOT NULL") \
|
108
|
-
.where("#{config.last_logout_at_attribute_name} IS NULL OR #{config.last_activity_at_attribute_name} > #{config.last_logout_at_attribute_name}") \
|
109
|
-
.where("#{config.last_activity_at_attribute_name} > ? ", config.activity_timeout.seconds.ago.utc.to_s(:db))
|
110
|
-
end
|
111
|
-
|
112
104
|
def transaction(&blk)
|
113
105
|
@klass.tap(&blk)
|
114
106
|
end
|
115
107
|
end
|
116
108
|
end
|
117
|
-
|
118
|
-
|
119
109
|
end
|
120
110
|
end
|
@@ -10,7 +10,7 @@ module Sorcery
|
|
10
10
|
attrs[name] = value.utc if value.is_a?(ActiveSupport::TimeWithZone)
|
11
11
|
@model.send(:"#{name}=", value)
|
12
12
|
end
|
13
|
-
@model.class.where(:
|
13
|
+
@model.class.where(_id: @model.id).update_all(attrs)
|
14
14
|
end
|
15
15
|
|
16
16
|
def update_attribute(name, value)
|
@@ -23,21 +23,29 @@ module Sorcery
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def mongoid_4?
|
26
|
-
Gem::Version.new(::Mongoid::VERSION) >= Gem::Version.new(
|
26
|
+
Gem::Version.new(::Mongoid::VERSION) >= Gem::Version.new('4.0.0.alpha')
|
27
27
|
end
|
28
28
|
|
29
29
|
class << self
|
30
|
-
|
31
|
-
def define_field(name, type, options={})
|
30
|
+
def define_field(name, type, options = {})
|
32
31
|
@klass.field name, options.slice(:default).merge(type: type)
|
33
32
|
end
|
34
33
|
|
35
|
-
def define_callback(time, event, method_name, options={})
|
36
|
-
@klass.send
|
34
|
+
def define_callback(time, event, method_name, options = {})
|
35
|
+
@klass.send callback_name(time, event, options), method_name, **options.slice(:if)
|
36
|
+
end
|
37
|
+
|
38
|
+
def callback_name(time, event, options)
|
39
|
+
if event == :commit
|
40
|
+
options[:on] == :create ? "#{time}_create" : "#{time}_save"
|
41
|
+
else
|
42
|
+
"#{time}_#{event}"
|
43
|
+
end
|
37
44
|
end
|
38
45
|
|
39
46
|
def credential_regex(credential)
|
40
|
-
return { :$regex =>
|
47
|
+
return { :$regex => /^#{Regexp.escape(credential)}$/i } if @klass.sorcery_config.downcase_username_before_authenticating
|
48
|
+
|
41
49
|
credential
|
42
50
|
end
|
43
51
|
|
@@ -73,7 +81,7 @@ module Sorcery
|
|
73
81
|
end
|
74
82
|
|
75
83
|
def find_by_username(username)
|
76
|
-
query = @klass.sorcery_config.username_attribute_names.map {|name| {name => username}}
|
84
|
+
query = @klass.sorcery_config.username_attribute_names.map { |name| { name => username } }
|
77
85
|
@klass.any_of(*query).first
|
78
86
|
end
|
79
87
|
|
@@ -87,9 +95,13 @@ module Sorcery
|
|
87
95
|
|
88
96
|
def get_current_users
|
89
97
|
config = @klass.sorcery_config
|
90
|
-
@klass.where(
|
91
|
-
|
92
|
-
.where(
|
98
|
+
@klass.where(
|
99
|
+
config.last_activity_at_attribute_name.ne => nil
|
100
|
+
).where(
|
101
|
+
"this.#{config.last_logout_at_attribute_name} == null || this.#{config.last_activity_at_attribute_name} > this.#{config.last_logout_at_attribute_name}"
|
102
|
+
).where(
|
103
|
+
config.last_activity_at_attribute_name.gt => config.activity_timeout.seconds.ago.utc
|
104
|
+
).order_by(%i[_id asc])
|
93
105
|
end
|
94
106
|
end
|
95
107
|
end
|
@@ -2,32 +2,35 @@ module Sorcery
|
|
2
2
|
module Controller
|
3
3
|
module Config
|
4
4
|
class << self
|
5
|
-
attr_accessor :submodules
|
6
|
-
|
7
|
-
|
5
|
+
attr_accessor :submodules
|
6
|
+
# what class to use as the user class.
|
7
|
+
attr_accessor :user_class
|
8
|
+
# what controller action to call for non-authenticated users.
|
9
|
+
attr_accessor :not_authenticated_action
|
10
|
+
# when a non logged in user tries to enter a page that requires login,
|
11
|
+
# save the URL he wanted to reach, and send him there after login.
|
12
|
+
attr_accessor :save_return_to_url
|
13
|
+
# set domain option for cookies
|
14
|
+
attr_accessor :cookie_domain
|
8
15
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
:login_sources,
|
16
|
-
:after_login,
|
17
|
-
:after_failed_login,
|
18
|
-
:before_logout,
|
19
|
-
:after_logout
|
16
|
+
attr_accessor :login_sources
|
17
|
+
attr_accessor :after_login
|
18
|
+
attr_accessor :after_failed_login
|
19
|
+
attr_accessor :before_logout
|
20
|
+
attr_accessor :after_logout
|
21
|
+
attr_accessor :after_remember_me
|
20
22
|
|
21
23
|
def init!
|
22
24
|
@defaults = {
|
23
25
|
:@user_class => nil,
|
24
26
|
:@submodules => [],
|
25
27
|
:@not_authenticated_action => :not_authenticated,
|
26
|
-
:@login_sources =>
|
27
|
-
:@after_login =>
|
28
|
-
:@after_failed_login =>
|
29
|
-
:@before_logout =>
|
30
|
-
:@after_logout =>
|
28
|
+
:@login_sources => Set.new,
|
29
|
+
:@after_login => Set.new,
|
30
|
+
:@after_failed_login => Set.new,
|
31
|
+
:@before_logout => Set.new,
|
32
|
+
:@after_logout => Set.new,
|
33
|
+
:@after_remember_me => Set.new,
|
31
34
|
:@save_return_to_url => true,
|
32
35
|
:@cookie_domain => nil
|
33
36
|
}
|
@@ -35,14 +38,14 @@ module Sorcery
|
|
35
38
|
|
36
39
|
# Resets all configuration options to their default values.
|
37
40
|
def reset!
|
38
|
-
@defaults.each do |k,v|
|
39
|
-
instance_variable_set(k,v)
|
41
|
+
@defaults.each do |k, v|
|
42
|
+
instance_variable_set(k, v)
|
40
43
|
end
|
41
44
|
end
|
42
45
|
|
43
46
|
def update!
|
44
|
-
@defaults.each do |k,v|
|
45
|
-
instance_variable_set(k,v)
|
47
|
+
@defaults.each do |k, v|
|
48
|
+
instance_variable_set(k, v) unless instance_variable_defined?(k)
|
46
49
|
end
|
47
50
|
end
|
48
51
|
|
@@ -58,6 +61,7 @@ module Sorcery
|
|
58
61
|
@configure_blk.call(self) if @configure_blk
|
59
62
|
end
|
60
63
|
end
|
64
|
+
|
61
65
|
init!
|
62
66
|
reset!
|
63
67
|
end
|
@@ -25,40 +25,36 @@ module Sorcery
|
|
25
25
|
@defaults.merge!(:@register_login_time => true,
|
26
26
|
:@register_logout_time => true,
|
27
27
|
:@register_last_activity_time => true,
|
28
|
-
:@register_last_ip_address => true
|
29
|
-
)
|
28
|
+
:@register_last_ip_address => true)
|
30
29
|
end
|
31
30
|
end
|
32
31
|
merge_activity_logging_defaults!
|
33
32
|
end
|
34
|
-
Config.after_login << :register_login_time_to_db
|
35
|
-
Config.after_login << :register_last_ip_address
|
36
|
-
Config.before_logout << :register_logout_time_to_db
|
37
|
-
base.after_filter :register_last_activity_time_to_db
|
38
|
-
end
|
39
33
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
ActiveSupport::Deprecation.warn("Sorcery: `current_users` method is deprecated. Read more on Github: https://github.com/NoamB/sorcery/issues/602")
|
34
|
+
Config.after_login << :register_login_time_to_db
|
35
|
+
Config.after_login << :register_last_ip_address
|
36
|
+
Config.before_logout << :register_logout_time_to_db
|
44
37
|
|
45
|
-
|
46
|
-
|
38
|
+
base.after_action :register_last_activity_time_to_db
|
39
|
+
end
|
47
40
|
|
41
|
+
module InstanceMethods
|
48
42
|
protected
|
49
43
|
|
50
44
|
# registers last login time on every login.
|
51
45
|
# This runs as a hook just after a successful login.
|
52
|
-
def register_login_time_to_db(user,
|
46
|
+
def register_login_time_to_db(user, _credentials)
|
53
47
|
return unless Config.register_login_time
|
48
|
+
|
54
49
|
user.set_last_login_at(Time.now.in_time_zone)
|
55
50
|
end
|
56
51
|
|
57
52
|
# registers last logout time on every logout.
|
58
53
|
# This runs as a hook just before a logout.
|
59
|
-
def register_logout_time_to_db
|
54
|
+
def register_logout_time_to_db
|
60
55
|
return unless Config.register_logout_time
|
61
|
-
|
56
|
+
|
57
|
+
current_user.set_last_logout_at(Time.now.in_time_zone)
|
62
58
|
end
|
63
59
|
|
64
60
|
# Updates last activity time on every request.
|
@@ -66,14 +62,16 @@ module Sorcery
|
|
66
62
|
def register_last_activity_time_to_db
|
67
63
|
return unless Config.register_last_activity_time
|
68
64
|
return unless logged_in?
|
65
|
+
|
69
66
|
current_user.set_last_activity_at(Time.now.in_time_zone)
|
70
67
|
end
|
71
68
|
|
72
69
|
# Updates IP address on every login.
|
73
70
|
# This runs as a hook just after a successful login.
|
74
|
-
def register_last_ip_address(
|
71
|
+
def register_last_ip_address(_user, _credentials)
|
75
72
|
return unless Config.register_last_ip_address
|
76
|
-
|
73
|
+
|
74
|
+
current_user.set_last_ip_address(request.remote_ip)
|
77
75
|
end
|
78
76
|
end
|
79
77
|
end
|
@@ -16,7 +16,6 @@ module Sorcery
|
|
16
16
|
end
|
17
17
|
|
18
18
|
module InstanceMethods
|
19
|
-
|
20
19
|
protected
|
21
20
|
|
22
21
|
# Increments the failed logins counter on every failed login.
|
@@ -28,7 +27,7 @@ module Sorcery
|
|
28
27
|
|
29
28
|
# Resets the failed logins counter.
|
30
29
|
# Runs as a hook after a successful login.
|
31
|
-
def reset_failed_logins_count!(user,
|
30
|
+
def reset_failed_logins_count!(user, _credentials)
|
32
31
|
user.sorcery_adapter.update_attribute(user_class.sorcery_config.failed_logins_count_attribute_name, 0)
|
33
32
|
end
|
34
33
|
end
|
@@ -19,6 +19,15 @@ module Sorcery
|
|
19
19
|
require 'sorcery/providers/google'
|
20
20
|
require 'sorcery/providers/jira'
|
21
21
|
require 'sorcery/providers/salesforce'
|
22
|
+
require 'sorcery/providers/paypal'
|
23
|
+
require 'sorcery/providers/slack'
|
24
|
+
require 'sorcery/providers/wechat'
|
25
|
+
require 'sorcery/providers/microsoft'
|
26
|
+
require 'sorcery/providers/instagram'
|
27
|
+
require 'sorcery/providers/auth0'
|
28
|
+
require 'sorcery/providers/line'
|
29
|
+
require 'sorcery/providers/discord'
|
30
|
+
require 'sorcery/providers/battlenet'
|
22
31
|
|
23
32
|
Config.module_eval do
|
24
33
|
class << self
|
@@ -29,17 +38,17 @@ module Sorcery
|
|
29
38
|
@external_providers = providers
|
30
39
|
|
31
40
|
providers.each do |name|
|
32
|
-
class_eval <<-
|
41
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
33
42
|
def self.#{name}
|
34
|
-
@#{name} ||= Sorcery::Providers.const_get('#{name}'.to_s.
|
43
|
+
@#{name} ||= Sorcery::Providers.const_get('#{name}'.to_s.camelcase).new
|
35
44
|
end
|
36
|
-
|
45
|
+
RUBY
|
37
46
|
end
|
38
47
|
end
|
39
48
|
|
40
49
|
def merge_external_defaults!
|
41
50
|
@defaults.merge!(:@external_providers => [],
|
42
|
-
:@ca_file => File.join(
|
51
|
+
:@ca_file => File.join(__dir__, '../../protocols/certs/ca-bundle.crt'))
|
43
52
|
end
|
44
53
|
end
|
45
54
|
merge_external_defaults!
|
@@ -52,6 +61,7 @@ module Sorcery
|
|
52
61
|
# save the singleton ProviderClient instance into @provider
|
53
62
|
def sorcery_get_provider(provider_name)
|
54
63
|
return unless Config.external_providers.include?(provider_name.to_sym)
|
64
|
+
|
55
65
|
Config.send(provider_name.to_sym)
|
56
66
|
end
|
57
67
|
|
@@ -60,12 +70,11 @@ module Sorcery
|
|
60
70
|
def sorcery_login_url(provider_name, args = {})
|
61
71
|
@provider = sorcery_get_provider provider_name
|
62
72
|
sorcery_fixup_callback_url @provider
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
end
|
73
|
+
|
74
|
+
return nil unless @provider.respond_to?(:login_url) && @provider.has_callback?
|
75
|
+
|
76
|
+
@provider.state = args[:state]
|
77
|
+
@provider.login_url(params, session)
|
69
78
|
end
|
70
79
|
|
71
80
|
# get the user hash from a provider using information from the params and session.
|
@@ -84,25 +93,26 @@ module Sorcery
|
|
84
93
|
# cache them in instance variables.
|
85
94
|
@access_token ||= @provider.process_callback(params, session) # sends request to oauth agent to get the token
|
86
95
|
@user_hash ||= @provider.get_user_hash(@access_token) # uses the token to send another request to the oauth agent requesting user info
|
96
|
+
nil
|
87
97
|
end
|
88
98
|
|
89
99
|
# for backwards compatibility
|
90
|
-
def access_token(*
|
100
|
+
def access_token(*_args)
|
91
101
|
@access_token
|
92
102
|
end
|
93
103
|
|
94
|
-
|
95
104
|
# this method should be somewhere else. It only does something once per application per provider.
|
96
105
|
def sorcery_fixup_callback_url(provider)
|
97
106
|
provider.original_callback_url ||= provider.callback_url
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
107
|
+
|
108
|
+
return unless provider.original_callback_url.present? && provider.original_callback_url[0] == '/'
|
109
|
+
|
110
|
+
uri = URI.parse(request.url.gsub(/\?.*$/, ''))
|
111
|
+
uri.path = ''
|
112
|
+
uri.query = nil
|
113
|
+
uri.scheme = 'https' if request.env['HTTP_X_FORWARDED_PROTO'] == 'https'
|
114
|
+
host = uri.to_s
|
115
|
+
provider.callback_url = "#{host}#{@provider.original_callback_url}"
|
106
116
|
end
|
107
117
|
|
108
118
|
# sends user to authenticate at the provider's website.
|
@@ -115,31 +125,31 @@ module Sorcery
|
|
115
125
|
def login_from(provider_name, should_remember = false)
|
116
126
|
sorcery_fetch_user_hash provider_name
|
117
127
|
|
118
|
-
|
119
|
-
# we found the user.
|
120
|
-
# clear the session
|
121
|
-
return_to_url = session[:return_to_url]
|
122
|
-
reset_sorcery_session
|
123
|
-
session[:return_to_url] = return_to_url
|
128
|
+
return unless (user = user_class.load_from_provider(provider_name, @user_hash[:uid].to_s))
|
124
129
|
|
125
|
-
|
126
|
-
|
127
|
-
|
130
|
+
# we found the user.
|
131
|
+
# clear the session
|
132
|
+
return_to_url = session[:return_to_url]
|
133
|
+
reset_sorcery_session
|
134
|
+
session[:return_to_url] = return_to_url
|
128
135
|
|
129
|
-
|
130
|
-
|
131
|
-
|
136
|
+
# sign in the user
|
137
|
+
auto_login(user, should_remember)
|
138
|
+
after_login!(user)
|
139
|
+
|
140
|
+
# return the user
|
141
|
+
user
|
132
142
|
end
|
133
143
|
|
134
144
|
# If user is logged, he can add all available providers into his account
|
135
145
|
def add_provider_to_user(provider_name)
|
136
146
|
sorcery_fetch_user_hash provider_name
|
137
|
-
config = user_class.sorcery_config
|
147
|
+
# config = user_class.sorcery_config # TODO: Unused, remove?
|
138
148
|
|
139
149
|
current_user.add_provider_to_user(provider_name.to_s, @user_hash[:uid].to_s)
|
140
150
|
end
|
141
151
|
|
142
|
-
#
|
152
|
+
# Initialize new user from provider informations.
|
143
153
|
# If a provider doesn't give required informations or username/email is already taken,
|
144
154
|
# we store provider/user infos into a session and can be rendered into registration form
|
145
155
|
def create_and_validate_from(provider_name)
|
@@ -150,12 +160,14 @@ module Sorcery
|
|
150
160
|
|
151
161
|
user, saved = user_class.create_and_validate_from_provider(provider_name, @user_hash[:uid], attrs)
|
152
162
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
163
|
+
unless saved
|
164
|
+
session[:incomplete_user] = {
|
165
|
+
provider: { config.provider_uid_attribute_name => @user_hash[:uid], config.provider_attribute_name => provider_name },
|
166
|
+
user_hash: attrs
|
167
|
+
}
|
168
|
+
end
|
157
169
|
|
158
|
-
|
170
|
+
user
|
159
171
|
end
|
160
172
|
|
161
173
|
# this method automatically creates a new user from the data in the external user hash.
|
@@ -176,23 +188,36 @@ module Sorcery
|
|
176
188
|
#
|
177
189
|
def create_from(provider_name, &block)
|
178
190
|
sorcery_fetch_user_hash provider_name
|
179
|
-
config = user_class.sorcery_config
|
191
|
+
# config = user_class.sorcery_config # TODO: Unused, remove?
|
180
192
|
|
181
193
|
attrs = user_attrs(@provider.user_info_mapping, @user_hash)
|
182
194
|
@user = user_class.create_from_provider(provider_name, @user_hash[:uid], attrs, &block)
|
183
195
|
end
|
184
196
|
|
197
|
+
# follows the same patterns as create_from, but builds the user instead of creating
|
198
|
+
def build_from(provider_name, &block)
|
199
|
+
sorcery_fetch_user_hash provider_name
|
200
|
+
# config = user_class.sorcery_config # TODO: Unused, remove?
|
201
|
+
|
202
|
+
attrs = user_attrs(@provider.user_info_mapping, @user_hash)
|
203
|
+
@user = user_class.build_from_provider(attrs, &block)
|
204
|
+
end
|
205
|
+
|
185
206
|
def user_attrs(user_info_mapping, user_hash)
|
186
207
|
attrs = {}
|
187
|
-
user_info_mapping.each do |k,v|
|
188
|
-
if (varr = v.split(
|
189
|
-
attribute_value =
|
208
|
+
user_info_mapping.each do |k, v|
|
209
|
+
if (varr = v.split('/')).size > 1
|
210
|
+
attribute_value = begin
|
211
|
+
varr.inject(user_hash[:user_info]) { |hash, value| hash[value] }
|
212
|
+
rescue StandardError
|
213
|
+
nil
|
214
|
+
end
|
190
215
|
attribute_value.nil? ? attrs : attrs.merge!(k => attribute_value)
|
191
216
|
else
|
192
217
|
attrs.merge!(k => user_hash[:user_info][v])
|
193
218
|
end
|
194
219
|
end
|
195
|
-
|
220
|
+
attrs
|
196
221
|
end
|
197
222
|
end
|
198
223
|
end
|