boilerplate_generator 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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
|
+
|