quo_vadis 1.0.2 → 1.0.3
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/.gitignore +1 -0
- data/README.md +40 -8
- data/Rakefile +9 -0
- data/app/controllers/controller_mixin.rb +38 -2
- data/app/controllers/quo_vadis/sessions_controller.rb +12 -3
- data/app/mailers/quo_vadis/notifier.rb +2 -0
- data/app/models/model_mixin.rb +35 -5
- data/config/initializers/quo_vadis.rb +13 -9
- data/lib/quo_vadis/version.rb +1 -1
- data/lib/quo_vadis.rb +21 -14
- data/test/dummy/config/locales/quo_vadis.en.yml +4 -3
- data/test/integration/cookie_test.rb +97 -0
- data/test/test_helper.rb +1 -0
- metadata +6 -4
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -8,14 +8,13 @@ Features:
|
|
8
8
|
* No surprises: it does what you expect.
|
9
9
|
* Easy to customise.
|
10
10
|
* Uses BCrypt to encrypt passwords.
|
11
|
-
* Sign in, sign out, forgotten password, authenticate actions.
|
11
|
+
* Sign in, sign out, forgotten password, authenticate actions, remember user between browser sessions.
|
12
12
|
|
13
13
|
Forthcoming features:
|
14
14
|
|
15
|
-
* Generate the views for you.
|
15
|
+
* Generate the views for you (for now, copy the examples given below).
|
16
16
|
* Let you choose which model(s) to authenticate (currently `User`).
|
17
17
|
* Let you choose the identification field (currently `username`).
|
18
|
-
* Remember authenticated user across browser sessions.
|
19
18
|
* HTTP basic/digest authentication (probably).
|
20
19
|
* Generate (User) model plus migration if it doesn't exist.
|
21
20
|
* Detect presence of `has_secure_password` (see below) and adapt appropriately.
|
@@ -58,7 +57,7 @@ Write the sign-in view. Your sign-in form must:
|
|
58
57
|
* be in `app/views/sessions/new.html.:format`
|
59
58
|
* POST the parameters `:username` and `:password` to `sign_in_url`
|
60
59
|
|
61
|
-
You have to write the view yourself because you'd inevitably want to change whatever markup I generated for you.
|
60
|
+
You have to write the view yourself because you'd inevitably want to change whatever markup I generated for you. You can find an example in the [test app](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/sessions/new.html.erb).
|
62
61
|
|
63
62
|
Remember to serve your sign in form over HTTPS -- to avoid [the credentials being stolen](http://blog.jgc.org/2011/01/code-injected-to-steal-passwords-in.html).
|
64
63
|
|
@@ -80,12 +79,12 @@ It'll take you about 5 minutes to implement this.
|
|
80
79
|
|
81
80
|
On your sign-in page, link to the forgotten-password view at `forgotten_sign_in_url`.
|
82
81
|
|
83
|
-
Write the forgotten-password view. The form must:
|
82
|
+
Write the forgotten-password view ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/sessions/forgotten.html.erb)). The form must:
|
84
83
|
|
85
84
|
* be in `app/views/sessions/forgotten.html.:format`
|
86
85
|
* POST the parameter `:username` to `forgotten_sign_in_url`
|
87
86
|
|
88
|
-
Now write the mailer view, i.e. the email which will be sent to your forgetful users. The view must:
|
87
|
+
Now write the mailer view, i.e. the email which will be sent to your forgetful users ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/notifier/change_password.text.erb)). The view must:
|
89
88
|
|
90
89
|
* be at `app/views/quo_vadis/notifier/change_password.text.erb`
|
91
90
|
* render `@url` somewhere (this is the link the user clicks to go to the change-password page)
|
@@ -98,7 +97,7 @@ Configure the default host so ActionMailer can generate the URL. In `config/env
|
|
98
97
|
|
99
98
|
config.action_mailer.default_url_options = {:host => 'yourdomain.com'}
|
100
99
|
|
101
|
-
Finally, write the change-password page. The form must:
|
100
|
+
Finally, write the change-password page ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/sessions/edit.html.erb)). The form must:
|
102
101
|
|
103
102
|
* be in `app/views/sessions/edit.html.:format`
|
104
103
|
* PUT the parameter `:password` to `change_password_url(params[:token])`
|
@@ -106,13 +105,34 @@ Finally, write the change-password page. The form must:
|
|
106
105
|
|
107
106
|
## Customisation
|
108
107
|
|
109
|
-
You can customise the flash messages in `config/locales/quo_vadis.en.yml`.
|
108
|
+
You can customise the flash messages and mailer from/subject in `config/locales/quo_vadis.en.yml`.
|
110
109
|
|
111
110
|
You can customise the sign-in and sign-out redirects in `config/initializers/quo_vadis.rb`; they both default to the root route. You can also hook into the sign-in and sign-out process if you need to run any other code.
|
112
111
|
|
113
112
|
If you want to add other session management type features, go right ahead: create a `SessionsController` as normal and carry on.
|
114
113
|
|
115
114
|
|
115
|
+
## Sign up / user registration
|
116
|
+
|
117
|
+
Quo Vadis doesn't offer sign-up because that's user management, not authentication.
|
118
|
+
|
119
|
+
However if you have implemented user sign-up yourself, you need to be able to sign in a newly created user. Do this by calling `sign_in(user)` in your controller. For example:
|
120
|
+
|
121
|
+
# In your app
|
122
|
+
class UsersController < ApplicationController
|
123
|
+
def create
|
124
|
+
@user = User.new params[:user]
|
125
|
+
if @user.save
|
126
|
+
sign_in @user # <-- NOTE: sign in your user here
|
127
|
+
else
|
128
|
+
render 'new'
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
The `sign_in(user)` method will redirect the user appropriately (you can configure this in `config/initializers/quo_vadis.rb`), as well as running any sign-in hook you may have defined in the initializer.
|
134
|
+
|
135
|
+
|
116
136
|
## See also
|
117
137
|
|
118
138
|
* Rails 3 edge's [ActiveModel::SecurePassword](https://github.com/rails/rails/blob/master/activemodel/lib/active_model/secure_password.rb). It's `has_secure_password` class method is similar to Quo Vadis's `authenticates` class method.
|
@@ -122,3 +142,15 @@ If you want to add other session management type features, go right ahead: creat
|
|
122
142
|
## What's up with the name?
|
123
143
|
|
124
144
|
Roman sentries used to challenge intruders with, "Halt! Who goes there?"; quo vadis is Latin for "Who goes there?". At least that's what my Latin teacher told us, but I was 8 years old then so I may not be remembering this entirely accurately.
|
145
|
+
|
146
|
+
|
147
|
+
## Questions, Problems, Feedback
|
148
|
+
|
149
|
+
Please use the GitHub [issue tracker](https://github.com/airblade/quo_vadis/issues) or email me.
|
150
|
+
|
151
|
+
|
152
|
+
## Intellectual property
|
153
|
+
|
154
|
+
Copyright 2011 Andy Stewart (boss@airbladesoftware.com).
|
155
|
+
|
156
|
+
Released under the MIT licence.
|
data/Rakefile
CHANGED
@@ -2,6 +2,7 @@ require 'bundler'
|
|
2
2
|
Bundler::GemHelper.install_tasks
|
3
3
|
|
4
4
|
require 'rake/testtask'
|
5
|
+
require 'rake/rdoctask'
|
5
6
|
|
6
7
|
Rake::TestTask.new(:test) do |t|
|
7
8
|
t.libs << 'lib'
|
@@ -10,4 +11,12 @@ Rake::TestTask.new(:test) do |t|
|
|
10
11
|
t.verbose = false
|
11
12
|
end
|
12
13
|
|
14
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
15
|
+
rdoc.rdoc_dir = 'rdoc'
|
16
|
+
rdoc.title = 'Quo Vadis'
|
17
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
18
|
+
rdoc.rdoc_files.include('README.md')
|
19
|
+
rdoc.rdoc_files.include('app/**/*.rb')
|
20
|
+
end
|
21
|
+
|
13
22
|
task :default => :test
|
@@ -5,14 +5,22 @@ module ControllerMixin
|
|
5
5
|
|
6
6
|
private
|
7
7
|
|
8
|
+
# Remembers the authenticated <tt>user</tt> (in this session and future sessions).
|
9
|
+
#
|
10
|
+
# If you want to sign in a <tt>user</tt>, call <tt>QuoVadis::SessionsController#sign_in</tt>
|
11
|
+
# instead.
|
8
12
|
def current_user=(user)
|
9
|
-
|
13
|
+
remember_user_in_session user
|
14
|
+
remember_user_between_sessions user
|
10
15
|
end
|
11
16
|
|
17
|
+
# Returns the authenticated user.
|
12
18
|
def current_user
|
13
|
-
@current_user ||=
|
19
|
+
@current_user ||= find_authenticated_user
|
14
20
|
end
|
15
21
|
|
22
|
+
# Does nothing if we already have an authenticated user. If we don't have an
|
23
|
+
# authenticated user, it stores the desired URL and redirects to the sign in URL.
|
16
24
|
def authenticate
|
17
25
|
unless current_user
|
18
26
|
session[:quo_vadis_original_url] = request.fullpath
|
@@ -20,4 +28,32 @@ module ControllerMixin
|
|
20
28
|
redirect_to sign_in_url
|
21
29
|
end
|
22
30
|
end
|
31
|
+
|
32
|
+
def remember_user_in_session(user) # :nodoc:
|
33
|
+
session[:current_user_id] = user ? user.id : nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def remember_user_between_sessions(user) # :nodoc:
|
37
|
+
if user && QuoVadis.remember_for
|
38
|
+
cookies.signed[:remember_me] = {
|
39
|
+
:value => [user.id, user.password_salt],
|
40
|
+
:expires => QuoVadis.remember_for.from_now,
|
41
|
+
:httponly => true
|
42
|
+
}
|
43
|
+
else
|
44
|
+
cookies.delete :remember_me
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def find_authenticated_user # :nodoc:
|
49
|
+
find_user_by_session || find_user_by_cookie
|
50
|
+
end
|
51
|
+
|
52
|
+
def find_user_by_cookie # :nodoc:
|
53
|
+
User.find_by_salt(*cookies.signed[:remember_me]) if cookies.signed[:remember_me]
|
54
|
+
end
|
55
|
+
|
56
|
+
def find_user_by_session # :nodoc:
|
57
|
+
User.find(session[:current_user_id]) if session[:current_user_id]
|
58
|
+
end
|
23
59
|
end
|
@@ -74,26 +74,35 @@ class QuoVadis::SessionsController < ApplicationController
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
|
77
|
+
protected
|
78
78
|
|
79
|
+
# Signs in a user, i.e. remembers them in the session, runs the sign-in hook,
|
80
|
+
# and redirects appropriately.
|
81
|
+
#
|
82
|
+
# This method should be called when you have just authenticated <tt>user</tt>
|
83
|
+
# and you need to sign them in. For example, if a new user has just signed up,
|
84
|
+
# you should call this method to sign them in.
|
79
85
|
def sign_in(user)
|
80
86
|
self.current_user = user
|
81
87
|
QuoVadis.signed_in_hook user, self
|
82
88
|
redirect_to QuoVadis.signed_in_url(user, original_url)
|
83
89
|
end
|
84
90
|
|
91
|
+
private
|
92
|
+
|
93
|
+
# Returns the URL if any which the user tried to visit before being forced to authenticate.
|
85
94
|
def original_url
|
86
95
|
url = session[:quo_vadis_original_url]
|
87
96
|
session[:quo_vadis_original_url] = nil
|
88
97
|
url
|
89
98
|
end
|
90
99
|
|
91
|
-
def invalid_token
|
100
|
+
def invalid_token # :nodoc:
|
92
101
|
flash[:alert] = t('quo_vadis.flash.forgotten.invalid_token') unless t('quo_vadis.flash.forgotten.invalid_token').blank?
|
93
102
|
redirect_to forgotten_sign_in_url
|
94
103
|
end
|
95
104
|
|
96
|
-
def quo_vadis_layout
|
105
|
+
def quo_vadis_layout # :nodoc:
|
97
106
|
QuoVadis.layout
|
98
107
|
end
|
99
108
|
|
data/app/models/model_mixin.rb
CHANGED
@@ -7,6 +7,9 @@ module ModelMixin
|
|
7
7
|
end
|
8
8
|
|
9
9
|
module ClassMethods
|
10
|
+
# Adds methods to set and authenticate against a password stored encrypted by BCrypt.
|
11
|
+
# Also adds methods to generate and clear a token, used to retrieve the record of a
|
12
|
+
# user who has forgotten their password.
|
10
13
|
def authenticates
|
11
14
|
send :include, InstanceMethodsOnActivation
|
12
15
|
|
@@ -20,6 +23,8 @@ module ModelMixin
|
|
20
23
|
scope :valid_token, lambda { |token| where("token = ? AND token_created_at > ?", token, 3.hours.ago) }
|
21
24
|
|
22
25
|
instance_eval <<-END
|
26
|
+
# Returns the user with the given <tt>username</tt> if the given password is
|
27
|
+
# correct, and <tt>nil</tt> otherwise.
|
23
28
|
def authenticate(username, plain_text_password)
|
24
29
|
user = where(:username => username).first
|
25
30
|
if user && user.has_matching_password?(plain_text_password)
|
@@ -28,17 +33,28 @@ module ModelMixin
|
|
28
33
|
nil
|
29
34
|
end
|
30
35
|
end
|
36
|
+
|
37
|
+
def find_by_salt(id, salt) # :nodoc:
|
38
|
+
user = User.find_by_id id
|
39
|
+
if user && user.has_matching_salt?(salt)
|
40
|
+
user
|
41
|
+
else
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
end
|
31
45
|
END
|
32
46
|
end
|
33
47
|
end
|
34
48
|
|
35
49
|
module InstanceMethodsOnActivation
|
36
|
-
def password=(plain_text_password)
|
50
|
+
def password=(plain_text_password) # :nodoc:
|
37
51
|
@password = plain_text_password
|
38
52
|
self.password_digest = BCrypt::Password.create plain_text_password
|
39
53
|
end
|
40
54
|
|
41
|
-
|
55
|
+
# Generates a unique, timestamped token which can be used in URLs, and
|
56
|
+
# saves the record. This is part of the forgotten-password workflow.
|
57
|
+
def generate_token # :nodoc:
|
42
58
|
begin
|
43
59
|
self.token = url_friendly_token
|
44
60
|
end while self.class.exists?(:token => token)
|
@@ -46,17 +62,31 @@ module ModelMixin
|
|
46
62
|
save
|
47
63
|
end
|
48
64
|
|
49
|
-
|
65
|
+
# Clears the user's timestamped token and saves the record.
|
66
|
+
# This is part of the forgotten-password workflow.
|
67
|
+
def clear_token # :nodoc:
|
50
68
|
update_attributes :token => nil, :token_created_at => nil
|
51
69
|
end
|
52
70
|
|
53
|
-
|
71
|
+
# Returns true if the given <tt>plain_text_password</tt> is the user's
|
72
|
+
# password, and false otherwise.
|
73
|
+
def has_matching_password?(plain_text_password) # :nodoc:
|
54
74
|
BCrypt::Password.new(password_digest) == plain_text_password
|
55
75
|
end
|
56
76
|
|
77
|
+
# Returns true if the given <tt>salt</tt> is the user's salt,
|
78
|
+
# and false otherwise.
|
79
|
+
def has_matching_salt?(salt) # :nodoc:
|
80
|
+
password_salt == salt
|
81
|
+
end
|
82
|
+
|
83
|
+
def password_salt # :nodoc:
|
84
|
+
BCrypt::Password.new(password_digest).salt
|
85
|
+
end
|
86
|
+
|
57
87
|
private
|
58
88
|
|
59
|
-
def url_friendly_token
|
89
|
+
def url_friendly_token # :nodoc:
|
60
90
|
ActiveSupport::SecureRandom.base64(10).tr('+/=', 'xyz')
|
61
91
|
end
|
62
92
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
QuoVadis.configure do |config|
|
2
2
|
|
3
3
|
#
|
4
|
-
#
|
4
|
+
# Sign in
|
5
5
|
#
|
6
6
|
|
7
7
|
# The URL to redirect the user to after s/he signs in.
|
@@ -18,14 +18,6 @@ QuoVadis.configure do |config|
|
|
18
18
|
# to reach when they were made to authenticate.
|
19
19
|
config.override_original_url = false
|
20
20
|
|
21
|
-
# The URL to redirect the user to after s/he signs out.
|
22
|
-
config.signed_out_url = :root
|
23
|
-
|
24
|
-
|
25
|
-
#
|
26
|
-
# Hooks
|
27
|
-
#
|
28
|
-
|
29
21
|
# Code to run when the user has signed in. E.g.:
|
30
22
|
#
|
31
23
|
# config.signed_in_hook = Proc.new do |user, controller|
|
@@ -40,6 +32,18 @@ QuoVadis.configure do |config|
|
|
40
32
|
# end
|
41
33
|
config.failed_sign_in_hook = nil
|
42
34
|
|
35
|
+
# How long to remember user across browser sessions.
|
36
|
+
# Set to <tt>nil</tt> to never remember user.
|
37
|
+
config.remember_for = 2.weeks
|
38
|
+
|
39
|
+
|
40
|
+
#
|
41
|
+
# Sign out
|
42
|
+
#
|
43
|
+
|
44
|
+
# The URL to redirect the user to after s/he signs out.
|
45
|
+
config.signed_out_url = :root
|
46
|
+
|
43
47
|
# Code to run just before the user has signed out. E.g.:
|
44
48
|
#
|
45
49
|
# config.signed_out_hook = Proc.new do |user, controller|
|
data/lib/quo_vadis/version.rb
CHANGED
data/lib/quo_vadis.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'quo_vadis/engine'
|
2
|
+
require 'active_support/core_ext/numeric/time'
|
2
3
|
|
3
4
|
module QuoVadis
|
4
5
|
|
5
6
|
#
|
6
|
-
#
|
7
|
+
# Sign in
|
7
8
|
#
|
8
9
|
|
9
10
|
# The URL to redirect the user to after s/he signs in.
|
@@ -15,7 +16,7 @@ module QuoVadis
|
|
15
16
|
mattr_accessor :override_original_url
|
16
17
|
@@override_original_url = false
|
17
18
|
|
18
|
-
def self.signed_in_url(user, original_url)
|
19
|
+
def self.signed_in_url(user, original_url) # :nodoc:
|
19
20
|
if original_url && !@@override_original_url
|
20
21
|
original_url
|
21
22
|
else
|
@@ -23,20 +24,11 @@ module QuoVadis
|
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
26
|
-
# The URL to redirect the user to after s/he signs out.
|
27
|
-
mattr_accessor :signed_out_url
|
28
|
-
@@signed_in_url = :root
|
29
|
-
|
30
|
-
|
31
|
-
#
|
32
|
-
# Hooks
|
33
|
-
#
|
34
|
-
|
35
27
|
# Code to run when the user has signed in.
|
36
28
|
mattr_accessor :signed_in_hook
|
37
29
|
@@signed_in_hook = nil
|
38
30
|
|
39
|
-
def self.signed_in_hook(user, controller)
|
31
|
+
def self.signed_in_hook(user, controller) # :nodoc:
|
40
32
|
@@signed_in_hook.call(user, controller) if @@signed_in_hook
|
41
33
|
end
|
42
34
|
|
@@ -44,15 +36,29 @@ module QuoVadis
|
|
44
36
|
mattr_accessor :failed_sign_in_hook
|
45
37
|
@@failed_sign_in_hook = nil
|
46
38
|
|
47
|
-
def self.failed_sign_in_hook(controller)
|
39
|
+
def self.failed_sign_in_hook(controller) # :nodoc:
|
48
40
|
@@failed_sign_in_hook.call(controller) if @@failed_sign_in_hook
|
49
41
|
end
|
50
42
|
|
43
|
+
# How long to remember user across browser sessions.
|
44
|
+
mattr_accessor :remember_for
|
45
|
+
@@remember_for = 2.weeks
|
46
|
+
|
47
|
+
|
48
|
+
#
|
49
|
+
# Sign out
|
50
|
+
#
|
51
|
+
|
52
|
+
# The URL to redirect the user to after s/he signs out.
|
53
|
+
mattr_accessor :signed_out_url
|
54
|
+
@@signed_in_url = :root
|
55
|
+
|
56
|
+
|
51
57
|
# Code to run just before the user has signed out.
|
52
58
|
mattr_accessor :signed_out_hook
|
53
59
|
@@signed_out_hook = nil
|
54
60
|
|
55
|
-
def self.signed_out_hook(user, controller)
|
61
|
+
def self.signed_out_hook(user, controller) # :nodoc:
|
56
62
|
@@signed_out_hook.call(user, controller) if @@signed_out_hook
|
57
63
|
end
|
58
64
|
|
@@ -70,6 +76,7 @@ module QuoVadis
|
|
70
76
|
@@subject = 'Change your password.'
|
71
77
|
|
72
78
|
|
79
|
+
|
73
80
|
#
|
74
81
|
# Miscellaneous
|
75
82
|
#
|
@@ -1,7 +1,8 @@
|
|
1
1
|
en:
|
2
2
|
quo_vadis:
|
3
3
|
flash:
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
sign_in:
|
5
|
+
before: 'Please sign in first.'
|
6
|
+
after: 'You have successfully signed in.'
|
7
|
+
failed: 'Sorry, we did not recognise you.'
|
7
8
|
sign_out: 'You have successfully signed out.'
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class CookieTest < ActiveSupport::IntegrationCase
|
4
|
+
|
5
|
+
teardown do
|
6
|
+
Capybara.reset_sessions!
|
7
|
+
reset_quo_vadis_configuration
|
8
|
+
end
|
9
|
+
|
10
|
+
test 'authenticated user is remembered between browser sessions' do
|
11
|
+
user_factory 'Bob', 'bob', 'secret'
|
12
|
+
sign_in_as 'bob', 'secret'
|
13
|
+
close_browser
|
14
|
+
visit root_path
|
15
|
+
within '#topnav' do
|
16
|
+
assert page.has_content?('You are signed in as Bob.')
|
17
|
+
end
|
18
|
+
assert page.has_no_css?('div.flash')
|
19
|
+
end
|
20
|
+
|
21
|
+
test "signing in updates the remember-me cookie's expiry time" do
|
22
|
+
user_factory 'Bob', 'bob', 'secret'
|
23
|
+
sign_in_as 'bob', 'secret'
|
24
|
+
cookie_a = get_cookie('remember_me')
|
25
|
+
assert_equal 2.weeks.from_now.httpdate, cookie_a.expires.httpdate
|
26
|
+
close_browser
|
27
|
+
sleep 1 # cookie expiry times are accurate to 1 second.
|
28
|
+
|
29
|
+
sign_in_as 'bob', 'secret'
|
30
|
+
cookie_b = get_cookie('remember_me')
|
31
|
+
assert cookie_b.expires > cookie_a.expires
|
32
|
+
assert_equal cookie_a.value, cookie_b.value
|
33
|
+
end
|
34
|
+
|
35
|
+
test 'signing out prevents the user being remembered in the next browser session' do
|
36
|
+
user_factory 'Bob', 'bob', 'secret'
|
37
|
+
sign_in_as 'bob', 'secret'
|
38
|
+
visit sign_out_path
|
39
|
+
close_browser
|
40
|
+
visit new_article_path
|
41
|
+
assert_equal sign_in_path, current_path
|
42
|
+
end
|
43
|
+
|
44
|
+
test "changing user's password prevents user being remembered in the next browser session" do
|
45
|
+
user_factory 'Bob', 'bob', 'secret'
|
46
|
+
sign_in_as 'bob', 'secret'
|
47
|
+
cookie = get_cookie('remember_me')
|
48
|
+
User.last.update_attributes! :password => 'topsecret'
|
49
|
+
close_browser
|
50
|
+
visit new_article_path
|
51
|
+
assert_equal sign_in_path, current_path
|
52
|
+
end
|
53
|
+
|
54
|
+
test 'length of time user is remembered can be configured' do
|
55
|
+
QuoVadis.remember_for = 1.second
|
56
|
+
user_factory 'Bob', 'bob', 'secret'
|
57
|
+
sign_in_as 'bob', 'secret'
|
58
|
+
close_browser
|
59
|
+
sleep 2
|
60
|
+
visit new_article_path
|
61
|
+
assert_equal sign_in_path, current_path
|
62
|
+
end
|
63
|
+
|
64
|
+
test 'remembering user between sessions can be turned off' do
|
65
|
+
QuoVadis.remember_for = nil
|
66
|
+
user_factory 'Bob', 'bob', 'secret'
|
67
|
+
sign_in_as 'bob', 'secret'
|
68
|
+
close_browser
|
69
|
+
visit new_article_path
|
70
|
+
assert_equal sign_in_path, current_path
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
#
|
75
|
+
# Code below from https://github.com/nruth/show_me_the_cookies
|
76
|
+
#
|
77
|
+
|
78
|
+
def delete_cookie(cookie_name)
|
79
|
+
cookie_jar.instance_variable_get(:@cookies).reject! do |existing_cookie|
|
80
|
+
existing_cookie.name.downcase == cookie_name
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_cookie(cookie_name)
|
85
|
+
cookie_jar.instance_variable_get(:@cookies).select do |existing_cookie|
|
86
|
+
existing_cookie.name.downcase == cookie_name
|
87
|
+
end.first
|
88
|
+
end
|
89
|
+
|
90
|
+
def cookie_jar
|
91
|
+
Capybara.current_session.driver.current_session.instance_variable_get(:@rack_mock_session).cookie_jar
|
92
|
+
end
|
93
|
+
|
94
|
+
def close_browser
|
95
|
+
delete_cookie Rails.application.config.session_options[:key]
|
96
|
+
end
|
97
|
+
end
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quo_vadis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 1.0.
|
9
|
+
- 3
|
10
|
+
version: 1.0.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Andy Stewart
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-02-07 00:00:00 +00:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -177,6 +177,7 @@ files:
|
|
177
177
|
- test/dummy/tmp/capybara/capybara-20110124135435.html
|
178
178
|
- test/integration/authenticate_test.rb
|
179
179
|
- test/integration/config_test.rb
|
180
|
+
- test/integration/cookie_test.rb
|
180
181
|
- test/integration/forgotten_test.rb
|
181
182
|
- test/integration/helper_test.rb
|
182
183
|
- test/integration/locale_test.rb
|
@@ -278,6 +279,7 @@ test_files:
|
|
278
279
|
- test/dummy/tmp/capybara/capybara-20110124135435.html
|
279
280
|
- test/integration/authenticate_test.rb
|
280
281
|
- test/integration/config_test.rb
|
282
|
+
- test/integration/cookie_test.rb
|
281
283
|
- test/integration/forgotten_test.rb
|
282
284
|
- test/integration/helper_test.rb
|
283
285
|
- test/integration/locale_test.rb
|