sorcery 0.1.3 → 0.2.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.
- data/Gemfile +4 -3
- data/Gemfile.lock +16 -13
- data/LICENSE.txt +1 -1
- data/README.rdoc +53 -36
- data/Rakefile +7 -13
- data/VERSION +1 -1
- data/lib/sorcery/controller/submodules/activity_logging.rb +58 -0
- data/lib/sorcery/controller/submodules/brute_force_protection.rb +15 -69
- data/lib/sorcery/controller/submodules/http_basic_auth.rb +13 -5
- data/lib/sorcery/controller/submodules/oauth/oauth1.rb +25 -0
- data/lib/sorcery/controller/submodules/oauth/oauth2.rb +23 -0
- data/lib/sorcery/controller/submodules/oauth/providers/facebook.rb +64 -0
- data/lib/sorcery/controller/submodules/oauth/providers/twitter.rb +61 -0
- data/lib/sorcery/controller/submodules/oauth.rb +95 -0
- data/lib/sorcery/controller/submodules/remember_me.rb +14 -5
- data/lib/sorcery/controller/submodules/session_timeout.rb +10 -2
- data/lib/sorcery/controller.rb +40 -22
- data/lib/sorcery/crypto_providers/bcrypt.rb +1 -5
- data/lib/sorcery/engine.rb +9 -2
- data/lib/sorcery/model/submodules/activity_logging.rb +40 -0
- data/lib/sorcery/model/submodules/brute_force_protection.rb +79 -0
- data/lib/sorcery/model/submodules/oauth.rb +53 -0
- data/lib/sorcery/model/submodules/remember_me.rb +6 -2
- data/lib/sorcery/model/submodules/reset_password.rb +96 -0
- data/lib/sorcery/model/submodules/user_activation.rb +40 -19
- data/lib/sorcery/model/temporary_token.rb +22 -0
- data/lib/sorcery/model.rb +10 -3
- data/lib/sorcery/test_helpers.rb +84 -0
- data/lib/sorcery.rb +16 -1
- data/sorcery.gemspec +84 -43
- data/spec/Gemfile +3 -2
- data/spec/Gemfile.lock +15 -2
- data/spec/rails3/app_root/.rspec +1 -0
- data/spec/rails3/{Gemfile → app_root/Gemfile} +5 -3
- data/spec/rails3/{Gemfile.lock → app_root/Gemfile.lock} +25 -2
- data/spec/rails3/app_root/app/controllers/application_controller.rb +44 -3
- data/spec/rails3/app_root/app/models/authentication.rb +3 -0
- data/spec/rails3/app_root/app/models/user.rb +4 -1
- data/spec/rails3/app_root/config/application.rb +1 -3
- data/spec/rails3/app_root/config/routes.rb +1 -10
- data/spec/rails3/app_root/db/migrate/activation/20101224223622_add_activation_to_users.rb +6 -4
- data/spec/rails3/app_root/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +17 -0
- data/spec/rails3/app_root/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +11 -0
- data/spec/rails3/app_root/db/migrate/core/20101224223620_create_users.rb +4 -4
- data/spec/rails3/app_root/db/migrate/oauth/20101224223628_create_authentications.rb +14 -0
- data/spec/rails3/app_root/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +13 -0
- data/spec/rails3/app_root/spec/controller_activity_logging_spec.rb +84 -0
- data/spec/rails3/app_root/spec/controller_brute_force_protection_spec.rb +65 -0
- data/spec/rails3/{controller_http_basic_auth_spec.rb → app_root/spec/controller_http_basic_auth_spec.rb} +13 -3
- data/spec/rails3/app_root/spec/controller_oauth2_spec.rb +117 -0
- data/spec/rails3/app_root/spec/controller_oauth_spec.rb +117 -0
- data/spec/rails3/{controller_remember_me_spec.rb → app_root/spec/controller_remember_me_spec.rb} +4 -4
- data/spec/rails3/{controller_session_timeout_spec.rb → app_root/spec/controller_session_timeout_spec.rb} +5 -4
- data/spec/rails3/{controller_spec.rb → app_root/spec/controller_spec.rb} +23 -16
- data/spec/rails3/app_root/spec/spec_helper.orig.rb +27 -0
- data/spec/rails3/app_root/spec/spec_helper.rb +61 -0
- data/spec/rails3/{user_activation_spec.rb → app_root/spec/user_activation_spec.rb} +60 -20
- data/spec/rails3/app_root/spec/user_activity_logging_spec.rb +36 -0
- data/spec/rails3/app_root/spec/user_brute_force_protection_spec.rb +76 -0
- data/spec/rails3/app_root/spec/user_oauth_spec.rb +39 -0
- data/spec/rails3/{user_remember_me_spec.rb → app_root/spec/user_remember_me_spec.rb} +4 -4
- data/spec/rails3/app_root/spec/user_reset_password_spec.rb +178 -0
- data/spec/rails3/{user_spec.rb → app_root/spec/user_spec.rb} +68 -38
- metadata +144 -63
- data/features/support/env.rb +0 -13
- data/lib/sorcery/model/submodules/password_reset.rb +0 -64
- data/spec/rails3/app_root/db/migrate/password_reset/20101224223622_add_password_reset_to_users.rb +0 -9
- data/spec/rails3/app_root/test/fixtures/users.yml +0 -9
- data/spec/rails3/app_root/test/performance/browsing_test.rb +0 -9
- data/spec/rails3/app_root/test/test_helper.rb +0 -13
- data/spec/rails3/app_root/test/unit/user_test.rb +0 -8
- data/spec/rails3/controller_brute_force_protection_spec.rb +0 -72
- data/spec/rails3/spec_helper.rb +0 -115
- data/spec/rails3/user_password_reset_spec.rb +0 -76
- /data/spec/rails3/{Rakefile → app_root/Rakefile} +0 -0
data/spec/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: ../../../
|
|
3
3
|
specs:
|
|
4
|
-
sorcery (0.1.
|
|
4
|
+
sorcery (0.1.4)
|
|
5
5
|
|
|
6
6
|
GEM
|
|
7
7
|
remote: http://rubygems.org/
|
|
@@ -33,6 +33,7 @@ GEM
|
|
|
33
33
|
activemodel (= 3.0.3)
|
|
34
34
|
activesupport (= 3.0.3)
|
|
35
35
|
activesupport (3.0.3)
|
|
36
|
+
addressable (2.2.4)
|
|
36
37
|
archive-tar-minitar (0.5.2)
|
|
37
38
|
arel (2.0.6)
|
|
38
39
|
bcrypt-ruby (2.1.3)
|
|
@@ -41,6 +42,10 @@ GEM
|
|
|
41
42
|
diff-lcs (1.1.2)
|
|
42
43
|
erubis (2.6.6)
|
|
43
44
|
abstract (>= 1.0.0)
|
|
45
|
+
faraday (0.5.5)
|
|
46
|
+
addressable (~> 2.2.4)
|
|
47
|
+
multipart-post (~> 1.1.0)
|
|
48
|
+
rack (< 2, >= 1.1.0)
|
|
44
49
|
i18n (0.5.0)
|
|
45
50
|
linecache19 (0.5.11)
|
|
46
51
|
ruby_core_source (>= 0.1.4)
|
|
@@ -50,6 +55,12 @@ GEM
|
|
|
50
55
|
mime-types (~> 1.16)
|
|
51
56
|
treetop (~> 1.4.8)
|
|
52
57
|
mime-types (1.16)
|
|
58
|
+
multi_json (0.0.5)
|
|
59
|
+
multipart-post (1.1.0)
|
|
60
|
+
oauth (0.4.4)
|
|
61
|
+
oauth2 (0.1.1)
|
|
62
|
+
faraday (~> 0.5.0)
|
|
63
|
+
multi_json (~> 0.0.4)
|
|
53
64
|
polyglot (0.3.1)
|
|
54
65
|
rack (1.2.1)
|
|
55
66
|
rack-mount (0.6.13)
|
|
@@ -101,8 +112,10 @@ PLATFORMS
|
|
|
101
112
|
|
|
102
113
|
DEPENDENCIES
|
|
103
114
|
bcrypt-ruby
|
|
115
|
+
oauth (>= 0.4.4)
|
|
116
|
+
oauth2 (>= 0.1.1)
|
|
104
117
|
rails (= 3.0.3)
|
|
105
118
|
rspec
|
|
106
119
|
ruby-debug19
|
|
107
120
|
simplecov (>= 0.3.8)
|
|
108
|
-
sorcery (= 0.1.
|
|
121
|
+
sorcery (= 0.1.4)!
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--colour
|
|
@@ -2,12 +2,14 @@ source 'http://rubygems.org'
|
|
|
2
2
|
|
|
3
3
|
gem 'rails', '3.0.3'
|
|
4
4
|
gem 'sqlite3-ruby', :require => 'sqlite3'
|
|
5
|
-
gem "sorcery", '0.1.
|
|
5
|
+
gem "sorcery", '0.1.4', :path => '../../../'
|
|
6
6
|
gem 'bcrypt-ruby', '~> 2.1.4', :require => 'bcrypt'
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
gem 'oauth', ">= 0.4.4"
|
|
8
|
+
gem 'oauth2', ">= 0.1.1"
|
|
9
|
+
group :development, :test do
|
|
9
10
|
gem 'rspec'
|
|
10
11
|
gem 'rspec-rails'
|
|
11
12
|
gem 'ruby-debug19'
|
|
12
13
|
gem 'simplecov', '>= 0.3.8', :require => false # Will install simplecov-html as a dependency
|
|
14
|
+
gem 'spork', '~> 0.9.0.rc'
|
|
13
15
|
end
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: ../../../
|
|
3
3
|
specs:
|
|
4
|
-
sorcery (0.1.
|
|
4
|
+
sorcery (0.1.4)
|
|
5
|
+
bcrypt-ruby (~> 2.1.4)
|
|
6
|
+
json (>= 1.5.1)
|
|
7
|
+
oauth (>= 0.4.4)
|
|
8
|
+
oauth (>= 0.4.4)
|
|
9
|
+
oauth2 (>= 0.1.1)
|
|
10
|
+
oauth2 (>= 0.1.1)
|
|
11
|
+
rails (>= 3.0.0)
|
|
5
12
|
|
|
6
13
|
GEM
|
|
7
14
|
remote: http://rubygems.org/
|
|
@@ -33,6 +40,7 @@ GEM
|
|
|
33
40
|
activemodel (= 3.0.3)
|
|
34
41
|
activesupport (= 3.0.3)
|
|
35
42
|
activesupport (3.0.3)
|
|
43
|
+
addressable (2.2.4)
|
|
36
44
|
archive-tar-minitar (0.5.2)
|
|
37
45
|
arel (2.0.6)
|
|
38
46
|
bcrypt-ruby (2.1.4)
|
|
@@ -41,7 +49,12 @@ GEM
|
|
|
41
49
|
diff-lcs (1.1.2)
|
|
42
50
|
erubis (2.6.6)
|
|
43
51
|
abstract (>= 1.0.0)
|
|
52
|
+
faraday (0.5.5)
|
|
53
|
+
addressable (~> 2.2.4)
|
|
54
|
+
multipart-post (~> 1.1.0)
|
|
55
|
+
rack (< 2, >= 1.1.0)
|
|
44
56
|
i18n (0.5.0)
|
|
57
|
+
json (1.5.1)
|
|
45
58
|
linecache19 (0.5.11)
|
|
46
59
|
ruby_core_source (>= 0.1.4)
|
|
47
60
|
mail (2.2.13)
|
|
@@ -50,6 +63,12 @@ GEM
|
|
|
50
63
|
mime-types (~> 1.16)
|
|
51
64
|
treetop (~> 1.4.8)
|
|
52
65
|
mime-types (1.16)
|
|
66
|
+
multi_json (0.0.5)
|
|
67
|
+
multipart-post (1.1.0)
|
|
68
|
+
oauth (0.4.4)
|
|
69
|
+
oauth2 (0.1.1)
|
|
70
|
+
faraday (~> 0.5.0)
|
|
71
|
+
multi_json (~> 0.0.4)
|
|
53
72
|
polyglot (0.3.1)
|
|
54
73
|
rack (1.2.1)
|
|
55
74
|
rack-mount (0.6.13)
|
|
@@ -96,6 +115,7 @@ GEM
|
|
|
96
115
|
simplecov (0.3.9)
|
|
97
116
|
simplecov-html (>= 0.3.7)
|
|
98
117
|
simplecov-html (0.3.9)
|
|
118
|
+
spork (0.9.0.rc3)
|
|
99
119
|
sqlite3-ruby (1.3.2)
|
|
100
120
|
thor (0.14.6)
|
|
101
121
|
treetop (1.4.9)
|
|
@@ -107,10 +127,13 @@ PLATFORMS
|
|
|
107
127
|
|
|
108
128
|
DEPENDENCIES
|
|
109
129
|
bcrypt-ruby (~> 2.1.4)
|
|
130
|
+
oauth (>= 0.4.4)
|
|
131
|
+
oauth2 (>= 0.1.1)
|
|
110
132
|
rails (= 3.0.3)
|
|
111
133
|
rspec
|
|
112
134
|
rspec-rails
|
|
113
135
|
ruby-debug19
|
|
114
136
|
simplecov (>= 0.3.8)
|
|
115
|
-
sorcery (= 0.1.
|
|
137
|
+
sorcery (= 0.1.4)!
|
|
138
|
+
spork (~> 0.9.0.rc)
|
|
116
139
|
sqlite3-ruby
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
require 'oauth'
|
|
2
|
+
|
|
1
3
|
class ApplicationController < ActionController::Base
|
|
2
4
|
protect_from_forgery
|
|
3
5
|
|
|
4
6
|
#before_filter :validate_session, :only => [:test_should_be_logged_in] if defined?(:validate_session)
|
|
5
|
-
before_filter :
|
|
6
|
-
before_filter :
|
|
7
|
+
before_filter :require_login_from_http_basic, :only => [:test_http_basic_auth]
|
|
8
|
+
before_filter :require_login, :only => [:test_logout, :test_should_be_logged_in, :some_action]
|
|
7
9
|
|
|
8
10
|
def index
|
|
9
11
|
render :text => ""
|
|
@@ -18,6 +20,11 @@ class ApplicationController < ActionController::Base
|
|
|
18
20
|
render :text => ""
|
|
19
21
|
end
|
|
20
22
|
|
|
23
|
+
def test_return_to
|
|
24
|
+
@user = login(params[:username], params[:password])
|
|
25
|
+
return_or_redirect_to(:index, :notice => 'haha!')
|
|
26
|
+
end
|
|
27
|
+
|
|
21
28
|
def test_logout
|
|
22
29
|
logout
|
|
23
30
|
render :text => ""
|
|
@@ -43,7 +50,7 @@ class ApplicationController < ActionController::Base
|
|
|
43
50
|
end
|
|
44
51
|
|
|
45
52
|
def test_login_from_cookie
|
|
46
|
-
@user =
|
|
53
|
+
@user = current_user
|
|
47
54
|
render :text => ""
|
|
48
55
|
end
|
|
49
56
|
|
|
@@ -59,6 +66,40 @@ class ApplicationController < ActionController::Base
|
|
|
59
66
|
render :text => "HTTP Basic Auth"
|
|
60
67
|
end
|
|
61
68
|
|
|
69
|
+
def auth_at_provider_test
|
|
70
|
+
auth_at_provider(:twitter)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def auth_at_provider_test2
|
|
74
|
+
auth_at_provider(:facebook)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def test_login_from_access_token
|
|
78
|
+
if @user = login_from_access_token(:twitter)
|
|
79
|
+
redirect_to "bla", :notice => "Success!"
|
|
80
|
+
else
|
|
81
|
+
redirect_to "blu", :alert => "Failed!"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def test_login_from_access_token2
|
|
86
|
+
if @user = login_from_access_token(:facebook)
|
|
87
|
+
redirect_to "bla", :notice => "Success!"
|
|
88
|
+
else
|
|
89
|
+
redirect_to "blu", :alert => "Failed!"
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def test_create_from_provider
|
|
94
|
+
provider = params[:provider]
|
|
95
|
+
login_from_access_token(provider)
|
|
96
|
+
if @user = create_from_provider!(provider)
|
|
97
|
+
redirect_to "bla", :notice => "Success!"
|
|
98
|
+
else
|
|
99
|
+
redirect_to "blu", :alert => "Failed!"
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
62
103
|
protected
|
|
63
104
|
|
|
64
105
|
|
|
@@ -38,9 +38,7 @@ module AppRoot
|
|
|
38
38
|
|
|
39
39
|
# Configure sensitive parameters which will be filtered from the log file.
|
|
40
40
|
config.filter_parameters += [:password]
|
|
41
|
-
|
|
42
|
-
config.root = File.expand_path('../..', __FILE__)
|
|
43
|
-
|
|
41
|
+
|
|
44
42
|
config.action_mailer.delivery_method = :test
|
|
45
43
|
|
|
46
44
|
config.active_support.deprecation = :stderr
|
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
AppRoot::Application.routes.draw do
|
|
2
2
|
root :to => "application#index"
|
|
3
|
-
match '/test_login', :to => "application#test_login"
|
|
4
|
-
match '/test_logout', :to => "application#test_logout"
|
|
5
|
-
match '/some_action', :to => "application#some_action"
|
|
6
|
-
match '/test_logout_with_remember', :to => "application#test_logout_with_remember"
|
|
7
|
-
match '/test_login_with_remember', :to => 'application#test_login_with_remember'
|
|
8
|
-
match '/test_login_with_remember_in_login', :to => 'application#test_login_with_remember_in_login'
|
|
9
|
-
match '/test_login_from_cookie', :to => 'application#test_login_from_cookie'
|
|
10
|
-
match '/test_should_be_logged_in', :to => 'application#test_should_be_logged_in'
|
|
11
|
-
match '/test_http_basic_auth', :to => 'application#test_http_basic_auth'
|
|
12
3
|
# The priority is based upon order of creation:
|
|
13
4
|
# first created -> highest priority.
|
|
14
5
|
|
|
@@ -64,5 +55,5 @@ AppRoot::Application.routes.draw do
|
|
|
64
55
|
|
|
65
56
|
# This is a legacy wild controller route that's not recommended for RESTful applications.
|
|
66
57
|
# Note: This route will make all actions in every controller accessible via GET requests.
|
|
67
|
-
|
|
58
|
+
match ':controller(/:action(/:id(.:format)))'
|
|
68
59
|
end
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
class AddActivationToUsers < ActiveRecord::Migration
|
|
2
2
|
def self.up
|
|
3
3
|
add_column :users, :activation_state, :string, :default => nil
|
|
4
|
-
add_column :users, :
|
|
4
|
+
add_column :users, :activation_token, :string, :default => nil
|
|
5
|
+
add_column :users, :activation_token_expires_at, :datetime, :default => nil
|
|
5
6
|
|
|
6
|
-
add_index :users, :
|
|
7
|
+
add_index :users, :activation_token
|
|
7
8
|
end
|
|
8
9
|
|
|
9
10
|
def self.down
|
|
10
|
-
remove_index :users, :
|
|
11
|
+
remove_index :users, :activation_token
|
|
11
12
|
|
|
12
|
-
remove_column :users, :
|
|
13
|
+
remove_column :users, :activation_token_expires_at
|
|
14
|
+
remove_column :users, :activation_token
|
|
13
15
|
remove_column :users, :activation_state
|
|
14
16
|
end
|
|
15
17
|
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class AddActivityLoggingToUsers < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
add_column :users, :last_login_at, :datetime, :default => nil
|
|
4
|
+
add_column :users, :last_logout_at, :datetime, :default => nil
|
|
5
|
+
add_column :users, :last_activity_at, :datetime, :default => nil
|
|
6
|
+
|
|
7
|
+
add_index :users, [:last_logout_at, :last_activity_at]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.down
|
|
11
|
+
remove_index :users, [:last_logout_at, :last_activity_at]
|
|
12
|
+
|
|
13
|
+
remove_column :users, :last_activity_at
|
|
14
|
+
remove_column :users, :last_logout_at
|
|
15
|
+
remove_column :users, :last_login_at
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class AddBruteForceProtectionToUsers < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
add_column :users, :failed_logins_count, :integer, :default => 0
|
|
4
|
+
add_column :users, :lock_expires_at, :datetime, :default => nil
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def self.down
|
|
8
|
+
remove_column :users, :lock_expires_at
|
|
9
|
+
remove_column :users, :failed_logins_count
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
class CreateUsers < ActiveRecord::Migration
|
|
2
2
|
def self.up
|
|
3
3
|
create_table :users do |t|
|
|
4
|
-
t.string :username
|
|
5
|
-
t.string :email,
|
|
6
|
-
t.string :crypted_password
|
|
7
|
-
t.string :salt
|
|
4
|
+
t.string :username, :null => false
|
|
5
|
+
t.string :email, :default => nil
|
|
6
|
+
t.string :crypted_password, :default => nil
|
|
7
|
+
t.string :salt, :default => nil
|
|
8
8
|
|
|
9
9
|
t.timestamps
|
|
10
10
|
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class CreateAuthentications < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
create_table :authentications do |t|
|
|
4
|
+
t.integer :user_id, :null => false
|
|
5
|
+
t.string :provider, :uid, :null => false
|
|
6
|
+
|
|
7
|
+
t.timestamps
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.down
|
|
12
|
+
drop_table :authentications
|
|
13
|
+
end
|
|
14
|
+
end
|
data/spec/rails3/app_root/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class AddResetPasswordToUsers < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
add_column :users, :reset_password_token, :string, :default => nil
|
|
4
|
+
add_column :users, :reset_password_token_expires_at, :datetime, :default => nil
|
|
5
|
+
add_column :users, :reset_password_email_sent_at, :datetime, :default => nil
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def self.down
|
|
9
|
+
remove_column :users, :reset_password_email_sent_at
|
|
10
|
+
remove_column :users, :reset_password_token_expires_at
|
|
11
|
+
remove_column :users, :reset_password_token
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
+
|
|
3
|
+
describe ApplicationController do
|
|
4
|
+
before(:all) do
|
|
5
|
+
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/activity_logging")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
after(:all) do
|
|
9
|
+
ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/activity_logging")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# ----------------- ACTIVITY LOGGING -----------------------
|
|
13
|
+
describe ApplicationController, "with activity logging features" do
|
|
14
|
+
before(:all) do
|
|
15
|
+
sorcery_reload!([:activity_logging])
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
before(:each) do
|
|
19
|
+
create_new_user
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
after(:each) do
|
|
23
|
+
User.delete_all
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should respond to 'current_users'" do
|
|
27
|
+
subject.should respond_to(:current_users)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "'current_users' should be empty when no users are logged in" do
|
|
31
|
+
subject.current_users.size.should == 0
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should log login time on login" do
|
|
35
|
+
now = Time.now.utc
|
|
36
|
+
login_user
|
|
37
|
+
@user.last_login_at.should_not be_nil
|
|
38
|
+
@user.last_login_at.to_s(:db).should >= now.to_s(:db)
|
|
39
|
+
@user.last_login_at.to_s(:db).should <= (now+2).to_s(:db)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "should log logout time on logout" do
|
|
43
|
+
login_user
|
|
44
|
+
now = Time.now.utc
|
|
45
|
+
logout_user
|
|
46
|
+
User.first.last_logout_at.should_not be_nil
|
|
47
|
+
User.first.last_logout_at.to_s(:db).should >= now.to_s(:db)
|
|
48
|
+
User.first.last_logout_at.to_s(:db).should <= (now+2).to_s(:db)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should log last activity time when logged in" do
|
|
52
|
+
login_user
|
|
53
|
+
now = Time.now.utc
|
|
54
|
+
get :some_action
|
|
55
|
+
User.first.last_activity_at.to_s(:db).should >= now.to_s(:db)
|
|
56
|
+
User.first.last_activity_at.to_s(:db).should <= (now+2).to_s(:db)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "'current_users' should hold the user object when 1 user is logged in" do
|
|
60
|
+
login_user
|
|
61
|
+
get :some_action
|
|
62
|
+
subject.current_users.size.should == 1
|
|
63
|
+
subject.current_users[0].should == @user
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "'current_users' should show all current_users, whether they have logged out before or not." do
|
|
67
|
+
user1 = create_new_user({:username => 'gizmo1', :email => "bla1@bla.com", :password => 'secret1'})
|
|
68
|
+
login_user(user1)
|
|
69
|
+
get :some_action
|
|
70
|
+
clear_user_without_logout
|
|
71
|
+
user2 = create_new_user({:username => 'gizmo2', :email => "bla2@bla.com", :password => 'secret2'})
|
|
72
|
+
login_user(user2)
|
|
73
|
+
get :some_action
|
|
74
|
+
clear_user_without_logout
|
|
75
|
+
user3 = create_new_user({:username => 'gizmo3', :email => "bla3@bla.com", :password => 'secret3'})
|
|
76
|
+
login_user(user3)
|
|
77
|
+
get :some_action
|
|
78
|
+
subject.current_users.size.should == 3
|
|
79
|
+
subject.current_users[0].should == user1
|
|
80
|
+
subject.current_users[1].should == user2
|
|
81
|
+
subject.current_users[2].should == user3
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
+
|
|
3
|
+
describe ApplicationController do
|
|
4
|
+
before(:all) do
|
|
5
|
+
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/brute_force_protection")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
after(:all) do
|
|
9
|
+
ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/brute_force_protection")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# ----------------- SESSION TIMEOUT -----------------------
|
|
13
|
+
describe ApplicationController, "with brute force protection features" do
|
|
14
|
+
before(:all) do
|
|
15
|
+
sorcery_reload!([:brute_force_protection])
|
|
16
|
+
create_new_user
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
after(:each) do
|
|
20
|
+
Sorcery::Controller::Config.reset!
|
|
21
|
+
sorcery_controller_property_set(:user_class, User)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "should count login retries" do
|
|
25
|
+
3.times {get :test_login, :username => 'gizmo', :password => 'blabla'}
|
|
26
|
+
User.find_by_username('gizmo').failed_logins_count.should == 3
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should reset the counter on a good login" do
|
|
30
|
+
sorcery_model_property_set(:consecutive_login_retries_amount_limit, 5)
|
|
31
|
+
3.times {get :test_login, :username => 'gizmo', :password => 'blabla'}
|
|
32
|
+
get :test_login, :username => 'gizmo', :password => 'secret'
|
|
33
|
+
User.find_by_username('gizmo').failed_logins_count.should == 0
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should lock user when number of retries reached the limit" do
|
|
37
|
+
User.find_by_username('gizmo').lock_expires_at.should be_nil
|
|
38
|
+
sorcery_model_property_set(:consecutive_login_retries_amount_limit, 1)
|
|
39
|
+
get :test_login, :username => 'gizmo', :password => 'blabla'
|
|
40
|
+
User.find_by_username('gizmo').lock_expires_at.should_not be_nil
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should unlock after lock time period passes" do
|
|
44
|
+
sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
|
|
45
|
+
sorcery_model_property_set(:login_lock_time_period, 0.2)
|
|
46
|
+
get :test_login, :username => 'gizmo', :password => 'blabla'
|
|
47
|
+
get :test_login, :username => 'gizmo', :password => 'blabla'
|
|
48
|
+
User.find_by_username('gizmo').lock_expires_at.should_not be_nil
|
|
49
|
+
sleep 0.3
|
|
50
|
+
get :test_login, :username => 'gizmo', :password => 'blabla'
|
|
51
|
+
User.find_by_username('gizmo').lock_expires_at.should be_nil
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "should not unlock if time period is 0 (permanent lock)" do
|
|
55
|
+
sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
|
|
56
|
+
sorcery_model_property_set(:login_lock_time_period, 0)
|
|
57
|
+
get :test_login, :username => 'gizmo', :password => 'blabla'
|
|
58
|
+
get :test_login, :username => 'gizmo', :password => 'blabla'
|
|
59
|
+
unlock_date = User.find_by_username('gizmo').lock_expires_at
|
|
60
|
+
sleep 1
|
|
61
|
+
get :test_login, :username => 'gizmo', :password => 'blabla'
|
|
62
|
+
User.find_by_username('gizmo').lock_expires_at.to_s.should == unlock_date.to_s
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -5,10 +5,14 @@ describe ApplicationController do
|
|
|
5
5
|
# ----------------- HTTP BASIC AUTH -----------------------
|
|
6
6
|
describe ApplicationController, "with http basic auth features" do
|
|
7
7
|
before(:all) do
|
|
8
|
-
|
|
8
|
+
sorcery_reload!([:http_basic_auth])
|
|
9
9
|
create_new_user
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
+
after(:each) do
|
|
13
|
+
logout_user
|
|
14
|
+
end
|
|
15
|
+
|
|
12
16
|
it "requests basic authentication when before_filter is used" do
|
|
13
17
|
get :test_http_basic_auth
|
|
14
18
|
response.code.should == "401"
|
|
@@ -27,14 +31,20 @@ describe ApplicationController do
|
|
|
27
31
|
end
|
|
28
32
|
|
|
29
33
|
it "should allow configuration option 'controller_to_realm_map'" do
|
|
30
|
-
|
|
34
|
+
sorcery_controller_property_set(:controller_to_realm_map, {"1" => "2"})
|
|
31
35
|
Sorcery::Controller::Config.controller_to_realm_map.should == {"1" => "2"}
|
|
32
36
|
end
|
|
33
37
|
|
|
34
38
|
it "should display the correct realm name configured for the controller" do
|
|
35
|
-
|
|
39
|
+
sorcery_controller_property_set(:controller_to_realm_map, {"application" => "Salad"})
|
|
36
40
|
get :test_http_basic_auth
|
|
37
41
|
response.headers["WWW-Authenticate"].should == "Basic realm=\"Salad\""
|
|
38
42
|
end
|
|
43
|
+
|
|
44
|
+
it "should sign in the user's session on successful login" do
|
|
45
|
+
@request.env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("#{@user.username}:secret")
|
|
46
|
+
get :test_http_basic_auth, nil, :http_authentication_used => true
|
|
47
|
+
session[:user_id].should == User.find_by_username(@user.username).id
|
|
48
|
+
end
|
|
39
49
|
end
|
|
40
50
|
end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
+
|
|
3
|
+
def stub_all_oauth2_requests!
|
|
4
|
+
@client = OAuth2::Client.new("key","secret", :site => "http://myapi.com")
|
|
5
|
+
OAuth2::Client.stub!(:new).and_return(@client)
|
|
6
|
+
@acc_token = OAuth2::AccessToken.new(@client, "", "asd", nil, {})
|
|
7
|
+
@webby = @client.web_server
|
|
8
|
+
OAuth2::Strategy::WebServer.stub!(:new).and_return(@webby)
|
|
9
|
+
@webby.stub!(:get_access_token).and_return(@acc_token)
|
|
10
|
+
@acc_token.stub!(:get).and_return({"id"=>"123", "name"=>"Noam Ben Ari", "first_name"=>"Noam", "last_name"=>"Ben Ari", "link"=>"http://www.facebook.com/nbenari1", "hometown"=>{"id"=>"110619208966868", "name"=>"Haifa, Israel"}, "location"=>{"id"=>"106906559341067", "name"=>"Pardes Hanah, Hefa, Israel"}, "bio"=>"I'm a new daddy, and enjoying it!", "gender"=>"male", "email"=>"nbenari@gmail.com", "timezone"=>2, "locale"=>"en_US", "languages"=>[{"id"=>"108405449189952", "name"=>"Hebrew"}, {"id"=>"106059522759137", "name"=>"English"}, {"id"=>"112624162082677", "name"=>"Russian"}], "verified"=>true, "updated_time"=>"2011-02-16T20:59:38+0000"}.to_json)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe ApplicationController do
|
|
14
|
+
before(:all) do
|
|
15
|
+
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/oauth")
|
|
16
|
+
sorcery_reload!([:oauth])
|
|
17
|
+
sorcery_controller_property_set(:oauth_providers, [:facebook])
|
|
18
|
+
sorcery_controller_oauth_property_set(:facebook, :key, "eYVNBjBDi33aa9GkA3w")
|
|
19
|
+
sorcery_controller_oauth_property_set(:facebook, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
|
|
20
|
+
sorcery_controller_oauth_property_set(:facebook, :callback_url, "http://blabla.com")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
after(:all) do
|
|
24
|
+
ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/oauth")
|
|
25
|
+
end
|
|
26
|
+
# ----------------- OAuth -----------------------
|
|
27
|
+
describe ApplicationController, "with OAuth features" do
|
|
28
|
+
|
|
29
|
+
before(:each) do
|
|
30
|
+
stub_all_oauth2_requests!
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
after(:each) do
|
|
34
|
+
User.delete_all
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "auth_at_provider redirects correctly" do
|
|
38
|
+
create_new_user
|
|
39
|
+
get :auth_at_provider_test2
|
|
40
|
+
response.should be_a_redirect
|
|
41
|
+
response.should redirect_to("http://myapi.com/oauth/authorize?client_id=key&redirect_uri=http%3A%2F%2Fblabla.com&scope=email%2Coffline_access&type=web_server")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "'login_from_access_token' logins if user exists" do
|
|
45
|
+
sorcery_model_property_set(:authentications_class, Authentication)
|
|
46
|
+
create_new_external_user(:facebook)
|
|
47
|
+
get :test_login_from_access_token2
|
|
48
|
+
flash[:notice].should == "Success!"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "'login_from_access_token' fails if user doesn't exist" do
|
|
52
|
+
sorcery_model_property_set(:authentications_class, Authentication)
|
|
53
|
+
create_new_user
|
|
54
|
+
get :test_login_from_access_token2
|
|
55
|
+
flash[:alert].should == "Failed!"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe ApplicationController, "'create_from_provider!'" do
|
|
60
|
+
before(:each) do
|
|
61
|
+
stub_all_oauth2_requests!
|
|
62
|
+
User.delete_all
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "should create a new user" do
|
|
66
|
+
sorcery_controller_property_set(:authentications_class, Authentication)
|
|
67
|
+
sorcery_controller_oauth_property_set(:facebook, :user_info_mapping, {:username => "name"})
|
|
68
|
+
lambda do
|
|
69
|
+
get :test_create_from_provider, :provider => "facebook"
|
|
70
|
+
end.should change(User, :count).by(1)
|
|
71
|
+
User.first.username.should == "Noam Ben Ari"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "should support nested attributes" do
|
|
75
|
+
sorcery_controller_property_set(:authentications_class, Authentication)
|
|
76
|
+
sorcery_controller_oauth_property_set(:facebook, :user_info_mapping, {:username => "hometown/name"})
|
|
77
|
+
lambda do
|
|
78
|
+
get :test_create_from_provider, :provider => "facebook"
|
|
79
|
+
end.should change(User, :count).by(1)
|
|
80
|
+
User.first.username.should == "Haifa, Israel"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
describe ApplicationController, "OAuth with User Activation features" do
|
|
85
|
+
before(:all) do
|
|
86
|
+
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/activation")
|
|
87
|
+
sorcery_reload!([:user_activation,:oauth], :user_activation_mailer => ::SorceryMailer)
|
|
88
|
+
sorcery_controller_property_set(:oauth_providers, [:facebook])
|
|
89
|
+
sorcery_controller_oauth_property_set(:facebook, :key, "eYVNBjBDi33aa9GkA3w")
|
|
90
|
+
sorcery_controller_oauth_property_set(:facebook, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
|
|
91
|
+
sorcery_controller_oauth_property_set(:facebook, :callback_url, "http://blabla.com")
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
after(:all) do
|
|
95
|
+
ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/activation")
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
after(:each) do
|
|
99
|
+
User.delete_all
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "should not send activation email to external users" do
|
|
103
|
+
old_size = ActionMailer::Base.deliveries.size
|
|
104
|
+
create_new_external_user(:facebook)
|
|
105
|
+
ActionMailer::Base.deliveries.size.should == old_size
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "should not send external users an activation success email" do
|
|
109
|
+
sorcery_model_property_set(:activation_success_email_method_name, nil)
|
|
110
|
+
create_new_external_user(:facebook)
|
|
111
|
+
old_size = ActionMailer::Base.deliveries.size
|
|
112
|
+
@user.activate!
|
|
113
|
+
ActionMailer::Base.deliveries.size.should == old_size
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
end
|