restful-authentication 1.2.1
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/CHANGELOG +68 -0
- data/README.textile +227 -0
- data/Rakefile +33 -0
- data/TODO +15 -0
- data/init.rb +5 -0
- data/lib/authentication.rb +40 -0
- data/lib/authentication/by_cookie_token.rb +82 -0
- data/lib/authentication/by_password.rb +65 -0
- data/lib/authorization.rb +14 -0
- data/lib/authorization/aasm_roles.rb +74 -0
- data/lib/authorization/stateful_roles.rb +62 -0
- data/lib/generators/authenticated/USAGE +1 -0
- data/lib/generators/authenticated/authenticated_generator.rb +524 -0
- data/lib/generators/authenticated/templates/_model_partial.html.erb +8 -0
- data/lib/generators/authenticated/templates/activation.erb +3 -0
- data/lib/generators/authenticated/templates/authenticated_system.rb +189 -0
- data/lib/generators/authenticated/templates/authenticated_test_helper.rb +22 -0
- data/lib/generators/authenticated/templates/controller.rb +41 -0
- data/lib/generators/authenticated/templates/features/accounts.feature +109 -0
- data/lib/generators/authenticated/templates/features/sessions.feature +134 -0
- data/lib/generators/authenticated/templates/features/step_definitions/ra_env.rb +9 -0
- data/lib/generators/authenticated/templates/features/step_definitions/ra_navigation_steps.rb +48 -0
- data/lib/generators/authenticated/templates/features/step_definitions/ra_resource_steps.rb +178 -0
- data/lib/generators/authenticated/templates/features/step_definitions/ra_response_steps.rb +169 -0
- data/lib/generators/authenticated/templates/features/step_definitions/rest_auth_features_helper.rb +81 -0
- data/lib/generators/authenticated/templates/features/step_definitions/user_steps.rb +131 -0
- data/lib/generators/authenticated/templates/helper.rb +2 -0
- data/lib/generators/authenticated/templates/login.html.erb +16 -0
- data/lib/generators/authenticated/templates/mailer.rb +26 -0
- data/lib/generators/authenticated/templates/migration.rb +26 -0
- data/lib/generators/authenticated/templates/model.rb +87 -0
- data/lib/generators/authenticated/templates/model_controller.rb +83 -0
- data/lib/generators/authenticated/templates/model_helper.rb +93 -0
- data/lib/generators/authenticated/templates/model_helper_spec.rb +158 -0
- data/lib/generators/authenticated/templates/observer.rb +11 -0
- data/lib/generators/authenticated/templates/signup.html.erb +19 -0
- data/lib/generators/authenticated/templates/signup_notification.erb +8 -0
- data/lib/generators/authenticated/templates/site_keys.rb +38 -0
- data/lib/generators/authenticated/templates/spec/controllers/access_control_spec.rb +90 -0
- data/lib/generators/authenticated/templates/spec/controllers/authenticated_system_spec.rb +102 -0
- data/lib/generators/authenticated/templates/spec/controllers/sessions_controller_spec.rb +139 -0
- data/lib/generators/authenticated/templates/spec/controllers/users_controller_spec.rb +198 -0
- data/lib/generators/authenticated/templates/spec/fixtures/users.yml +60 -0
- data/lib/generators/authenticated/templates/spec/helpers/users_helper_spec.rb +141 -0
- data/lib/generators/authenticated/templates/spec/models/user_spec.rb +290 -0
- data/lib/generators/authenticated/templates/test/functional_test.rb +82 -0
- data/lib/generators/authenticated/templates/test/mailer_test.rb +32 -0
- data/lib/generators/authenticated/templates/test/model_functional_test.rb +93 -0
- data/lib/generators/authenticated/templates/test/unit_test.rb +164 -0
- data/lib/tasks/auth.rake +33 -0
- data/lib/trustification.rb +14 -0
- data/lib/trustification/email_validation.rb +20 -0
- metadata +105 -0
@@ -0,0 +1,8 @@
|
|
1
|
+
<%% if logged_in? -%>
|
2
|
+
<div id="<%= file_name %>-bar-greeting">Logged in as <%%= link_to_current_<%= file_name %> :content_method => :login %></div>
|
3
|
+
<div id="<%= file_name %>-bar-action" >(<%%= link_to "Log out", logout_path, { :title => "Log out" } %>)</div>
|
4
|
+
<%% else -%>
|
5
|
+
<div id="<%= file_name %>-bar-greeting"><%%= link_to_login_with_IP 'Not logged in', :style => 'border: none;' %></div>
|
6
|
+
<div id="<%= file_name %>-bar-action" ><%%= link_to "Log in", login_path, { :title => "Log in" } %> /
|
7
|
+
<%%= link_to "Sign up", signup_path, { :title => "Create an account" } %></div>
|
8
|
+
<%% end -%>
|
@@ -0,0 +1,189 @@
|
|
1
|
+
module AuthenticatedSystem
|
2
|
+
protected
|
3
|
+
# Returns true or false if the <%= file_name %> is logged in.
|
4
|
+
# Preloads @current_<%= file_name %> with the <%= file_name %> model if they're logged in.
|
5
|
+
def logged_in?
|
6
|
+
!!current_<%= file_name %>
|
7
|
+
end
|
8
|
+
|
9
|
+
# Accesses the current <%= file_name %> from the session.
|
10
|
+
# Future calls avoid the database because nil is not equal to false.
|
11
|
+
def current_<%= file_name %>
|
12
|
+
@current_<%= file_name %> ||= (login_from_session || login_from_basic_auth || login_from_cookie) unless @current_<%= file_name %> == false
|
13
|
+
end
|
14
|
+
|
15
|
+
# Store the given <%= file_name %> id in the session.
|
16
|
+
def current_<%= file_name %>=(new_<%= file_name %>)
|
17
|
+
session[:<%= file_name %>_id] = new_<%= file_name %> ? new_<%= file_name %>.id : nil
|
18
|
+
@current_<%= file_name %> = new_<%= file_name %> || false
|
19
|
+
end
|
20
|
+
|
21
|
+
# Check if the <%= file_name %> is authorized
|
22
|
+
#
|
23
|
+
# Override this method in your controllers if you want to restrict access
|
24
|
+
# to only a few actions or if you want to check if the <%= file_name %>
|
25
|
+
# has the correct rights.
|
26
|
+
#
|
27
|
+
# Example:
|
28
|
+
#
|
29
|
+
# # only allow nonbobs
|
30
|
+
# def authorized?
|
31
|
+
# current_<%= file_name %>.login != "bob"
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
def authorized?(action = action_name, resource = nil)
|
35
|
+
logged_in?
|
36
|
+
end
|
37
|
+
|
38
|
+
# Filter method to enforce a login requirement.
|
39
|
+
#
|
40
|
+
# To require logins for all actions, use this in your controllers:
|
41
|
+
#
|
42
|
+
# before_filter :login_required
|
43
|
+
#
|
44
|
+
# To require logins for specific actions, use this in your controllers:
|
45
|
+
#
|
46
|
+
# before_filter :login_required, :only => [ :edit, :update ]
|
47
|
+
#
|
48
|
+
# To skip this in a subclassed controller:
|
49
|
+
#
|
50
|
+
# skip_before_filter :login_required
|
51
|
+
#
|
52
|
+
def login_required
|
53
|
+
authorized? || access_denied
|
54
|
+
end
|
55
|
+
|
56
|
+
# Redirect as appropriate when an access request fails.
|
57
|
+
#
|
58
|
+
# The default action is to redirect to the login screen.
|
59
|
+
#
|
60
|
+
# Override this method in your controllers if you want to have special
|
61
|
+
# behavior in case the <%= file_name %> is not authorized
|
62
|
+
# to access the requested action. For example, a popup window might
|
63
|
+
# simply close itself.
|
64
|
+
def access_denied
|
65
|
+
respond_to do |format|
|
66
|
+
format.html do
|
67
|
+
store_location
|
68
|
+
redirect_to new_<%= controller_routing_name %>_path
|
69
|
+
end
|
70
|
+
# format.any doesn't work in rails version < http://dev.rubyonrails.org/changeset/8987
|
71
|
+
# Add any other API formats here. (Some browsers, notably IE6, send Accept: */* and trigger
|
72
|
+
# the 'format.any' block incorrectly. See http://bit.ly/ie6_borken or http://bit.ly/ie6_borken2
|
73
|
+
# for a workaround.)
|
74
|
+
format.any(:json, :xml) do
|
75
|
+
request_http_basic_authentication 'Web Password'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Store the URI of the current request in the session.
|
81
|
+
#
|
82
|
+
# We can return to this location by calling #redirect_back_or_default.
|
83
|
+
def store_location
|
84
|
+
session[:return_to] = request.request_uri
|
85
|
+
end
|
86
|
+
|
87
|
+
# Redirect to the URI stored by the most recent store_location call or
|
88
|
+
# to the passed default. Set an appropriately modified
|
89
|
+
# after_filter :store_location, :only => [:index, :new, :show, :edit]
|
90
|
+
# for any controller you want to be bounce-backable.
|
91
|
+
def redirect_back_or_default(default, options = {})
|
92
|
+
redirect_to((session[:return_to] || default), options)
|
93
|
+
session[:return_to] = nil
|
94
|
+
end
|
95
|
+
|
96
|
+
# Inclusion hook to make #current_<%= file_name %> and #logged_in?
|
97
|
+
# available as ActionView helper methods.
|
98
|
+
def self.included(base)
|
99
|
+
base.send :helper_method, :current_<%= file_name %>, :logged_in?, :authorized? if base.respond_to? :helper_method
|
100
|
+
end
|
101
|
+
|
102
|
+
#
|
103
|
+
# Login
|
104
|
+
#
|
105
|
+
|
106
|
+
# Called from #current_<%= file_name %>. First attempt to login by the <%= file_name %> id stored in the session.
|
107
|
+
def login_from_session
|
108
|
+
self.current_<%= file_name %> = <%= class_name %>.find_by_id(session[:<%= file_name %>_id]) if session[:<%= file_name %>_id]
|
109
|
+
end
|
110
|
+
|
111
|
+
# Called from #current_<%= file_name %>. Now, attempt to login by basic authentication information.
|
112
|
+
def login_from_basic_auth
|
113
|
+
authenticate_with_http_basic do |login, password|
|
114
|
+
self.current_<%= file_name %> = <%= class_name %>.authenticate(login, password)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
#
|
119
|
+
# Logout
|
120
|
+
#
|
121
|
+
|
122
|
+
# Called from #current_<%= file_name %>. Finaly, attempt to login by an expiring token in the cookie.
|
123
|
+
# for the paranoid: we _should_ be storing <%= file_name %>_token = hash(cookie_token, request IP)
|
124
|
+
def login_from_cookie
|
125
|
+
<%= file_name %> = cookies[:auth_token] && <%= class_name %>.find_by_remember_token(cookies[:auth_token].value)
|
126
|
+
if <%= file_name %> && <%= file_name %>.remember_token?
|
127
|
+
self.current_<%= file_name %> = <%= file_name %>
|
128
|
+
handle_remember_cookie! false # freshen cookie token (keeping date)
|
129
|
+
self.current_<%= file_name %>
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# This is ususally what you want; resetting the session willy-nilly wreaks
|
134
|
+
# havoc with forgery protection, and is only strictly necessary on login.
|
135
|
+
# However, **all session state variables should be unset here**.
|
136
|
+
def logout_keeping_session!
|
137
|
+
# Kill server-side auth cookie
|
138
|
+
@current_<%= file_name %>.forget_me if @current_<%= file_name %>.is_a? <%= class_name %>
|
139
|
+
@current_<%= file_name %> = false # not logged in, and don't do it for me
|
140
|
+
kill_remember_cookie! # Kill client-side auth cookie
|
141
|
+
session[:<%= file_name %>_id] = nil # keeps the session but kill our variable
|
142
|
+
# explicitly kill any other session variables you set
|
143
|
+
end
|
144
|
+
|
145
|
+
# The session should only be reset at the tail end of a form POST --
|
146
|
+
# otherwise the request forgery protection fails. It's only really necessary
|
147
|
+
# when you cross quarantine (logged-out to logged-in).
|
148
|
+
def logout_killing_session!
|
149
|
+
logout_keeping_session!
|
150
|
+
reset_session
|
151
|
+
end
|
152
|
+
|
153
|
+
#
|
154
|
+
# Remember_me Tokens
|
155
|
+
#
|
156
|
+
# Cookies shouldn't be allowed to persist past their freshness date,
|
157
|
+
# and they should be changed at each login
|
158
|
+
|
159
|
+
# Cookies shouldn't be allowed to persist past their freshness date,
|
160
|
+
# and they should be changed at each login
|
161
|
+
|
162
|
+
def valid_remember_cookie?
|
163
|
+
return nil unless @current_<%= file_name %>
|
164
|
+
(@current_<%= file_name %>.remember_token?) &&
|
165
|
+
(cookies[:auth_token] == @current_<%= file_name %>.remember_token)
|
166
|
+
end
|
167
|
+
|
168
|
+
# Refresh the cookie auth token if it exists, create it otherwise
|
169
|
+
def handle_remember_cookie!(new_cookie_flag)
|
170
|
+
return unless @current_<%= file_name %>
|
171
|
+
case
|
172
|
+
when valid_remember_cookie? then @current_<%= file_name %>.refresh_token # keeping same expiry date
|
173
|
+
when new_cookie_flag then @current_<%= file_name %>.remember_me
|
174
|
+
else @current_<%= file_name %>.forget_me
|
175
|
+
end
|
176
|
+
send_remember_cookie!
|
177
|
+
end
|
178
|
+
|
179
|
+
def kill_remember_cookie!
|
180
|
+
cookies.delete :auth_token
|
181
|
+
end
|
182
|
+
|
183
|
+
def send_remember_cookie!
|
184
|
+
cookies[:auth_token] = {
|
185
|
+
:value => @current_<%= file_name %>.remember_token,
|
186
|
+
:expires => @current_<%= file_name %>.remember_token_expires_at }
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module AuthenticatedTestHelper
|
2
|
+
# Sets the current <%= file_name %> in the session from the <%= file_name %> fixtures.
|
3
|
+
def login_as(<%= file_name %>)
|
4
|
+
@request.session[:<%= file_name %>_id] = <%= file_name %> ? (<%= file_name %>.is_a?(<%= file_name.camelize %>) ? <%= file_name %>.id : <%= table_name %>(<%= file_name %>).id) : nil
|
5
|
+
end
|
6
|
+
|
7
|
+
def authorize_as(<%= file_name %>)
|
8
|
+
@request.env["HTTP_AUTHORIZATION"] = <%= file_name %> ? ActionController::HttpAuthentication::Basic.encode_credentials(<%= table_name %>(<%= file_name %>).login, 'monkey') : nil
|
9
|
+
end
|
10
|
+
|
11
|
+
<% if options.rspec? -%>
|
12
|
+
# rspec
|
13
|
+
def mock_<%= file_name %>
|
14
|
+
<%= file_name %> = mock_model(<%= class_name %>, :id => 1,
|
15
|
+
:login => 'user_name',
|
16
|
+
:name => 'U. Surname',
|
17
|
+
:to_xml => "<%= class_name %>-in-XML", :to_json => "<%= class_name %>-in-JSON",
|
18
|
+
:errors => [])
|
19
|
+
<%= file_name %>
|
20
|
+
end
|
21
|
+
<% end -%>
|
22
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# This controller handles the login/logout function of the site.
|
2
|
+
class <%= controller_class_name %>Controller < ApplicationController
|
3
|
+
# Be sure to include AuthenticationSystem in Application Controller instead
|
4
|
+
include AuthenticatedSystem
|
5
|
+
|
6
|
+
# render new.rhtml
|
7
|
+
def new
|
8
|
+
end
|
9
|
+
|
10
|
+
def create
|
11
|
+
logout_keeping_session!
|
12
|
+
<%= file_name %> = <%= class_name %>.authenticate(params[:login], params[:password])
|
13
|
+
if <%= file_name %>
|
14
|
+
# Protects against session fixation attacks, causes request forgery
|
15
|
+
# protection if user resubmits an earlier form using back
|
16
|
+
# button. Uncomment if you understand the tradeoffs.
|
17
|
+
# reset_session
|
18
|
+
self.current_<%= file_name %> = <%= file_name %>
|
19
|
+
new_cookie_flag = (params[:remember_me] == "1")
|
20
|
+
handle_remember_cookie! new_cookie_flag
|
21
|
+
redirect_back_or_default('/', :notice => "Logged in successfully")
|
22
|
+
else
|
23
|
+
note_failed_signin
|
24
|
+
@login = params[:login]
|
25
|
+
@remember_me = params[:remember_me]
|
26
|
+
render :action => 'new'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def destroy
|
31
|
+
logout_killing_session!
|
32
|
+
redirect_back_or_default('/', :notice => "You have been logged out.")
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
# Track failed login attempts
|
37
|
+
def note_failed_signin
|
38
|
+
flash.now[:error] = "Couldn't log you in as '#{params[:login]}'"
|
39
|
+
logger.warn "Failed login for '#{params[:login]}' from #{request.remote_ip} at #{Time.now.utc}"
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
Visitors should be in control of creating an account and of proving their
|
2
|
+
essential humanity/accountability or whatever it is people think the
|
3
|
+
id-validation does. We should be fairly skeptical about this process, as the
|
4
|
+
identity+trust chain starts here.
|
5
|
+
|
6
|
+
Story: Creating an account
|
7
|
+
As an anonymous user
|
8
|
+
I want to be able to create an account
|
9
|
+
So that I can be one of the cool kids
|
10
|
+
|
11
|
+
#
|
12
|
+
# Account Creation: Get entry form
|
13
|
+
#
|
14
|
+
Scenario: Anonymous user can start creating an account
|
15
|
+
Given an anonymous user
|
16
|
+
When she goes to /signup
|
17
|
+
Then she should be at the 'users/new' page
|
18
|
+
And the page should look AWESOME
|
19
|
+
And she should see a <form> containing a textfield: Login, textfield: Email, password: Password, password: 'Confirm Password', submit: 'Sign up'
|
20
|
+
|
21
|
+
#
|
22
|
+
# Account Creation
|
23
|
+
#
|
24
|
+
Scenario: Anonymous user can create an account
|
25
|
+
Given an anonymous user
|
26
|
+
And no user with login: 'Oona' exists
|
27
|
+
When she registers an account as the preloaded 'Oona'
|
28
|
+
Then she should be redirected to the home page
|
29
|
+
When she follows that redirect!
|
30
|
+
Then she should see a notice message 'Thanks for signing up!'
|
31
|
+
And a user with login: 'oona' should exist
|
32
|
+
And the user should have login: 'oona', and email: 'unactivated@example.com'
|
33
|
+
|
34
|
+
And oona should be logged in
|
35
|
+
|
36
|
+
|
37
|
+
#
|
38
|
+
# Account Creation Failure: Account exists
|
39
|
+
#
|
40
|
+
|
41
|
+
|
42
|
+
Scenario: Anonymous user can not create an account replacing an activated account
|
43
|
+
Given an anonymous user
|
44
|
+
And an activated user named 'Reggie'
|
45
|
+
And we try hard to remember the user's updated_at, and created_at
|
46
|
+
When she registers an account with login: 'reggie', password: 'monkey', and email: 'reggie@example.com'
|
47
|
+
Then she should be at the 'users/new' page
|
48
|
+
And she should see an errorExplanation message 'Login has already been taken'
|
49
|
+
And she should not see an errorExplanation message 'Email has already been taken'
|
50
|
+
And a user with login: 'reggie' should exist
|
51
|
+
And the user should have email: 'registered@example.com'
|
52
|
+
|
53
|
+
And the user's created_at should stay the same under to_s
|
54
|
+
And the user's updated_at should stay the same under to_s
|
55
|
+
And she should not be logged in
|
56
|
+
|
57
|
+
#
|
58
|
+
# Account Creation Failure: Incomplete input
|
59
|
+
#
|
60
|
+
Scenario: Anonymous user can not create an account with incomplete or incorrect input
|
61
|
+
Given an anonymous user
|
62
|
+
And no user with login: 'Oona' exists
|
63
|
+
When she registers an account with login: '', password: 'monkey', password_confirmation: 'monkey' and email: 'unactivated@example.com'
|
64
|
+
Then she should be at the 'users/new' page
|
65
|
+
And she should see an errorExplanation message 'Login can't be blank'
|
66
|
+
And no user with login: 'oona' should exist
|
67
|
+
|
68
|
+
Scenario: Anonymous user can not create an account with no password
|
69
|
+
Given an anonymous user
|
70
|
+
And no user with login: 'Oona' exists
|
71
|
+
When she registers an account with login: 'oona', password: '', password_confirmation: 'monkey' and email: 'unactivated@example.com'
|
72
|
+
Then she should be at the 'users/new' page
|
73
|
+
And she should see an errorExplanation message 'Password can't be blank'
|
74
|
+
And no user with login: 'oona' should exist
|
75
|
+
|
76
|
+
Scenario: Anonymous user can not create an account with no password_confirmation
|
77
|
+
Given an anonymous user
|
78
|
+
And no user with login: 'Oona' exists
|
79
|
+
When she registers an account with login: 'oona', password: 'monkey', password_confirmation: '' and email: 'unactivated@example.com'
|
80
|
+
Then she should be at the 'users/new' page
|
81
|
+
And she should see an errorExplanation message 'Password confirmation can't be blank'
|
82
|
+
And no user with login: 'oona' should exist
|
83
|
+
|
84
|
+
Scenario: Anonymous user can not create an account with mismatched password & password_confirmation
|
85
|
+
Given an anonymous user
|
86
|
+
And no user with login: 'Oona' exists
|
87
|
+
When she registers an account with login: 'oona', password: 'monkey', password_confirmation: 'monkeY' and email: 'unactivated@example.com'
|
88
|
+
Then she should be at the 'users/new' page
|
89
|
+
And she should see an errorExplanation message 'Password doesn't match confirmation'
|
90
|
+
And no user with login: 'oona' should exist
|
91
|
+
|
92
|
+
Scenario: Anonymous user can not create an account with bad email
|
93
|
+
Given an anonymous user
|
94
|
+
And no user with login: 'Oona' exists
|
95
|
+
When she registers an account with login: 'oona', password: 'monkey', password_confirmation: 'monkey' and email: ''
|
96
|
+
Then she should be at the 'users/new' page
|
97
|
+
And she should see an errorExplanation message 'Email can't be blank'
|
98
|
+
And no user with login: 'oona' should exist
|
99
|
+
When she registers an account with login: 'oona', password: 'monkey', password_confirmation: 'monkey' and email: 'unactivated@example.com'
|
100
|
+
Then she should be redirected to the home page
|
101
|
+
When she follows that redirect!
|
102
|
+
Then she should see a notice message 'Thanks for signing up!'
|
103
|
+
And a user with login: 'oona' should exist
|
104
|
+
And the user should have login: 'oona', and email: 'unactivated@example.com'
|
105
|
+
|
106
|
+
And oona should be logged in
|
107
|
+
|
108
|
+
|
109
|
+
|
@@ -0,0 +1,134 @@
|
|
1
|
+
Users want to know that nobody can masquerade as them. We want to extend trust
|
2
|
+
only to visitors who present the appropriate credentials. Everyone wants this
|
3
|
+
identity verification to be as secure and convenient as possible.
|
4
|
+
|
5
|
+
Story: Logging in
|
6
|
+
As an anonymous user with an account
|
7
|
+
I want to log in to my account
|
8
|
+
So that I can be myself
|
9
|
+
|
10
|
+
#
|
11
|
+
# Log in: get form
|
12
|
+
#
|
13
|
+
Scenario: Anonymous user can get a login form.
|
14
|
+
Given an anonymous user
|
15
|
+
When she goes to /login
|
16
|
+
Then she should be at the new sessions page
|
17
|
+
And the page should look AWESOME
|
18
|
+
And she should see a <form> containing a textfield: Login, password: Password, and submit: 'Log in'
|
19
|
+
|
20
|
+
#
|
21
|
+
# Log in successfully, but don't remember me
|
22
|
+
#
|
23
|
+
Scenario: Anonymous user can log in
|
24
|
+
Given an anonymous user
|
25
|
+
And an activated user named 'reggie'
|
26
|
+
When she creates a singular sessions with login: 'reggie', password: 'monkey', remember me: ''
|
27
|
+
Then she should be redirected to the home page
|
28
|
+
When she follows that redirect!
|
29
|
+
Then she should see a notice message 'Logged in successfully'
|
30
|
+
And reggie should be logged in
|
31
|
+
And she should not have an auth_token cookie
|
32
|
+
|
33
|
+
Scenario: Logged-in user who logs in should be the new one
|
34
|
+
Given an activated user named 'reggie'
|
35
|
+
And an activated user logged in as 'oona'
|
36
|
+
When she creates a singular sessions with login: 'reggie', password: 'monkey', remember me: ''
|
37
|
+
Then she should be redirected to the home page
|
38
|
+
When she follows that redirect!
|
39
|
+
Then she should see a notice message 'Logged in successfully'
|
40
|
+
And reggie should be logged in
|
41
|
+
And she should not have an auth_token cookie
|
42
|
+
|
43
|
+
#
|
44
|
+
# Log in successfully, remember me
|
45
|
+
#
|
46
|
+
Scenario: Anonymous user can log in and be remembered
|
47
|
+
Given an anonymous user
|
48
|
+
And an activated user named 'reggie'
|
49
|
+
When she creates a singular sessions with login: 'reggie', password: 'monkey', remember me: '1'
|
50
|
+
Then she should be redirected to the home page
|
51
|
+
When she follows that redirect!
|
52
|
+
Then she should see a notice message 'Logged in successfully'
|
53
|
+
And reggie should be logged in
|
54
|
+
And she should have an auth_token cookie
|
55
|
+
# assumes fixtures were run sometime
|
56
|
+
And her session store should have user_id: 4
|
57
|
+
|
58
|
+
#
|
59
|
+
# Log in unsuccessfully
|
60
|
+
#
|
61
|
+
|
62
|
+
Scenario: Logged-in user who fails logs in should be logged out
|
63
|
+
Given an activated user named 'oona'
|
64
|
+
When she creates a singular sessions with login: 'oona', password: '1234oona', remember me: '1'
|
65
|
+
Then she should be redirected to the home page
|
66
|
+
When she follows that redirect!
|
67
|
+
Then she should see a notice message 'Logged in successfully'
|
68
|
+
And oona should be logged in
|
69
|
+
And she should have an auth_token cookie
|
70
|
+
When she creates a singular sessions with login: 'reggie', password: 'i_haxxor_joo'
|
71
|
+
Then she should be at the new sessions page
|
72
|
+
Then she should see an error message 'Couldn't log you in as 'reggie''
|
73
|
+
And she should not be logged in
|
74
|
+
And she should not have an auth_token cookie
|
75
|
+
And her session store should not have user_id
|
76
|
+
|
77
|
+
Scenario: Log-in with bogus info should fail until it doesn't
|
78
|
+
Given an activated user named 'reggie'
|
79
|
+
When she creates a singular sessions with login: 'reggie', password: 'i_haxxor_joo'
|
80
|
+
Then she should be at the new sessions page
|
81
|
+
Then she should see an error message 'Couldn't log you in as 'reggie''
|
82
|
+
And she should not be logged in
|
83
|
+
And she should not have an auth_token cookie
|
84
|
+
And her session store should not have user_id
|
85
|
+
When she creates a singular sessions with login: 'reggie', password: ''
|
86
|
+
Then she should be at the new sessions page
|
87
|
+
Then she should see an error message 'Couldn't log you in as 'reggie''
|
88
|
+
And she should not be logged in
|
89
|
+
And she should not have an auth_token cookie
|
90
|
+
And her session store should not have user_id
|
91
|
+
When she creates a singular sessions with login: '', password: 'monkey'
|
92
|
+
Then she should be at the new sessions page
|
93
|
+
Then she should see an error message 'Couldn't log you in as '''
|
94
|
+
And she should not be logged in
|
95
|
+
And she should not have an auth_token cookie
|
96
|
+
And her session store should not have user_id
|
97
|
+
When she creates a singular sessions with login: 'leonard_shelby', password: 'monkey'
|
98
|
+
Then she should be at the new sessions page
|
99
|
+
Then she should see an error message 'Couldn't log you in as 'leonard_shelby''
|
100
|
+
And she should not be logged in
|
101
|
+
And she should not have an auth_token cookie
|
102
|
+
And her session store should not have user_id
|
103
|
+
When she creates a singular sessions with login: 'reggie', password: 'monkey', remember me: '1'
|
104
|
+
Then she should be redirected to the home page
|
105
|
+
When she follows that redirect!
|
106
|
+
Then she should see a notice message 'Logged in successfully'
|
107
|
+
And reggie should be logged in
|
108
|
+
And she should have an auth_token cookie
|
109
|
+
# assumes fixtures were run sometime
|
110
|
+
And her session store should have user_id: 4
|
111
|
+
|
112
|
+
|
113
|
+
#
|
114
|
+
# Log out successfully (should always succeed)
|
115
|
+
#
|
116
|
+
Scenario: Anonymous (logged out) user can log out.
|
117
|
+
Given an anonymous user
|
118
|
+
When she goes to /logout
|
119
|
+
Then she should be redirected to the home page
|
120
|
+
When she follows that redirect!
|
121
|
+
Then she should see a notice message 'You have been logged out'
|
122
|
+
And she should not be logged in
|
123
|
+
And she should not have an auth_token cookie
|
124
|
+
And her session store should not have user_id
|
125
|
+
|
126
|
+
Scenario: Logged in user can log out.
|
127
|
+
Given an activated user logged in as 'reggie'
|
128
|
+
When she goes to /logout
|
129
|
+
Then she should be redirected to the home page
|
130
|
+
When she follows that redirect!
|
131
|
+
Then she should see a notice message 'You have been logged out'
|
132
|
+
And she should not be logged in
|
133
|
+
And she should not have an auth_token cookie
|
134
|
+
And her session store should not have user_id
|