boilerplate_generator 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +3 -0
- data/Manifest.txt +32 -0
- data/README.txt +152 -0
- data/USAGE +30 -0
- data/boilerplate_generator.rb +69 -0
- data/lib/boilerplate_generator/version.rb +9 -0
- data/templates/app/controllers/account_controller.rb +19 -0
- data/templates/app/controllers/application.rb +6 -0
- data/templates/app/controllers/user_controller.rb +34 -0
- data/templates/app/helpers/account_helper.rb +2 -0
- data/templates/app/helpers/user_helper.rb +2 -0
- data/templates/app/models/user.rb +71 -0
- data/templates/app/views/account/login.haml +16 -0
- data/templates/app/views/account/login.html.erb +17 -0
- data/templates/app/views/layouts/application.haml +11 -0
- data/templates/app/views/layouts/application.html.erb +17 -0
- data/templates/app/views/user/_form.haml +17 -0
- data/templates/app/views/user/_form.html.erb +13 -0
- data/templates/app/views/user/edit.haml +7 -0
- data/templates/app/views/user/edit.html.erb +8 -0
- data/templates/app/views/user/new.haml +11 -0
- data/templates/app/views/user/new.html.erb +11 -0
- data/templates/app/views/user/show.haml +4 -0
- data/templates/app/views/user/show.html.erb +4 -0
- data/templates/config/routes.rb +12 -0
- data/templates/db/migrate/create_users.rb +18 -0
- data/templates/lib/authentication_system.rb +167 -0
- data/templates/test/fixtures/users.yml +15 -0
- data/templates/test/functional/account_controller_test.rb +77 -0
- data/templates/test/functional/user_controller_test.rb +119 -0
- data/templates/test/test_helper.rb +37 -0
- data/templates/test/unit/user_test.rb +116 -0
- metadata +77 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
README.txt
|
4
|
+
USAGE
|
5
|
+
boilerplate_generator.rb
|
6
|
+
lib/boilerplate_generator/version.rb
|
7
|
+
templates/app/controllers/account_controller.rb
|
8
|
+
templates/app/controllers/application.rb
|
9
|
+
templates/app/controllers/user_controller.rb
|
10
|
+
templates/app/helpers/account_helper.rb
|
11
|
+
templates/app/helpers/user_helper.rb
|
12
|
+
templates/app/models/user.rb
|
13
|
+
templates/app/views/account/login.haml
|
14
|
+
templates/app/views/account/login.html.erb
|
15
|
+
templates/app/views/layouts/application.haml
|
16
|
+
templates/app/views/layouts/application.html.erb
|
17
|
+
templates/app/views/user/_form.haml
|
18
|
+
templates/app/views/user/_form.html.erb
|
19
|
+
templates/app/views/user/edit.haml
|
20
|
+
templates/app/views/user/edit.html.erb
|
21
|
+
templates/app/views/user/new.haml
|
22
|
+
templates/app/views/user/new.html.erb
|
23
|
+
templates/app/views/user/show.haml
|
24
|
+
templates/app/views/user/show.html.erb
|
25
|
+
templates/config/routes.rb
|
26
|
+
templates/db/migrate/create_users.rb
|
27
|
+
templates/lib/authentication_system.rb
|
28
|
+
templates/test/fixtures/users.yml
|
29
|
+
templates/test/functional/account_controller_test.rb
|
30
|
+
templates/test/functional/user_controller_test.rb
|
31
|
+
templates/test/test_helper.rb
|
32
|
+
templates/test/unit/user_test.rb
|
data/README.txt
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
= Boilerplate Generator
|
2
|
+
|
3
|
+
Boilerplate is a generator for new Rails projects. It automatically creates a
|
4
|
+
working account system for user login and registration, a basic layout, some
|
5
|
+
named routes, and (of course) a comprehensive suite of tests.
|
6
|
+
|
7
|
+
If you have any questions, comments, criticisms, or unmelted chocolate
|
8
|
+
sundaes, please contact me via electronic mail. My address is
|
9
|
+
packagetheif@gmail.com
|
10
|
+
|
11
|
+
== Why?
|
12
|
+
|
13
|
+
Because I get tired of creating the same basic things each time I start a new
|
14
|
+
project. Steeped in frustration, I extracted all the preliminary code from last
|
15
|
+
project I created and packaged it up for posterity.
|
16
|
+
|
17
|
+
== What's included?
|
18
|
+
|
19
|
+
Nothing fancy, really. That's the whole idea: no smoke, no mirrors. Just simple
|
20
|
+
code that's easy to modify and/or extend.
|
21
|
+
|
22
|
+
models
|
23
|
+
A User model with support for hashed (and salted) passwords, all the necessary
|
24
|
+
validations, and an authenticate class method. Take a look at
|
25
|
+
db/migrate/###_create_users.rb if you want to see the schema definition
|
26
|
+
|
27
|
+
views
|
28
|
+
Views for login and signup, plus a simple xhtml layout that includes
|
29
|
+
the default javascript libraries
|
30
|
+
|
31
|
+
controllers
|
32
|
+
An account controller with index, login, signup, and logout actions; a
|
33
|
+
modified application_controller that mixes in the AuthenticationSystem module.
|
34
|
+
The current_user method returns a User object provided a User with an id equal
|
35
|
+
to session[:user] can be found; the authenticate method redirects to the
|
36
|
+
login_url if current_user returns false
|
37
|
+
|
38
|
+
routes
|
39
|
+
Named routes for signup_url, login_url, and logout_url and a resource route
|
40
|
+
for users (map.resource :user)
|
41
|
+
|
42
|
+
migrations
|
43
|
+
A migration to create the Users table
|
44
|
+
|
45
|
+
tests
|
46
|
+
A comprehensive suite of tests covering the User model, and the all the
|
47
|
+
Account and User actions
|
48
|
+
|
49
|
+
== Test Specs
|
50
|
+
|
51
|
+
Account controller should:
|
52
|
+
* login user and redirect
|
53
|
+
* not login invalid user
|
54
|
+
* logout and redirect
|
55
|
+
* remember login if remember me is set
|
56
|
+
* not remember login if remember me is not set
|
57
|
+
* delete token on logout
|
58
|
+
* login automatically from cookie
|
59
|
+
* fail cookie login with expired cookie
|
60
|
+
* fail cookie login with invalid cookie
|
61
|
+
|
62
|
+
User controller should:
|
63
|
+
* create user
|
64
|
+
* require login on create
|
65
|
+
* require unique login on create
|
66
|
+
* require password on create
|
67
|
+
* require password confirmation on create
|
68
|
+
* require email on create
|
69
|
+
* require valid email on create
|
70
|
+
* require authentication for show
|
71
|
+
* require authentication for edit
|
72
|
+
* require authentication for update
|
73
|
+
* accept http basic authentication
|
74
|
+
|
75
|
+
User should:
|
76
|
+
* create user
|
77
|
+
* update user
|
78
|
+
* destroy user
|
79
|
+
* accept valid emails
|
80
|
+
* not allow invalid emails
|
81
|
+
* not allow spaces or dots in login
|
82
|
+
* reset password
|
83
|
+
* not rehash password when unchanged
|
84
|
+
* authenticate user
|
85
|
+
* set remember token
|
86
|
+
* unset remember token
|
87
|
+
* remember login for one week
|
88
|
+
* remember login until one week from now
|
89
|
+
* remember login for default two weeks
|
90
|
+
|
91
|
+
== Usage
|
92
|
+
|
93
|
+
Boilerplate is intended to be used on a fresh Rails application. You're free to
|
94
|
+
use it on an app with code in it already; it will prompt you before it tries
|
95
|
+
to overwrite any existing files.
|
96
|
+
|
97
|
+
To generate the boilerplate code for your application, use the generate script:
|
98
|
+
|
99
|
+
$ ./script/generate boilerplate
|
100
|
+
|
101
|
+
Assuming you have the databases set up for your application, run the migration
|
102
|
+
script which will create the User table:
|
103
|
+
|
104
|
+
$ rake db:migrate
|
105
|
+
|
106
|
+
Run the test suite to make sure everything is kosher:
|
107
|
+
|
108
|
+
$ rake test
|
109
|
+
|
110
|
+
== Generated files
|
111
|
+
|
112
|
+
The following files are generated:
|
113
|
+
|
114
|
+
+-- app
|
115
|
+
| |-- controllers
|
116
|
+
| | |-- account_controller.rb
|
117
|
+
| | |-- user_controller.rb
|
118
|
+
| | `-- application.rb
|
119
|
+
| |-- models
|
120
|
+
| | `-- user.rb
|
121
|
+
| `-- views
|
122
|
+
| |-- account
|
123
|
+
| | |-- index.rhtml
|
124
|
+
| | |-- login.rhtml
|
125
|
+
| | `-- signup.rhtml
|
126
|
+
| |-- user
|
127
|
+
| | |-- login.rhtml
|
128
|
+
| | |-- show.rhtml
|
129
|
+
| | `-- signup.rhtml
|
130
|
+
| `-- layouts
|
131
|
+
| `-- application.rhtml
|
132
|
+
|-- config
|
133
|
+
| `-- routes.rb
|
134
|
+
|-- db
|
135
|
+
| `-- migrate
|
136
|
+
| |-- ###_create_sessions.rb
|
137
|
+
| `-- ###_create_users.rb
|
138
|
+
|-- lib
|
139
|
+
| `-- authentication_system.rb
|
140
|
+
`-- test
|
141
|
+
|-- fixtures
|
142
|
+
| `-- users.yml
|
143
|
+
|-- functional
|
144
|
+
| |-- user_controller_test.rb
|
145
|
+
| `-- account_controller_test.rb
|
146
|
+
|-- test_helper.rb
|
147
|
+
`-- unit
|
148
|
+
`-- user_test.rb
|
149
|
+
|
150
|
+
|
151
|
+
---
|
152
|
+
Copyright (c) 2007 Jeffrey Allan Hardy, released under the MIT license
|
data/USAGE
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
NAME
|
2
|
+
boilerplate - creates a working account system for user login and
|
3
|
+
registration
|
4
|
+
|
5
|
+
SYNOPSIS
|
6
|
+
boilerplate
|
7
|
+
|
8
|
+
DESCRIPTION
|
9
|
+
Automatically creates a working account system for user login and
|
10
|
+
registration, a basic layout, some named routes, and (of course) a
|
11
|
+
comprehensive suite of tests.
|
12
|
+
|
13
|
+
Boilerplate is intended to be used on a fresh Rails application.
|
14
|
+
You're free to use it on an app with code in it already; it will
|
15
|
+
prompt you before it tries to overwrite any existing files.
|
16
|
+
|
17
|
+
EXAMPLE
|
18
|
+
To generate the boilerplate code for your application, use the
|
19
|
+
generate script:
|
20
|
+
|
21
|
+
./script/generate boilerplate
|
22
|
+
|
23
|
+
Assuming you have the databases set up for your application, run
|
24
|
+
the migration script which will create the User table:
|
25
|
+
|
26
|
+
rake db:migrate
|
27
|
+
|
28
|
+
Run the test suite to make sure everything is kosher:
|
29
|
+
|
30
|
+
rake test
|
@@ -0,0 +1,69 @@
|
|
1
|
+
class BoilerplateGenerator < Rails::Generator::Base
|
2
|
+
def manifest
|
3
|
+
record do |m|
|
4
|
+
# Set the file extension to use for templates
|
5
|
+
ext = (File.exist?('vendor/plugins/haml')) ? 'haml' : 'html.erb'
|
6
|
+
|
7
|
+
# Models
|
8
|
+
dir = 'app/models'
|
9
|
+
m.template File.join(dir, file = 'user.rb'), File.join(dir, file)
|
10
|
+
|
11
|
+
# Views
|
12
|
+
dir = 'app/views/account'
|
13
|
+
m.directory dir
|
14
|
+
m.template File.join(dir, file = "login.#{ext}"), File.join(dir, file)
|
15
|
+
|
16
|
+
dir = 'app/views/user'
|
17
|
+
m.directory dir
|
18
|
+
m.template File.join(dir, file = "_form.#{ext}"), File.join(dir, file)
|
19
|
+
m.template File.join(dir, file = "edit.#{ext}"), File.join(dir, file)
|
20
|
+
m.template File.join(dir, file = "show.#{ext}"), File.join(dir, file)
|
21
|
+
m.template File.join(dir, file = "new.#{ext}"), File.join(dir, file)
|
22
|
+
|
23
|
+
# Layouts
|
24
|
+
dir = 'app/views/layouts'
|
25
|
+
m.template File.join(dir, file = "application.#{ext}"), File.join(dir, file)
|
26
|
+
|
27
|
+
# Helpers
|
28
|
+
dir = 'app/helpers'
|
29
|
+
m.template File.join(dir, file = 'account_helper.rb'), File.join(dir, file)
|
30
|
+
m.template File.join(dir, file = 'user_helper.rb'), File.join(dir, file)
|
31
|
+
|
32
|
+
# Controllers
|
33
|
+
dir = 'app/controllers'
|
34
|
+
m.template File.join(dir, file = 'account_controller.rb'), File.join(dir, file)
|
35
|
+
m.template File.join(dir, file = 'user_controller.rb'), File.join(dir, file)
|
36
|
+
m.template File.join(dir, file = 'application.rb'), File.join(dir, file)
|
37
|
+
|
38
|
+
# Libraries
|
39
|
+
dir = 'lib'
|
40
|
+
m.template File.join(dir, file = 'authentication_system.rb'), File.join(dir, file)
|
41
|
+
|
42
|
+
# Routes
|
43
|
+
dir = 'config'
|
44
|
+
m.template File.join(dir, file = 'routes.rb'), File.join(dir, file)
|
45
|
+
|
46
|
+
# Migrations
|
47
|
+
dir = 'db/migrate'
|
48
|
+
m.directory dir
|
49
|
+
m.migration_template File.join(dir, file = 'create_users.rb'), dir, :migration_file_name => file.sub(/\.rb$/, '')
|
50
|
+
|
51
|
+
# Test Helpers
|
52
|
+
dir = 'test'
|
53
|
+
m.template File.join(dir, file = 'test_helper.rb'), File.join(dir, file)
|
54
|
+
|
55
|
+
# Fixtures
|
56
|
+
dir = 'test/fixtures'
|
57
|
+
m.template File.join(dir, file = 'users.yml'), File.join(dir, file)
|
58
|
+
|
59
|
+
# Functional Tests
|
60
|
+
dir = 'test/functional'
|
61
|
+
m.template File.join(dir, file = 'account_controller_test.rb'), File.join(dir, file)
|
62
|
+
m.template File.join(dir, file = 'user_controller_test.rb'), File.join(dir, file)
|
63
|
+
|
64
|
+
# Unit Tests
|
65
|
+
dir = 'test/unit'
|
66
|
+
m.template File.join(dir, file = 'user_test.rb'), File.join(dir, file)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class AccountController < ApplicationController
|
2
|
+
def login
|
3
|
+
if request.post?
|
4
|
+
if self.current_user = User.authenticate(params[:login], params[:password])
|
5
|
+
remember_current_user if params[:remember_me] == '1'
|
6
|
+
redirect_back_or_to user_url
|
7
|
+
else
|
8
|
+
flash[:error] = 'Invalid user/password combination'
|
9
|
+
redirect_to login_path
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def logout
|
15
|
+
logout_current_user!
|
16
|
+
flash[:notice] = 'You have been logged out'
|
17
|
+
redirect_to login_path
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class UserController < ApplicationController
|
2
|
+
before_filter :authenticate, :except => [:new, :create]
|
3
|
+
|
4
|
+
def show
|
5
|
+
@user = current_user
|
6
|
+
end
|
7
|
+
|
8
|
+
def new
|
9
|
+
@user = User.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def create
|
13
|
+
@user = User.new(params[:user])
|
14
|
+
if @user.save
|
15
|
+
self.current_user = @user
|
16
|
+
flash[:notice] = 'Thanks for signing up!'
|
17
|
+
redirect_to root_url
|
18
|
+
else
|
19
|
+
render :action => 'new'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def edit
|
24
|
+
@user = current_user
|
25
|
+
end
|
26
|
+
|
27
|
+
def update
|
28
|
+
@user = current_user
|
29
|
+
if @user.update_attributes(params[:user])
|
30
|
+
flash[:notice] = 'Account information updated'
|
31
|
+
redirect_to edit_user_url
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
|
3
|
+
class User < ActiveRecord::Base
|
4
|
+
attr_accessor :password
|
5
|
+
|
6
|
+
validates_presence_of :login
|
7
|
+
validates_length_of :login, :within => 3..40
|
8
|
+
validates_uniqueness_of :login, :case_sensitive => false
|
9
|
+
validates_format_of :login, :with => /^[\w-]+$/i, :message => 'cannot contain spaces or special characters'
|
10
|
+
|
11
|
+
validates_presence_of :email
|
12
|
+
validates_format_of :email, :with => /^[^@][\w.-]*@[\w.-]+[.][a-z]{2,4}$/i
|
13
|
+
|
14
|
+
validates_presence_of :password, :if => :password_required?
|
15
|
+
validates_length_of :password, :within => 4..40, :if => :password_required?
|
16
|
+
validates_presence_of :password_confirmation, :if => :password_required?
|
17
|
+
validates_confirmation_of :password, :if => :password_required?
|
18
|
+
|
19
|
+
validates_acceptance_of :terms_of_service
|
20
|
+
|
21
|
+
before_save :hash_password
|
22
|
+
|
23
|
+
attr_protected :hashed_password, :remember_token, :remember_token_expires_at
|
24
|
+
|
25
|
+
def self.authenticate(login, password)
|
26
|
+
user = find_by_login(login)
|
27
|
+
return user if user && user.authenticated?(password)
|
28
|
+
end
|
29
|
+
|
30
|
+
def authenticated?(password)
|
31
|
+
hashed_password == encrypt(password)
|
32
|
+
end
|
33
|
+
|
34
|
+
def remember
|
35
|
+
remember_for 2.weeks
|
36
|
+
end
|
37
|
+
|
38
|
+
def remember_for(time)
|
39
|
+
remember_until time.from_now.utc
|
40
|
+
end
|
41
|
+
|
42
|
+
def remember_until(time)
|
43
|
+
self.remember_token_expires_at = time
|
44
|
+
self.remember_token = encrypt("#{email}--#{remember_token_expires_at}")
|
45
|
+
save
|
46
|
+
end
|
47
|
+
|
48
|
+
def forget
|
49
|
+
self.remember_token_expires_at = nil
|
50
|
+
self.remember_token = nil
|
51
|
+
save
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_s
|
55
|
+
login
|
56
|
+
end
|
57
|
+
|
58
|
+
protected
|
59
|
+
def hash_password
|
60
|
+
return if password.blank?
|
61
|
+
self.hashed_password = encrypt(password)
|
62
|
+
end
|
63
|
+
|
64
|
+
def password_required?
|
65
|
+
hashed_password.blank? || !password.blank?
|
66
|
+
end
|
67
|
+
|
68
|
+
def encrypt(string)
|
69
|
+
Digest::SHA1.hexdigest(string)
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
%h1 Login
|
2
|
+
|
3
|
+
- form_tag do
|
4
|
+
%fieldset
|
5
|
+
%p
|
6
|
+
Login:<br />
|
7
|
+
= text_field_tag :login
|
8
|
+
%p
|
9
|
+
Password:<br />
|
10
|
+
= password_field_tag :password
|
11
|
+
%p
|
12
|
+
= "#{check_box_tag :remember_me} Remember me for 2 weeks"
|
13
|
+
%p
|
14
|
+
= submit_tag 'Login'
|
15
|
+
|
16
|
+
%h2= "Don't have an account? You should #{link_to 'Sign up!', new_user_url}"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<h1>Login</h1>
|
2
|
+
|
3
|
+
<%% form_tag do -%>
|
4
|
+
<fieldset>
|
5
|
+
<p><label for="login">Login:</label><br />
|
6
|
+
<%%= text_field_tag :login %></p>
|
7
|
+
|
8
|
+
<p><label for="password">Password:</label><br />
|
9
|
+
<%%= password_field_tag :password %></p>
|
10
|
+
|
11
|
+
<p><label><%%= check_box_tag :remember_me %> Remember me for 2 weeks</label></p>
|
12
|
+
|
13
|
+
<p><%%= submit_tag 'Login' %></p>
|
14
|
+
</fieldset>
|
15
|
+
<%% end -%>
|
16
|
+
|
17
|
+
<h2>Don't have an account? You should <%%= link_to 'Sign up!', new_user_url %></h2>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
!!!
|
2
|
+
%html
|
3
|
+
%head
|
4
|
+
%title= controller.controller_name.capitalize
|
5
|
+
%meta{'http-equiv' => 'Content-Type', 'content' => 'text/html; charset=utf-8'}/
|
6
|
+
= javascript_include_tag :defaults
|
7
|
+
%body
|
8
|
+
#container
|
9
|
+
#content
|
10
|
+
= [:notice, :error].collect {|k| content_tag(:div, flash[k], :class => "flash #{k}") if flash[k] }.join
|
11
|
+
= yield
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title><%%= controller.controller_name.capitalize %></title>
|
5
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
6
|
+
<%%= javascript_include_tag :defaults %>
|
7
|
+
</head>
|
8
|
+
|
9
|
+
<body>
|
10
|
+
<div id="container">
|
11
|
+
<div id="content">
|
12
|
+
<%%= [:notice, :error].collect {|k| content_tag(:div, flash[k], :class => "flash #{k}") if flash[k] }.join %>
|
13
|
+
<%%= yield %>
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
</body>
|
17
|
+
</html>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
= error_messages_for 'user'
|
2
|
+
|
3
|
+
%p
|
4
|
+
Login:<br />
|
5
|
+
= text_field :user, :login
|
6
|
+
|
7
|
+
%p
|
8
|
+
Email:<br />
|
9
|
+
= text_field :user, :email
|
10
|
+
|
11
|
+
%p
|
12
|
+
Password:<br />
|
13
|
+
= password_field :user, :password
|
14
|
+
|
15
|
+
%p
|
16
|
+
Password confirmation:<br />
|
17
|
+
= password_field :user, :password_confirmation
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<%%= error_messages_for 'user' %>
|
2
|
+
|
3
|
+
<p><label>Login:</label><br />
|
4
|
+
<%%= text_field :user, :login %></p>
|
5
|
+
|
6
|
+
<p><label>Email:</label><br />
|
7
|
+
<%%= text_field :user, :email %></p>
|
8
|
+
|
9
|
+
<p><label>Password:</label><br />
|
10
|
+
<%%= password_field :user, :password %></p>
|
11
|
+
|
12
|
+
<p><label>Password confirmation:</label><br />
|
13
|
+
<%%= password_field :user, :password_confirmation %></p>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
%h1 Signup for an account
|
2
|
+
|
3
|
+
- form_tag user_path do
|
4
|
+
%fieldset
|
5
|
+
= render :partial => 'form'
|
6
|
+
%p
|
7
|
+
= "#{check_box :user, :terms_of_service} Yes, I have read and accept your #{link_to 'terms of service'}"
|
8
|
+
%p
|
9
|
+
= submit_tag 'Signup'
|
10
|
+
|
11
|
+
%h2= "Already have an account? #{link_to 'Log in', login_url}"
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<h1>Signup for an account</h1>
|
2
|
+
|
3
|
+
<%% form_tag user_path do -%>
|
4
|
+
<fieldset>
|
5
|
+
<%%= render :partial => 'form' %>
|
6
|
+
<p><label><%%= check_box :user, :terms_of_service %> Yes, I have read and accept your</label> <%%= link_to 'terms of service', '#' %></p>
|
7
|
+
<p><%%= submit_tag 'Signup' %></p>
|
8
|
+
</fieldset>
|
9
|
+
<%% end -%>
|
10
|
+
|
11
|
+
<h2>Already have an account? <%%= link_to 'Log in', login_url %></h2>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
ActionController::Routing::Routes.draw do |map|
|
2
|
+
map.root :controller => 'account', :action => 'login'
|
3
|
+
|
4
|
+
map.login 'login', :controller => 'account', :action => 'login'
|
5
|
+
map.logout 'logout', :controller => 'account', :action => 'logout'
|
6
|
+
|
7
|
+
map.resource :user
|
8
|
+
|
9
|
+
# Install the default routes as the lowest priority.
|
10
|
+
map.connect ':controller/:action/:id'
|
11
|
+
map.connect ':controller/:action/:id.:format'
|
12
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class CreateUsers < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :users do |t|
|
4
|
+
t.column :login, :string
|
5
|
+
t.column :email, :string
|
6
|
+
t.column :hashed_password, :string
|
7
|
+
t.column :remember_token, :string
|
8
|
+
t.column :remember_token_expires_at, :datetime
|
9
|
+
t.column :created_at, :datetime
|
10
|
+
t.column :updated_at, :datetime
|
11
|
+
end
|
12
|
+
add_index :users, [:login, :hashed_password]
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.down
|
16
|
+
drop_table :users
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
# Heavily influenced by xal's original login_generator (circa 2004) and
|
2
|
+
# technoweenie's acts_as_authenticated.
|
3
|
+
#
|
4
|
+
# Provides a simple authentication system with support for HTTP Basic
|
5
|
+
# Authentication and remember-me goodness via cookies. To use simply
|
6
|
+
# mix in to ApplicationController.
|
7
|
+
#
|
8
|
+
# Assumes a named login route (login_url), a User model with the class
|
9
|
+
# method `authenticate(login, password)` and the following schema:
|
10
|
+
#
|
11
|
+
# create_table :users do |t|
|
12
|
+
# t.column :login, :string
|
13
|
+
# t.column :email, :string
|
14
|
+
# t.column :hashed_password, :string
|
15
|
+
# t.column :remember_token, :string
|
16
|
+
# t.column :remember_token_expires_at, :datetime
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# ---
|
20
|
+
# Copyright (c) 2006 Jeffrey Hardy (packagethief)
|
21
|
+
#
|
22
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
23
|
+
# a copy of this software and associated documentation files (the
|
24
|
+
# "Software"), to deal in the Software without restriction, including
|
25
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
26
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
27
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
28
|
+
# the following conditions:
|
29
|
+
#
|
30
|
+
# The above copyright notice and this permission notice shall be
|
31
|
+
# included in all copies or substantial portions of the Software.
|
32
|
+
#
|
33
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
34
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
35
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
36
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
37
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
38
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
39
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
40
|
+
module AuthenticationSystem
|
41
|
+
protected
|
42
|
+
|
43
|
+
def self.included(controller)
|
44
|
+
controller.helper_method :current_user, :logged_in?
|
45
|
+
controller.filter_parameter_logging :password
|
46
|
+
end
|
47
|
+
|
48
|
+
def find_current_user
|
49
|
+
if session[:user_id]
|
50
|
+
User.find_by_id(session[:user_id])
|
51
|
+
else
|
52
|
+
authenticate_with_http_basic {|u, p| User.authenticate(u, p) }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def current_user
|
57
|
+
@current_user ||= find_current_user
|
58
|
+
end
|
59
|
+
|
60
|
+
def current_user=(user)
|
61
|
+
@current_user = user.is_a?(User) ? user : nil
|
62
|
+
session[:user_id] = @current_user ? @current_user.id : nil
|
63
|
+
end
|
64
|
+
|
65
|
+
def logged_in?
|
66
|
+
current_user.is_a?(User)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Filter method to enforce a login requirement
|
70
|
+
# Apply as a before_filter on any controller you want to protect
|
71
|
+
def authenticate
|
72
|
+
(logged_in? && authorized?) ? true : access_denied
|
73
|
+
end
|
74
|
+
|
75
|
+
# Filter method to login a user using a cookie
|
76
|
+
# Apply as a before_filter on the application controller
|
77
|
+
def authenticate_with_cookies
|
78
|
+
return if logged_in? or cookies[:auth_token].nil?
|
79
|
+
self.current_user = User.find_by_remember_token(cookies[:auth_token])
|
80
|
+
end
|
81
|
+
|
82
|
+
# Overwrite in idividual controllers to control authorization
|
83
|
+
def authorized?
|
84
|
+
true
|
85
|
+
end
|
86
|
+
|
87
|
+
# Overwrite in idividual controllers to customize the flash message shown when authorization fails
|
88
|
+
def unauthorized_message
|
89
|
+
"Please login first and we'll send you right along"
|
90
|
+
end
|
91
|
+
|
92
|
+
# Sets the appropriate cookies to remember the current user
|
93
|
+
def remember_current_user
|
94
|
+
if logged_in?
|
95
|
+
current_user.remember
|
96
|
+
cookies[:auth_token] = { :value => current_user.remember_token, :expires => current_user.remember_token_expires_at }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Logs out the current user by removing the session, cookie, and any HTTP auth data
|
101
|
+
def logout_current_user!
|
102
|
+
current_user.forget rescue nil
|
103
|
+
cookies.delete :auth_token
|
104
|
+
self.current_user = nil
|
105
|
+
request.env['HTTP_AUTHORIZATION'] = nil
|
106
|
+
end
|
107
|
+
|
108
|
+
def access_denied
|
109
|
+
respond_to do |format|
|
110
|
+
format.html do
|
111
|
+
store_location
|
112
|
+
flash[:notice] = unauthorized_message
|
113
|
+
redirect_to login_url
|
114
|
+
end
|
115
|
+
format.xml do
|
116
|
+
headers['Status'] = 'Unauthorized'
|
117
|
+
headers['WWW-Authenticate'] = 'Basic realm="Application"'
|
118
|
+
render :text => "401 Unauthorized\n", :status => :unauthorized
|
119
|
+
end
|
120
|
+
end
|
121
|
+
false
|
122
|
+
end
|
123
|
+
|
124
|
+
def store_location
|
125
|
+
session[:return_to] = request.request_uri
|
126
|
+
end
|
127
|
+
|
128
|
+
def redirect_back_or_to(options)
|
129
|
+
session[:return_to] ? redirect_to(session[:return_to]) : redirect_to(options)
|
130
|
+
session[:return_to] = nil
|
131
|
+
end
|
132
|
+
|
133
|
+
# Inspired by DHH's http_authentication plugin
|
134
|
+
# See http://dev.rubyonrails.org/svn/rails/plugins/http_authentication
|
135
|
+
def authenticate_with_http_basic(&login_procedure)
|
136
|
+
if authorization = request.env['HTTP_AUTHORIZATION'] || request.env['X-HTTP_AUTHORIZATION']
|
137
|
+
login_procedure.call(*Base64.decode64(authorization.split.last).split(/:/, 2))
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Helpers to make testing the functionality provided by this library
|
142
|
+
# easier. Include AuthenticationSystem::TestHelpers in RAILS_ROOT/test/test_helper.rb
|
143
|
+
module TestHelpers
|
144
|
+
def login_as(user)
|
145
|
+
@request.session[:user_id] = users(user.to_sym).id
|
146
|
+
end
|
147
|
+
|
148
|
+
def authenticate_as(login, password)
|
149
|
+
@request.env['HTTP_ACCEPT'] = @request.env['Content-Type'] = 'text/xml'
|
150
|
+
@request.env["HTTP_AUTHORIZATION"] = "Basic #{Base64.encode64("#{login}:#{password}")}"
|
151
|
+
end
|
152
|
+
|
153
|
+
def logout!
|
154
|
+
@request.session[:user_id] = nil
|
155
|
+
@controller.instance_variable_set('@current_user', nil)
|
156
|
+
@request.env['HTTP_AUTHORIZATION'] = nil
|
157
|
+
end
|
158
|
+
|
159
|
+
def auth_token(token)
|
160
|
+
CGI::Cookie.new('name' => 'auth_token', 'value' => token)
|
161
|
+
end
|
162
|
+
|
163
|
+
def cookie_for(user)
|
164
|
+
auth_token(users(user).remember_token)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
eugene:
|
2
|
+
id: 1
|
3
|
+
login: 'eugene'
|
4
|
+
email: 'eugene@example.com'
|
5
|
+
hashed_password: 'e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4' # => secret
|
6
|
+
created_at: <%%= Time.now.to_s :db %>
|
7
|
+
updated_at: <%%= Time.now.to_s :db %>
|
8
|
+
|
9
|
+
arthur:
|
10
|
+
id: 2
|
11
|
+
login: 'arthur'
|
12
|
+
email: 'arthur@example.com'
|
13
|
+
hashed_password: 'e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4' # => secret
|
14
|
+
created_at: <%%= Time.now.to_s :db %>
|
15
|
+
updated_at: <%%= Time.now.to_s :db %>
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
require 'account_controller'
|
3
|
+
|
4
|
+
# Re-raise errors caught by the controller.
|
5
|
+
class AccountController; def rescue_action(e) raise e end; end
|
6
|
+
|
7
|
+
class AccountControllerTest < Test::Unit::TestCase
|
8
|
+
fixtures :users
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@controller = AccountController.new
|
12
|
+
@request = ActionController::TestRequest.new
|
13
|
+
@response = ActionController::TestResponse.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_should_login_user_and_redirect
|
17
|
+
post :login, :login => 'eugene', :password => 'secret'
|
18
|
+
assert @controller.send(:logged_in?)
|
19
|
+
assert session[:user_id]
|
20
|
+
assert_response :redirect
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_should_not_login_invalid_user
|
24
|
+
post :login, :login => 'eugene', :password => 'bad password'
|
25
|
+
assert !@controller.send(:logged_in?)
|
26
|
+
assert_nil session[:user_id]
|
27
|
+
assert flash[:error]
|
28
|
+
assert_response :redirect
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_should_logout_and_redirect
|
32
|
+
login_as :eugene
|
33
|
+
get :logout
|
34
|
+
assert_nil session[:user_id]
|
35
|
+
assert flash[:notice]
|
36
|
+
assert_response :redirect
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_should_remember_login_if_remember_me_is_set
|
40
|
+
post :login, :login => 'eugene', :password => 'secret', :remember_me => "1"
|
41
|
+
assert @controller.send(:logged_in?)
|
42
|
+
assert_not_nil @response.cookies["auth_token"]
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_should_not_remember_login_if_remember_me_is_not_set
|
46
|
+
post :login, :login => 'eugene', :password => 'secret', :remember_me => "0"
|
47
|
+
assert_nil @response.cookies["auth_token"]
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_should_delete_token_on_logout
|
51
|
+
login_as :eugene
|
52
|
+
get :logout
|
53
|
+
assert_equal @response.cookies['auth_token'], []
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_should_login_automatically_from_cookie
|
57
|
+
users(:eugene).remember
|
58
|
+
@request.cookies['auth_token'] = cookie_for(:eugene)
|
59
|
+
get :login
|
60
|
+
assert @controller.send(:logged_in?)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_should_fail_cookie_login_with_expired_cookie
|
64
|
+
users(:eugene).remember
|
65
|
+
users(:eugene).update_attribute :remember_token_expires_at, 5.minutes.ago.utc
|
66
|
+
@request.cookies['auth_token'] = cookie_for(:eugene)
|
67
|
+
get :login
|
68
|
+
assert_equal false, !@controller.send(:logged_in?)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_should_fail_cookie_login_with_invalid_cookie
|
72
|
+
users(:eugene).remember
|
73
|
+
@request.cookies['auth_token'] = auth_token('invalid_auth_token')
|
74
|
+
get :login
|
75
|
+
assert !@controller.send(:logged_in?)
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
require 'user_controller'
|
3
|
+
|
4
|
+
# Re-raise errors caught by the controller.
|
5
|
+
class UserController; def rescue_action(e) raise e end; end
|
6
|
+
|
7
|
+
class UserControllerTest < Test::Unit::TestCase
|
8
|
+
fixtures :users
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@controller = UserController.new
|
12
|
+
@request = ActionController::TestRequest.new
|
13
|
+
@response = ActionController::TestResponse.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_should_create_user
|
17
|
+
assert_difference 'User.count' do
|
18
|
+
post :create, :user => valid_user
|
19
|
+
assert assigns(:user)
|
20
|
+
assert flash[:notice]
|
21
|
+
assert_response :redirect
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_should_require_login_on_create
|
26
|
+
assert_no_difference 'User.count' do
|
27
|
+
post :create, :user => valid_user(:login => nil)
|
28
|
+
assert assigns(:user).errors.on(:login)
|
29
|
+
assert_response :success
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_should_require_unique_login_on_create
|
34
|
+
assert_no_difference 'User.count' do
|
35
|
+
post :create, :user => valid_user(:login => 'eugene')
|
36
|
+
assert assigns(:user).errors.on(:login)
|
37
|
+
assert_response :success
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_should_require_password_on_create
|
42
|
+
assert_no_difference 'User.count' do
|
43
|
+
post :create, :user => valid_user(:password => nil)
|
44
|
+
assert assigns(:user).errors.on(:password)
|
45
|
+
assert_response :success
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_should_require_password_confirmation_on_create
|
50
|
+
assert_no_difference 'User.count' do
|
51
|
+
post :create, :user => valid_user(:password_confirmation => nil)
|
52
|
+
assert_response :success
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_should_require_email_on_create
|
57
|
+
assert_no_difference 'User.count' do
|
58
|
+
post :create, :user => valid_user(:email => nil)
|
59
|
+
assert assigns(:user).errors.on(:email)
|
60
|
+
assert_response :success
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_should_require_valid_email_on_create
|
65
|
+
assert_no_difference 'User.count' do
|
66
|
+
post :create, :user => valid_user(:email => 'invalid@')
|
67
|
+
assert assigns(:user).errors.on(:email)
|
68
|
+
assert_response :success
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_should_require_authentication_for_show
|
73
|
+
get :show
|
74
|
+
assert_redirected_to login_url
|
75
|
+
|
76
|
+
@request.env['HTTP_ACCEPT'] = @request.env['Content-Type'] = 'text/xml'
|
77
|
+
get :show
|
78
|
+
assert_response :unauthorized
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_should_require_authentication_for_edit
|
82
|
+
get :edit
|
83
|
+
assert_redirected_to login_url
|
84
|
+
|
85
|
+
@request.env['HTTP_ACCEPT'] = @request.env['Content-Type'] = 'text/xml'
|
86
|
+
get :edit
|
87
|
+
assert_response :unauthorized
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_should_require_authentication_for_update
|
91
|
+
post :update
|
92
|
+
assert_redirected_to login_url
|
93
|
+
|
94
|
+
@request.env['HTTP_ACCEPT'] = @request.env['Content-Type'] = 'text/xml'
|
95
|
+
post :update
|
96
|
+
assert_response :unauthorized
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_should_accept_http_basic_authentication
|
100
|
+
login_as('eugene')
|
101
|
+
get :edit
|
102
|
+
assert_response :success
|
103
|
+
|
104
|
+
logout!
|
105
|
+
|
106
|
+
# HTTP_AUTH
|
107
|
+
authenticate_as('eugene', 'secret')
|
108
|
+
get :edit
|
109
|
+
assert_response :success
|
110
|
+
end
|
111
|
+
|
112
|
+
protected
|
113
|
+
def valid_user(overrides = {})
|
114
|
+
{ :login => 'rusty',
|
115
|
+
:email => 'rusty@example.com',
|
116
|
+
:password => 'secret',
|
117
|
+
:password_confirmation => 'secret' }.merge(overrides)
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
ENV["RAILS_ENV"] = "test"
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
|
3
|
+
require 'test_help'
|
4
|
+
|
5
|
+
class Test::Unit::TestCase
|
6
|
+
# Transactional fixtures accelerate your tests by wrapping each test method
|
7
|
+
# in a transaction that's rolled back on completion. This ensures that the
|
8
|
+
# test database remains unchanged so your fixtures don't have to be reloaded
|
9
|
+
# between every test method. Fewer database queries means faster tests.
|
10
|
+
#
|
11
|
+
# Read Mike Clark's excellent walkthrough at
|
12
|
+
# http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting
|
13
|
+
#
|
14
|
+
# Every Active Record database supports transactions except MyISAM tables
|
15
|
+
# in MySQL. Turn off transactional fixtures in this case; however, if you
|
16
|
+
# don't care one way or the other, switching from MyISAM to InnoDB tables
|
17
|
+
# is recommended.
|
18
|
+
self.use_transactional_fixtures = true
|
19
|
+
|
20
|
+
# Instantiated fixtures are slow, but give you @david where otherwise you
|
21
|
+
# would need people(:david). If you don't want to migrate your existing
|
22
|
+
# test cases which use the @david style and don't mind the speed hit (each
|
23
|
+
# instantiated fixtures translates to a database query per test method),
|
24
|
+
# then set this back to true.
|
25
|
+
self.use_instantiated_fixtures = false
|
26
|
+
|
27
|
+
# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
|
28
|
+
# If you need to control the loading order (due to foreign key constraints etc), you'll
|
29
|
+
# need to change this line to explicitly name the order you desire.
|
30
|
+
#
|
31
|
+
# Note: You'll currently still have to declare fixtures explicitly in integration tests
|
32
|
+
# -- they do not yet inherent this setting
|
33
|
+
#fixtures :all
|
34
|
+
|
35
|
+
# Mixin the helpers provided by the authentication library
|
36
|
+
include AuthenticationSystem::TestHelpers
|
37
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class UserTest < Test::Unit::TestCase
|
4
|
+
fixtures :users
|
5
|
+
|
6
|
+
def test_should_create_user
|
7
|
+
assert_difference 'User.count' do
|
8
|
+
user = User.create(valid_user)
|
9
|
+
assert !user.new_record?, "#{user.errors.full_messages.to_sentence}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_should_update_user
|
14
|
+
u = users(:eugene)
|
15
|
+
attributes = {
|
16
|
+
:login => 'eugene_smith',
|
17
|
+
:email => 'eugene.smith@example.com',
|
18
|
+
:password => 'terces',
|
19
|
+
:password_confirmation => 'terces'
|
20
|
+
}
|
21
|
+
assert u.update_attributes(attributes), u.errors.full_messages
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_should_destroy_user
|
25
|
+
assert_difference 'User.count', -1 do
|
26
|
+
User.find(:first).destroy
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_should_accept_valid_emails
|
31
|
+
%w(user@example.com user@example.co.uk ab@cd.ef 1@example.ca john.q@example.com john_q-pub.lic@ex-ample.co.uk 8375309@90210.org).each do |email|
|
32
|
+
assert_valid User.new(valid_user(:email => email))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_should_not_allow_invalid_emails
|
37
|
+
user = User.new(valid_user)
|
38
|
+
|
39
|
+
%w(@foo.bar foo@ foo@bar @).each do |email|
|
40
|
+
user.email = email
|
41
|
+
assert !user.valid?
|
42
|
+
assert user.errors.on(:email)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_should_not_allow_spaces_or_dots_in_login
|
47
|
+
user = User.new(valid_user)
|
48
|
+
|
49
|
+
['foo.bar', 'foo bar'].each do |login|
|
50
|
+
user.login = login
|
51
|
+
assert !user.valid?
|
52
|
+
assert user.errors.on(:login)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_should_reset_password
|
57
|
+
users(:eugene).update_attributes(:password => 'new password', :password_confirmation => 'new password')
|
58
|
+
assert_equal users(:eugene), User.authenticate('eugene', 'new password')
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_should_not_rehash_password_when_unchanged
|
62
|
+
users(:eugene).update_attributes(:login => 'enegue')
|
63
|
+
assert_equal users(:eugene), User.authenticate('enegue', 'secret')
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_should_authenticate_user
|
67
|
+
assert_equal users(:eugene), User.authenticate('eugene', 'secret')
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_should_set_remember_token
|
71
|
+
users(:eugene).remember
|
72
|
+
assert_not_nil users(:eugene).remember_token
|
73
|
+
assert_not_nil users(:eugene).remember_token_expires_at
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_should_unset_remember_token
|
77
|
+
users(:eugene).remember
|
78
|
+
assert_not_nil users(:eugene).remember_token
|
79
|
+
users(:eugene).forget
|
80
|
+
assert_nil users(:eugene).remember_token
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_should_remember_login_for_one_week
|
84
|
+
before = 1.week.from_now.utc
|
85
|
+
users(:eugene).remember_for 1.week
|
86
|
+
after = 1.week.from_now.utc
|
87
|
+
assert_not_nil users(:eugene).remember_token
|
88
|
+
assert_not_nil users(:eugene).remember_token_expires_at
|
89
|
+
assert users(:eugene).remember_token_expires_at.between?(before, after)
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_should_remember_login_until_one_week_from_now
|
93
|
+
time = 1.week.from_now.utc
|
94
|
+
users(:eugene).remember_until time
|
95
|
+
assert_not_nil users(:eugene).remember_token
|
96
|
+
assert_not_nil users(:eugene).remember_token_expires_at
|
97
|
+
assert_equal users(:eugene).remember_token_expires_at, time
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_should_remember_login_for_default_two_weeks
|
101
|
+
before = 2.weeks.from_now.utc
|
102
|
+
users(:eugene).remember
|
103
|
+
after = 2.weeks.from_now.utc
|
104
|
+
assert_not_nil users(:eugene).remember_token
|
105
|
+
assert_not_nil users(:eugene).remember_token_expires_at
|
106
|
+
assert users(:eugene).remember_token_expires_at.between?(before, after)
|
107
|
+
end
|
108
|
+
|
109
|
+
protected
|
110
|
+
def valid_user(overrides={})
|
111
|
+
{ :login => 'rusty',
|
112
|
+
:email => 'rusty@example.com',
|
113
|
+
:password => 'secret',
|
114
|
+
:password_confirmation => 'secret' }.merge(overrides)
|
115
|
+
end
|
116
|
+
end
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.2
|
3
|
+
specification_version: 1
|
4
|
+
name: boilerplate_generator
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.0.1
|
7
|
+
date: 2007-05-08 00:00:00 -04:00
|
8
|
+
summary: Boilerplate is a generator for new Rails projects
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: packagethief@gmail.com
|
12
|
+
homepage: http://boilerplate.rubyforge.org
|
13
|
+
rubyforge_project: boilerplate
|
14
|
+
description: Boilerplate is a generator for new Rails projects
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Jeffrey Hardy (packagethief)
|
31
|
+
files:
|
32
|
+
- History.txt
|
33
|
+
- Manifest.txt
|
34
|
+
- README.txt
|
35
|
+
- USAGE
|
36
|
+
- boilerplate_generator.rb
|
37
|
+
- lib/boilerplate_generator/version.rb
|
38
|
+
- templates/app/controllers/account_controller.rb
|
39
|
+
- templates/app/controllers/application.rb
|
40
|
+
- templates/app/controllers/user_controller.rb
|
41
|
+
- templates/app/helpers/account_helper.rb
|
42
|
+
- templates/app/helpers/user_helper.rb
|
43
|
+
- templates/app/models/user.rb
|
44
|
+
- templates/app/views/account/login.haml
|
45
|
+
- templates/app/views/account/login.html.erb
|
46
|
+
- templates/app/views/layouts/application.haml
|
47
|
+
- templates/app/views/layouts/application.html.erb
|
48
|
+
- templates/app/views/user/_form.haml
|
49
|
+
- templates/app/views/user/_form.html.erb
|
50
|
+
- templates/app/views/user/edit.haml
|
51
|
+
- templates/app/views/user/edit.html.erb
|
52
|
+
- templates/app/views/user/new.haml
|
53
|
+
- templates/app/views/user/new.html.erb
|
54
|
+
- templates/app/views/user/show.haml
|
55
|
+
- templates/app/views/user/show.html.erb
|
56
|
+
- templates/config/routes.rb
|
57
|
+
- templates/db/migrate/create_users.rb
|
58
|
+
- templates/lib/authentication_system.rb
|
59
|
+
- templates/test/fixtures/users.yml
|
60
|
+
- templates/test/functional/account_controller_test.rb
|
61
|
+
- templates/test/functional/user_controller_test.rb
|
62
|
+
- templates/test/test_helper.rb
|
63
|
+
- templates/test/unit/user_test.rb
|
64
|
+
test_files: []
|
65
|
+
|
66
|
+
rdoc_options: []
|
67
|
+
|
68
|
+
extra_rdoc_files: []
|
69
|
+
|
70
|
+
executables: []
|
71
|
+
|
72
|
+
extensions: []
|
73
|
+
|
74
|
+
requirements: []
|
75
|
+
|
76
|
+
dependencies: []
|
77
|
+
|