quo_vadis 1.1.2 → 1.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/CHANGELOG.md CHANGED
@@ -1,6 +1,11 @@
1
1
  # CHANGELOG
2
2
 
3
3
 
4
+ ## 1.2.0 (18 July 2012)
5
+
6
+ * User activation.
7
+
8
+
4
9
  ## 1.1.2 (7 February 2012)
5
10
 
6
11
  * Replace ActiveSupport::SecureRandom with SecureRandom.
data/README.md CHANGED
@@ -10,7 +10,7 @@ Features:
10
10
  * No surprises: it does what you expect.
11
11
  * Easy to customise.
12
12
  * Uses BCrypt to encrypt passwords.
13
- * Sign in, sign out, forgotten password, authenticate actions, remember user between browser sessions.
13
+ * Sign in, sign out, forgotten password, authenticate actions, remember user between browser sessions, user activation.
14
14
  * Block accounts.
15
15
  * Let you choose which model(s) to authenticate (defaults to `User`).
16
16
 
@@ -25,7 +25,6 @@ Forthcoming features:
25
25
  What it doesn't and won't do:
26
26
 
27
27
  * Authorisation.
28
- * Sign up; that's user management, not authentication.
29
28
  * Work outside Rails 3.
30
29
  * OpenID, OAuth, LDAP, CAS, etc.
31
30
  * Separate identity from authentication services (cf OmniAuth).
@@ -106,36 +105,87 @@ Finally, write the change-password page ([example](https://github.com/airblade/q
106
105
  * PUT the parameter `:password` to `change_password_url(params[:token])`
107
106
 
108
107
 
109
- ## Customisation
110
-
111
- You can customise the flash messages and mailer from/subject in `config/locales/quo_vadis.en.yml`.
108
+ ## Sign up (directly, without activation)
112
109
 
113
- 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.
110
+ When you create a user, you need to sign them in. Do this by calling `sign_in(user)` in your controller. For example:
114
111
 
115
- If you want to add other session management type features, go right ahead: create a `SessionsController` as normal and carry on.
116
-
117
- You can skip the validation of authentication attributes (password etc) by overriding `should_authenticate?` in your model. Perhaps only some of the users should be able to sign in, so you don't want to force them to have a password.
112
+ # In your app
113
+ class UsersController < ApplicationController
114
+ def create
115
+ @user = User.new params[:user]
116
+ if @user.save
117
+ sign_in @user # <-- NOTE: sign in your user here
118
+ else
119
+ render 'new'
120
+ end
121
+ end
122
+ end
118
123
 
124
+ 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.
119
125
 
120
- ## Sign up / user registration
121
126
 
122
- Quo Vadis doesn't offer sign-up because that's user management, not authentication.
127
+ ## Sign up (with activation)
123
128
 
124
- 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:
129
+ To create a user who must activate their account (via email) before they can sign in, do this:
125
130
 
126
131
  # In your app
127
132
  class UsersController < ApplicationController
128
133
  def create
129
- @user = User.new params[:user]
134
+ @user = User.new_for_activation params[:user] # <-- NOTE: different constructor
130
135
  if @user.save
131
- sign_in @user # <-- NOTE: sign in your user here
136
+ QuoVadis::SessionsController.new.invite_to_activate @user # <-- NOTE: email user here
137
+ redirect_to root_path, notice: "Emailed sign-in instructions to #{@user.name}" # or whatever
132
138
  else
133
139
  render 'new'
134
140
  end
135
141
  end
136
142
  end
137
143
 
138
- 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.
144
+ The user will receive an email with a link which takes them to a page (which you must write) where they can choose a username and password for themselves. When they submit the form their new credentials are stored and they are signed in.
145
+
146
+ Here's the workflow:
147
+
148
+ 1. [New user page, without username/password fields] You or user fills in and submits form.
149
+ 2. [Users controller] Create user and invite to activate. See code snippet above.
150
+ 3. Quo Vadis emails the user a message with an invitation link. The link is valid for 3 hours.
151
+ 4. [The email] The user clicks the link.
152
+ 5. [Invitation page] The user fills in their new username and password.
153
+ 6. Quo Vadis sets the user's username and password and signs the user in.
154
+
155
+ It'll take you about 3 minutes to implement this.
156
+
157
+ Update your user controller's `create` action as above.
158
+
159
+ Write the mailer view, i.e. the email which will be sent to your new users ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/notifier/invite.text.erb)). The view must:
160
+
161
+ * be at `app/views/quo_vadis/notifier/invite.text.erb`
162
+ * render `@url` somewhere (this is the link the user clicks to go to the invitation page)
163
+
164
+ You can also refer to `@user` in the email view, as well as any other data you pass to `invite_to_activate`.
165
+
166
+ Configure the email's from address in `config/initializers/quo_vadis.rb`.
167
+
168
+ Configure the default host so ActionMailer can generate the URL. In `config/environments/<env>.rb`:
169
+
170
+ config.action_mailer.default_url_options = {:host => 'yourdomain.com'}
171
+
172
+ Finally, write the invitation page ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/sessions/invite.html.erb)). The form must:
173
+
174
+ * be in `app/views/sessions/invite.html.:format`
175
+ * POST the parameters `:username` and `:password` to `activation_url(params[:token])`
176
+
177
+ If the token expires and you need to generate a new one, re-invite the user with: `invite_to_activate @user`.
178
+
179
+
180
+ ## Customisation
181
+
182
+ You can customise the flash messages and mailer from/subject in `config/locales/quo_vadis.en.yml`.
183
+
184
+ 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.
185
+
186
+ If you want to add other session management type features, go right ahead: create a `SessionsController` as normal and carry on.
187
+
188
+ You can skip the validation of authentication attributes (password etc) by overriding `should_authenticate?` in your model. Perhaps only some of the users should be able to sign in, so you don't want to force them to have a password.
139
189
 
140
190
 
141
191
  ## See also
@@ -39,7 +39,7 @@ class QuoVadis::SessionsController < ApplicationController
39
39
  if params[:username].present? &&
40
40
  (user = QuoVadis.model_class.where(:username => params[:username]).first)
41
41
  if user.email.present?
42
- user.generate_token
42
+ user.generate_token!
43
43
  QuoVadis::Notifier.change_password(user).deliver
44
44
  flash_if_present :notice, 'quo_vadis.flash.forgotten.sent_email'
45
45
  redirect_to :root
@@ -59,7 +59,7 @@ class QuoVadis::SessionsController < ApplicationController
59
59
  if QuoVadis.model_class.valid_token(params[:token]).first
60
60
  render 'sessions/edit'
61
61
  else
62
- invalid_token
62
+ invalid_token :forgotten
63
63
  end
64
64
  end
65
65
 
@@ -79,15 +79,58 @@ class QuoVadis::SessionsController < ApplicationController
79
79
  render 'sessions/edit'
80
80
  end
81
81
  else
82
- invalid_token
82
+ invalid_token :forgotten
83
83
  end
84
84
  end
85
85
 
86
+ # GET invitation_path /sign-in/invite/:token
87
+ def invite
88
+ if (user = QuoVadis.model_class.valid_token(params[:token]).first)
89
+ render 'sessions/invite'
90
+ else
91
+ invalid_token :activation
92
+ end
93
+ end
94
+
95
+ # POST activation_path /sign-in/accept/:token
96
+ def accept
97
+ if (user = QuoVadis.model_class.valid_token(params[:token]).first)
98
+ user.username, user.password = params[:username], params[:password]
99
+ # When we create a user who must activate their account, we give them
100
+ # a random username and password. However we want to treat them as if
101
+ # they weren't set at all.
102
+ user.password_digest = nil if params[:password].blank?
103
+ if user.save
104
+ user.clear_token
105
+ flash_if_present :notice, 'quo_vadis.flash.activation.accepted'
106
+ sign_in user
107
+ else
108
+ render 'sessions/invite'
109
+ end
110
+ else
111
+ invalid_token :activation
112
+ end
113
+ end
114
+
115
+ # Invites a user to set up their sign-in credentials.
116
+ def invite_to_activate(user, data = {})
117
+ return false if user.email.blank?
118
+ user.generate_token!
119
+ QuoVadis::Notifier.invite(user, data).deliver
120
+ true
121
+ end
122
+ hide_action :send_invitation
123
+
86
124
  private
87
125
 
88
- def invalid_token # :nodoc:
89
- flash_if_present :alert, 'quo_vadis.flash.forgotten.invalid_token'
90
- redirect_to forgotten_sign_in_url
126
+ def invalid_token(workflow) # :nodoc:
127
+ if workflow == :activation
128
+ flash_if_present :alert, 'quo_vadis.flash.activation.invalid_token'
129
+ redirect_to root_path
130
+ else
131
+ flash_if_present :alert, 'quo_vadis.flash.forgotten.invalid_token'
132
+ redirect_to forgotten_sign_in_url
133
+ end
91
134
  end
92
135
 
93
136
  def quo_vadis_layout # :nodoc:
@@ -6,7 +6,19 @@ module QuoVadis
6
6
  def change_password(user)
7
7
  @username = user.username
8
8
  @url = change_password_url user.token
9
- mail :to => user.email, :from => QuoVadis.from, :subject => QuoVadis.subject
9
+ mail :to => user.email, :from => QuoVadis.from, :subject => QuoVadis.subject_change_password
10
+ end
11
+
12
+ # Sends an email to <tt>user</tt> with a link to a page where they
13
+ # can choose their username and password.
14
+ #
15
+ # `data` - hash of data to pass to view via instance variables. A key of `:foo`
16
+ # will be available via `@foo`.
17
+ def invite(user, data = {})
18
+ @user = user
19
+ @url = invitation_url user.token
20
+ data.each { |k,v| instance_variable_set :"@#{k}", v }
21
+ mail :to => user.email, :from => QuoVadis.from, :subject => QuoVadis.subject_invitation
10
22
  end
11
23
 
12
24
  end
@@ -44,6 +44,17 @@ module ModelMixin
44
44
  nil
45
45
  end
46
46
  end
47
+
48
+ # Instantiates a user suitable for user-activation.
49
+ def new_for_activation(attributes = nil)
50
+ user = new attributes
51
+ # Satisfy username and password validations by setting to random values.
52
+ begin
53
+ user.username = SecureRandom.base64(10)
54
+ end while exists?(:username => user.username)
55
+ user.password = SecureRandom.base64(10)
56
+ user
57
+ end
47
58
  END
48
59
  end
49
60
  end
@@ -61,13 +72,18 @@ module ModelMixin
61
72
  end
62
73
  end
63
74
 
64
- # Generates a unique, timestamped token which can be used in URLs, and
65
- # saves the record. This is part of the forgotten-password workflow.
75
+ # Generates a unique, timestamped token.
66
76
  def generate_token # :nodoc:
67
77
  begin
68
78
  self.token = url_friendly_token
69
79
  end while self.class.exists?(:token => token)
70
80
  self.token_created_at = Time.now.utc
81
+ end
82
+
83
+ # Generates a unique, timestamped token which can be used in URLs, and
84
+ # saves the record. This is part of the forgotten-password workflow.
85
+ def generate_token! # :nodoc:
86
+ generate_token
71
87
  save
72
88
  end
73
89
 
@@ -15,3 +15,7 @@ en:
15
15
  sent_email: "We've emailed you a link where you can change your password."
16
16
  invalid_token: "Sorry, this link isn't valid anymore."
17
17
  password_changed: "You have successfully changed your password and you're now signed in."
18
+
19
+ activation:
20
+ accepted: "Your account is active and you're now signed in."
21
+ invalid_token: "Sorry, this link isn't valid anymore."
data/config/routes.rb CHANGED
@@ -6,8 +6,10 @@ Rails.application.routes.draw do
6
6
  get 'sign-in/forgotten' => 'sessions#forgotten', :as => 'forgotten_sign_in'
7
7
  post 'sign-in/forgotten' => 'sessions#forgotten', :as => 'forgotten_sign_in'
8
8
  constraints :token => /.+/ do
9
- get 'sign-in/change-password/:token' => 'sessions#edit', :as => 'change_password'
10
- put 'sign-in/change-password/:token' => 'sessions#update', :as => 'change_password'
9
+ get 'sign-in/change-password/:token' => 'sessions#edit', :as => 'change_password'
10
+ put 'sign-in/change-password/:token' => 'sessions#update', :as => 'change_password'
11
+ get 'sign-in/invite/:token' => 'sessions#invite', :as => 'invitation'
12
+ post 'sign-in/accept/:token' => 'sessions#accept', :as => 'activation'
11
13
  end
12
14
  end
13
15
  end
@@ -3,9 +3,9 @@ class AddAuthenticationTo<%= model_name.pluralize.camelize %> < ActiveRecord::Mi
3
3
  add_column :<%= model_name.tableize %>, :username, :string # for user identification
4
4
  add_column :<%= model_name.tableize %>, :password_digest, :string
5
5
 
6
- add_column :<%= model_name.tableize %>, :email, :string # for forgotten-credentials
7
- add_column :<%= model_name.tableize %>, :token, :string # for forgotten-credentials
8
- add_column :<%= model_name.tableize %>, :token_created_at, :string # for forgotten-credentials
6
+ add_column :<%= model_name.tableize %>, :email, :string # for forgotten-credentials / activation
7
+ add_column :<%= model_name.tableize %>, :token, :string # for forgotten-credentials / activation
8
+ add_column :<%= model_name.tableize %>, :token_created_at, :string # for forgotten-credentials / activation
9
9
  end
10
10
 
11
11
  def self.down
@@ -73,14 +73,17 @@ QuoVadis.configure do |config|
73
73
 
74
74
 
75
75
  #
76
- # Forgotten-password Mailer
76
+ # Forgotten-password and activation Mailer
77
77
  #
78
78
 
79
79
  # From whom the forgotten-password email should be sent.
80
80
  config.from = 'noreply@example.com'
81
81
 
82
82
  # Subject of the forgotten-password email.
83
- config.subject = 'Change your password'
83
+ config.subject_change_password = 'Change your password'
84
+
85
+ # Subject of the invitation email.
86
+ config.subject_invitation = 'Activate your account'
84
87
 
85
88
 
86
89
  #
@@ -1,3 +1,3 @@
1
1
  module QuoVadis
2
- VERSION = '1.1.2'
2
+ VERSION = '1.2.0'
3
3
  end
data/lib/quo_vadis.rb CHANGED
@@ -94,7 +94,7 @@ module QuoVadis
94
94
 
95
95
 
96
96
  #
97
- # Forgotten-password Mailer
97
+ # Forgotten-password and activation Mailer
98
98
  #
99
99
 
100
100
  # From whom the forgotten-password email should be sent.
@@ -102,9 +102,12 @@ module QuoVadis
102
102
  @@from = 'noreply@example.com'
103
103
 
104
104
  # Subject of the forgotten-password email.
105
- mattr_accessor :subject
106
- @@subject = 'Change your password.'
105
+ mattr_accessor :subject_change_password
106
+ @@subject_change_password = 'Change your password.'
107
107
 
108
+ # Subject of the invitation email.
109
+ mattr_accessor :subject_invitation
110
+ @@subject_invitation = 'Activate your account'
108
111
 
109
112
 
110
113
  #
@@ -0,0 +1,8 @@
1
+ Hello <%= @user.name %>,
2
+
3
+ You can activate your account by clicking this link (valid for 3 hours):
4
+ <%= @url %>
5
+
6
+ <% if instance_variable_defined? :@foo %><%= @foo %><% end %>
7
+
8
+ Thanks!
@@ -0,0 +1,15 @@
1
+ <h1>Choose your username and password</h1>
2
+
3
+ <%= form_tag activation_path(params[:token]) do %>
4
+ <p>
5
+ <%= label_tag :username %>
6
+ <%= text_field_tag :username %>
7
+ </p>
8
+ <p>
9
+ <%= label_tag :password %>
10
+ <%= password_field_tag :password %>
11
+ </p>
12
+ <p>
13
+ <%= submit_tag 'Save my details' %>
14
+ </p>
15
+ <% end %>
@@ -68,7 +68,10 @@ QuoVadis.configure do |config|
68
68
  config.from = 'noreply@example.com'
69
69
 
70
70
  # Subject of the forgotten-password email.
71
- config.subject = 'Change your password'
71
+ config.subject_change_password = 'Change your password'
72
+
73
+ # Subject of the invitation email.
74
+ config.subject_invitation = 'Activate your account'
72
75
 
73
76
 
74
77
  #
@@ -0,0 +1,16 @@
1
+ # TODO: remove once on Rack 1.3.0.
2
+ # https://github.com/jnicklas/capybara/issues/87#issuecomment-2106788
3
+ module Rack
4
+ module Utils
5
+
6
+ def escape(s)
7
+ CGI.escape s.to_s
8
+ end
9
+
10
+ def unescape(s)
11
+ CGI.unescape s
12
+ end
13
+
14
+ end
15
+ end
16
+
@@ -15,3 +15,7 @@ en:
15
15
  sent_email: "We've emailed you a link where you can change your password."
16
16
  invalid_token: "Sorry, this link isn't valid anymore."
17
17
  password_changed: "You have successfully changed your password and you're now signed in."
18
+
19
+ activation:
20
+ accepted: "Your account is active and you're now signed in."
21
+ invalid_token: "Sorry, this link isn't valid anymore."
@@ -0,0 +1,98 @@
1
+ require 'test_helper'
2
+
3
+ class ActivationTest < ActiveSupport::IntegrationCase
4
+
5
+ teardown do
6
+ Capybara.reset_sessions!
7
+ end
8
+
9
+ test 'a user can be invited' do
10
+ user = User.new_for_activation :name => 'Bob', :email => 'bob@example.com'
11
+ assert user.save
12
+ assert QuoVadis::SessionsController.new.invite_to_activate user
13
+
14
+ assert ActionMailer::Base.deliveries.last
15
+ assert !ActionMailer::Base.deliveries.empty?
16
+ email = ActionMailer::Base.deliveries.last
17
+
18
+ assert_equal ['bob@example.com'], email.to
19
+ assert_equal ['noreply@example.com'], email.from
20
+ assert_equal 'Activate your account', email.subject
21
+ # Why doesn't this use the default url option set up in test/test_helper.rb#9?
22
+ assert_match Regexp.new(Regexp.escape(invitation_url user.token, :host => 'www.example.com')), email.encoded
23
+ end
24
+
25
+ test 'a user without email cannot be invited' do
26
+ user = User.new_for_activation :name => 'Bob'
27
+ assert user.save
28
+ assert ! QuoVadis::SessionsController.new.invite_to_activate(user)
29
+ end
30
+
31
+ test 'user can accept a valid invitation and set valid credentials' do
32
+ user = User.new_for_activation :name => 'Bob', :email => 'bob@example.com'
33
+ user.generate_token
34
+ assert user.save
35
+
36
+ visit invitation_url(user.token, :host => 'www.example.com')
37
+ fill_in 'Username', :with => 'bob'
38
+ fill_in 'Password', :with => 'secret'
39
+ click_button 'Save my details'
40
+ assert_equal root_path, current_path
41
+ within '.flash.notice' do
42
+ assert page.has_content?("Your account is active and you're now signed in.")
43
+ end
44
+ assert_nil user.reload.token
45
+ assert_nil user.token_created_at
46
+ end
47
+
48
+ test 'user can accept a valid invitation but not set invalid credentials' do
49
+ user = User.new_for_activation :name => 'Bob', :email => 'bob@example.com'
50
+ user.generate_token
51
+ assert user.save
52
+
53
+ visit invitation_url(user.token, :host => 'www.example.com')
54
+ fill_in 'Username', :with => 'bob'
55
+ fill_in 'Password', :with => ''
56
+ click_button 'Save my details'
57
+ assert_equal activation_path(user.token), current_path
58
+ assert user.reload.token
59
+ assert user.token_created_at
60
+ end
61
+
62
+ test 'user cannot view an expired invitation' do
63
+ user = User.new_for_activation :name => 'Bob', :email => 'bob@example.com'
64
+ user.generate_token
65
+ assert user.save
66
+ user.update_attributes :token_created_at => 1.day.ago
67
+
68
+ visit invitation_url(user.token, :host => 'www.example.com')
69
+ assert_equal root_path, current_path
70
+ within '.flash.alert' do
71
+ assert page.has_content?("Sorry, this link isn't valid anymore.")
72
+ end
73
+ end
74
+
75
+ test 'user cannot accept an expired invitation' do
76
+ user = User.new_for_activation :name => 'Bob', :email => 'bob@example.com'
77
+ user.generate_token
78
+ assert user.save
79
+
80
+ visit invitation_url(user.token, :host => 'www.example.com')
81
+ user.update_attributes :token_created_at => 1.day.ago
82
+ fill_in 'Username', :with => 'bob'
83
+ fill_in 'Password', :with => 'secret'
84
+ click_button 'Save my details'
85
+ assert_equal root_path, current_path
86
+ within '.flash.alert' do
87
+ assert page.has_content?("Sorry, this link isn't valid anymore.")
88
+ end
89
+ end
90
+
91
+ test 'data can be passed to invitation email' do
92
+ user = User.new_for_activation :name => 'Bob', :email => 'bob@example.com'
93
+ assert user.save
94
+ assert QuoVadis::SessionsController.new.invite_to_activate user, :foo => 'Barbaz'
95
+ email = ActionMailer::Base.deliveries.last
96
+ assert_match Regexp.new('Barbaz'), email.encoded
97
+ end
98
+ end
@@ -108,18 +108,25 @@ class ConfigTest < ActiveSupport::IntegrationCase
108
108
  assert page.has_content?('Sessions layout')
109
109
  end
110
110
 
111
- test 'mailer from config' do
111
+ test 'change-password mailer from config' do
112
112
  QuoVadis.from = 'jim@example.com'
113
113
  (user = User.last).generate_token
114
114
  email = QuoVadis::Notifier.change_password(user)
115
115
  assert_equal ['jim@example.com'], email.from
116
116
  end
117
117
 
118
- test 'mailer subject config' do
119
- QuoVadis.subject = 'You idiot!'
118
+ test 'change-password mailer subject config' do
119
+ QuoVadis.subject_change_password = 'You idiot!'
120
120
  (user = User.last).generate_token
121
121
  email = QuoVadis::Notifier.change_password(user)
122
122
  assert_equal 'You idiot!', email.subject
123
123
  end
124
124
 
125
+ test 'invitation mailer subject config' do
126
+ QuoVadis.subject_invitation = 'Wooha'
127
+ (user = User.last).generate_token
128
+ email = QuoVadis::Notifier.invite(user)
129
+ assert_equal 'Wooha', email.subject
130
+ end
131
+
125
132
  end
@@ -171,7 +171,7 @@ class LocaleTest < ActiveSupport::IntegrationCase
171
171
 
172
172
  test 'forgotten.password_changed flash' do
173
173
  user_factory 'Bob', 'bob', 'secret', 'bob@example.com'
174
- User.last.generate_token
174
+ User.last.generate_token!
175
175
  visit change_password_path(User.last.token)
176
176
  fill_in :password, :with => 'topsecret'
177
177
  click_button 'Change my password'
@@ -184,7 +184,7 @@ class LocaleTest < ActiveSupport::IntegrationCase
184
184
  begin
185
185
  I18n.backend.store_translations :en, {:quo_vadis => {:flash => {:forgotten => {:password_changed => ''}}}}
186
186
  user_factory 'Bob', 'bob', 'secret', 'bob@example.com'
187
- User.last.generate_token
187
+ User.last.generate_token!
188
188
  visit change_password_path(User.last.token)
189
189
  fill_in :password, :with => 'topsecret'
190
190
  click_button 'Change my password'
@@ -14,13 +14,13 @@ class SignInPersonTest < ActiveSupport::IntegrationCase
14
14
 
15
15
  END
16
16
 
17
- # person_factory 'James', 'jim', 'secret'
18
- # sign_in_as 'jim', 'secret'
17
+ person_factory 'James', 'jim', 'secret'
18
+ sign_in_as 'jim', 'secret'
19
19
 
20
- # assert_equal root_path, current_path
21
- # within '.flash.notice' do
22
- # assert page.has_content?('You have successfully signed in.')
23
- # end
20
+ assert_equal root_path, current_path
21
+ within '.flash.notice' do
22
+ assert page.has_content?('You have successfully signed in.')
23
+ end
24
24
  end
25
25
 
26
26
  end
data/test/test_helper.rb CHANGED
@@ -56,7 +56,8 @@ def reset_quo_vadis_configuration
56
56
  QuoVadis.signed_out_hook = nil
57
57
  QuoVadis.layout = 'application'
58
58
  QuoVadis.from = 'noreply@example.com'
59
- QuoVadis.subject = 'Change your password'
59
+ QuoVadis.subject_change_password = 'Change your password'
60
+ QuoVadis.subject_invitation = 'Activate your account'
60
61
  QuoVadis.remember_for = 2.weeks
61
62
  QuoVadis.blocked = false
62
63
  end
@@ -51,4 +51,14 @@ class UserTest < ActiveSupport::TestCase
51
51
  assert user.valid?
52
52
  end
53
53
 
54
+ test 'create for activation' do
55
+ user = User.new_for_activation :name => 'Bob'
56
+ assert user.valid?
57
+
58
+ user = User.new_for_activation :name => 'John', :username => 'john', :password => 'secret'
59
+ assert user.valid?
60
+ assert_not_equal 'john', user.username
61
+ assert_not_equal 'secret', user.password
62
+ end
63
+
54
64
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quo_vadis
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-07 00:00:00.000000000 Z
12
+ date: 2012-07-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &2157988380 !ruby/object:Gem::Requirement
16
+ requirement: &2156553540 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '3.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2157988380
24
+ version_requirements: *2156553540
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bcrypt-ruby
27
- requirement: &2157987500 !ruby/object:Gem::Requirement
27
+ requirement: &2156550300 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 3.0.0
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2157987500
35
+ version_requirements: *2156550300
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rails
38
- requirement: &2157986780 !ruby/object:Gem::Requirement
38
+ requirement: &2156568880 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 3.0.4
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2157986780
46
+ version_requirements: *2156568880
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: sqlite3-ruby
49
- requirement: &2157986100 !ruby/object:Gem::Requirement
49
+ requirement: &2156564820 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *2157986100
57
+ version_requirements: *2156564820
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: capybara
60
- requirement: &2157967940 !ruby/object:Gem::Requirement
60
+ requirement: &2152428460 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '1.1'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *2157967940
68
+ version_requirements: *2152428460
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: launchy
71
- requirement: &2157967080 !ruby/object:Gem::Requirement
71
+ requirement: &2152426880 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *2157967080
79
+ version_requirements: *2152426880
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rake
82
- requirement: &2157965940 !ruby/object:Gem::Requirement
82
+ requirement: &2152425340 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *2157965940
90
+ version_requirements: *2152425340
91
91
  description: Simple username/password authentication for Rails 3.
92
92
  email:
93
93
  - boss@airbladesoftware.com
@@ -128,8 +128,10 @@ files:
128
128
  - test/dummy/app/views/layouts/application.html.erb
129
129
  - test/dummy/app/views/layouts/sessions.html.erb
130
130
  - test/dummy/app/views/quo_vadis/notifier/change_password.text.erb
131
+ - test/dummy/app/views/quo_vadis/notifier/invite.text.erb
131
132
  - test/dummy/app/views/sessions/edit.html.erb
132
133
  - test/dummy/app/views/sessions/forgotten.html.erb
134
+ - test/dummy/app/views/sessions/invite.html.erb
133
135
  - test/dummy/app/views/sessions/new.html.erb
134
136
  - test/dummy/app/views/users/new.html.erb
135
137
  - test/dummy/config.ru
@@ -144,6 +146,7 @@ files:
144
146
  - test/dummy/config/initializers/inflections.rb
145
147
  - test/dummy/config/initializers/mime_types.rb
146
148
  - test/dummy/config/initializers/quo_vadis.rb
149
+ - test/dummy/config/initializers/rack_patch.rb
147
150
  - test/dummy/config/initializers/secret_token.rb
148
151
  - test/dummy/config/initializers/session_store.rb
149
152
  - test/dummy/config/locales/en.yml
@@ -167,6 +170,7 @@ files:
167
170
  - test/dummy/public/javascripts/rails.js
168
171
  - test/dummy/public/stylesheets/.gitkeep
169
172
  - test/dummy/script/rails
173
+ - test/integration/activation_test.rb
170
174
  - test/integration/authenticate_test.rb
171
175
  - test/integration/blocked_test.rb
172
176
  - test/integration/config_test.rb
@@ -198,7 +202,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
198
202
  version: '0'
199
203
  segments:
200
204
  - 0
201
- hash: 4176509777758211908
205
+ hash: -4183127178798820750
202
206
  required_rubygems_version: !ruby/object:Gem::Requirement
203
207
  none: false
204
208
  requirements:
@@ -207,7 +211,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
207
211
  version: '0'
208
212
  segments:
209
213
  - 0
210
- hash: 4176509777758211908
214
+ hash: -4183127178798820750
211
215
  requirements: []
212
216
  rubyforge_project: quo_vadis
213
217
  rubygems_version: 1.8.11
@@ -230,8 +234,10 @@ test_files:
230
234
  - test/dummy/app/views/layouts/application.html.erb
231
235
  - test/dummy/app/views/layouts/sessions.html.erb
232
236
  - test/dummy/app/views/quo_vadis/notifier/change_password.text.erb
237
+ - test/dummy/app/views/quo_vadis/notifier/invite.text.erb
233
238
  - test/dummy/app/views/sessions/edit.html.erb
234
239
  - test/dummy/app/views/sessions/forgotten.html.erb
240
+ - test/dummy/app/views/sessions/invite.html.erb
235
241
  - test/dummy/app/views/sessions/new.html.erb
236
242
  - test/dummy/app/views/users/new.html.erb
237
243
  - test/dummy/config.ru
@@ -246,6 +252,7 @@ test_files:
246
252
  - test/dummy/config/initializers/inflections.rb
247
253
  - test/dummy/config/initializers/mime_types.rb
248
254
  - test/dummy/config/initializers/quo_vadis.rb
255
+ - test/dummy/config/initializers/rack_patch.rb
249
256
  - test/dummy/config/initializers/secret_token.rb
250
257
  - test/dummy/config/initializers/session_store.rb
251
258
  - test/dummy/config/locales/en.yml
@@ -269,6 +276,7 @@ test_files:
269
276
  - test/dummy/public/javascripts/rails.js
270
277
  - test/dummy/public/stylesheets/.gitkeep
271
278
  - test/dummy/script/rails
279
+ - test/integration/activation_test.rb
272
280
  - test/integration/authenticate_test.rb
273
281
  - test/integration/blocked_test.rb
274
282
  - test/integration/config_test.rb