thoughtbot-clearance 0.3.7 → 0.3.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|