clearance 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of clearance might be problematic. Click here for more details.
- data/CHANGELOG.textile +194 -0
- data/LICENSE +21 -0
- data/README.textile +123 -0
- data/Rakefile +103 -0
- data/TODO.textile +6 -0
- data/app/controllers/clearance/confirmations_controller.rb +75 -0
- data/app/controllers/clearance/passwords_controller.rb +84 -0
- data/app/controllers/clearance/sessions_controller.rb +66 -0
- data/app/controllers/clearance/users_controller.rb +35 -0
- data/app/models/clearance_mailer.rb +23 -0
- data/app/views/clearance_mailer/change_password.html.erb +9 -0
- data/app/views/clearance_mailer/confirmation.html.erb +5 -0
- data/app/views/passwords/edit.html.erb +23 -0
- data/app/views/passwords/new.html.erb +15 -0
- data/app/views/sessions/new.html.erb +24 -0
- data/app/views/users/_form.html.erb +13 -0
- data/app/views/users/new.html.erb +6 -0
- data/config/clearance_routes.rb +30 -0
- data/generators/clearance/USAGE +1 -0
- data/generators/clearance/clearance_generator.rb +41 -0
- data/generators/clearance/lib/insert_commands.rb +33 -0
- data/generators/clearance/lib/rake_commands.rb +22 -0
- data/generators/clearance/templates/README +22 -0
- data/generators/clearance/templates/factories.rb +13 -0
- data/generators/clearance/templates/migrations/create_users.rb +21 -0
- data/generators/clearance/templates/migrations/update_users.rb +41 -0
- data/generators/clearance/templates/user.rb +3 -0
- data/generators/clearance_features/USAGE +1 -0
- data/generators/clearance_features/clearance_features_generator.rb +20 -0
- data/generators/clearance_features/templates/features/password_reset.feature +33 -0
- data/generators/clearance_features/templates/features/sign_in.feature +35 -0
- data/generators/clearance_features/templates/features/sign_out.feature +15 -0
- data/generators/clearance_features/templates/features/sign_up.feature +45 -0
- data/generators/clearance_features/templates/features/step_definitions/clearance_steps.rb +116 -0
- data/generators/clearance_features/templates/features/step_definitions/factory_girl_steps.rb +5 -0
- data/generators/clearance_features/templates/features/support/paths.rb +22 -0
- data/generators/clearance_views/USAGE +0 -0
- data/generators/clearance_views/clearance_views_generator.rb +27 -0
- data/generators/clearance_views/templates/formtastic/passwords/edit.html.erb +21 -0
- data/generators/clearance_views/templates/formtastic/passwords/new.html.erb +15 -0
- data/generators/clearance_views/templates/formtastic/sessions/new.html.erb +21 -0
- data/generators/clearance_views/templates/formtastic/users/_inputs.html.erb +6 -0
- data/generators/clearance_views/templates/formtastic/users/new.html.erb +10 -0
- data/lib/clearance.rb +6 -0
- data/lib/clearance/authentication.rb +125 -0
- data/lib/clearance/extensions/errors.rb +6 -0
- data/lib/clearance/extensions/rescue.rb +3 -0
- data/lib/clearance/extensions/routes.rb +14 -0
- data/lib/clearance/user.rb +199 -0
- data/rails/init.rb +1 -0
- data/shoulda_macros/clearance.rb +266 -0
- metadata +120 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
class Clearance::ConfirmationsController < ApplicationController
|
2
|
+
unloadable
|
3
|
+
|
4
|
+
before_filter :redirect_signed_in_confirmed_user, :only => [:new, :create]
|
5
|
+
before_filter :redirect_signed_out_confirmed_user, :only => [:new, :create]
|
6
|
+
before_filter :forbid_missing_token, :only => [:new, :create]
|
7
|
+
before_filter :forbid_non_existent_user, :only => [:new, :create]
|
8
|
+
|
9
|
+
filter_parameter_logging :token
|
10
|
+
|
11
|
+
def new
|
12
|
+
create
|
13
|
+
end
|
14
|
+
|
15
|
+
def create
|
16
|
+
@user = ::User.find_by_id_and_confirmation_token(
|
17
|
+
params[:user_id], params[:token])
|
18
|
+
@user.confirm_email!
|
19
|
+
|
20
|
+
sign_in(@user)
|
21
|
+
flash_success_after_create
|
22
|
+
redirect_to(url_after_create)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def redirect_signed_in_confirmed_user
|
28
|
+
user = ::User.find_by_id(params[:user_id])
|
29
|
+
if user && user.email_confirmed? && current_user == user
|
30
|
+
flash_success_after_create
|
31
|
+
redirect_to(url_after_create)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def redirect_signed_out_confirmed_user
|
36
|
+
user = ::User.find_by_id(params[:user_id])
|
37
|
+
if user && user.email_confirmed? && signed_out?
|
38
|
+
flash_already_confirmed
|
39
|
+
redirect_to(url_already_confirmed)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def forbid_missing_token
|
44
|
+
if params[:token].blank?
|
45
|
+
raise ActionController::Forbidden, "missing token"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def forbid_non_existent_user
|
50
|
+
unless ::User.find_by_id_and_confirmation_token(
|
51
|
+
params[:user_id], params[:token])
|
52
|
+
raise ActionController::Forbidden, "non-existent user"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def flash_success_after_create
|
57
|
+
flash[:success] = translate(:confirmed_email,
|
58
|
+
:scope => [:clearance, :controllers, :confirmations],
|
59
|
+
:default => "Confirmed email and signed in.")
|
60
|
+
end
|
61
|
+
|
62
|
+
def flash_already_confirmed
|
63
|
+
flash[:success] = translate(:already_confirmed_email,
|
64
|
+
:scope => [:clearance, :controllers, :confirmations],
|
65
|
+
:default => "Already confirmed email. Please sign in.")
|
66
|
+
end
|
67
|
+
|
68
|
+
def url_after_create
|
69
|
+
root_url
|
70
|
+
end
|
71
|
+
|
72
|
+
def url_already_confirmed
|
73
|
+
sign_in_url
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
class Clearance::PasswordsController < ApplicationController
|
2
|
+
unloadable
|
3
|
+
|
4
|
+
before_filter :forbid_missing_token, :only => [:edit, :update]
|
5
|
+
before_filter :forbid_non_existent_user, :only => [:edit, :update]
|
6
|
+
filter_parameter_logging :password, :password_confirmation
|
7
|
+
|
8
|
+
def new
|
9
|
+
render :template => 'passwords/new'
|
10
|
+
end
|
11
|
+
|
12
|
+
def create
|
13
|
+
if user = ::User.find_by_email(params[:password][:email])
|
14
|
+
user.forgot_password!
|
15
|
+
::ClearanceMailer.deliver_change_password user
|
16
|
+
flash_notice_after_create
|
17
|
+
redirect_to(url_after_create)
|
18
|
+
else
|
19
|
+
flash_failure_after_create
|
20
|
+
render :template => 'passwords/new'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def edit
|
25
|
+
@user = ::User.find_by_id_and_confirmation_token(
|
26
|
+
params[:user_id], params[:token])
|
27
|
+
render :template => 'passwords/edit'
|
28
|
+
end
|
29
|
+
|
30
|
+
def update
|
31
|
+
@user = ::User.find_by_id_and_confirmation_token(
|
32
|
+
params[:user_id], params[:token])
|
33
|
+
|
34
|
+
if @user.update_password(params[:user][:password],
|
35
|
+
params[:user][:password_confirmation])
|
36
|
+
@user.confirm_email!
|
37
|
+
sign_in(@user)
|
38
|
+
flash_success_after_update
|
39
|
+
redirect_to(url_after_update)
|
40
|
+
else
|
41
|
+
render :template => 'passwords/edit'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def forbid_missing_token
|
48
|
+
if params[:token].blank?
|
49
|
+
raise ActionController::Forbidden, "missing token"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def forbid_non_existent_user
|
54
|
+
unless ::User.find_by_id_and_confirmation_token(
|
55
|
+
params[:user_id], params[:token])
|
56
|
+
raise ActionController::Forbidden, "non-existent user"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def flash_notice_after_create
|
61
|
+
flash[:notice] = translate(:deliver_change_password,
|
62
|
+
:scope => [:clearance, :controllers, :passwords],
|
63
|
+
:default => "You will receive an email within the next few minutes. " <<
|
64
|
+
"It contains instructions for changing your password.")
|
65
|
+
end
|
66
|
+
|
67
|
+
def flash_failure_after_create
|
68
|
+
flash.now[:failure] = translate(:unknown_email,
|
69
|
+
:scope => [:clearance, :controllers, :passwords],
|
70
|
+
:default => "Unknown email.")
|
71
|
+
end
|
72
|
+
|
73
|
+
def url_after_create
|
74
|
+
new_session_url
|
75
|
+
end
|
76
|
+
|
77
|
+
def flash_success_after_update
|
78
|
+
flash[:success] = translate(:signed_in, :default => "Signed in.")
|
79
|
+
end
|
80
|
+
|
81
|
+
def url_after_update
|
82
|
+
root_url
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
class Clearance::SessionsController < ApplicationController
|
2
|
+
unloadable
|
3
|
+
|
4
|
+
protect_from_forgery :except => :create
|
5
|
+
filter_parameter_logging :password
|
6
|
+
|
7
|
+
def new
|
8
|
+
render :template => 'sessions/new'
|
9
|
+
end
|
10
|
+
|
11
|
+
def create
|
12
|
+
@user = ::User.authenticate(params[:session][:email],
|
13
|
+
params[:session][:password])
|
14
|
+
if @user.nil?
|
15
|
+
flash_failure_after_create
|
16
|
+
render :template => 'sessions/new', :status => :unauthorized
|
17
|
+
else
|
18
|
+
if @user.email_confirmed?
|
19
|
+
sign_in(@user)
|
20
|
+
flash_success_after_create
|
21
|
+
redirect_back_or(url_after_create)
|
22
|
+
else
|
23
|
+
::ClearanceMailer.deliver_confirmation(@user)
|
24
|
+
flash_notice_after_create
|
25
|
+
redirect_to(new_session_url)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def destroy
|
31
|
+
sign_out
|
32
|
+
flash_success_after_destroy
|
33
|
+
redirect_to(url_after_destroy)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def flash_failure_after_create
|
39
|
+
flash.now[:failure] = translate(:bad_email_or_password,
|
40
|
+
:scope => [:clearance, :controllers, :sessions],
|
41
|
+
:default => "Bad email or password.")
|
42
|
+
end
|
43
|
+
|
44
|
+
def flash_success_after_create
|
45
|
+
flash[:success] = translate(:signed_in, :default => "Signed in.")
|
46
|
+
end
|
47
|
+
|
48
|
+
def flash_notice_after_create
|
49
|
+
flash[:notice] = translate(:unconfirmed_email,
|
50
|
+
:scope => [:clearance, :controllers, :sessions],
|
51
|
+
:default => "User has not confirmed email. " <<
|
52
|
+
"Confirmation email will be resent.")
|
53
|
+
end
|
54
|
+
|
55
|
+
def url_after_create
|
56
|
+
root_url
|
57
|
+
end
|
58
|
+
|
59
|
+
def flash_success_after_destroy
|
60
|
+
flash[:success] = translate(:signed_out, :default => "Signed out.")
|
61
|
+
end
|
62
|
+
|
63
|
+
def url_after_destroy
|
64
|
+
new_session_url
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class Clearance::UsersController < ApplicationController
|
2
|
+
unloadable
|
3
|
+
|
4
|
+
before_filter :redirect_to_root, :only => [:new, :create], :if => :signed_in?
|
5
|
+
filter_parameter_logging :password
|
6
|
+
|
7
|
+
def new
|
8
|
+
@user = ::User.new(params[:user])
|
9
|
+
render :template => 'users/new'
|
10
|
+
end
|
11
|
+
|
12
|
+
def create
|
13
|
+
@user = ::User.new params[:user]
|
14
|
+
if @user.save
|
15
|
+
::ClearanceMailer.deliver_confirmation @user
|
16
|
+
flash_notice_after_create
|
17
|
+
redirect_to(url_after_create)
|
18
|
+
else
|
19
|
+
render :template => 'users/new'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def flash_notice_after_create
|
26
|
+
flash[:notice] = translate(:deliver_confirmation,
|
27
|
+
:scope => [:clearance, :controllers, :users],
|
28
|
+
:default => "You will receive an email within the next few minutes. " <<
|
29
|
+
"It contains instructions for confirming your account.")
|
30
|
+
end
|
31
|
+
|
32
|
+
def url_after_create
|
33
|
+
new_session_url
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class ClearanceMailer < ActionMailer::Base
|
2
|
+
|
3
|
+
default_url_options[:host] = HOST
|
4
|
+
|
5
|
+
def change_password(user)
|
6
|
+
from DO_NOT_REPLY
|
7
|
+
recipients user.email
|
8
|
+
subject I18n.t(:change_password,
|
9
|
+
:scope => [:clearance, :models, :clearance_mailer],
|
10
|
+
:default => "Change your password")
|
11
|
+
body :user => user
|
12
|
+
end
|
13
|
+
|
14
|
+
def confirmation(user)
|
15
|
+
from DO_NOT_REPLY
|
16
|
+
recipients user.email
|
17
|
+
subject I18n.t(:confirmation,
|
18
|
+
:scope => [:clearance, :models, :clearance_mailer],
|
19
|
+
:default => "Account confirmation")
|
20
|
+
body :user => user
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Someone, hopefully you, has requested that we send you a link to change your password.
|
2
|
+
|
3
|
+
Here's the link:
|
4
|
+
|
5
|
+
<%= edit_user_password_url(@user,
|
6
|
+
:token => @user.confirmation_token,
|
7
|
+
:escape => false) %>
|
8
|
+
|
9
|
+
If you didn't request this, ignore this email. Don't worry. Your password hasn't been changed.
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<h2>Change your password</h2>
|
2
|
+
|
3
|
+
<p>
|
4
|
+
Your password has been reset. Choose a new password below.
|
5
|
+
</p>
|
6
|
+
|
7
|
+
<%= error_messages_for :user %>
|
8
|
+
|
9
|
+
<% form_for(:user,
|
10
|
+
:url => user_password_path(@user, :token => @user.confirmation_token),
|
11
|
+
:html => { :method => :put }) do |form| %>
|
12
|
+
<div class="password_field">
|
13
|
+
<%= form.label :password, "Choose password" %>
|
14
|
+
<%= form.password_field :password %>
|
15
|
+
</div>
|
16
|
+
<div class="password_field">
|
17
|
+
<%= form.label :password_confirmation, "Confirm password" %>
|
18
|
+
<%= form.password_field :password_confirmation %>
|
19
|
+
</div>
|
20
|
+
<div class="submit_field">
|
21
|
+
<%= form.submit "Save this password", :disable_with => "Please wait..." %>
|
22
|
+
</div>
|
23
|
+
<% end %>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<h2>Change your password</h2>
|
2
|
+
|
3
|
+
<p>
|
4
|
+
We will email you a link to change your password.
|
5
|
+
</p>
|
6
|
+
|
7
|
+
<% form_for :password, :url => passwords_path do |form| %>
|
8
|
+
<div class="text_field">
|
9
|
+
<%= form.label :email, "Email address" %>
|
10
|
+
<%= form.text_field :email %>
|
11
|
+
</div>
|
12
|
+
<div class="submit_field">
|
13
|
+
<%= form.submit "Reset password", :disable_with => "Please wait..." %>
|
14
|
+
</div>
|
15
|
+
<% end %>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<h2>Sign in</h2>
|
2
|
+
|
3
|
+
<% form_for :session, :url => session_path do |form| %>
|
4
|
+
<div class="text_field">
|
5
|
+
<%= form.label :email %>
|
6
|
+
<%= form.text_field :email %>
|
7
|
+
</div>
|
8
|
+
<div class="text_field">
|
9
|
+
<%= form.label :password %>
|
10
|
+
<%= form.password_field :password %>
|
11
|
+
</div>
|
12
|
+
<div class="submit_field">
|
13
|
+
<%= form.submit "Sign in", :disable_with => "Please wait..." %>
|
14
|
+
</div>
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<ul>
|
18
|
+
<li>
|
19
|
+
<%= link_to "Sign up", new_user_path %>
|
20
|
+
</li>
|
21
|
+
<li>
|
22
|
+
<%= link_to "Forgot password?", new_password_path %>
|
23
|
+
</li>
|
24
|
+
</ul>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<%= form.error_messages %>
|
2
|
+
<div class="text_field">
|
3
|
+
<%= form.label :email %>
|
4
|
+
<%= form.text_field :email %>
|
5
|
+
</div>
|
6
|
+
<div class="password_field">
|
7
|
+
<%= form.label :password %>
|
8
|
+
<%= form.password_field :password %>
|
9
|
+
</div>
|
10
|
+
<div class="password_field">
|
11
|
+
<%= form.label :password_confirmation, "Confirm password" %>
|
12
|
+
<%= form.password_field :password_confirmation %>
|
13
|
+
</div>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
ActionController::Routing::Routes.draw do |map|
|
2
|
+
map.resources :passwords,
|
3
|
+
:controller => 'clearance/passwords',
|
4
|
+
:only => [:new, :create]
|
5
|
+
|
6
|
+
map.resource :session,
|
7
|
+
:controller => 'clearance/sessions',
|
8
|
+
:only => [:new, :create, :destroy]
|
9
|
+
|
10
|
+
map.resources :users, :controller => 'clearance/users' do |users|
|
11
|
+
users.resource :password,
|
12
|
+
:controller => 'clearance/passwords',
|
13
|
+
:only => [:create, :edit, :update]
|
14
|
+
|
15
|
+
users.resource :confirmation,
|
16
|
+
:controller => 'clearance/confirmations',
|
17
|
+
:only => [:new, :create]
|
18
|
+
end
|
19
|
+
|
20
|
+
map.sign_up 'sign_up',
|
21
|
+
:controller => 'clearance/users',
|
22
|
+
:action => 'new'
|
23
|
+
map.sign_in 'sign_in',
|
24
|
+
:controller => 'clearance/sessions',
|
25
|
+
:action => 'new'
|
26
|
+
map.sign_out 'sign_out',
|
27
|
+
:controller => 'clearance/sessions',
|
28
|
+
:action => 'destroy',
|
29
|
+
:method => :delete
|
30
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
script/generate clearance
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/lib/insert_commands.rb")
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + "/lib/rake_commands.rb")
|
3
|
+
require 'factory_girl'
|
4
|
+
|
5
|
+
class ClearanceGenerator < Rails::Generator::Base
|
6
|
+
|
7
|
+
def manifest
|
8
|
+
record do |m|
|
9
|
+
m.insert_into "app/controllers/application_controller.rb",
|
10
|
+
"include Clearance::Authentication"
|
11
|
+
|
12
|
+
user_model = "app/models/user.rb"
|
13
|
+
if File.exists?(user_model)
|
14
|
+
m.insert_into user_model, "include Clearance::User"
|
15
|
+
else
|
16
|
+
m.directory File.join("app", "models")
|
17
|
+
m.file "user.rb", user_model
|
18
|
+
end
|
19
|
+
|
20
|
+
m.directory File.join("test", "factories")
|
21
|
+
m.file "factories.rb", "test/factories/clearance.rb"
|
22
|
+
|
23
|
+
m.migration_template "migrations/#{migration_name}.rb",
|
24
|
+
'db/migrate',
|
25
|
+
:migration_file_name => "clearance_#{migration_name}"
|
26
|
+
|
27
|
+
m.readme "README"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def migration_name
|
34
|
+
if ActiveRecord::Base.connection.table_exists?(:users)
|
35
|
+
'update_users'
|
36
|
+
else
|
37
|
+
'create_users'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|