sorcery 0.8.5 → 0.9.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.
- checksums.yaml +4 -4
- data/.gitignore +3 -1
- data/.travis.yml +122 -5
- data/CHANGELOG.md +37 -1
- data/Gemfile +10 -18
- data/README.md +159 -88
- data/gemfiles/active_record-rails40.gemfile +7 -0
- data/gemfiles/active_record-rails41.gemfile +7 -0
- data/gemfiles/mongo_mapper-rails40.gemfile +9 -0
- data/gemfiles/mongo_mapper-rails41.gemfile +9 -0
- data/gemfiles/mongoid-rails40.gemfile +9 -0
- data/gemfiles/mongoid-rails41.gemfile +9 -0
- data/gemfiles/mongoid3-rails32.gemfile +9 -0
- data/lib/generators/sorcery/USAGE +1 -1
- data/lib/generators/sorcery/install_generator.rb +19 -5
- data/lib/generators/sorcery/templates/initializer.rb +34 -9
- data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +3 -1
- data/lib/generators/sorcery/templates/migration/core.rb +2 -2
- data/lib/generators/sorcery/templates/migration/external.rb +3 -1
- data/lib/sorcery/adapters/active_record_adapter.rb +120 -0
- data/lib/sorcery/adapters/base_adapter.rb +30 -0
- data/lib/sorcery/adapters/data_mapper_adapter.rb +176 -0
- data/lib/sorcery/adapters/mongo_mapper_adapter.rb +110 -0
- data/lib/sorcery/adapters/mongoid_adapter.rb +97 -0
- data/lib/sorcery/controller/config.rb +65 -0
- data/lib/sorcery/controller/submodules/activity_logging.rb +16 -21
- data/lib/sorcery/controller/submodules/brute_force_protection.rb +6 -6
- data/lib/sorcery/controller/submodules/external.rb +35 -40
- data/lib/sorcery/controller/submodules/remember_me.rb +4 -4
- data/lib/sorcery/controller/submodules/session_timeout.rb +10 -6
- data/lib/sorcery/controller.rb +10 -74
- data/lib/sorcery/model/config.rb +96 -0
- data/lib/sorcery/model/submodules/activity_logging.rb +30 -13
- data/lib/sorcery/model/submodules/brute_force_protection.rb +21 -21
- data/lib/sorcery/model/submodules/external.rb +53 -9
- data/lib/sorcery/model/submodules/remember_me.rb +15 -19
- data/lib/sorcery/model/submodules/reset_password.rb +33 -34
- data/lib/sorcery/model/submodules/user_activation.rb +36 -47
- data/lib/sorcery/model/temporary_token.rb +4 -4
- data/lib/sorcery/model.rb +73 -173
- data/lib/sorcery/protocols/oauth.rb +42 -0
- data/lib/sorcery/protocols/oauth2.rb +47 -0
- data/lib/sorcery/providers/base.rb +38 -0
- data/lib/sorcery/providers/facebook.rb +63 -0
- data/lib/sorcery/providers/github.rb +51 -0
- data/lib/sorcery/providers/google.rb +51 -0
- data/lib/sorcery/providers/heroku.rb +57 -0
- data/lib/sorcery/providers/jira.rb +77 -0
- data/lib/sorcery/providers/linkedin.rb +66 -0
- data/lib/sorcery/providers/liveid.rb +53 -0
- data/lib/sorcery/providers/salesforce.rb +50 -0
- data/lib/sorcery/providers/twitter.rb +59 -0
- data/lib/sorcery/providers/vk.rb +63 -0
- data/lib/sorcery/providers/xing.rb +64 -0
- data/lib/sorcery/test_helpers/internal/rails.rb +14 -3
- data/lib/sorcery/test_helpers/internal.rb +7 -3
- data/lib/sorcery/test_helpers/rails/controller.rb +21 -0
- data/lib/sorcery/test_helpers/rails/integration.rb +26 -0
- data/lib/sorcery/version.rb +3 -0
- data/lib/sorcery.rb +82 -58
- data/sorcery.gemspec +19 -19
- data/spec/active_record/user_activation_spec.rb +1 -1
- data/spec/active_record/user_activity_logging_spec.rb +10 -1
- data/spec/active_record/user_brute_force_protection_spec.rb +1 -1
- data/spec/active_record/user_oauth_spec.rb +1 -1
- data/spec/active_record/user_remember_me_spec.rb +1 -1
- data/spec/active_record/user_reset_password_spec.rb +1 -1
- data/spec/active_record/user_spec.rb +7 -8
- data/spec/controllers/controller_activity_logging_spec.rb +124 -0
- data/spec/controllers/controller_brute_force_protection_spec.rb +43 -0
- data/spec/controllers/controller_http_basic_auth_spec.rb +68 -0
- data/spec/controllers/controller_oauth2_spec.rb +414 -0
- data/spec/controllers/controller_oauth_spec.rb +240 -0
- data/spec/controllers/controller_remember_me_spec.rb +117 -0
- data/spec/controllers/controller_session_timeout_spec.rb +80 -0
- data/spec/controllers/controller_spec.rb +218 -0
- data/spec/data_mapper/user_activation_spec.rb +10 -0
- data/spec/data_mapper/user_activity_logging_spec.rb +14 -0
- data/spec/data_mapper/user_brute_force_protection_spec.rb +9 -0
- data/spec/data_mapper/user_oauth_spec.rb +9 -0
- data/spec/data_mapper/user_remember_me_spec.rb +8 -0
- data/spec/data_mapper/user_reset_password_spec.rb +8 -0
- data/spec/data_mapper/user_spec.rb +27 -0
- data/spec/mongo_mapper/user_activation_spec.rb +1 -2
- data/spec/mongo_mapper/user_activity_logging_spec.rb +1 -1
- data/spec/mongo_mapper/user_brute_force_protection_spec.rb +1 -1
- data/spec/mongo_mapper/user_oauth_spec.rb +1 -1
- data/spec/mongo_mapper/user_remember_me_spec.rb +1 -1
- data/spec/mongo_mapper/user_reset_password_spec.rb +1 -1
- data/spec/mongo_mapper/user_spec.rb +7 -8
- data/spec/mongoid/user_activation_spec.rb +1 -2
- data/spec/mongoid/user_activity_logging_spec.rb +1 -2
- data/spec/mongoid/user_brute_force_protection_spec.rb +1 -2
- data/spec/mongoid/user_oauth_spec.rb +1 -2
- data/spec/mongoid/user_remember_me_spec.rb +1 -2
- data/spec/mongoid/user_reset_password_spec.rb +1 -2
- data/spec/mongoid/user_spec.rb +21 -9
- data/spec/orm/active_record.rb +14 -0
- data/spec/orm/data_mapper.rb +48 -0
- data/spec/orm/mongo_mapper.rb +1 -1
- data/spec/orm/mongoid.rb +5 -0
- data/spec/rails_app/app/controllers/sorcery_controller.rb +125 -59
- data/spec/rails_app/app/data_mapper/authentication.rb +8 -0
- data/spec/rails_app/app/data_mapper/user.rb +7 -0
- data/spec/rails_app/app/mongo_mapper/user.rb +2 -0
- data/spec/rails_app/config/routes.rb +27 -13
- data/spec/rails_app/db/migrate/core/20101224223620_create_users.rb +2 -2
- data/spec/shared_examples/user_activation_shared_examples.rb +108 -91
- data/spec/shared_examples/user_activity_logging_shared_examples.rb +83 -15
- data/spec/shared_examples/user_brute_force_protection_shared_examples.rb +140 -21
- data/spec/shared_examples/user_oauth_shared_examples.rb +21 -16
- data/spec/shared_examples/user_remember_me_shared_examples.rb +36 -24
- data/spec/shared_examples/user_reset_password_shared_examples.rb +138 -117
- data/spec/shared_examples/user_shared_examples.rb +297 -150
- data/spec/sorcery_crypto_providers_spec.rb +28 -28
- data/spec/spec_helper.rb +12 -18
- metadata +99 -165
- data/Gemfile.rails4 +0 -24
- data/VERSION +0 -1
- data/lib/sorcery/controller/submodules/external/protocols/oauth1.rb +0 -46
- data/lib/sorcery/controller/submodules/external/protocols/oauth2.rb +0 -50
- data/lib/sorcery/controller/submodules/external/providers/base.rb +0 -21
- data/lib/sorcery/controller/submodules/external/providers/facebook.rb +0 -99
- data/lib/sorcery/controller/submodules/external/providers/github.rb +0 -93
- data/lib/sorcery/controller/submodules/external/providers/google.rb +0 -92
- data/lib/sorcery/controller/submodules/external/providers/linkedin.rb +0 -103
- data/lib/sorcery/controller/submodules/external/providers/liveid.rb +0 -93
- data/lib/sorcery/controller/submodules/external/providers/twitter.rb +0 -94
- data/lib/sorcery/controller/submodules/external/providers/vk.rb +0 -101
- data/lib/sorcery/controller/submodules/external/providers/xing.rb +0 -98
- data/lib/sorcery/model/adapters/active_record.rb +0 -49
- data/lib/sorcery/model/adapters/mongo_mapper.rb +0 -56
- data/lib/sorcery/model/adapters/mongoid.rb +0 -88
- data/lib/sorcery/test_helpers/rails.rb +0 -16
- data/lib/sorcery/test_helpers.rb +0 -5
- data/spec/active_record/controller_activity_logging_spec.rb +0 -140
- data/spec/active_record/controller_brute_force_protection_spec.rb +0 -136
- data/spec/active_record/controller_http_basic_auth_spec.rb +0 -59
- data/spec/active_record/controller_oauth2_spec.rb +0 -417
- data/spec/active_record/controller_oauth_spec.rb +0 -212
- data/spec/active_record/controller_remember_me_spec.rb +0 -96
- data/spec/active_record/controller_session_timeout_spec.rb +0 -55
- data/spec/active_record/controller_spec.rb +0 -182
- data/spec/active_record/integration_spec.rb +0 -23
- data/spec/mongo_mapper/controller_spec.rb +0 -175
- data/spec/mongoid/controller_activity_logging_spec.rb +0 -111
- data/spec/mongoid/controller_spec.rb +0 -186
- data/spec/rails_app/public/404.html +0 -26
- data/spec/rails_app/public/422.html +0 -26
- data/spec/rails_app/public/500.html +0 -26
- data/spec/rails_app/public/favicon.ico +0 -0
- data/spec/rails_app/public/images/rails.png +0 -0
- data/spec/rails_app/public/javascripts/application.js +0 -2
- data/spec/rails_app/public/javascripts/controls.js +0 -965
- data/spec/rails_app/public/javascripts/dragdrop.js +0 -974
- data/spec/rails_app/public/javascripts/effects.js +0 -1123
- data/spec/rails_app/public/javascripts/prototype.js +0 -6001
- data/spec/rails_app/public/javascripts/rails.js +0 -175
- data/spec/rails_app/public/robots.txt +0 -5
- data/spec/rails_app/public/stylesheets/.gitkeep +0 -0
- data/spec/shared_examples/controller_oauth2_shared_examples.rb +0 -56
- data/spec/shared_examples/controller_oauth_shared_examples.rb +0 -69
- /data/lib/sorcery/{controller/submodules/external/protocols → protocols}/certs/ca-bundle.crt +0 -0
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
module Sorcery
|
|
2
|
-
module Controller
|
|
3
|
-
module Submodules
|
|
4
|
-
module External
|
|
5
|
-
module Providers
|
|
6
|
-
# This module adds support for OAuth with xing.com.
|
|
7
|
-
# When included in the 'config.providers' option, it adds a new option, 'config.xing'.
|
|
8
|
-
# Via this new option you can configure Xing specific settings like your app's key and secret.
|
|
9
|
-
#
|
|
10
|
-
# config.xing.key = <key>
|
|
11
|
-
# config.xing.secret = <secret>
|
|
12
|
-
# ...
|
|
13
|
-
#
|
|
14
|
-
module Xing
|
|
15
|
-
def self.included(base)
|
|
16
|
-
base.module_eval do
|
|
17
|
-
class << self
|
|
18
|
-
attr_reader :xing
|
|
19
|
-
|
|
20
|
-
def merge_xing_defaults!
|
|
21
|
-
@defaults.merge!(:@xing => XingClient)
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
merge_xing_defaults!
|
|
25
|
-
update!
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
module XingClient
|
|
30
|
-
include Base::BaseClient
|
|
31
|
-
class << self
|
|
32
|
-
attr_accessor :key,
|
|
33
|
-
:secret,
|
|
34
|
-
:callback_url,
|
|
35
|
-
:site,
|
|
36
|
-
:authorize_path,
|
|
37
|
-
:request_token_path,
|
|
38
|
-
:access_token_path,
|
|
39
|
-
:user_info_path,
|
|
40
|
-
:user_info_mapping,
|
|
41
|
-
:state
|
|
42
|
-
attr_reader :access_token
|
|
43
|
-
|
|
44
|
-
include Protocols::Oauth1
|
|
45
|
-
|
|
46
|
-
# Override included get_consumer method to provide authorize_path
|
|
47
|
-
def get_consumer
|
|
48
|
-
::OAuth::Consumer.new(@key, @secret, @configuration)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def init
|
|
52
|
-
@configuration = {
|
|
53
|
-
site: "https://api.xing.com/v1",
|
|
54
|
-
authorize_path: '/authorize',
|
|
55
|
-
request_token_path: '/request_token',
|
|
56
|
-
access_token_path: '/access_token'
|
|
57
|
-
}
|
|
58
|
-
@user_info_path = "/users/me"
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def get_user_hash(access_token)
|
|
62
|
-
user_hash = {}
|
|
63
|
-
response = access_token.get(@user_info_path)
|
|
64
|
-
user_hash[:user_info] = JSON.parse(response.body)['users'].first
|
|
65
|
-
user_hash[:uid] = user_hash[:user_info]['id'].to_s
|
|
66
|
-
user_hash
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def has_callback?
|
|
70
|
-
true
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
# calculates and returns the url to which the user should be redirected,
|
|
74
|
-
# to get authenticated at the external provider's site.
|
|
75
|
-
def login_url(params,session)
|
|
76
|
-
req_token = self.get_request_token
|
|
77
|
-
session[:request_token] = req_token.token
|
|
78
|
-
session[:request_token_secret] = req_token.secret
|
|
79
|
-
self.authorize_url({:request_token => req_token.token, :request_token_secret => req_token.secret})
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# tries to login the user from access token
|
|
83
|
-
def process_callback(params, session)
|
|
84
|
-
args = {}
|
|
85
|
-
args.merge!({:oauth_verifier => params[:oauth_verifier], :request_token => session[:request_token], :request_token_secret => session[:request_token_secret]})
|
|
86
|
-
args.merge!({:code => params[:code]}) if params[:code]
|
|
87
|
-
return self.get_access_token(args)
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
end
|
|
91
|
-
init
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
end
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
module Sorcery
|
|
2
|
-
module Model
|
|
3
|
-
module Adapters
|
|
4
|
-
module ActiveRecord
|
|
5
|
-
def self.included(klass)
|
|
6
|
-
klass.extend ClassMethods
|
|
7
|
-
klass.send(:include, InstanceMethods)
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
module InstanceMethods
|
|
11
|
-
def update_many_attributes(attrs)
|
|
12
|
-
attrs.each do |name, value|
|
|
13
|
-
self.send(:"#{name}=", value)
|
|
14
|
-
end
|
|
15
|
-
primary_key = self.class.primary_key
|
|
16
|
-
self.class.where(:"#{primary_key}" => self.send(:"#{primary_key}")).update_all(attrs)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def update_single_attribute(name, value)
|
|
20
|
-
update_many_attributes(name => value)
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
module ClassMethods
|
|
25
|
-
def column_name(attribute)
|
|
26
|
-
return "LOWER(#{attribute})" if (@sorcery_config.downcase_username_before_authenticating)
|
|
27
|
-
return "#{attribute}"
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def find_by_credentials(credentials)
|
|
31
|
-
sql = @sorcery_config.username_attribute_names.map{|attribute| column_name(attribute) + " = :login"}
|
|
32
|
-
where(sql.join(' OR '), :login => credentials[0]).first
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def find_by_sorcery_token(token_attr_name, token)
|
|
36
|
-
where("#{token_attr_name} = ?", token).first
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def get_current_users
|
|
40
|
-
config = sorcery_config
|
|
41
|
-
where("#{config.last_activity_at_attribute_name} IS NOT NULL") \
|
|
42
|
-
.where("#{config.last_logout_at_attribute_name} IS NULL OR #{config.last_activity_at_attribute_name} > #{config.last_logout_at_attribute_name}") \
|
|
43
|
-
.where("#{config.last_activity_at_attribute_name} > ? ", config.activity_timeout.seconds.ago.utc.to_s(:db))
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
module Sorcery
|
|
2
|
-
module Model
|
|
3
|
-
module Adapters
|
|
4
|
-
module MongoMapper
|
|
5
|
-
extend ActiveSupport::Concern
|
|
6
|
-
|
|
7
|
-
included do
|
|
8
|
-
include Sorcery::Model
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def increment(attr)
|
|
12
|
-
self.class.increment(id, attr => 1)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def save!(options = {})
|
|
16
|
-
save(options)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def update_many_attributes(attrs)
|
|
20
|
-
update_attributes(attrs)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
module ClassMethods
|
|
24
|
-
def credential_regex(credential)
|
|
25
|
-
return { :$regex => /^#{credential}$/i } if (@sorcery_config.downcase_username_before_authenticating)
|
|
26
|
-
return credential
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def find_by_credentials(credentials)
|
|
30
|
-
@sorcery_config.username_attribute_names.each do |attribute|
|
|
31
|
-
@user = where(attribute => credential_regex(credentials[0])).first
|
|
32
|
-
break if @user
|
|
33
|
-
end
|
|
34
|
-
@user
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def find_by_id(id)
|
|
38
|
-
find(id)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def find_by_activation_token(token)
|
|
42
|
-
where(sorcery_config.activation_token_attribute_name => token).first
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def transaction(&blk)
|
|
46
|
-
tap(&blk)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def find_by_sorcery_token(token_attr_name, token)
|
|
50
|
-
where(token_attr_name => token).first
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
module Sorcery
|
|
2
|
-
module Model
|
|
3
|
-
module Adapters
|
|
4
|
-
module Mongoid
|
|
5
|
-
def self.included(klass)
|
|
6
|
-
klass.extend ClassMethods
|
|
7
|
-
klass.send(:include, InstanceMethods)
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
module InstanceMethods
|
|
11
|
-
def increment(attr)
|
|
12
|
-
self.inc(attr, 1)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def update_many_attributes(attrs)
|
|
16
|
-
attrs.each do |name, value|
|
|
17
|
-
attrs[name] = value.utc if value.is_a?(ActiveSupport::TimeWithZone)
|
|
18
|
-
self.send(:"#{name}=", value)
|
|
19
|
-
end
|
|
20
|
-
self.class.where(:_id => self.id).update_all(attrs)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def update_single_attribute(name, value)
|
|
24
|
-
update_many_attributes(name => value)
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
module ClassMethods
|
|
29
|
-
def credential_regex(credential)
|
|
30
|
-
return { :$regex => /^#{credential}$/i } if (@sorcery_config.downcase_username_before_authenticating)
|
|
31
|
-
credential
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def find_by_credentials(credentials)
|
|
35
|
-
@sorcery_config.username_attribute_names.each do |attribute|
|
|
36
|
-
@user = where(attribute => credential_regex(credentials[0])).first
|
|
37
|
-
break if @user
|
|
38
|
-
end
|
|
39
|
-
@user
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def find_by_provider_and_uid(provider, uid)
|
|
43
|
-
@user_klass ||= ::Sorcery::Controller::Config.user_class.to_s.constantize
|
|
44
|
-
where(@user_klass.sorcery_config.provider_attribute_name => provider, @user_klass.sorcery_config.provider_uid_attribute_name => uid).first
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def find_by_id(id)
|
|
48
|
-
find(id)
|
|
49
|
-
rescue ::Mongoid::Errors::DocumentNotFound
|
|
50
|
-
nil
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def find_by_activation_token(token)
|
|
54
|
-
where(sorcery_config.activation_token_attribute_name => token).first
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def find_by_remember_me_token(token)
|
|
58
|
-
where(sorcery_config.remember_me_token_attribute_name => token).first
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def find_by_username(username)
|
|
62
|
-
query = sorcery_config.username_attribute_names.map {|name| {name => username}}
|
|
63
|
-
any_of(*query).first
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def transaction(&blk)
|
|
67
|
-
tap(&blk)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def find_by_sorcery_token(token_attr_name, token)
|
|
71
|
-
where(token_attr_name => token).first
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def find_by_email(email)
|
|
75
|
-
where(sorcery_config.email_attribute_name => email).first
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def get_current_users
|
|
79
|
-
config = sorcery_config
|
|
80
|
-
where(config.last_activity_at_attribute_name.ne => nil) \
|
|
81
|
-
.where("this.#{config.last_logout_at_attribute_name} == null || this.#{config.last_activity_at_attribute_name} > this.#{config.last_logout_at_attribute_name}") \
|
|
82
|
-
.where(config.last_activity_at_attribute_name.gt => config.activity_timeout.seconds.ago.utc).order_by([:_id,:asc])
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
end
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
module Sorcery
|
|
2
|
-
module TestHelpers
|
|
3
|
-
module Rails
|
|
4
|
-
# logins a user and calls all callbacks
|
|
5
|
-
def login_user(user = nil)
|
|
6
|
-
user ||= @user
|
|
7
|
-
@controller.send(:auto_login, user)
|
|
8
|
-
@controller.send(:after_login!, user, [user.send(user.sorcery_config.username_attribute_names.first), 'secret'])
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def logout_user
|
|
12
|
-
@controller.send(:logout)
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
data/lib/sorcery/test_helpers.rb
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe SorceryController do
|
|
4
|
-
before(:all) do
|
|
5
|
-
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/activity_logging")
|
|
6
|
-
User.reset_column_information
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
after(:all) do
|
|
10
|
-
ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/activity_logging")
|
|
11
|
-
|
|
12
|
-
sorcery_controller_property_set(:register_login_time, true)
|
|
13
|
-
sorcery_controller_property_set(:register_logout_time, true)
|
|
14
|
-
sorcery_controller_property_set(:register_last_activity_time, true)
|
|
15
|
-
# sorcery_controller_property_set(:last_login_from_ip_address_name, true)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# ----------------- ACTIVITY LOGGING -----------------------
|
|
19
|
-
describe SorceryController, "with activity logging features" do
|
|
20
|
-
before(:all) do
|
|
21
|
-
sorcery_reload!([:activity_logging])
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
before(:each) do
|
|
25
|
-
create_new_user
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
after(:each) do
|
|
29
|
-
User.delete_all
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
specify { subject.should respond_to(:current_users) }
|
|
33
|
-
|
|
34
|
-
it "'current_users' should be empty when no users are logged in" do
|
|
35
|
-
subject.current_users.size.should == 0
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
it "should log login time on login" do
|
|
39
|
-
now = Time.now.in_time_zone
|
|
40
|
-
login_user
|
|
41
|
-
@user.last_login_at.should_not be_nil
|
|
42
|
-
@user.last_login_at.to_s(:db).should >= now.to_s(:db)
|
|
43
|
-
@user.last_login_at.to_s(:db).should <= (now+2).to_s(:db)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
it "should log logout time on logout" do
|
|
47
|
-
login_user
|
|
48
|
-
now = Time.now.in_time_zone
|
|
49
|
-
logout_user
|
|
50
|
-
|
|
51
|
-
User.last.last_logout_at.should_not be_nil
|
|
52
|
-
|
|
53
|
-
User.last.last_logout_at.to_s(:db).should >= now.to_s(:db)
|
|
54
|
-
User.last.last_logout_at.to_s(:db).should <= (now+2).to_s(:db)
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
it "should log last activity time when logged in" do
|
|
58
|
-
sorcery_controller_property_set(:register_last_activity_time, true)
|
|
59
|
-
|
|
60
|
-
login_user
|
|
61
|
-
now = Time.now.in_time_zone
|
|
62
|
-
get :some_action
|
|
63
|
-
|
|
64
|
-
last_activity_at = User.last.last_activity_at
|
|
65
|
-
|
|
66
|
-
last_activity_at.should be_present
|
|
67
|
-
last_activity_at.to_s(:db).should >= now.to_s(:db)
|
|
68
|
-
last_activity_at.to_s(:db).should <= (now+2).to_s(:db)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
it "should log last IP address when logged in" do
|
|
72
|
-
login_user
|
|
73
|
-
get :some_action
|
|
74
|
-
User.last.last_login_from_ip_address.should == "0.0.0.0"
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
it "should update nothing but activity fields" do
|
|
78
|
-
original_user_name = User.last.username
|
|
79
|
-
login_user
|
|
80
|
-
get :some_action_making_a_non_persisted_change_to_the_user
|
|
81
|
-
User.last.username.should == original_user_name
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
it "'current_users' should hold the user object when 1 user is logged in" do
|
|
85
|
-
login_user
|
|
86
|
-
get :some_action
|
|
87
|
-
subject.current_users.size.should == 1
|
|
88
|
-
subject.current_users[0].should == @user
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
it "'current_users' should show all current_users, whether they have logged out before or not." do
|
|
92
|
-
user1 = create_new_user({:username => 'gizmo1', :email => "bla1@bla.com", :password => 'secret1'})
|
|
93
|
-
login_user(user1)
|
|
94
|
-
get :some_action
|
|
95
|
-
clear_user_without_logout
|
|
96
|
-
user2 = create_new_user({:username => 'gizmo2', :email => "bla2@bla.com", :password => 'secret2'})
|
|
97
|
-
login_user(user2)
|
|
98
|
-
get :some_action
|
|
99
|
-
clear_user_without_logout
|
|
100
|
-
user3 = create_new_user({:username => 'gizmo3', :email => "bla3@bla.com", :password => 'secret3'})
|
|
101
|
-
login_user(user3)
|
|
102
|
-
get :some_action
|
|
103
|
-
subject.current_users.size.should == 3
|
|
104
|
-
subject.current_users[0].should == user1
|
|
105
|
-
subject.current_users[1].should == user2
|
|
106
|
-
subject.current_users[2].should == user3
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
it "should not register login time if configured so" do
|
|
110
|
-
sorcery_controller_property_set(:register_login_time, false)
|
|
111
|
-
now = Time.now.in_time_zone
|
|
112
|
-
login_user
|
|
113
|
-
@user.last_login_at.should be_nil
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
it "should not register logout time if configured so" do
|
|
117
|
-
sorcery_controller_property_set(:register_logout_time, false)
|
|
118
|
-
now = Time.now.in_time_zone
|
|
119
|
-
login_user
|
|
120
|
-
logout_user
|
|
121
|
-
@user.last_logout_at.should be_nil
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
it "should not register last activity time if configured so" do
|
|
125
|
-
sorcery_controller_property_set(:register_last_activity_time, false)
|
|
126
|
-
now = Time.now.in_time_zone
|
|
127
|
-
login_user
|
|
128
|
-
get :some_action
|
|
129
|
-
@user.last_activity_at.should be_nil
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
it "should not register last IP address if configured so" do
|
|
133
|
-
sorcery_controller_property_set(:register_last_ip_address, false)
|
|
134
|
-
ip_address = "127.0.0.1"
|
|
135
|
-
login_user
|
|
136
|
-
get :some_action
|
|
137
|
-
@user.last_activity_at.should be_nil
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
end
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe SorceryController do
|
|
4
|
-
before(:all) do
|
|
5
|
-
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/brute_force_protection")
|
|
6
|
-
User.reset_column_information
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
after(:all) do
|
|
10
|
-
ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/brute_force_protection")
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
# ----------------- SESSION TIMEOUT -----------------------
|
|
14
|
-
describe SorceryController, "with brute force protection features" do
|
|
15
|
-
before(:all) do
|
|
16
|
-
sorcery_reload!([:brute_force_protection])
|
|
17
|
-
create_new_user
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
after(:each) do
|
|
21
|
-
Sorcery::Controller::Config.reset!
|
|
22
|
-
sorcery_controller_property_set(:user_class, User)
|
|
23
|
-
Timecop.return
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
it "should count login retries" do
|
|
27
|
-
3.times {get :test_login, :email => 'bla@bla.com', :password => 'blabla'}
|
|
28
|
-
User.find_by_email('bla@bla.com').failed_logins_count.should == 3
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
it "should generate unlock token before mail is sent" do
|
|
32
|
-
sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
|
|
33
|
-
sorcery_model_property_set(:login_lock_time_period, 0)
|
|
34
|
-
sorcery_model_property_set(:unlock_token_mailer, SorceryMailer)
|
|
35
|
-
3.times {get :test_login, :email => "bla@bla.com", :password => "blabla"}
|
|
36
|
-
ActionMailer::Base.deliveries.last.body.to_s.match(User.find_by_email('bla@bla.com').unlock_token).should_not be_nil
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
it "should unlock after entering unlock token" do
|
|
40
|
-
sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
|
|
41
|
-
sorcery_model_property_set(:login_lock_time_period, 0)
|
|
42
|
-
sorcery_model_property_set(:unlock_token_mailer, SorceryMailer)
|
|
43
|
-
3.times {get :test_login, :email => "bla@bla.com", :password => "blabla"}
|
|
44
|
-
User.find_by_email('bla@bla.com').unlock_token.should_not be_nil
|
|
45
|
-
token = User.find_by_email('bla@bla.com').unlock_token
|
|
46
|
-
user = User.load_from_unlock_token(token)
|
|
47
|
-
user.should_not be_nil
|
|
48
|
-
user.unlock!
|
|
49
|
-
User.load_from_unlock_token(token).should be_nil
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
it "should reset the counter on a good login" do
|
|
53
|
-
# dirty hack for rails 4
|
|
54
|
-
@controller.stub(:register_last_activity_time_to_db)
|
|
55
|
-
|
|
56
|
-
sorcery_model_property_set(:consecutive_login_retries_amount_limit, 5)
|
|
57
|
-
3.times {get :test_login, :email => 'bla@bla.com', :password => 'blabla'}
|
|
58
|
-
get :test_login, :email => 'bla@bla.com', :password => 'secret'
|
|
59
|
-
User.find_by_email('bla@bla.com').failed_logins_count.should == 0
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
it "should lock user when number of retries reached the limit" do
|
|
63
|
-
User.find_by_email('bla@bla.com').lock_expires_at.should be_nil
|
|
64
|
-
sorcery_model_property_set(:consecutive_login_retries_amount_limit, 1)
|
|
65
|
-
get :test_login, :email => 'bla@bla.com', :password => 'blabla'
|
|
66
|
-
User.find_by_email('bla@bla.com').lock_expires_at.should_not be_nil
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
it "should unlock after lock time period passes" do
|
|
70
|
-
sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
|
|
71
|
-
sorcery_model_property_set(:login_lock_time_period, 0.2)
|
|
72
|
-
get :test_login, :email => 'bla@bla.com', :password => 'blabla'
|
|
73
|
-
get :test_login, :email => 'bla@bla.com', :password => 'blabla'
|
|
74
|
-
User.find_by_email('bla@bla.com').lock_expires_at.should_not be_nil
|
|
75
|
-
Timecop.travel(Time.now.in_time_zone + 0.3)
|
|
76
|
-
get :test_login, :email => 'bla@bla.com', :password => 'blabla'
|
|
77
|
-
User.find_by_email('bla@bla.com').lock_expires_at.should be_nil
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
it "should not unlock if time period is 0 (permanent lock)" do
|
|
81
|
-
sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
|
|
82
|
-
sorcery_model_property_set(:login_lock_time_period, 0)
|
|
83
|
-
get :test_login, :email => 'bla@bla.com', :password => 'blabla'
|
|
84
|
-
get :test_login, :email => 'bla@bla.com', :password => 'blabla'
|
|
85
|
-
unlock_date = User.find_by_email('bla@bla.com').lock_expires_at
|
|
86
|
-
Timecop.travel(Time.now.in_time_zone + 1)
|
|
87
|
-
get :test_login, :email => 'bla@bla.com', :password => 'blabla'
|
|
88
|
-
User.find_by_email('bla@bla.com').lock_expires_at.to_s.should == unlock_date.to_s
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
context "unlock_token_mailer_disabled is true" do
|
|
92
|
-
|
|
93
|
-
before(:each) do
|
|
94
|
-
sorcery_model_property_set(:unlock_token_mailer_disabled, true)
|
|
95
|
-
sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
|
|
96
|
-
sorcery_model_property_set(:login_lock_time_period, 0)
|
|
97
|
-
sorcery_model_property_set(:unlock_token_mailer, SorceryMailer)
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
it "should generate unlock token after user locked" do
|
|
101
|
-
3.times {get :test_login, :email => "bla@bla.com", :password => "blabla"}
|
|
102
|
-
User.find_by_email('bla@bla.com').unlock_token.should_not be_nil
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
it "should *not* automatically send unlock mail" do
|
|
106
|
-
old_size = ActionMailer::Base.deliveries.size
|
|
107
|
-
3.times {get :test_login, :email => "bla@bla.com", :password => "blabla"}
|
|
108
|
-
ActionMailer::Base.deliveries.size.should == old_size
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
context "unlock_token_mailer_disabled is false" do
|
|
114
|
-
|
|
115
|
-
before(:each) do
|
|
116
|
-
sorcery_model_property_set(:unlock_token_mailer_disabled, false)
|
|
117
|
-
sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
|
|
118
|
-
sorcery_model_property_set(:login_lock_time_period, 0)
|
|
119
|
-
sorcery_model_property_set(:unlock_token_mailer, SorceryMailer)
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
it "should set the unlock token after user locked" do
|
|
123
|
-
3.times {get :test_login, :email => "bla@bla.com", :password => "blabla"}
|
|
124
|
-
User.find_by_email('bla@bla.com').unlock_token.should_not be_nil
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
it "should automatically send unlock mail" do
|
|
128
|
-
old_size = ActionMailer::Base.deliveries.size
|
|
129
|
-
3.times {get :test_login, :email => "bla@bla.com", :password => "blabla"}
|
|
130
|
-
ActionMailer::Base.deliveries.size.should == old_size + 1
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
end
|
|
136
|
-
end
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe SorceryController do
|
|
4
|
-
|
|
5
|
-
# ----------------- HTTP BASIC AUTH -----------------------
|
|
6
|
-
describe SorceryController, "with http basic auth features" do
|
|
7
|
-
before(:all) do
|
|
8
|
-
sorcery_reload!([:http_basic_auth])
|
|
9
|
-
|
|
10
|
-
sorcery_controller_property_set(:controller_to_realm_map, {"sorcery" => "sorcery"})
|
|
11
|
-
create_new_user
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
after(:each) do
|
|
15
|
-
logout_user
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
it "requests basic authentication when before_filter is used" do
|
|
19
|
-
get :test_http_basic_auth
|
|
20
|
-
response.code.should == "401"
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
it "authenticates from http basic if credentials are sent" do
|
|
24
|
-
# dirty hack for rails 4
|
|
25
|
-
@controller.stub(:register_last_activity_time_to_db)
|
|
26
|
-
|
|
27
|
-
@request.env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("#{@user.email}:secret")
|
|
28
|
-
get :test_http_basic_auth, nil, :http_authentication_used => true
|
|
29
|
-
response.should be_a_success
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
it "fails authentication if credentials are wrong" do
|
|
33
|
-
@request.env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("#{@user.email}:wrong!")
|
|
34
|
-
get :test_http_basic_auth, nil, :http_authentication_used => true
|
|
35
|
-
response.code.should redirect_to root_url
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
it "should allow configuration option 'controller_to_realm_map'" do
|
|
39
|
-
sorcery_controller_property_set(:controller_to_realm_map, {"1" => "2"})
|
|
40
|
-
Sorcery::Controller::Config.controller_to_realm_map.should == {"1" => "2"}
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
it "should display the correct realm name configured for the controller" do
|
|
44
|
-
sorcery_controller_property_set(:controller_to_realm_map, {"sorcery" => "Salad"})
|
|
45
|
-
|
|
46
|
-
get :test_http_basic_auth
|
|
47
|
-
response.headers["WWW-Authenticate"].should == "Basic realm=\"Salad\""
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
it "should sign in the user's session on successful login" do
|
|
51
|
-
# dirty hack for rails 4
|
|
52
|
-
@controller.stub(:register_last_activity_time_to_db)
|
|
53
|
-
|
|
54
|
-
@request.env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("#{@user.email}:secret")
|
|
55
|
-
get :test_http_basic_auth, nil, :http_authentication_used => true
|
|
56
|
-
session[:user_id].should == User.find_by_email(@user.email).id
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|