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.

Files changed (74) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +220 -0
  3. data/Rakefile +45 -0
  4. data/TODO +37 -0
  5. data/app/controllers/confirmations_controller.rb +32 -0
  6. data/app/controllers/passwords_controller.rb +38 -0
  7. data/app/controllers/sessions_controller.rb +35 -0
  8. data/app/models/notifier.rb +47 -0
  9. data/app/views/confirmations/new.html.erb +16 -0
  10. data/app/views/notifier/confirmation_instructions.html.erb +5 -0
  11. data/app/views/notifier/reset_password_instructions.html.erb +8 -0
  12. data/app/views/passwords/edit.html.erb +20 -0
  13. data/app/views/passwords/new.html.erb +16 -0
  14. data/app/views/sessions/new.html.erb +23 -0
  15. data/config/locales/en.yml +16 -0
  16. data/init.rb +2 -0
  17. data/lib/devise.rb +48 -0
  18. data/lib/devise/active_record.rb +86 -0
  19. data/lib/devise/controllers/filters.rb +109 -0
  20. data/lib/devise/controllers/helpers.rb +91 -0
  21. data/lib/devise/controllers/url_helpers.rb +47 -0
  22. data/lib/devise/hooks/rememberable.rb +24 -0
  23. data/lib/devise/mapping.rb +95 -0
  24. data/lib/devise/migrations.rb +50 -0
  25. data/lib/devise/models/authenticable.rb +98 -0
  26. data/lib/devise/models/confirmable.rb +125 -0
  27. data/lib/devise/models/recoverable.rb +88 -0
  28. data/lib/devise/models/rememberable.rb +71 -0
  29. data/lib/devise/models/validatable.rb +36 -0
  30. data/lib/devise/routes.rb +95 -0
  31. data/lib/devise/strategies/authenticable.rb +45 -0
  32. data/lib/devise/strategies/base.rb +24 -0
  33. data/lib/devise/strategies/rememberable.rb +33 -0
  34. data/lib/devise/version.rb +3 -0
  35. data/lib/devise/warden.rb +64 -0
  36. data/test/active_record_test.rb +96 -0
  37. data/test/controllers/filters_test.rb +97 -0
  38. data/test/controllers/helpers_test.rb +40 -0
  39. data/test/controllers/url_helpers_test.rb +47 -0
  40. data/test/integration/authenticable_test.rb +191 -0
  41. data/test/integration/confirmable_test.rb +60 -0
  42. data/test/integration/recoverable_test.rb +131 -0
  43. data/test/integration/rememberable_test.rb +56 -0
  44. data/test/mailers/confirmation_instructions_test.rb +59 -0
  45. data/test/mailers/reset_password_instructions_test.rb +62 -0
  46. data/test/mapping_test.rb +71 -0
  47. data/test/models/authenticable_test.rb +138 -0
  48. data/test/models/confirmable_test.rb +206 -0
  49. data/test/models/recoverable_test.rb +145 -0
  50. data/test/models/rememberable_test.rb +68 -0
  51. data/test/models/validatable_test.rb +99 -0
  52. data/test/rails_app/app/controllers/admins_controller.rb +6 -0
  53. data/test/rails_app/app/controllers/application_controller.rb +10 -0
  54. data/test/rails_app/app/controllers/home_controller.rb +4 -0
  55. data/test/rails_app/app/controllers/users_controller.rb +7 -0
  56. data/test/rails_app/app/helpers/application_helper.rb +3 -0
  57. data/test/rails_app/app/models/account.rb +3 -0
  58. data/test/rails_app/app/models/admin.rb +3 -0
  59. data/test/rails_app/app/models/organizer.rb +3 -0
  60. data/test/rails_app/app/models/user.rb +3 -0
  61. data/test/rails_app/config/boot.rb +110 -0
  62. data/test/rails_app/config/environment.rb +41 -0
  63. data/test/rails_app/config/environments/development.rb +17 -0
  64. data/test/rails_app/config/environments/production.rb +28 -0
  65. data/test/rails_app/config/environments/test.rb +28 -0
  66. data/test/rails_app/config/initializers/new_rails_defaults.rb +21 -0
  67. data/test/rails_app/config/initializers/session_store.rb +15 -0
  68. data/test/rails_app/config/routes.rb +18 -0
  69. data/test/routes_test.rb +75 -0
  70. data/test/support/assertions_helper.rb +22 -0
  71. data/test/support/integration_tests_helper.rb +66 -0
  72. data/test/support/model_tests_helper.rb +40 -0
  73. data/test/test_helper.rb +39 -0
  74. 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,5 @@
1
+ Welcome <%= @resource.email %>!
2
+
3
+ You can confirm your account through the link below:
4
+
5
+ <%= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @resource.confirmation_token) %>
@@ -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
@@ -0,0 +1,2 @@
1
+ # We need to load devise here to ensure routes extensions are loaded.
2
+ require 'devise'
@@ -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