devise 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of devise might be problematic. Click here for more details.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +220 -0
- data/Rakefile +45 -0
- data/TODO +37 -0
- data/app/controllers/confirmations_controller.rb +32 -0
- data/app/controllers/passwords_controller.rb +38 -0
- data/app/controllers/sessions_controller.rb +35 -0
- data/app/models/notifier.rb +47 -0
- data/app/views/confirmations/new.html.erb +16 -0
- data/app/views/notifier/confirmation_instructions.html.erb +5 -0
- data/app/views/notifier/reset_password_instructions.html.erb +8 -0
- data/app/views/passwords/edit.html.erb +20 -0
- data/app/views/passwords/new.html.erb +16 -0
- data/app/views/sessions/new.html.erb +23 -0
- data/config/locales/en.yml +16 -0
- data/init.rb +2 -0
- data/lib/devise.rb +48 -0
- data/lib/devise/active_record.rb +86 -0
- data/lib/devise/controllers/filters.rb +109 -0
- data/lib/devise/controllers/helpers.rb +91 -0
- data/lib/devise/controllers/url_helpers.rb +47 -0
- data/lib/devise/hooks/rememberable.rb +24 -0
- data/lib/devise/mapping.rb +95 -0
- data/lib/devise/migrations.rb +50 -0
- data/lib/devise/models/authenticable.rb +98 -0
- data/lib/devise/models/confirmable.rb +125 -0
- data/lib/devise/models/recoverable.rb +88 -0
- data/lib/devise/models/rememberable.rb +71 -0
- data/lib/devise/models/validatable.rb +36 -0
- data/lib/devise/routes.rb +95 -0
- data/lib/devise/strategies/authenticable.rb +45 -0
- data/lib/devise/strategies/base.rb +24 -0
- data/lib/devise/strategies/rememberable.rb +33 -0
- data/lib/devise/version.rb +3 -0
- data/lib/devise/warden.rb +64 -0
- data/test/active_record_test.rb +96 -0
- data/test/controllers/filters_test.rb +97 -0
- data/test/controllers/helpers_test.rb +40 -0
- data/test/controllers/url_helpers_test.rb +47 -0
- data/test/integration/authenticable_test.rb +191 -0
- data/test/integration/confirmable_test.rb +60 -0
- data/test/integration/recoverable_test.rb +131 -0
- data/test/integration/rememberable_test.rb +56 -0
- data/test/mailers/confirmation_instructions_test.rb +59 -0
- data/test/mailers/reset_password_instructions_test.rb +62 -0
- data/test/mapping_test.rb +71 -0
- data/test/models/authenticable_test.rb +138 -0
- data/test/models/confirmable_test.rb +206 -0
- data/test/models/recoverable_test.rb +145 -0
- data/test/models/rememberable_test.rb +68 -0
- data/test/models/validatable_test.rb +99 -0
- data/test/rails_app/app/controllers/admins_controller.rb +6 -0
- data/test/rails_app/app/controllers/application_controller.rb +10 -0
- data/test/rails_app/app/controllers/home_controller.rb +4 -0
- data/test/rails_app/app/controllers/users_controller.rb +7 -0
- data/test/rails_app/app/helpers/application_helper.rb +3 -0
- data/test/rails_app/app/models/account.rb +3 -0
- data/test/rails_app/app/models/admin.rb +3 -0
- data/test/rails_app/app/models/organizer.rb +3 -0
- data/test/rails_app/app/models/user.rb +3 -0
- data/test/rails_app/config/boot.rb +110 -0
- data/test/rails_app/config/environment.rb +41 -0
- data/test/rails_app/config/environments/development.rb +17 -0
- data/test/rails_app/config/environments/production.rb +28 -0
- data/test/rails_app/config/environments/test.rb +28 -0
- data/test/rails_app/config/initializers/new_rails_defaults.rb +21 -0
- data/test/rails_app/config/initializers/session_store.rb +15 -0
- data/test/rails_app/config/routes.rb +18 -0
- data/test/routes_test.rb +75 -0
- data/test/support/assertions_helper.rb +22 -0
- data/test/support/integration_tests_helper.rb +66 -0
- data/test/support/model_tests_helper.rb +40 -0
- data/test/test_helper.rb +39 -0
- metadata +136 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
<h2>Resend confirmation instructions</h2>
|
2
|
+
|
3
|
+
<% form_for resource_name, :url => confirmation_path(resource_name) do |f| %>
|
4
|
+
<%= f.error_messages %>
|
5
|
+
|
6
|
+
<p><%= f.label :email %></p>
|
7
|
+
<p><%= f.text_field :email %></p>
|
8
|
+
|
9
|
+
<p><%= f.submit "Resend confirmation instructions" %></p>
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
<%= link_to "Sign in", new_session_path(resource_name) %><br />
|
13
|
+
|
14
|
+
<%- if devise_mapping.recoverable? %>
|
15
|
+
<%= link_to "Forgot password?", new_password_path(resource_name) %><br />
|
16
|
+
<% end -%>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
Hello <%= @resource.email %>!
|
2
|
+
|
3
|
+
Someone has requested a link to change your password, and you can do this through the link below.
|
4
|
+
|
5
|
+
<%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token) %>
|
6
|
+
|
7
|
+
If you didn't request this, please ignore this email.
|
8
|
+
Your password won't change until you access the link above and create a new one.
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<h2>Change your password</h2>
|
2
|
+
|
3
|
+
<% form_for resource_name, :url => password_path(resource_name), :html => { :method => :put } do |f| %>
|
4
|
+
<%= f.error_messages %>
|
5
|
+
<%= f.hidden_field :reset_password_token %>
|
6
|
+
|
7
|
+
<p><%= f.label :password %></p>
|
8
|
+
<p><%= f.password_field :password %></p>
|
9
|
+
|
10
|
+
<p><%= f.label :password_confirmation %></p>
|
11
|
+
<p><%= f.password_field :password_confirmation %></p>
|
12
|
+
|
13
|
+
<p><%= f.submit "Change my password" %></p>
|
14
|
+
<% end %>
|
15
|
+
|
16
|
+
<%= link_to "Sign in", new_session_path(resource_name) %><br />
|
17
|
+
|
18
|
+
<%- if devise_mapping.confirmable? %>
|
19
|
+
<%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
|
20
|
+
<% end -%>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<h2>Forgot your password?</h2>
|
2
|
+
|
3
|
+
<% form_for resource_name, :url => password_path(resource_name) do |f| %>
|
4
|
+
<%= f.error_messages %>
|
5
|
+
|
6
|
+
<p><%= f.label :email %></p>
|
7
|
+
<p><%= f.text_field :email %></p>
|
8
|
+
|
9
|
+
<p><%= f.submit "Send me reset password instructions" %></p>
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
<%= link_to "Sign in", new_session_path(resource_name) %><br />
|
13
|
+
|
14
|
+
<%- if devise_mapping.confirmable? %>
|
15
|
+
<%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
|
16
|
+
<% end -%>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<h2>Sign in</h2>
|
2
|
+
|
3
|
+
<% form_for resource_name, :url => session_path(resource_name) do |f| -%>
|
4
|
+
<p><%= f.label :email %></p>
|
5
|
+
<p><%= f.text_field :email %></p>
|
6
|
+
|
7
|
+
<p><%= f.label :password %></p>
|
8
|
+
<p><%= f.password_field :password %></p>
|
9
|
+
|
10
|
+
<% if devise_mapping.rememberable? -%>
|
11
|
+
<p><%= f.check_box :remember_me %> <%= f.label :remember_me %></p>
|
12
|
+
<% end -%>
|
13
|
+
|
14
|
+
<p><%= f.submit "Sign in" %></p>
|
15
|
+
<% end -%>
|
16
|
+
|
17
|
+
<%- if devise_mapping.recoverable? %>
|
18
|
+
<%= link_to "Forgot password?", new_password_path(resource_name) %><br />
|
19
|
+
<% end -%>
|
20
|
+
|
21
|
+
<%- if devise_mapping.confirmable? %>
|
22
|
+
<%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
|
23
|
+
<% end -%>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
en:
|
2
|
+
devise:
|
3
|
+
sessions:
|
4
|
+
signed_in: 'Signed in successfully.'
|
5
|
+
signed_out: 'Signed out successfully.'
|
6
|
+
unauthenticated: 'Invalid email or password.'
|
7
|
+
passwords:
|
8
|
+
send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
|
9
|
+
updated: 'Your password was changed successfully. You are now signed in.'
|
10
|
+
confirmations:
|
11
|
+
send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
|
12
|
+
confirmed: 'Your account was successfully confirmed. You are now signed in.'
|
13
|
+
notifier:
|
14
|
+
confirmation_instructions: 'Confirmation instructions'
|
15
|
+
reset_password_instructions: 'Reset password instructions'
|
16
|
+
|
data/init.rb
ADDED
data/lib/devise.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module Devise
|
2
|
+
ALL = [:authenticable, :confirmable, :recoverable, :rememberable, :validatable].freeze
|
3
|
+
|
4
|
+
# Maps controller names to devise modules
|
5
|
+
CONTROLLERS = {
|
6
|
+
:sessions => :authenticable,
|
7
|
+
:passwords => :recoverable,
|
8
|
+
:confirmations => :confirmable
|
9
|
+
}.freeze
|
10
|
+
|
11
|
+
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE'].freeze
|
12
|
+
|
13
|
+
MODEL_CONFIG = []
|
14
|
+
|
15
|
+
def self.model_config(klass, accessor, default=nil)
|
16
|
+
# Create Devise accessor
|
17
|
+
mattr_accessor accessor
|
18
|
+
|
19
|
+
# Set default value
|
20
|
+
send(:"#{accessor}=", default)
|
21
|
+
|
22
|
+
# Store configuration method
|
23
|
+
MODEL_CONFIG << accessor
|
24
|
+
|
25
|
+
# Set default value
|
26
|
+
klass.class_eval <<-METHOD
|
27
|
+
def #{accessor}
|
28
|
+
Devise.#{accessor}
|
29
|
+
end
|
30
|
+
METHOD
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Devise initialization process goes like this:
|
35
|
+
#
|
36
|
+
# 1) Include Devise::ActiveRecord and Devise::Migrations
|
37
|
+
# 2) Load and config warden
|
38
|
+
# 3) Add routes extensions
|
39
|
+
# 4) Load routes definitions
|
40
|
+
# 5) Include filters and helpers in controllers and views
|
41
|
+
#
|
42
|
+
Rails.configuration.after_initialize do
|
43
|
+
ActiveRecord::Base.extend Devise::ActiveRecord
|
44
|
+
ActiveRecord::ConnectionAdapters::TableDefinition.send :include, Devise::Migrations
|
45
|
+
end
|
46
|
+
|
47
|
+
require 'devise/warden'
|
48
|
+
require 'devise/routes'
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Devise
|
2
|
+
module ActiveRecord
|
3
|
+
# Shortcut method for including all devise modules inside your model.
|
4
|
+
# You can give some extra options while declaring devise in your model:
|
5
|
+
#
|
6
|
+
# * except: convenient option that allows you to add all devise modules,
|
7
|
+
# removing only the modules you setup here:
|
8
|
+
#
|
9
|
+
# devise :all, :except => :rememberable
|
10
|
+
#
|
11
|
+
# * pepper: setup a pepper to generate de encrypted password. By default no
|
12
|
+
# pepper is used:
|
13
|
+
#
|
14
|
+
# devise :all, :pepper => 'my_pepper'
|
15
|
+
#
|
16
|
+
# * stretches: configure how many times you want the password is reencrypted.
|
17
|
+
#
|
18
|
+
# devise :all, :stretches => 20
|
19
|
+
#
|
20
|
+
# You can refer to Authenticable for more information about writing your own
|
21
|
+
# method to setup pepper and stretches.
|
22
|
+
#
|
23
|
+
# Examples:
|
24
|
+
#
|
25
|
+
# # include only authenticable module (default)
|
26
|
+
# devise
|
27
|
+
#
|
28
|
+
# # include authenticable + confirmable modules
|
29
|
+
# devise :confirmable
|
30
|
+
#
|
31
|
+
# # include authenticable + recoverable modules
|
32
|
+
# devise :recoverable
|
33
|
+
#
|
34
|
+
# # include authenticable + rememberable modules
|
35
|
+
# devise :rememberable
|
36
|
+
#
|
37
|
+
# # include authenticable + validatable modules
|
38
|
+
# devise :validatable
|
39
|
+
#
|
40
|
+
# # include authenticable + confirmable + recoverable + rememberable + validatable
|
41
|
+
# devise :confirmable, :recoverable, :rememberable, :validatable
|
42
|
+
#
|
43
|
+
# # shortcut to include all modules (same as above)
|
44
|
+
# devise :all
|
45
|
+
#
|
46
|
+
# # include all except recoverable
|
47
|
+
# devise :all, :except => :recoverable
|
48
|
+
#
|
49
|
+
def devise(*modules)
|
50
|
+
options = modules.extract_options!
|
51
|
+
options.assert_valid_keys(:except, *Devise::MODEL_CONFIG)
|
52
|
+
|
53
|
+
modules = Devise::ALL if modules.include?(:all)
|
54
|
+
modules -= Array(options.delete(:except)) if options.key?(:except)
|
55
|
+
modules |= [:authenticable]
|
56
|
+
|
57
|
+
modules.each do |m|
|
58
|
+
devise_modules << m.to_sym
|
59
|
+
include Devise::Models.const_get(m.to_s.classify)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Convert new keys to methods which overwrites Devise defaults
|
63
|
+
options.each do |key, value|
|
64
|
+
case value
|
65
|
+
when Proc
|
66
|
+
define_method key, &value
|
67
|
+
next
|
68
|
+
when ActiveSupport::Duration
|
69
|
+
value = value.to_i
|
70
|
+
end
|
71
|
+
|
72
|
+
class_eval <<-END_EVAL, __FILE__, __LINE__
|
73
|
+
def #{key}
|
74
|
+
#{value.inspect}
|
75
|
+
end
|
76
|
+
END_EVAL
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Stores all modules included inside the model, so we are able to verify
|
81
|
+
# which routes are needed.
|
82
|
+
def devise_modules
|
83
|
+
@devise_modules ||= []
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module Devise
|
2
|
+
module Controllers
|
3
|
+
module Filters
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.class_eval do
|
7
|
+
helper_method :warden, :signed_in?,
|
8
|
+
*Devise.mappings.keys.map { |m| [:"current_#{m}", :"#{m}_signed_in?"] }.flatten
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# The main accessor for the warden proxy instance
|
13
|
+
def warden
|
14
|
+
request.env['warden']
|
15
|
+
end
|
16
|
+
|
17
|
+
# Attempts to authenticate the given scope by running authentication hooks,
|
18
|
+
# but does not redirect in case of failures.
|
19
|
+
def authenticate(scope)
|
20
|
+
warden.authenticate(:scope => scope)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Attempts to authenticate the given scope by running authentication hooks,
|
24
|
+
# redirecting in case of failures.
|
25
|
+
def authenticate!(scope)
|
26
|
+
warden.authenticate!(:scope => scope)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Check if the given scope is signed in session, without running
|
30
|
+
# authentication hooks.
|
31
|
+
def signed_in?(scope)
|
32
|
+
warden.authenticated?(scope)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Set the warden user with the scope, signing in the resource automatically,
|
36
|
+
# without running hooks.
|
37
|
+
def sign_in(scope, resource)
|
38
|
+
warden.set_user(resource, :scope => scope)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Sign out based on scope.
|
42
|
+
def sign_out(scope, *args)
|
43
|
+
warden.user(scope) # Without loading user here, before_logout hook is not called
|
44
|
+
warden.raw_session.inspect # Without this inspect here. The session does not clear.
|
45
|
+
warden.logout(scope, *args)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Define authentication filters and accessor helpers based on mappings.
|
49
|
+
# These filters should be used inside the controllers as before_filters,
|
50
|
+
# so you can control the scope of the user who should be signed in to
|
51
|
+
# access that specific controller/action.
|
52
|
+
# Example:
|
53
|
+
#
|
54
|
+
# Maps:
|
55
|
+
# User => :authenticable
|
56
|
+
# Admin => :authenticable
|
57
|
+
#
|
58
|
+
# Generated methods:
|
59
|
+
# authenticate_user! # Signs user in or redirect
|
60
|
+
# authenticate_admin! # Signs admin in or redirect
|
61
|
+
# user_signed_in? # Checks whether there is an user signed in or not
|
62
|
+
# admin_signed_in? # Checks whether there is an admin signed in or not
|
63
|
+
# current_user # Current signed in user
|
64
|
+
# current_admin # Currend signed in admin
|
65
|
+
# user_session # Session data available only to the user scope
|
66
|
+
# admin_session # Session data available only to the admin scope
|
67
|
+
#
|
68
|
+
# Use:
|
69
|
+
# before_filter :authenticate_user! # Tell devise to use :user map
|
70
|
+
# before_filter :authenticate_admin! # Tell devise to use :admin map
|
71
|
+
#
|
72
|
+
Devise.mappings.each_key do |mapping|
|
73
|
+
class_eval <<-METHODS, __FILE__, __LINE__
|
74
|
+
def authenticate_#{mapping}!
|
75
|
+
warden.authenticate!(:scope => :#{mapping})
|
76
|
+
end
|
77
|
+
|
78
|
+
def #{mapping}_signed_in?
|
79
|
+
warden.authenticated?(:#{mapping})
|
80
|
+
end
|
81
|
+
|
82
|
+
def current_#{mapping}
|
83
|
+
@current_#{mapping} ||= warden.user(:#{mapping})
|
84
|
+
end
|
85
|
+
|
86
|
+
def #{mapping}_session
|
87
|
+
warden.session(:#{mapping})
|
88
|
+
end
|
89
|
+
METHODS
|
90
|
+
end
|
91
|
+
|
92
|
+
protected
|
93
|
+
|
94
|
+
# Helper for use in before_filters where no authentication is required.
|
95
|
+
#
|
96
|
+
# Example:
|
97
|
+
# before_filter :require_no_authentication, :only => :new
|
98
|
+
def require_no_authentication
|
99
|
+
redirect_to root_path if warden.authenticated?(resource_name)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Checks whether it's a devise mapped resource or not.
|
103
|
+
def is_devise_resource? #:nodoc:
|
104
|
+
raise ActionController::UnknownAction unless devise_mapping && devise_mapping.allows?(controller_name)
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Devise
|
2
|
+
module Controllers
|
3
|
+
module Helpers
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.class_eval do
|
7
|
+
helper_method :resource, :resource_name, :resource_class, :devise_mapping
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# Gets the actual resource stored in the instance variable
|
12
|
+
def resource
|
13
|
+
instance_variable_get(:"@#{resource_name}")
|
14
|
+
end
|
15
|
+
|
16
|
+
# Proxy to devise map name
|
17
|
+
def resource_name
|
18
|
+
devise_mapping.name
|
19
|
+
end
|
20
|
+
|
21
|
+
# Proxy to devise map class
|
22
|
+
def resource_class
|
23
|
+
devise_mapping.to
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
# Redirects to stored uri before signing in or the default path and clear
|
29
|
+
# return to.
|
30
|
+
def redirect_back_or_to(default)
|
31
|
+
redirect_to(return_to || default)
|
32
|
+
clear_return_to
|
33
|
+
end
|
34
|
+
|
35
|
+
# Access to scoped stored uri
|
36
|
+
def return_to
|
37
|
+
session[:"#{resource_name}.return_to"]
|
38
|
+
end
|
39
|
+
|
40
|
+
# Clear scoped stored uri
|
41
|
+
def clear_return_to
|
42
|
+
session[:"#{resource_name}.return_to"] = nil
|
43
|
+
end
|
44
|
+
|
45
|
+
# Checks for the existence of the resource root path. If it exists,
|
46
|
+
# returns it, otherwise returns the default root_path.
|
47
|
+
# Used after authenticating a user, confirming it's account or updating
|
48
|
+
# it's password, so we are able to redirect to scoped root paths.
|
49
|
+
# Examples (for a user scope):
|
50
|
+
# map.user_root '/users', :controller => 'users' # creates user_root_path
|
51
|
+
#
|
52
|
+
# map.namespace :users do |users|
|
53
|
+
# users.root # creates user_root_path
|
54
|
+
# end
|
55
|
+
def home_or_root_path
|
56
|
+
home_path = :"#{resource_name}_root_path"
|
57
|
+
respond_to?(home_path, true) ? send(home_path) : root_path
|
58
|
+
end
|
59
|
+
|
60
|
+
# Attempt to find the mapped route for devise based on request path
|
61
|
+
def devise_mapping
|
62
|
+
@devise_mapping ||= Devise.find_mapping_by_path(request.path)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Sets the resource creating an instance variable
|
66
|
+
def resource=(new_resource)
|
67
|
+
instance_variable_set(:"@#{resource_name}", new_resource)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Sets the flash message with :key, using I18n. By default you are able
|
71
|
+
# to setup your messages using specific resource scope, and if no one is
|
72
|
+
# found we look to default scope.
|
73
|
+
# Example (i18n locale file):
|
74
|
+
#
|
75
|
+
# en:
|
76
|
+
# devise:
|
77
|
+
# passwords:
|
78
|
+
# #default_scope_messages - only if resource_scope is not found
|
79
|
+
# user:
|
80
|
+
# #resource_scope_messages
|
81
|
+
#
|
82
|
+
# Please refer to README or en.yml locale file to check what messages are
|
83
|
+
# available.
|
84
|
+
def set_flash_message(key, kind)
|
85
|
+
flash[key] = I18n.t(:"#{resource_name}.#{kind}",
|
86
|
+
:scope => [:devise, controller_name.to_sym], :default => kind)
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|