ramon-devise 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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