quo_vadis 1.0.7 → 1.1.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 +21 -0
- data/README.md +7 -5
- data/app/controllers/controller_mixin.rb +51 -48
- data/app/controllers/quo_vadis/sessions_controller.rb +26 -16
- data/app/models/model_mixin.rb +10 -5
- data/lib/generators/quo_vadis/install_generator.rb +3 -2
- data/lib/generators/quo_vadis/templates/migration.rb.erb +18 -0
- data/{config/initializers/quo_vadis.rb → lib/generators/quo_vadis/templates/quo_vadis.rb.erb} +14 -2
- data/lib/quo_vadis/version.rb +1 -1
- data/lib/quo_vadis.rb +24 -3
- data/quo_vadis.gemspec +1 -1
- data/test/dummy/.gitignore +1 -0
- data/test/dummy/app/models/person.rb +3 -0
- data/test/dummy/app/views/layouts/application.html.erb +7 -1
- data/test/dummy/db/migrate/20111004112209_create_people.rb +13 -0
- data/test/dummy/db/migrate/20111004132342_add_authentication_to_people.rb +18 -0
- data/test/integration/config_test.rb +2 -2
- data/test/integration/forgotten_test.rb +10 -0
- data/test/integration/sign_in_person_test.rb +26 -0
- data/test/test_helper.rb +5 -0
- data/test/unit/user_test.rb +17 -0
- metadata +20 -22
- data/lib/generators/quo_vadis/templates/migration.rb +0 -18
- data/test/dummy/tmp/capybara/capybara-20110124133149.html +0 -27
- data/test/dummy/tmp/capybara/capybara-20110124133340.html +0 -27
- data/test/dummy/tmp/capybara/capybara-20110124134001.html +0 -27
- data/test/dummy/tmp/capybara/capybara-20110124134214.html +0 -27
- data/test/dummy/tmp/capybara/capybara-20110124135435.html +0 -39
data/CHANGELOG.md
CHANGED
@@ -1,10 +1,31 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 1.1.0 (7 October 2011)
|
4
|
+
|
5
|
+
* Correctly handle blank username in password reset.
|
6
|
+
* Allow configuration of cookie domain.
|
7
|
+
* Pass controller to signed_{in,out}_url to allow routes with options/parameters.
|
8
|
+
* Fix bug where `signed_in_url` config setting was overwritten.
|
9
|
+
* Harmonise bcrypt-ruby dependency with ActiveModel::SecurePassword.
|
10
|
+
* Allow conditional validation of authentication attributes.
|
11
|
+
* Allow authentication of any model.
|
12
|
+
|
13
|
+
|
14
|
+
## 1.0.7 (4 October 2011)
|
15
|
+
|
16
|
+
* Allow more recent bcrypt-ruby versions.
|
17
|
+
|
18
|
+
|
19
|
+
## 1.0.6 (4 October 2011)
|
20
|
+
|
21
|
+
* Fix sign-in hook when called outside Quo Vadis.
|
22
|
+
|
3
23
|
|
4
24
|
## 1.0.5 (23 February 2011)
|
5
25
|
|
6
26
|
* Support blocking of sign-in process.
|
7
27
|
|
28
|
+
|
8
29
|
## 1.0.4 (22 February 2011)
|
9
30
|
|
10
31
|
* Work with Rails' improved CSRF protection.
|
data/README.md
CHANGED
@@ -12,14 +12,14 @@ Features:
|
|
12
12
|
* Uses BCrypt to encrypt passwords.
|
13
13
|
* Sign in, sign out, forgotten password, authenticate actions, remember user between browser sessions.
|
14
14
|
* Block accounts.
|
15
|
+
* Let you choose which model(s) to authenticate (defaults to `User`).
|
15
16
|
|
16
17
|
Forthcoming features:
|
17
18
|
|
18
19
|
* Generate the views for you (for now, copy the examples given below).
|
19
|
-
* Let you choose which model(s) to authenticate (currently `User`).
|
20
20
|
* Let you choose the identification field (currently `username`).
|
21
21
|
* HTTP basic/digest authentication (probably).
|
22
|
-
* Generate
|
22
|
+
* Generate model plus migration if it doesn't exist.
|
23
23
|
* Detect presence of `has_secure_password` (see below) and adapt appropriately.
|
24
24
|
|
25
25
|
What it doesn't and won't do:
|
@@ -37,11 +37,11 @@ What it doesn't and won't do:
|
|
37
37
|
|
38
38
|
If this takes you more than 5 minutes, you can have your money back ;)
|
39
39
|
|
40
|
-
Install and run the generator: add `gem 'quo_vadis'` to your Gemfile, run `bundle install`, then `rails generate quo_vadis:install
|
40
|
+
Install and run the generator: add `gem 'quo_vadis'` to your Gemfile, run `bundle install`, then `rails generate quo_vadis:install [MODEL_NAME]` (where model name is optional and defaults to `User`).
|
41
41
|
|
42
|
-
Edit and run the generated migration to add the authentication columns: `rake db:migrate`. Note the migration (currently) assumes you already have a
|
42
|
+
Edit and run the generated migration to add the authentication columns: `rake db:migrate`. Note the migration (currently) assumes you already have a table for your model.
|
43
43
|
|
44
|
-
In your `User` model, add `authenticates`:
|
44
|
+
In your `User` (or whichever) model, add `authenticates`:
|
45
45
|
|
46
46
|
class User < ActiveRecord::Base
|
47
47
|
authenticates
|
@@ -114,6 +114,8 @@ You can customise the sign-in and sign-out redirects in `config/initializers/quo
|
|
114
114
|
|
115
115
|
If you want to add other session management type features, go right ahead: create a `SessionsController` as normal and carry on.
|
116
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.
|
118
|
+
|
117
119
|
|
118
120
|
## Sign up / user registration
|
119
121
|
|
@@ -1,72 +1,83 @@
|
|
1
1
|
module ControllerMixin
|
2
2
|
def self.included(base)
|
3
|
-
base.helper_method :
|
3
|
+
base.helper_method :"current_#{QuoVadis.model_instance_name}"
|
4
4
|
end
|
5
5
|
|
6
6
|
protected
|
7
7
|
|
8
8
|
def handle_unverified_request
|
9
9
|
super
|
10
|
-
cookies.delete :remember_me
|
10
|
+
cookies.delete :remember_me, :domain => QuoVadis.cookie_domain
|
11
11
|
end
|
12
12
|
|
13
13
|
private
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
15
|
+
class_eval <<-END, __FILE__, __LINE__ + 1
|
16
|
+
# Remembers the authenticated <tt>user</tt> (in this session and future sessions).
|
17
|
+
#
|
18
|
+
# If you want to sign in a <tt>user</tt> you have just created, call <tt>sign_in</tt>
|
19
|
+
# instead.
|
20
|
+
def current_#{QuoVadis.model_instance_name}=(user)
|
21
|
+
remember_user_in_session user
|
22
|
+
remember_user_between_sessions user
|
23
|
+
end
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
# Returns the authenticated user.
|
26
|
+
def current_#{QuoVadis.model_instance_name}
|
27
|
+
@current_#{QuoVadis.model_instance_name} ||= find_authenticated_user
|
28
|
+
end
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
# Does nothing if we already have an authenticated user. If we don't have an
|
31
|
+
# authenticated user, it stores the desired URL and redirects to the sign in URL.
|
32
|
+
def authenticate
|
33
|
+
unless current_#{QuoVadis.model_instance_name}
|
34
|
+
session[:quo_vadis_original_url] = request.fullpath
|
35
|
+
flash[:notice] = t('quo_vadis.flash.sign_in.before') unless t('quo_vadis.flash.sign_in.before').blank?
|
36
|
+
redirect_to sign_in_url
|
37
|
+
end
|
36
38
|
end
|
37
|
-
end
|
38
39
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
40
|
+
# Signs in a user, i.e. remembers them in the session, runs the sign-in hook,
|
41
|
+
# and redirects appropriately.
|
42
|
+
#
|
43
|
+
# This method should be called when you have just authenticated a <tt>user</tt>
|
44
|
+
# and you need to sign them in. For example, if a new user has just signed up,
|
45
|
+
# you should call this method to sign them in.
|
46
|
+
def sign_in(user)
|
47
|
+
prevent_session_fixation
|
48
|
+
self.current_#{QuoVadis.model_instance_name} = user
|
49
|
+
QuoVadis.signed_in_hook user, self
|
50
|
+
redirect_to QuoVadis.signed_in_url(user, original_url, self)
|
51
|
+
end
|
52
|
+
|
53
|
+
def remember_user_in_session(user) # :nodoc:
|
54
|
+
session[:current_#{QuoVadis.model_instance_name}_id] = user ? user.id : nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def find_user_by_cookie # :nodoc:
|
58
|
+
#{QuoVadis.model}.find_by_salt(*cookies.signed[:remember_me]) if cookies.signed[:remember_me]
|
59
|
+
end
|
60
|
+
|
61
|
+
def find_user_by_session # :nodoc:
|
62
|
+
#{QuoVadis.model}.find(session[:current_#{QuoVadis.model_instance_name}_id]) if session[:current_#{QuoVadis.model_instance_name}_id]
|
63
|
+
end
|
64
|
+
END
|
51
65
|
|
52
66
|
# Returns true if the sign-in process is blocked to the user, false otherwise.
|
53
67
|
def blocked?
|
54
68
|
QuoVadis.blocked?(self)
|
55
69
|
end
|
56
70
|
|
57
|
-
def remember_user_in_session(user) # :nodoc:
|
58
|
-
session[:current_user_id] = user ? user.id : nil
|
59
|
-
end
|
60
|
-
|
61
71
|
def remember_user_between_sessions(user) # :nodoc:
|
62
72
|
if user && QuoVadis.remember_for
|
63
73
|
cookies.signed[:remember_me] = {
|
64
74
|
:value => [user.id, user.password_salt],
|
65
75
|
:expires => QuoVadis.remember_for.from_now,
|
66
|
-
:httponly => true
|
76
|
+
:httponly => true,
|
77
|
+
:domain => QuoVadis.cookie_domain
|
67
78
|
}
|
68
79
|
else
|
69
|
-
cookies.delete :remember_me
|
80
|
+
cookies.delete :remember_me, :domain => QuoVadis.cookie_domain
|
70
81
|
end
|
71
82
|
end
|
72
83
|
|
@@ -74,14 +85,6 @@ module ControllerMixin
|
|
74
85
|
find_user_by_session || find_user_by_cookie
|
75
86
|
end
|
76
87
|
|
77
|
-
def find_user_by_cookie # :nodoc:
|
78
|
-
User.find_by_salt(*cookies.signed[:remember_me]) if cookies.signed[:remember_me]
|
79
|
-
end
|
80
|
-
|
81
|
-
def find_user_by_session # :nodoc:
|
82
|
-
User.find(session[:current_user_id]) if session[:current_user_id]
|
83
|
-
end
|
84
|
-
|
85
88
|
# Returns the URL if any which the user tried to visit before being forced to authenticate.
|
86
89
|
def original_url
|
87
90
|
url = session[:quo_vadis_original_url]
|
@@ -1,4 +1,5 @@
|
|
1
1
|
class QuoVadis::SessionsController < ApplicationController
|
2
|
+
skip_filter :authenticate, :except => [:destroy]
|
2
3
|
layout :quo_vadis_layout
|
3
4
|
|
4
5
|
# GET sign_in_path
|
@@ -9,24 +10,24 @@ class QuoVadis::SessionsController < ApplicationController
|
|
9
10
|
# POST sign_in_path
|
10
11
|
def create
|
11
12
|
if blocked?
|
12
|
-
|
13
|
+
flash_if_present :alert, 'quo_vadis.flash.sign_in.blocked', :now
|
13
14
|
render 'sessions/new'
|
14
|
-
elsif user =
|
15
|
-
|
15
|
+
elsif user = QuoVadis.model_class.authenticate(params[:username], params[:password])
|
16
|
+
flash_if_present :notice, 'quo_vadis.flash.sign_in.after'
|
16
17
|
sign_in user
|
17
18
|
else
|
18
19
|
QuoVadis.failed_sign_in_hook self
|
19
|
-
|
20
|
+
flash_if_present :alert, 'quo_vadis.flash.sign_in.failed', :now
|
20
21
|
render 'sessions/new'
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
24
25
|
# GET sign_out_path
|
25
26
|
def destroy
|
26
|
-
QuoVadis.signed_out_hook
|
27
|
-
self.
|
28
|
-
|
29
|
-
redirect_to QuoVadis.signed_out_url
|
27
|
+
QuoVadis.signed_out_hook send(:"current_#{QuoVadis.model_instance_name}"), self
|
28
|
+
self.send :"current_#{QuoVadis.model_instance_name}=", nil
|
29
|
+
flash_if_present :notice, 'quo_vadis.flash.sign_out'
|
30
|
+
redirect_to QuoVadis.signed_out_url(self)
|
30
31
|
end
|
31
32
|
|
32
33
|
# GET forgotten_sign_in_path
|
@@ -35,18 +36,19 @@ class QuoVadis::SessionsController < ApplicationController
|
|
35
36
|
if request.get?
|
36
37
|
render 'sessions/forgotten'
|
37
38
|
elsif request.post?
|
38
|
-
if
|
39
|
+
if params[:username].present? &&
|
40
|
+
(user = QuoVadis.model_class.where(:username => params[:username]).first)
|
39
41
|
if user.email.present?
|
40
42
|
user.generate_token
|
41
43
|
QuoVadis::Notifier.change_password(user).deliver
|
42
|
-
|
44
|
+
flash_if_present :notice, 'quo_vadis.flash.forgotten.sent_email'
|
43
45
|
redirect_to :root
|
44
46
|
else
|
45
|
-
|
47
|
+
flash_if_present :alert, 'quo_vadis.flash.forgotten.no_email', :now
|
46
48
|
render 'sessions/forgotten'
|
47
49
|
end
|
48
50
|
else
|
49
|
-
|
51
|
+
flash_if_present :alert, 'quo_vadis.flash.forgotten.unknown', :now
|
50
52
|
render 'sessions/forgotten'
|
51
53
|
end
|
52
54
|
end
|
@@ -54,7 +56,7 @@ class QuoVadis::SessionsController < ApplicationController
|
|
54
56
|
|
55
57
|
# GET change_password_path /sign-in/change-password/:token
|
56
58
|
def edit
|
57
|
-
if
|
59
|
+
if QuoVadis.model_class.valid_token(params[:token]).first
|
58
60
|
render 'sessions/edit'
|
59
61
|
else
|
60
62
|
invalid_token
|
@@ -63,11 +65,11 @@ class QuoVadis::SessionsController < ApplicationController
|
|
63
65
|
|
64
66
|
# PUT change_password_path /sign-in/change-password/:token
|
65
67
|
def update
|
66
|
-
if (user =
|
68
|
+
if (user = QuoVadis.model_class.valid_token(params[:token]).first)
|
67
69
|
user.password = params[:password]
|
68
70
|
if user.save
|
69
71
|
user.clear_token
|
70
|
-
|
72
|
+
flash_if_present :notice, 'quo_vadis.flash.forgotten.password_changed'
|
71
73
|
sign_in user
|
72
74
|
else
|
73
75
|
render 'sessions/edit'
|
@@ -80,7 +82,7 @@ class QuoVadis::SessionsController < ApplicationController
|
|
80
82
|
private
|
81
83
|
|
82
84
|
def invalid_token # :nodoc:
|
83
|
-
|
85
|
+
flash_if_present :alert, 'quo_vadis.flash.forgotten.invalid_token'
|
84
86
|
redirect_to forgotten_sign_in_url
|
85
87
|
end
|
86
88
|
|
@@ -88,4 +90,12 @@ class QuoVadis::SessionsController < ApplicationController
|
|
88
90
|
QuoVadis.layout
|
89
91
|
end
|
90
92
|
|
93
|
+
def flash_if_present(key, i18n_key, now = false)
|
94
|
+
if now
|
95
|
+
flash.now[key] = t(i18n_key) if t(i18n_key).present?
|
96
|
+
else
|
97
|
+
flash[key] = t(i18n_key) if t(i18n_key).present?
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
91
101
|
end
|
data/app/models/model_mixin.rb
CHANGED
@@ -16,13 +16,13 @@ module ModelMixin
|
|
16
16
|
attr_reader :password
|
17
17
|
attr_protected :password_digest
|
18
18
|
|
19
|
-
validates :username, :presence => true, :uniqueness => true
|
20
|
-
validates :password, :presence => true, :if => Proc.new { |u| u.changed.include?('password_digest') }
|
21
|
-
validates :password_digest, :presence => true
|
19
|
+
validates :username, :presence => true, :uniqueness => true, :if => :should_authenticate?
|
20
|
+
validates :password, :presence => true, :if => Proc.new { |u| u.should_authenticate? && u.changed.include?('password_digest') }
|
21
|
+
validates :password_digest, :presence => true, :if => :should_authenticate?
|
22
22
|
|
23
23
|
scope :valid_token, lambda { |token| where("token = ? AND token_created_at > ?", token, 3.hours.ago) }
|
24
24
|
|
25
|
-
instance_eval <<-END
|
25
|
+
instance_eval <<-END, __FILE__, __LINE__ + 1
|
26
26
|
# Returns the user with the given <tt>username</tt> if the given password is
|
27
27
|
# correct, and <tt>nil</tt> otherwise.
|
28
28
|
def authenticate(username, plain_text_password)
|
@@ -35,7 +35,7 @@ module ModelMixin
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def find_by_salt(id, salt) # :nodoc:
|
38
|
-
user =
|
38
|
+
user = find_by_id id
|
39
39
|
if user && user.has_matching_salt?(salt)
|
40
40
|
user
|
41
41
|
else
|
@@ -47,6 +47,11 @@ module ModelMixin
|
|
47
47
|
end
|
48
48
|
|
49
49
|
module InstanceMethodsOnActivation
|
50
|
+
# Override this in your model if you need to bypass the Quo Vadis validations.
|
51
|
+
def should_authenticate?
|
52
|
+
true
|
53
|
+
end
|
54
|
+
|
50
55
|
def password=(plain_text_password) # :nodoc:
|
51
56
|
@password = plain_text_password
|
52
57
|
self.password_digest = BCrypt::Password.create plain_text_password
|
@@ -8,6 +8,7 @@ module QuoVadis
|
|
8
8
|
extend ActiveRecord::Generators::Migration
|
9
9
|
|
10
10
|
source_root File.expand_path('../templates', __FILE__)
|
11
|
+
argument :model_name, :type => :string, :default => 'User'
|
11
12
|
|
12
13
|
desc 'Copies an initializer, a locale file, and a migration to your application.'
|
13
14
|
|
@@ -17,11 +18,11 @@ module QuoVadis
|
|
17
18
|
end
|
18
19
|
|
19
20
|
def copy_initializer_file
|
20
|
-
|
21
|
+
template 'quo_vadis.rb.erb', 'config/initializers/quo_vadis.rb'
|
21
22
|
end
|
22
23
|
|
23
24
|
def create_migration_file
|
24
|
-
migration_template 'migration.rb',
|
25
|
+
migration_template 'migration.rb.erb', "db/migrate/add_authentication_to_#{model_name.tableize}.rb"
|
25
26
|
end
|
26
27
|
|
27
28
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class AddAuthenticationTo<%= model_name.pluralize.camelize %> < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
add_column :<%= model_name.tableize %>, :username, :string # for user identification
|
4
|
+
add_column :<%= model_name.tableize %>, :password_digest, :string
|
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
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.down
|
12
|
+
remove_column :<%= model_name.tableize %>, :username
|
13
|
+
remove_column :<%= model_name.tableize %>, :password_digest
|
14
|
+
remove_column :<%= model_name.tableize %>, :email
|
15
|
+
remove_column :<%= model_name.tableize %>, :token
|
16
|
+
remove_column :<%= model_name.tableize %>, :token_created_at
|
17
|
+
end
|
18
|
+
end
|
data/{config/initializers/quo_vadis.rb → lib/generators/quo_vadis/templates/quo_vadis.rb.erb}
RENAMED
@@ -1,13 +1,17 @@
|
|
1
1
|
QuoVadis.configure do |config|
|
2
2
|
|
3
|
+
# The model we want to authenticate.
|
4
|
+
config.model = '<%= model_name.pluralize.classify %>'
|
5
|
+
|
6
|
+
|
3
7
|
#
|
4
8
|
# Sign in
|
5
9
|
#
|
6
10
|
|
7
11
|
# The URL to redirect the user to after s/he signs in.
|
8
|
-
# Use a proc if the URL depends on the user. E.g.:
|
12
|
+
# Use a proc if the URL depends on the user on controller. E.g.:
|
9
13
|
#
|
10
|
-
# config.signed_in_url = Proc.new do |user|
|
14
|
+
# config.signed_in_url = Proc.new do |user, controller|
|
11
15
|
# user.admin? ? :admin : :root
|
12
16
|
# end
|
13
17
|
#
|
@@ -36,6 +40,9 @@ QuoVadis.configure do |config|
|
|
36
40
|
# Set to <tt>nil</tt> to never remember user.
|
37
41
|
config.remember_for = 2.weeks
|
38
42
|
|
43
|
+
# The domain to use for remember-me cookies.
|
44
|
+
config.cookie_domain = :all
|
45
|
+
|
39
46
|
# Code to run to determine whether the sign-in process is blocked to the user. E.g.:
|
40
47
|
#
|
41
48
|
# config.blocked = Proc.new do |controller|
|
@@ -50,6 +57,11 @@ QuoVadis.configure do |config|
|
|
50
57
|
#
|
51
58
|
|
52
59
|
# The URL to redirect the user to after s/he signs out.
|
60
|
+
# Use a proc if the URL depends on the controller. E.g.:
|
61
|
+
#
|
62
|
+
# config.signed_out_url = Proc.new do |controller|
|
63
|
+
# controller.root_url(:subdomain => nil)
|
64
|
+
# end
|
53
65
|
config.signed_out_url = :root
|
54
66
|
|
55
67
|
# Code to run just before the user has signed out. E.g.:
|
data/lib/quo_vadis/version.rb
CHANGED
data/lib/quo_vadis.rb
CHANGED
@@ -3,6 +3,19 @@ require 'active_support/core_ext/numeric/time'
|
|
3
3
|
|
4
4
|
module QuoVadis
|
5
5
|
|
6
|
+
# The model we want to authenticate.
|
7
|
+
mattr_accessor :model # :nodoc:
|
8
|
+
@@model = 'User'
|
9
|
+
|
10
|
+
def self.model_class # :nodoc
|
11
|
+
@@model.constantize
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.model_instance_name # :nodoc
|
15
|
+
@@model.tableize.singularize # e.g. 'user'
|
16
|
+
end
|
17
|
+
|
18
|
+
|
6
19
|
#
|
7
20
|
# Sign in
|
8
21
|
#
|
@@ -16,11 +29,11 @@ module QuoVadis
|
|
16
29
|
mattr_accessor :override_original_url
|
17
30
|
@@override_original_url = false
|
18
31
|
|
19
|
-
def self.signed_in_url(user, original_url) # :nodoc:
|
32
|
+
def self.signed_in_url(user, original_url, controller) # :nodoc:
|
20
33
|
if original_url && !@@override_original_url
|
21
34
|
original_url
|
22
35
|
else
|
23
|
-
@@signed_in_url.respond_to?(:call) ? @@signed_in_url.call(user) : @@signed_in_url
|
36
|
+
@@signed_in_url.respond_to?(:call) ? @@signed_in_url.call(user, controller) : @@signed_in_url
|
24
37
|
end
|
25
38
|
end
|
26
39
|
|
@@ -44,6 +57,10 @@ module QuoVadis
|
|
44
57
|
mattr_accessor :remember_for
|
45
58
|
@@remember_for = 2.weeks
|
46
59
|
|
60
|
+
# The domain to use for remember-me cookies.
|
61
|
+
mattr_accessor :cookie_domain
|
62
|
+
@@cookie_domain = :all
|
63
|
+
|
47
64
|
|
48
65
|
# Whether the sign-in process is blocked to the user.
|
49
66
|
mattr_writer :blocked
|
@@ -60,7 +77,11 @@ module QuoVadis
|
|
60
77
|
|
61
78
|
# The URL to redirect the user to after s/he signs out.
|
62
79
|
mattr_accessor :signed_out_url
|
63
|
-
@@
|
80
|
+
@@signed_out_url = :root
|
81
|
+
|
82
|
+
def self.signed_out_url(controller) # :nodoc:
|
83
|
+
@@signed_out_url.respond_to?(:call) ? @@signed_out_url.call(controller) : @@signed_out_url
|
84
|
+
end
|
64
85
|
|
65
86
|
|
66
87
|
# Code to run just before the user has signed out.
|
data/quo_vadis.gemspec
CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.require_paths = ['lib']
|
21
21
|
|
22
22
|
s.add_dependency 'rails', '~>3.0'
|
23
|
-
s.add_dependency 'bcrypt-ruby', '
|
23
|
+
s.add_dependency 'bcrypt-ruby', '~> 3.0.0'
|
24
24
|
|
25
25
|
s.add_development_dependency 'rails', '>=3.0.4' # so we can test CSRF protection
|
26
26
|
s.add_development_dependency 'sqlite3-ruby'
|
data/test/dummy/.gitignore
CHANGED
@@ -9,11 +9,17 @@
|
|
9
9
|
<body>
|
10
10
|
|
11
11
|
<div id='topnav'>
|
12
|
-
<% if current_user %>
|
12
|
+
<% if defined?(current_user) && current_user %>
|
13
13
|
You are signed in as <%= current_user.name %>.
|
14
14
|
<%= link_to 'Sign out', sign_out_path %>
|
15
|
+
|
16
|
+
<% elsif defined?(current_person) && current_person %>
|
17
|
+
You are signed in as <%= current_person.name %>.
|
18
|
+
<%= link_to 'Sign out', sign_out_path %>
|
19
|
+
|
15
20
|
<% else %>
|
16
21
|
<%= link_to 'Sign in', sign_in_path %>
|
22
|
+
|
17
23
|
<% end %>
|
18
24
|
</div>
|
19
25
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class AddAuthenticationToPeople < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
add_column :people, :username, :string # for user identification
|
4
|
+
add_column :people, :password_digest, :string
|
5
|
+
|
6
|
+
add_column :people, :email, :string # for forgotten-credentials
|
7
|
+
add_column :people, :token, :string # for forgotten-credentials
|
8
|
+
add_column :people, :token_created_at, :string # for forgotten-credentials
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.down
|
12
|
+
remove_column :people, :username
|
13
|
+
remove_column :people, :password_digest
|
14
|
+
remove_column :people, :email
|
15
|
+
remove_column :people, :token
|
16
|
+
remove_column :people, :token_created_at
|
17
|
+
end
|
18
|
+
end
|
@@ -18,13 +18,13 @@ class ConfigTest < ActiveSupport::IntegrationCase
|
|
18
18
|
end
|
19
19
|
|
20
20
|
test 'signed_in_url proc config' do
|
21
|
-
QuoVadis.signed_in_url = Proc.new do |user|
|
21
|
+
QuoVadis.signed_in_url = Proc.new do |user, controller|
|
22
22
|
user.name == 'Bob' ? :articles : :root
|
23
23
|
end
|
24
24
|
sign_in_as 'bob', 'secret'
|
25
25
|
assert_equal articles_path, current_path
|
26
26
|
|
27
|
-
QuoVadis.signed_in_url = Proc.new do |user|
|
27
|
+
QuoVadis.signed_in_url = Proc.new do |user, controller|
|
28
28
|
user.name != 'Bob' ? :articles : :root
|
29
29
|
end
|
30
30
|
sign_in_as 'bob', 'secret'
|
@@ -6,6 +6,16 @@ class ForgottenTest < ActiveSupport::IntegrationCase
|
|
6
6
|
Capybara.reset_sessions!
|
7
7
|
end
|
8
8
|
|
9
|
+
test 'user fills in forgotten-password form with blank username' do
|
10
|
+
u = user_factory 'Bob', 'bob', 'secret'
|
11
|
+
u.update_attribute :username, ''
|
12
|
+
submit_forgotten_details ''
|
13
|
+
assert_equal forgotten_sign_in_path, current_path
|
14
|
+
within '.flash.alert' do
|
15
|
+
assert page.has_content?("Sorry, we did not recognise you.")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
9
19
|
test 'user fills in forgotten-password form with invalid username' do
|
10
20
|
submit_forgotten_details 'bob'
|
11
21
|
assert_equal forgotten_sign_in_path, current_path
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class SignInPersonTest < ActiveSupport::IntegrationCase
|
4
|
+
|
5
|
+
# NOTE: it would be great if I could figure out how to re-initialise the method's
|
6
|
+
# mixed into the controller with the new model.
|
7
|
+
test 'successful sign in for a non-user model' do
|
8
|
+
puts <<-END
|
9
|
+
NOTE: this test (#{__FILE__}) has to be run individually like this:
|
10
|
+
|
11
|
+
1. Change lib/quo_vadis.rb's @@model to 'Person'.
|
12
|
+
2. Uncomment the test code.
|
13
|
+
3. bundle exec ruby -Ilib:test #{__FILE__}
|
14
|
+
|
15
|
+
END
|
16
|
+
|
17
|
+
# person_factory 'James', 'jim', 'secret'
|
18
|
+
# sign_in_as 'jim', 'secret'
|
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
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -42,8 +42,13 @@ def user_factory(name, username, password, email = nil)
|
|
42
42
|
User.create! :name => name, :username => username, :password => password, :email => email
|
43
43
|
end
|
44
44
|
|
45
|
+
def person_factory(name, username, password, email = nil)
|
46
|
+
Person.create! :name => name, :username => username, :password => password, :email => email
|
47
|
+
end
|
48
|
+
|
45
49
|
def reset_quo_vadis_configuration
|
46
50
|
QuoVadis.signed_in_url = :root
|
51
|
+
QuoVadis.cookie_domain = :all
|
47
52
|
QuoVadis.override_original_url = false
|
48
53
|
QuoVadis.signed_out_url = :root
|
49
54
|
QuoVadis.signed_in_hook = nil
|
data/test/unit/user_test.rb
CHANGED
@@ -28,4 +28,21 @@ class UserTest < ActiveSupport::TestCase
|
|
28
28
|
assert user.has_matching_password?('secret')
|
29
29
|
end
|
30
30
|
|
31
|
+
test 'conditional validation' do
|
32
|
+
user = User.new
|
33
|
+
user.class_eval <<-END
|
34
|
+
def should_authenticate?
|
35
|
+
username == 'bob'
|
36
|
+
end
|
37
|
+
END
|
38
|
+
user.username = 'bob'
|
39
|
+
assert !user.valid?
|
40
|
+
|
41
|
+
user.username = 'robert'
|
42
|
+
assert user.valid?
|
43
|
+
|
44
|
+
user.username = nil
|
45
|
+
assert user.valid?
|
46
|
+
end
|
47
|
+
|
31
48
|
end
|
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: 19
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 1.0.7
|
10
|
+
version: 1.1.0
|
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-10-
|
18
|
+
date: 2011-10-07 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -39,14 +39,14 @@ dependencies:
|
|
39
39
|
version_requirements: &id002 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
|
-
- -
|
42
|
+
- - ~>
|
43
43
|
- !ruby/object:Gem::Version
|
44
|
-
hash:
|
44
|
+
hash: 7
|
45
45
|
segments:
|
46
|
-
-
|
47
|
-
-
|
48
|
-
-
|
49
|
-
version:
|
46
|
+
- 3
|
47
|
+
- 0
|
48
|
+
- 0
|
49
|
+
version: 3.0.0
|
50
50
|
type: :runtime
|
51
51
|
requirement: *id002
|
52
52
|
- !ruby/object:Gem::Dependency
|
@@ -128,11 +128,11 @@ files:
|
|
128
128
|
- app/controllers/quo_vadis/sessions_controller.rb
|
129
129
|
- app/mailers/quo_vadis/notifier.rb
|
130
130
|
- app/models/model_mixin.rb
|
131
|
-
- config/initializers/quo_vadis.rb
|
132
131
|
- config/locales/quo_vadis.en.yml
|
133
132
|
- config/routes.rb
|
134
133
|
- lib/generators/quo_vadis/install_generator.rb
|
135
|
-
- lib/generators/quo_vadis/templates/migration.rb
|
134
|
+
- lib/generators/quo_vadis/templates/migration.rb.erb
|
135
|
+
- lib/generators/quo_vadis/templates/quo_vadis.rb.erb
|
136
136
|
- lib/quo_vadis.rb
|
137
137
|
- lib/quo_vadis/engine.rb
|
138
138
|
- lib/quo_vadis/version.rb
|
@@ -145,6 +145,7 @@ files:
|
|
145
145
|
- test/dummy/app/helpers/application_helper.rb
|
146
146
|
- test/dummy/app/helpers/articles_helper.rb
|
147
147
|
- test/dummy/app/models/article.rb
|
148
|
+
- test/dummy/app/models/person.rb
|
148
149
|
- test/dummy/app/models/user.rb
|
149
150
|
- test/dummy/app/views/articles/index.html.erb
|
150
151
|
- test/dummy/app/views/articles/new.html.erb
|
@@ -175,6 +176,8 @@ files:
|
|
175
176
|
- test/dummy/db/migrate/20110124125037_create_users.rb
|
176
177
|
- test/dummy/db/migrate/20110124131535_create_articles.rb
|
177
178
|
- test/dummy/db/migrate/20110127094709_add_authentication_to_users.rb
|
179
|
+
- test/dummy/db/migrate/20111004112209_create_people.rb
|
180
|
+
- test/dummy/db/migrate/20111004132342_add_authentication_to_people.rb
|
178
181
|
- test/dummy/db/schema.rb
|
179
182
|
- test/dummy/public/404.html
|
180
183
|
- test/dummy/public/422.html
|
@@ -188,11 +191,6 @@ files:
|
|
188
191
|
- test/dummy/public/javascripts/rails.js
|
189
192
|
- test/dummy/public/stylesheets/.gitkeep
|
190
193
|
- test/dummy/script/rails
|
191
|
-
- test/dummy/tmp/capybara/capybara-20110124133149.html
|
192
|
-
- test/dummy/tmp/capybara/capybara-20110124133340.html
|
193
|
-
- test/dummy/tmp/capybara/capybara-20110124134001.html
|
194
|
-
- test/dummy/tmp/capybara/capybara-20110124134214.html
|
195
|
-
- test/dummy/tmp/capybara/capybara-20110124135435.html
|
196
194
|
- test/integration/authenticate_test.rb
|
197
195
|
- test/integration/blocked_test.rb
|
198
196
|
- test/integration/config_test.rb
|
@@ -202,6 +200,7 @@ files:
|
|
202
200
|
- test/integration/helper_test.rb
|
203
201
|
- test/integration/locale_test.rb
|
204
202
|
- test/integration/navigation_test.rb
|
203
|
+
- test/integration/sign_in_person_test.rb
|
205
204
|
- test/integration/sign_in_test.rb
|
206
205
|
- test/integration/sign_out_test.rb
|
207
206
|
- test/integration/sign_up_test.rb
|
@@ -252,6 +251,7 @@ test_files:
|
|
252
251
|
- test/dummy/app/helpers/application_helper.rb
|
253
252
|
- test/dummy/app/helpers/articles_helper.rb
|
254
253
|
- test/dummy/app/models/article.rb
|
254
|
+
- test/dummy/app/models/person.rb
|
255
255
|
- test/dummy/app/models/user.rb
|
256
256
|
- test/dummy/app/views/articles/index.html.erb
|
257
257
|
- test/dummy/app/views/articles/new.html.erb
|
@@ -282,6 +282,8 @@ test_files:
|
|
282
282
|
- test/dummy/db/migrate/20110124125037_create_users.rb
|
283
283
|
- test/dummy/db/migrate/20110124131535_create_articles.rb
|
284
284
|
- test/dummy/db/migrate/20110127094709_add_authentication_to_users.rb
|
285
|
+
- test/dummy/db/migrate/20111004112209_create_people.rb
|
286
|
+
- test/dummy/db/migrate/20111004132342_add_authentication_to_people.rb
|
285
287
|
- test/dummy/db/schema.rb
|
286
288
|
- test/dummy/public/404.html
|
287
289
|
- test/dummy/public/422.html
|
@@ -295,11 +297,6 @@ test_files:
|
|
295
297
|
- test/dummy/public/javascripts/rails.js
|
296
298
|
- test/dummy/public/stylesheets/.gitkeep
|
297
299
|
- test/dummy/script/rails
|
298
|
-
- test/dummy/tmp/capybara/capybara-20110124133149.html
|
299
|
-
- test/dummy/tmp/capybara/capybara-20110124133340.html
|
300
|
-
- test/dummy/tmp/capybara/capybara-20110124134001.html
|
301
|
-
- test/dummy/tmp/capybara/capybara-20110124134214.html
|
302
|
-
- test/dummy/tmp/capybara/capybara-20110124135435.html
|
303
300
|
- test/integration/authenticate_test.rb
|
304
301
|
- test/integration/blocked_test.rb
|
305
302
|
- test/integration/config_test.rb
|
@@ -309,6 +306,7 @@ test_files:
|
|
309
306
|
- test/integration/helper_test.rb
|
310
307
|
- test/integration/locale_test.rb
|
311
308
|
- test/integration/navigation_test.rb
|
309
|
+
- test/integration/sign_in_person_test.rb
|
312
310
|
- test/integration/sign_in_test.rb
|
313
311
|
- test/integration/sign_out_test.rb
|
314
312
|
- test/integration/sign_up_test.rb
|
@@ -1,18 +0,0 @@
|
|
1
|
-
class AddAuthenticationToUsers < ActiveRecord::Migration
|
2
|
-
def self.up
|
3
|
-
add_column :users, :username, :string # for user identification
|
4
|
-
add_column :users, :password_digest, :string
|
5
|
-
|
6
|
-
add_column :users, :email, :string # for forgotten-credentials
|
7
|
-
add_column :users, :token, :string # for forgotten-credentials
|
8
|
-
add_column :users, :token_created_at, :string # for forgotten-credentials
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.down
|
12
|
-
remove_column :users, :username
|
13
|
-
remove_column :users, :password_digest
|
14
|
-
remove_column :users, :email
|
15
|
-
remove_column :users, :token
|
16
|
-
remove_column :users, :token_created_at
|
17
|
-
end
|
18
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<title>Dummy</title>
|
5
|
-
|
6
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/prototype.js?1295870562" type="text/javascript"></script>
|
7
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/effects.js?1295870562" type="text/javascript"></script>
|
8
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/dragdrop.js?1295870562" type="text/javascript"></script>
|
9
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/controls.js?1295870562" type="text/javascript"></script>
|
10
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/rails.js?1295870562" type="text/javascript"></script>
|
11
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/application.js?1295870562" type="text/javascript"></script>
|
12
|
-
|
13
|
-
</head>
|
14
|
-
<body>
|
15
|
-
|
16
|
-
<div id='topnav'>
|
17
|
-
You are signed in as Bob.
|
18
|
-
<a href="/sign-out">Sign out</a>
|
19
|
-
</div>
|
20
|
-
|
21
|
-
<div class='flash notice'>You have successfully signed in.</div>
|
22
|
-
|
23
|
-
<h1>Articles</h1>
|
24
|
-
|
25
|
-
|
26
|
-
</body>
|
27
|
-
</html>
|
@@ -1,27 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<title>Dummy</title>
|
5
|
-
|
6
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/prototype.js?1295870562" type="text/javascript"></script>
|
7
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/effects.js?1295870562" type="text/javascript"></script>
|
8
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/dragdrop.js?1295870562" type="text/javascript"></script>
|
9
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/controls.js?1295870562" type="text/javascript"></script>
|
10
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/rails.js?1295870562" type="text/javascript"></script>
|
11
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/application.js?1295870562" type="text/javascript"></script>
|
12
|
-
|
13
|
-
</head>
|
14
|
-
<body>
|
15
|
-
|
16
|
-
<div id='topnav'>
|
17
|
-
You are signed in as Bob.
|
18
|
-
<a href="/sign-out">Sign out</a>
|
19
|
-
</div>
|
20
|
-
|
21
|
-
<div class='flash notice'>You have successfully signed in.</div>
|
22
|
-
|
23
|
-
<h1>Articles</h1>
|
24
|
-
|
25
|
-
|
26
|
-
</body>
|
27
|
-
</html>
|
@@ -1,27 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<title>Dummy</title>
|
5
|
-
|
6
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/prototype.js?1295870562" type="text/javascript"></script>
|
7
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/effects.js?1295870562" type="text/javascript"></script>
|
8
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/dragdrop.js?1295870562" type="text/javascript"></script>
|
9
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/controls.js?1295870562" type="text/javascript"></script>
|
10
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/rails.js?1295870562" type="text/javascript"></script>
|
11
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/application.js?1295870562" type="text/javascript"></script>
|
12
|
-
|
13
|
-
</head>
|
14
|
-
<body>
|
15
|
-
|
16
|
-
<div id='topnav'>
|
17
|
-
You are signed in as Bob.
|
18
|
-
<a href="/sign-out">Sign out</a>
|
19
|
-
</div>
|
20
|
-
|
21
|
-
<div class='flash notice'>You have successfully signed in.</div>
|
22
|
-
|
23
|
-
<h1>Articles</h1>
|
24
|
-
|
25
|
-
|
26
|
-
</body>
|
27
|
-
</html>
|
@@ -1,27 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<title>Dummy</title>
|
5
|
-
|
6
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/prototype.js?1295870562" type="text/javascript"></script>
|
7
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/effects.js?1295870562" type="text/javascript"></script>
|
8
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/dragdrop.js?1295870562" type="text/javascript"></script>
|
9
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/controls.js?1295870562" type="text/javascript"></script>
|
10
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/rails.js?1295870562" type="text/javascript"></script>
|
11
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/application.js?1295870562" type="text/javascript"></script>
|
12
|
-
|
13
|
-
</head>
|
14
|
-
<body>
|
15
|
-
|
16
|
-
<div id='topnav'>
|
17
|
-
You are signed in as Bob.
|
18
|
-
<a href="/sign-out">Sign out</a>
|
19
|
-
</div>
|
20
|
-
|
21
|
-
<div class='flash notice'>You have successfully signed in.</div>
|
22
|
-
|
23
|
-
<h1>Articles</h1>
|
24
|
-
|
25
|
-
|
26
|
-
</body>
|
27
|
-
</html>
|
@@ -1,39 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<title>Dummy</title>
|
5
|
-
|
6
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/prototype.js?1295870562" type="text/javascript"></script>
|
7
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/effects.js?1295870562" type="text/javascript"></script>
|
8
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/dragdrop.js?1295870562" type="text/javascript"></script>
|
9
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/controls.js?1295870562" type="text/javascript"></script>
|
10
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/rails.js?1295870562" type="text/javascript"></script>
|
11
|
-
<script src="/Users/andy/code/src/quo_vadis/test/dummy/public/javascripts/application.js?1295870562" type="text/javascript"></script>
|
12
|
-
|
13
|
-
</head>
|
14
|
-
<body>
|
15
|
-
|
16
|
-
<div id='topnav'>
|
17
|
-
<a href="/sign-in">Sign in</a>
|
18
|
-
</div>
|
19
|
-
|
20
|
-
<div class='flash notice'>Please sign in first.</div>
|
21
|
-
|
22
|
-
<h1>Sign in</h1>
|
23
|
-
|
24
|
-
<form accept-charset="UTF-8" action="/sign-in" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /></div>
|
25
|
-
<p>
|
26
|
-
<label for="username">Username</label>
|
27
|
-
<input id="username" name="username" type="text" />
|
28
|
-
</p>
|
29
|
-
<p>
|
30
|
-
<label for="password">Password</label>
|
31
|
-
<input id="password" name="password" type="password" />
|
32
|
-
</p>
|
33
|
-
<p>
|
34
|
-
<input name="commit" type="submit" value="Sign in" />
|
35
|
-
</p>
|
36
|
-
</form>
|
37
|
-
|
38
|
-
</body>
|
39
|
-
</html>
|