quo_vadis 1.0.7 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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>
|