ramon-devise 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. data/CHANGELOG.rdoc +109 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +243 -0
  4. data/Rakefile +45 -0
  5. data/TODO +8 -0
  6. data/app/controllers/confirmations_controller.rb +33 -0
  7. data/app/controllers/passwords_controller.rb +41 -0
  8. data/app/controllers/sessions_controller.rb +33 -0
  9. data/app/models/devise_mailer.rb +53 -0
  10. data/app/views/confirmations/new.html.erb +16 -0
  11. data/app/views/devise_mailer/confirmation_instructions.html.erb +5 -0
  12. data/app/views/devise_mailer/reset_password_instructions.html.erb +8 -0
  13. data/app/views/passwords/edit.html.erb +20 -0
  14. data/app/views/passwords/new.html.erb +16 -0
  15. data/app/views/sessions/new.html.erb +23 -0
  16. data/generators/devise/USAGE +5 -0
  17. data/generators/devise/devise_generator.rb +25 -0
  18. data/generators/devise/lib/route_devise.rb +32 -0
  19. data/generators/devise/templates/README +22 -0
  20. data/generators/devise/templates/migration.rb +20 -0
  21. data/generators/devise/templates/model.rb +5 -0
  22. data/generators/devise_install/USAGE +3 -0
  23. data/generators/devise_install/devise_install_generator.rb +9 -0
  24. data/generators/devise_install/templates/devise.rb +40 -0
  25. data/generators/devise_views/USAGE +3 -0
  26. data/generators/devise_views/devise_views_generator.rb +24 -0
  27. data/init.rb +2 -0
  28. data/lib/devise.rb +79 -0
  29. data/lib/devise/controllers/filters.rb +111 -0
  30. data/lib/devise/controllers/helpers.rb +130 -0
  31. data/lib/devise/controllers/url_helpers.rb +49 -0
  32. data/lib/devise/failure.rb +38 -0
  33. data/lib/devise/hooks/confirmable.rb +11 -0
  34. data/lib/devise/hooks/rememberable.rb +27 -0
  35. data/lib/devise/locales/en.yml +18 -0
  36. data/lib/devise/mapping.rb +120 -0
  37. data/lib/devise/migrations.rb +51 -0
  38. data/lib/devise/models.rb +105 -0
  39. data/lib/devise/models/authenticatable.rb +97 -0
  40. data/lib/devise/models/confirmable.rb +156 -0
  41. data/lib/devise/models/recoverable.rb +88 -0
  42. data/lib/devise/models/rememberable.rb +95 -0
  43. data/lib/devise/models/validatable.rb +36 -0
  44. data/lib/devise/rails.rb +17 -0
  45. data/lib/devise/rails/routes.rb +109 -0
  46. data/lib/devise/rails/warden_compat.rb +26 -0
  47. data/lib/devise/strategies/authenticatable.rb +46 -0
  48. data/lib/devise/strategies/base.rb +24 -0
  49. data/lib/devise/strategies/rememberable.rb +35 -0
  50. data/lib/devise/version.rb +3 -0
  51. data/lib/devise/warden.rb +24 -0
  52. data/test/controllers/filters_test.rb +103 -0
  53. data/test/controllers/helpers_test.rb +55 -0
  54. data/test/controllers/url_helpers_test.rb +47 -0
  55. data/test/devise_test.rb +72 -0
  56. data/test/failure_test.rb +34 -0
  57. data/test/integration/authenticatable_test.rb +187 -0
  58. data/test/integration/confirmable_test.rb +89 -0
  59. data/test/integration/recoverable_test.rb +131 -0
  60. data/test/integration/rememberable_test.rb +65 -0
  61. data/test/mailers/confirmation_instructions_test.rb +59 -0
  62. data/test/mailers/reset_password_instructions_test.rb +62 -0
  63. data/test/mapping_test.rb +101 -0
  64. data/test/models/authenticatable_test.rb +118 -0
  65. data/test/models/confirmable_test.rb +237 -0
  66. data/test/models/recoverable_test.rb +141 -0
  67. data/test/models/rememberable_test.rb +130 -0
  68. data/test/models/validatable_test.rb +99 -0
  69. data/test/models_test.rb +111 -0
  70. data/test/rails_app/app/controllers/admins_controller.rb +6 -0
  71. data/test/rails_app/app/controllers/application_controller.rb +10 -0
  72. data/test/rails_app/app/controllers/home_controller.rb +4 -0
  73. data/test/rails_app/app/controllers/users_controller.rb +7 -0
  74. data/test/rails_app/app/helpers/application_helper.rb +3 -0
  75. data/test/rails_app/app/models/account.rb +3 -0
  76. data/test/rails_app/app/models/admin.rb +3 -0
  77. data/test/rails_app/app/models/organizer.rb +3 -0
  78. data/test/rails_app/app/models/user.rb +3 -0
  79. data/test/rails_app/config/boot.rb +110 -0
  80. data/test/rails_app/config/environment.rb +41 -0
  81. data/test/rails_app/config/environments/development.rb +17 -0
  82. data/test/rails_app/config/environments/production.rb +28 -0
  83. data/test/rails_app/config/environments/test.rb +28 -0
  84. data/test/rails_app/config/initializers/new_rails_defaults.rb +21 -0
  85. data/test/rails_app/config/initializers/session_store.rb +15 -0
  86. data/test/rails_app/config/routes.rb +18 -0
  87. data/test/routes_test.rb +79 -0
  88. data/test/support/assertions_helper.rb +22 -0
  89. data/test/support/integration_tests_helper.rb +66 -0
  90. data/test/support/model_tests_helper.rb +51 -0
  91. data/test/test_helper.rb +40 -0
  92. metadata +154 -0
@@ -0,0 +1,111 @@
1
+ module Devise
2
+ module Controllers
3
+ # Those filters are convenience methods added to ApplicationController to
4
+ # deal with Warden.
5
+ module Filters
6
+
7
+ def self.included(base)
8
+ base.class_eval do
9
+ helper_method :warden, :signed_in?, :devise_controller?,
10
+ *Devise.mappings.keys.map { |m| [:"current_#{m}", :"#{m}_signed_in?"] }.flatten
11
+
12
+ # Use devise default_url_options. We have to declare it here to overwrite
13
+ # default definitions.
14
+ def default_url_options(options=nil)
15
+ Devise::Mapping.default_url_options
16
+ end
17
+ end
18
+ end
19
+
20
+ # The main accessor for the warden proxy instance
21
+ def warden
22
+ request.env['warden']
23
+ end
24
+
25
+ # Return true if it's a devise_controller. false to all controllers unless
26
+ # the controllers defined inside devise. Useful if you want to apply a before
27
+ # filter to all controller, except the ones in devise:
28
+ #
29
+ # before_filter :my_filter, :unless => { |c| c.devise_controller? }
30
+ def devise_controller?
31
+ false
32
+ end
33
+
34
+ # Attempts to authenticate the given scope by running authentication hooks,
35
+ # but does not redirect in case of failures.
36
+ def authenticate(scope)
37
+ warden.authenticate(:scope => scope)
38
+ end
39
+
40
+ # Attempts to authenticate the given scope by running authentication hooks,
41
+ # redirecting in case of failures.
42
+ def authenticate!(scope)
43
+ warden.authenticate!(:scope => scope)
44
+ end
45
+
46
+ # Check if the given scope is signed in session, without running
47
+ # authentication hooks.
48
+ def signed_in?(scope)
49
+ warden.authenticated?(scope)
50
+ end
51
+
52
+ # Set the warden user with the scope, signing in the resource automatically,
53
+ # without running hooks.
54
+ def sign_in(scope, resource)
55
+ warden.set_user(resource, :scope => scope)
56
+ end
57
+
58
+ # Sign out based on scope.
59
+ def sign_out(scope, *args)
60
+ warden.user(scope) # Without loading user here, before_logout hook is not called
61
+ warden.raw_session.inspect # Without this inspect here. The session does not clear.
62
+ warden.logout(scope, *args)
63
+ end
64
+
65
+ # Define authentication filters and accessor helpers based on mappings.
66
+ # These filters should be used inside the controllers as before_filters,
67
+ # so you can control the scope of the user who should be signed in to
68
+ # access that specific controller/action.
69
+ # Example:
70
+ #
71
+ # Maps:
72
+ # User => :authenticatable
73
+ # Admin => :authenticatable
74
+ #
75
+ # Generated methods:
76
+ # authenticate_user! # Signs user in or redirect
77
+ # authenticate_admin! # Signs admin in or redirect
78
+ # user_signed_in? # Checks whether there is an user signed in or not
79
+ # admin_signed_in? # Checks whether there is an admin signed in or not
80
+ # current_user # Current signed in user
81
+ # current_admin # Currend signed in admin
82
+ # user_session # Session data available only to the user scope
83
+ # admin_session # Session data available only to the admin scope
84
+ #
85
+ # Use:
86
+ # before_filter :authenticate_user! # Tell devise to use :user map
87
+ # before_filter :authenticate_admin! # Tell devise to use :admin map
88
+ #
89
+ Devise.mappings.each_key do |mapping|
90
+ class_eval <<-METHODS, __FILE__, __LINE__
91
+ def authenticate_#{mapping}!
92
+ warden.authenticate!(:scope => :#{mapping})
93
+ end
94
+
95
+ def #{mapping}_signed_in?
96
+ warden.authenticated?(:#{mapping})
97
+ end
98
+
99
+ def current_#{mapping}
100
+ @current_#{mapping} ||= warden.user(:#{mapping})
101
+ end
102
+
103
+ def #{mapping}_session
104
+ warden.session(:#{mapping})
105
+ end
106
+ METHODS
107
+ end
108
+
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,130 @@
1
+ module Devise
2
+ module Controllers
3
+ # Those helpers are used only inside Devise controllers and should not be
4
+ # included in ApplicationController since they all depend on the url being
5
+ # accessed.
6
+ module Helpers
7
+
8
+ def self.included(base)
9
+ base.class_eval do
10
+ helper_method :resource, :resource_name, :resource_class, :devise_mapping, :devise_controller?
11
+ hide_action :resource, :resource_name, :resource_class, :devise_mapping, :devise_controller?
12
+
13
+ skip_before_filter *Devise.mappings.keys.map { |m| :"authenticate_#{m}!" }
14
+ before_filter :is_devise_resource?
15
+ end
16
+ end
17
+
18
+ # Gets the actual resource stored in the instance variable
19
+ def resource
20
+ instance_variable_get(:"@#{resource_name}")
21
+ end
22
+
23
+ # Proxy to devise map name
24
+ def resource_name
25
+ devise_mapping.name
26
+ end
27
+
28
+ # Proxy to devise map class
29
+ def resource_class
30
+ devise_mapping.to
31
+ end
32
+
33
+ # Attempt to find the mapped route for devise based on request path
34
+ def devise_mapping
35
+ @devise_mapping ||= Devise::Mapping.find_by_path(request.path)
36
+ end
37
+
38
+ # Overwrites devise_controller? to return true
39
+ def devise_controller?
40
+ true
41
+ end
42
+
43
+ protected
44
+
45
+ # Redirects to stored uri before signing in or the default path and clear
46
+ # return to.
47
+ def redirect_back_or_to(default)
48
+ redirect_to(return_to || default)
49
+ clear_return_to
50
+ end
51
+
52
+ # Access to scoped stored uri
53
+ def return_to
54
+ session[:"#{resource_name}.return_to"]
55
+ end
56
+
57
+ # Clear scoped stored uri
58
+ def clear_return_to
59
+ session[:"#{resource_name}.return_to"] = nil
60
+ end
61
+
62
+ # Checks for the existence of the resource root path. If it exists,
63
+ # returns it, otherwise returns the default root_path.
64
+ # Used after authenticating a user, confirming it's account or updating
65
+ # it's password, so we are able to redirect to scoped root paths.
66
+ # Examples (for a user scope):
67
+ # map.user_root '/users', :controller => 'users' # creates user_root_path
68
+ #
69
+ # map.namespace :users do |users|
70
+ # users.root # creates user_root_path
71
+ # end
72
+ def home_or_root_path
73
+ home_path = :"#{resource_name}_root_path"
74
+ respond_to?(home_path, true) ? send(home_path) : root_path
75
+ end
76
+
77
+ # Checks whether it's a devise mapped resource or not.
78
+ def is_devise_resource? #:nodoc:
79
+ raise ActionController::UnknownAction unless devise_mapping && devise_mapping.allows?(controller_name)
80
+ end
81
+
82
+ # Sets the resource creating an instance variable
83
+ def resource=(new_resource)
84
+ instance_variable_set(:"@#{resource_name}", new_resource)
85
+ end
86
+
87
+ # Build a devise resource without setting password and password confirmation fields.
88
+ def build_resource
89
+ self.resource ||= begin
90
+ attributes = params[resource_name].try(:except, :password, :password_confirmation)
91
+ resource_class.new(attributes)
92
+ end
93
+ end
94
+
95
+ # Helper for use in before_filters where no authentication is required.
96
+ #
97
+ # Example:
98
+ # before_filter :require_no_authentication, :only => :new
99
+ def require_no_authentication
100
+ redirect_to home_or_root_path if warden.authenticated?(resource_name)
101
+ end
102
+
103
+ # Sets the flash message with :key, using I18n. By default you are able
104
+ # to setup your messages using specific resource scope, and if no one is
105
+ # found we look to default scope.
106
+ # Example (i18n locale file):
107
+ #
108
+ # en:
109
+ # devise:
110
+ # passwords:
111
+ # #default_scope_messages - only if resource_scope is not found
112
+ # user:
113
+ # #resource_scope_messages
114
+ #
115
+ # Please refer to README or en.yml locale file to check what messages are
116
+ # available.
117
+ def set_flash_message(key, kind, now=false)
118
+ flash_hash = now ? flash.now : flash
119
+ flash_hash[key] = I18n.t(:"#{resource_name}.#{kind}",
120
+ :scope => [:devise, controller_name.to_sym], :default => kind)
121
+ end
122
+
123
+ # Shortcut to set flash.now message. Same rules applied from set_flash_message
124
+ def set_now_flash_message(key, kind)
125
+ set_flash_message(key, kind, true)
126
+ end
127
+
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,49 @@
1
+ module Devise
2
+ module Controllers
3
+ # Create url helpers to be used with resource/scope configuration. Acts as
4
+ # proxies to the generated routes created by devise.
5
+ # Resource param can be a string or symbol, a class, or an instance object.
6
+ # Example using a :user resource:
7
+ #
8
+ # new_session_path(:user) => new_user_session_path
9
+ # session_path(:user) => user_session_path
10
+ # destroy_session_path(:user) => destroy_user_session_path
11
+ #
12
+ # new_password_path(:user) => new_user_password_path
13
+ # password_path(:user) => user_password_path
14
+ # edit_password_path(:user) => edit_user_password_path
15
+ #
16
+ # new_confirmation_path(:user) => new_user_confirmation_path
17
+ # confirmation_path(:user) => user_confirmation_path
18
+ #
19
+ # Those helpers are added to your ApplicationController.
20
+ module UrlHelpers
21
+
22
+ [:session, :password, :confirmation].each do |module_name|
23
+ [:path, :url].each do |path_or_url|
24
+ actions = [ nil, :new_ ]
25
+ actions << :edit_ if module_name == :password
26
+ actions << :destroy_ if module_name == :session
27
+
28
+ actions.each do |action|
29
+ class_eval <<-URL_HELPERS
30
+ def #{action}#{module_name}_#{path_or_url}(resource, *args)
31
+ resource = case resource
32
+ when Symbol, String
33
+ resource
34
+ when Class
35
+ resource.name.underscore
36
+ else
37
+ resource.class.name.underscore
38
+ end
39
+
40
+ send("#{action}\#{resource}_#{module_name}_#{path_or_url}", *args)
41
+ end
42
+ URL_HELPERS
43
+ end
44
+ end
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,38 @@
1
+ module Devise
2
+ module Failure
3
+ mattr_accessor :default_url
4
+
5
+ # Failure application that will be called every time :warden is thrown from
6
+ # any strategy or hook. Responsible for redirect the user to the sign in
7
+ # page based on current scope and mapping. If no scope is given, redirect
8
+ # to the default_url.
9
+ def self.call(env)
10
+ options = env['warden.options']
11
+ scope = options[:scope]
12
+ params = case env['warden'].try(:message)
13
+ when Symbol
14
+ { env['warden'].message => true }
15
+ when String
16
+ { :message => env['warden'].message }
17
+ else
18
+ options[:params]
19
+ end
20
+
21
+ env['warden'].logout
22
+
23
+ redirect_path = if mapping = Devise.mappings[scope]
24
+ "#{mapping.parsed_path}/#{mapping.path_names[:sign_in]}"
25
+ else
26
+ "/#{default_url}"
27
+ end
28
+
29
+ headers = {}
30
+ headers["Location"] = redirect_path
31
+ headers["Location"] << "?" << Rack::Utils.build_query(params) if params
32
+ headers["Content-Type"] = 'text/plain'
33
+
34
+ message = options[:message] || "You are being redirected to #{redirect_path}"
35
+ [302, headers, [message]]
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,11 @@
1
+ # Each time the user is set we verify if it is still able to really sign in.
2
+ # This is done by checking the time frame the user is able to sign in without
3
+ # confirming it's account. If the user has not confirmed it's account during
4
+ # this time frame, he/she will not able to sign in anymore.
5
+ Warden::Manager.after_set_user do |record, auth, options|
6
+ if record && record.respond_to?(:active?) && !record.active?
7
+ scope = options[:scope]
8
+ auth.logout(scope)
9
+ throw :warden, :scope => scope, :params => { :unconfirmed => true }
10
+ end
11
+ end
@@ -0,0 +1,27 @@
1
+ # After authenticate hook to verify if the user in the given scope asked to be
2
+ # remembered while he does not sign out. Generates a new remember token for
3
+ # that specific user and adds a cookie with this user info to sign in this user
4
+ # automatically without asking for credentials. Refer to rememberable strategy
5
+ # for more info.
6
+ Warden::Manager.after_authentication do |record, auth, options|
7
+ scope = options[:scope]
8
+ remember_me = auth.params[scope].try(:fetch, :remember_me, nil)
9
+
10
+ if Devise::TRUE_VALUES.include?(remember_me) && record.respond_to?(:remember_me!)
11
+ record.remember_me!
12
+ auth.cookies['remember_token'] = {
13
+ :value => record.class.serialize_into_cookie(record),
14
+ :expires => record.remember_expires_at
15
+ }
16
+ end
17
+ end
18
+
19
+ # Before logout hook to forget the user in the given scope, only if rememberable
20
+ # is activated for this scope. Also clear remember token to ensure the user
21
+ # won't be remembered again.
22
+ Warden::Manager.before_logout do |record, auth, scope|
23
+ if record.respond_to?(:forget_me!)
24
+ record.forget_me!
25
+ auth.cookies.delete('remember_token')
26
+ end
27
+ end
@@ -0,0 +1,18 @@
1
+ en:
2
+ devise:
3
+ sessions:
4
+ signed_in: 'Signed in successfully.'
5
+ signed_out: 'Signed out successfully.'
6
+ unauthenticated: 'You need to sign in or sign up before continuing.'
7
+ unconfirmed: 'You have to confirm your account before continuing.'
8
+ invalid: 'Invalid email or password.'
9
+ passwords:
10
+ send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
11
+ updated: 'Your password was changed successfully. You are now signed in.'
12
+ confirmations:
13
+ send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
14
+ confirmed: 'Your account was successfully confirmed. You are now signed in.'
15
+ mailer:
16
+ confirmation_instructions: 'Confirmation instructions'
17
+ reset_password_instructions: 'Reset password instructions'
18
+
@@ -0,0 +1,120 @@
1
+ module Devise
2
+ # Responsible for handling devise mappings and routes configuration. Each
3
+ # resource configured by devise_for in routes is actually creating a mapping
4
+ # object. You can refer to devise_for in routes for usage options.
5
+ #
6
+ # The required value in devise_for is actually not used internally, but it's
7
+ # inflected to find all other values.
8
+ #
9
+ # map.devise_for :users
10
+ # mapping = Devise.mappings[:user]
11
+ #
12
+ # mapping.name #=> :user
13
+ # # is the scope used in controllers and warden, given in the route as :singular.
14
+ #
15
+ # mapping.as #=> "users"
16
+ # # how the mapping should be search in the path, given in the route as :as.
17
+ #
18
+ # mapping.to #=> User
19
+ # # is the class to be loaded from routes, given in the route as :class_name.
20
+ #
21
+ # mapping.for #=> [:authenticatable]
22
+ # # is the modules included in the class
23
+ #
24
+ class Mapping #:nodoc:
25
+ attr_reader :name, :as, :path_names, :path_prefix
26
+
27
+ # Loop through all mappings looking for a map that matches with the requested
28
+ # path (ie /users/sign_in). If a path prefix is given, it's taken into account.
29
+ def self.find_by_path(path)
30
+ Devise.mappings.each_value do |mapping|
31
+ route = path.split("/")[mapping.as_position]
32
+ return mapping if mapping.as == route.to_sym
33
+ end
34
+ nil
35
+ end
36
+
37
+ # Default url options which can be used as prefix.
38
+ def self.default_url_options
39
+ {}
40
+ end
41
+
42
+ def initialize(name, options) #:nodoc:
43
+ options.assert_valid_keys(:class_name, :as, :path_names, :singular, :path_prefix)
44
+
45
+ @as = (options[:as] || name).to_sym
46
+ @klass = (options[:class_name] || name.to_s.classify).to_s
47
+ @name = (options[:singular] || name.to_s.singularize).to_sym
48
+ @path_names = options[:path_names] || {}
49
+ @path_prefix = options[:path_prefix] || ""
50
+ @path_prefix << "/" unless @path_prefix[-1] == ?/
51
+
52
+ setup_path_names
53
+ end
54
+
55
+ # Return modules for the mapping.
56
+ def for
57
+ @for ||= to.devise_modules
58
+ end
59
+
60
+ # Reload mapped class each time when cache_classes is false.
61
+ def to
62
+ return @to if @to
63
+ klass = @klass.constantize
64
+ @to = klass if Rails.configuration.cache_classes
65
+ klass
66
+ end
67
+
68
+ # Check if the respective controller has a module in the mapping class.
69
+ def allows?(controller)
70
+ self.for.include?(CONTROLLERS[controller.to_sym])
71
+ end
72
+
73
+ # Return in which position in the path prefix devise should find the as mapping.
74
+ def as_position
75
+ self.path_prefix.count("/")
76
+ end
77
+
78
+ # Returns the raw path using path_prefix and as.
79
+ def raw_path
80
+ path_prefix + as.to_s
81
+ end
82
+
83
+ # Returns the parsed path. If you need meta information in your path_prefix,
84
+ # you should overwrite this method to use it. The only information supported
85
+ # by default is I18n.locale.
86
+ #
87
+ def parsed_path
88
+ returning raw_path do |path|
89
+ self.class.default_url_options.each do |key, value|
90
+ path.gsub!(key.inspect, value.to_s)
91
+ end
92
+ end
93
+ end
94
+
95
+ # Create magic predicates for verifying what module is activated by this map.
96
+ # Example:
97
+ #
98
+ # def confirmable?
99
+ # self.for.include?(:confirmable)
100
+ # end
101
+ #
102
+ ALL.each do |m|
103
+ class_eval <<-METHOD, __FILE__, __LINE__
104
+ def #{m}?
105
+ self.for.include?(:#{m})
106
+ end
107
+ METHOD
108
+ end
109
+
110
+ private
111
+
112
+ # Configure default path names, allowing the user overwrite defaults by
113
+ # passing a hash in :path_names.
114
+ def setup_path_names
115
+ [:sign_in, :sign_out, :password, :confirmation].each do |path_name|
116
+ @path_names[path_name] ||= path_name.to_s
117
+ end
118
+ end
119
+ end
120
+ end