thoughtbot-clearance 0.3.7 → 0.3.8
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/README.textile +147 -60
- data/Rakefile +29 -21
- data/TODO.textile +1 -15
- data/generators/clearance/clearance_generator.rb +31 -9
- data/generators/clearance/lib/insert_commands.rb +103 -0
- data/generators/clearance/lib/rake_commands.rb +22 -0
- data/generators/clearance/templates/README +37 -0
- data/generators/clearance/templates/app/views/clearance_mailer/change_password.html.erb +3 -1
- data/generators/clearance/templates/app/views/passwords/edit.html.erb +4 -4
- data/generators/clearance/templates/db/migrate/create_users_with_clearance_columns.rb +21 -0
- data/generators/clearance/templates/db/migrate/update_users_with_clearance_columns.rb +41 -0
- data/generators/clearance/templates/test/{factories.rb → factories/clearance_user.rb} +1 -1
- data/lib/clearance.rb +3 -4
- data/lib/clearance/app/controllers/application_controller.rb +47 -61
- data/lib/clearance/app/controllers/confirmations_controller.rb +25 -33
- data/lib/clearance/app/controllers/passwords_controller.rb +41 -46
- data/lib/clearance/app/controllers/sessions_controller.rb +49 -56
- data/lib/clearance/app/controllers/users_controller.rb +21 -29
- data/lib/clearance/app/models/clearance_mailer.rb +15 -19
- data/lib/clearance/app/models/user.rb +53 -56
- data/lib/clearance/test/functional/confirmations_controller_test.rb +4 -35
- data/lib/clearance/test/functional/passwords_controller_test.rb +9 -5
- data/lib/clearance/test/functional/sessions_controller_test.rb +67 -17
- data/lib/clearance/test/functional/users_controller_test.rb +15 -7
- data/lib/clearance/test/test_helper.rb +10 -81
- data/lib/clearance/test/unit/clearance_mailer_test.rb +5 -5
- data/lib/clearance/test/unit/user_test.rb +42 -59
- data/rails/init.rb +1 -0
- data/shoulda_macros/clearance.rb +45 -0
- metadata +14 -6
- data/generators/clearance/templates/app/views/confirmations/new.html.erb +0 -6
- data/lib/clearance/version.rb +0 -7
@@ -0,0 +1,22 @@
|
|
1
|
+
Rails::Generator::Commands::Create.class_eval do
|
2
|
+
def rake_db_migrate
|
3
|
+
logger.rake "db:migrate"
|
4
|
+
unless system("rake db:migrate")
|
5
|
+
logger.rake "db:migrate failed. Rolling back"
|
6
|
+
command(:destroy).invoke!
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
Rails::Generator::Commands::Destroy.class_eval do
|
12
|
+
def rake_db_migrate
|
13
|
+
logger.rake "db:rollback"
|
14
|
+
system "rake db:rollback"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Rails::Generator::Commands::List.class_eval do
|
19
|
+
def rake_db_migrate
|
20
|
+
logger.rake "db:migrate"
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
*******************************************************************************
|
2
|
+
Ok, enough fancy automatic stuff. Time for some old school monkey copy-pasting.
|
3
|
+
|
4
|
+
1. For any other file(s) that you already had and didn't want to overwrite, add
|
5
|
+
the corresponding Clearance module. They are namespaced exactly like the
|
6
|
+
directory structure of a Rails app, e.g:
|
7
|
+
|
8
|
+
if app/models/user.rb already exists, add:
|
9
|
+
|
10
|
+
class User < ActiveRecord::Base
|
11
|
+
include Clearance::App::Models::User
|
12
|
+
...
|
13
|
+
|
14
|
+
2. You need to define HOST constant in your environments files. In config/environments/test.rb and config/environments/development.rb it can be:
|
15
|
+
|
16
|
+
HOST = "localhost"
|
17
|
+
|
18
|
+
While in config/environments/production.rb it must be the actual host your application is deployed to because the constant is used by mailers to generate URLs in emails.
|
19
|
+
|
20
|
+
In config/environment.rb:
|
21
|
+
|
22
|
+
DO_NOT_REPLY = "donotreply@example.com"
|
23
|
+
|
24
|
+
3. Clearance depends on root_url, so please make sure that it is defined in
|
25
|
+
your config/routes.rb:
|
26
|
+
|
27
|
+
map.root :controller => 'my_home_controller'
|
28
|
+
|
29
|
+
4. To run tests you need to add the Clearance module to your
|
30
|
+
test/test_helper.rb:
|
31
|
+
|
32
|
+
class Test::Unit::TestCase
|
33
|
+
self.use_transactional_fixtures = true
|
34
|
+
self.use_instantiated_fixtures = false
|
35
|
+
include Clearance::Test::TestHelper
|
36
|
+
end
|
37
|
+
*******************************************************************************
|
@@ -1,6 +1,8 @@
|
|
1
1
|
Someone, hopefully you, has requested that we send you a link to change your password.
|
2
2
|
|
3
3
|
Here's the link:
|
4
|
-
<%= edit_user_password_url
|
4
|
+
<%= edit_user_password_url(@user,
|
5
|
+
:email => @user.email,
|
6
|
+
:password => @user.crypted_password) %>
|
5
7
|
|
6
8
|
If you didn't request this, no need to freak out, your password hasn't been changed. You can just ignore this email.
|
@@ -3,11 +3,11 @@
|
|
3
3
|
</p>
|
4
4
|
|
5
5
|
<%= error_messages_for :user %>
|
6
|
+
|
6
7
|
<% form_for(:user,
|
7
|
-
:url => user_password_path(
|
8
|
-
|
9
|
-
|
10
|
-
:password => @user.crypted_password),
|
8
|
+
:url => user_password_path(@user,
|
9
|
+
:email => @user.email,
|
10
|
+
:password => @user.crypted_password),
|
11
11
|
:html => { :method => :put }) do |form| %>
|
12
12
|
<div class="password_field">
|
13
13
|
<%= form.label :password, 'Choose password' %>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class CreateOrUpdateUsersWithClearanceColumns < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table(:users) do |t|
|
4
|
+
t.string :email
|
5
|
+
t.string :crypted_password, :limit => 40
|
6
|
+
t.string :salt, :limit => 40
|
7
|
+
t.string :remember_token
|
8
|
+
t.datetime :remember_token_expires_at
|
9
|
+
t.boolean :confirmed, :default => false, :null => false
|
10
|
+
end
|
11
|
+
|
12
|
+
add_index :users, [:email, :crypted_password]
|
13
|
+
add_index :users, [:id, :salt]
|
14
|
+
add_index :users, :email
|
15
|
+
add_index :users, :remember_token
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.down
|
19
|
+
drop_table :users
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class CreateOrUpdateUsersWithClearanceColumns < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
<%
|
4
|
+
existing_columns = ActiveRecord::Base.connection.columns(:users).map { |column| column.name }
|
5
|
+
columns = [
|
6
|
+
[:email, 't.string :email'],
|
7
|
+
[:crypted_password, 't.string :crypted_password, :limit => 40'],
|
8
|
+
[:salt, 't.string :salt, :limit => 40'],
|
9
|
+
[:remember_token, 't.string :remember_token'],
|
10
|
+
[:remember_token_expires_at, 't.datetime :remember_token_expires_at'],
|
11
|
+
[:confirmed, 't.boolean :confirmed, :default => false, :null => false']
|
12
|
+
].delete_if {|c| existing_columns.include?(c.first.to_s)}
|
13
|
+
-%>
|
14
|
+
change_table(:users) do |t|
|
15
|
+
<% columns.each do |c| -%>
|
16
|
+
<%= c.last %>
|
17
|
+
<% end -%>
|
18
|
+
end
|
19
|
+
|
20
|
+
<%
|
21
|
+
existing_indexes = ActiveRecord::Base.connection.indexes(:users).map { |index| index.name }
|
22
|
+
indexes = [
|
23
|
+
[:index_users_on_email_and_crypted_password, 'add_index :users, [:email, :crypted_password]'],
|
24
|
+
[:index_users_on_id_and_salt, 'add_index :users, [:id, :salt]'],
|
25
|
+
[:index_users_on_email, 'add_index :users, :email'],
|
26
|
+
[:index_users_on_remember_token, 'add_index :users, :remember_token']
|
27
|
+
].delete_if {|i| existing_indexes.include?(i.first.to_s)}
|
28
|
+
-%>
|
29
|
+
<% indexes.each do |i| -%>
|
30
|
+
<%= i.last %>
|
31
|
+
<% end -%>
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.down
|
35
|
+
change_table(:users) do |t|
|
36
|
+
<% unless columns.empty? -%>
|
37
|
+
t.remove <%= columns.collect {|c| ":#{c.first}" }.join(',') %>
|
38
|
+
<% end -%>
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/clearance.rb
CHANGED
@@ -3,13 +3,12 @@ require 'clearance/app/controllers/confirmations_controller'
|
|
3
3
|
require 'clearance/app/controllers/passwords_controller'
|
4
4
|
require 'clearance/app/controllers/sessions_controller'
|
5
5
|
require 'clearance/app/controllers/users_controller'
|
6
|
-
require 'clearance/app/models/user'
|
7
6
|
require 'clearance/app/models/clearance_mailer'
|
7
|
+
require 'clearance/app/models/user'
|
8
8
|
require 'clearance/test/functional/confirmations_controller_test'
|
9
|
+
require 'clearance/test/functional/passwords_controller_test'
|
9
10
|
require 'clearance/test/functional/sessions_controller_test'
|
10
11
|
require 'clearance/test/functional/users_controller_test'
|
11
|
-
require 'clearance/test/functional/passwords_controller_test'
|
12
12
|
require 'clearance/test/test_helper'
|
13
|
-
require 'clearance/test/unit/user_test'
|
14
13
|
require 'clearance/test/unit/clearance_mailer_test'
|
15
|
-
require 'clearance/
|
14
|
+
require 'clearance/test/unit/user_test'
|
@@ -3,79 +3,65 @@ module Clearance
|
|
3
3
|
module Controllers
|
4
4
|
module ApplicationController
|
5
5
|
|
6
|
-
def self.included(
|
7
|
-
|
6
|
+
def self.included(controller)
|
7
|
+
controller.class_eval do
|
8
8
|
helper_method :current_user
|
9
9
|
helper_method :logged_in?
|
10
10
|
|
11
|
-
|
11
|
+
def current_user
|
12
|
+
user_from_session || user_from_cookie
|
13
|
+
end
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
def logged_in?
|
24
|
-
! current_user.nil?
|
25
|
-
end
|
26
|
-
end
|
15
|
+
def logged_in?
|
16
|
+
! current_user.nil?
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def authenticate
|
22
|
+
deny_access unless logged_in?
|
23
|
+
end
|
27
24
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
25
|
+
def user_from_session
|
26
|
+
User.find_by_id session[:user_id]
|
27
|
+
end
|
32
28
|
|
33
|
-
|
34
|
-
|
35
|
-
|
29
|
+
def user_from_cookie
|
30
|
+
if cookies[:auth_token]
|
31
|
+
user = User.find_by_remember_token(cookies[:auth_token])
|
32
|
+
end
|
33
|
+
user && user.remember_token? ? user : nil
|
34
|
+
end
|
36
35
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
# Level of indirection so you can easily overwrite this method
|
37
|
+
# but also call #login .
|
38
|
+
def log_user_in(user)
|
39
|
+
login(user)
|
40
|
+
end
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
login(user)
|
46
|
-
end
|
47
|
-
|
48
|
-
def login(user)
|
49
|
-
session[:user_id] = user.id if user
|
50
|
-
@current_user = user
|
51
|
-
end
|
42
|
+
def login(user)
|
43
|
+
session[:user_id] = user.id if user
|
44
|
+
end
|
52
45
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
def redirect_to_root
|
59
|
-
redirect_to root_url
|
60
|
-
end
|
46
|
+
def redirect_back_or(default)
|
47
|
+
session[:return_to] ||= params[:return_to]
|
48
|
+
session[:return_to] ? redirect_to(session[:return_to]) : redirect_to(default)
|
49
|
+
session[:return_to] = nil
|
50
|
+
end
|
61
51
|
|
62
|
-
|
63
|
-
|
64
|
-
|
52
|
+
def redirect_to_root
|
53
|
+
redirect_to root_url
|
54
|
+
end
|
65
55
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
flash[:error] = flash_message if flash_message
|
70
|
-
redirect_to opts[:redirect]
|
71
|
-
end
|
72
|
-
|
73
|
-
def user_model
|
74
|
-
User
|
75
|
-
end
|
56
|
+
def store_location
|
57
|
+
session[:return_to] = request.request_uri
|
58
|
+
end
|
76
59
|
|
77
|
-
|
78
|
-
|
60
|
+
def deny_access(flash_message = nil, opts = {})
|
61
|
+
store_location
|
62
|
+
flash[:failure] = flash_message if flash_message
|
63
|
+
render :template => "/sessions/new",:status => :unauthorized
|
64
|
+
end
|
79
65
|
end
|
80
66
|
end
|
81
67
|
end
|
@@ -3,44 +3,36 @@ module Clearance
|
|
3
3
|
module Controllers
|
4
4
|
module ConfirmationsController
|
5
5
|
|
6
|
-
def self.included(
|
7
|
-
|
8
|
-
before_filter :existing_user?, :only =>
|
6
|
+
def self.included(controller)
|
7
|
+
controller.class_eval do
|
8
|
+
before_filter :existing_user?, :only => :new
|
9
9
|
|
10
|
-
|
10
|
+
def new
|
11
|
+
create
|
12
|
+
end
|
13
|
+
|
14
|
+
def create
|
15
|
+
@user.confirm!
|
16
|
+
session[:user_id] = @user.id
|
17
|
+
redirect_to url_after_create
|
18
|
+
end
|
11
19
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
20
|
+
private
|
21
|
+
|
22
|
+
def existing_user?
|
23
|
+
@user = User.find_by_id_and_salt(params[:user_id], params[:salt])
|
24
|
+
if @user.nil?
|
25
|
+
render :nothing => true, :status => :not_found
|
26
|
+
end
|
27
|
+
end
|
21
28
|
|
22
|
-
|
23
|
-
|
24
|
-
@user.confirm!
|
25
|
-
session[:user_id] = @user.id
|
26
|
-
redirect_to url_after_create
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
module PrivateInstanceMethods
|
31
|
-
def existing_user?
|
32
|
-
user = User.find_by_id_and_salt(params[:user_id], params[:salt])
|
33
|
-
if user.nil?
|
34
|
-
render :nothing => true, :status => :not_found
|
29
|
+
def url_after_create
|
30
|
+
root_url
|
35
31
|
end
|
32
|
+
|
36
33
|
end
|
37
|
-
|
38
|
-
def url_after_create
|
39
|
-
root_url
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
34
|
+
end
|
43
35
|
end
|
44
36
|
end
|
45
37
|
end
|
46
|
-
end
|
38
|
+
end
|
@@ -3,64 +3,59 @@ module Clearance
|
|
3
3
|
module Controllers
|
4
4
|
module PasswordsController
|
5
5
|
|
6
|
-
def self.included(
|
7
|
-
|
6
|
+
def self.included(controller)
|
7
|
+
controller.class_eval do
|
8
8
|
before_filter :existing_user?, :only => [:edit, :update]
|
9
9
|
filter_parameter_logging :password, :password_confirmation
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
private
|
14
|
-
include PrivateInstanceMethods
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
module InstanceMethods
|
19
|
-
def new
|
20
|
-
end
|
11
|
+
def new
|
12
|
+
end
|
21
13
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
14
|
+
def create
|
15
|
+
user = User.find_by_email(params[:password][:email])
|
16
|
+
if user.nil?
|
17
|
+
flash.now[:warning] = 'Unknown email'
|
18
|
+
render :action => :new
|
19
|
+
else
|
20
|
+
ClearanceMailer.deliver_change_password user
|
21
|
+
flash[:notice] = "Details for changing your password " <<
|
22
|
+
"have been sent to #{user.email}"
|
23
|
+
redirect_to url_after_create
|
24
|
+
end
|
30
25
|
end
|
31
|
-
end
|
32
26
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
27
|
+
def edit
|
28
|
+
@user = User.find_by_email_and_crypted_password(params[:email],
|
29
|
+
params[:password])
|
30
|
+
end
|
37
31
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
32
|
+
def update
|
33
|
+
@user = User.find_by_email_and_crypted_password(params[:email],
|
34
|
+
params[:password])
|
35
|
+
if @user.update_attributes params[:user]
|
36
|
+
session[:user_id] = @user.id
|
37
|
+
redirect_to @user
|
38
|
+
else
|
39
|
+
render :action => :edit
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def existing_user?
|
46
|
+
user = User.find_by_email_and_crypted_password(params[:email],
|
47
|
+
params[:password])
|
48
|
+
if user.nil?
|
49
|
+
render :nothing => true, :status => :not_found
|
50
|
+
end
|
46
51
|
end
|
47
|
-
end
|
48
|
-
end
|
49
52
|
|
50
|
-
|
51
|
-
|
52
|
-
user = User.find_by_email_and_crypted_password(params[:email],
|
53
|
-
params[:password])
|
54
|
-
if user.nil?
|
55
|
-
render :nothing => true, :status => :not_found
|
53
|
+
def url_after_create
|
54
|
+
new_session_url
|
56
55
|
end
|
57
|
-
|
58
|
-
|
59
|
-
def url_after_create
|
60
|
-
new_session_url
|
56
|
+
|
61
57
|
end
|
62
58
|
end
|
63
|
-
|
64
59
|
end
|
65
60
|
end
|
66
61
|
end
|