devise-tokens 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/devise_tokens/application_controller.rb +77 -0
  3. data/app/controllers/devise_tokens/concerns/resource_finder.rb +42 -0
  4. data/app/controllers/devise_tokens/concerns/set_user_by_token.rb +160 -0
  5. data/app/controllers/devise_tokens/confirmations_controller.rb +79 -0
  6. data/app/controllers/devise_tokens/omniauth_callbacks_controller.rb +284 -0
  7. data/app/controllers/devise_tokens/passwords_controller.rb +204 -0
  8. data/app/controllers/devise_tokens/registrations_controller.rb +203 -0
  9. data/app/controllers/devise_tokens/sessions_controller.rb +128 -0
  10. data/app/controllers/devise_tokens/token_validations_controller.rb +29 -0
  11. data/app/controllers/devise_tokens/unlocks_controller.rb +87 -0
  12. data/app/models/devise_token_auth/concerns/active_record_support.rb +16 -0
  13. data/app/models/devise_token_auth/concerns/mongoid_support.rb +19 -0
  14. data/app/models/devise_token_auth/concerns/tokens_serialization.rb +19 -0
  15. data/app/models/devise_token_auth/concerns/user.rb +253 -0
  16. data/app/models/devise_token_auth/concerns/user_omniauth_callbacks.rb +28 -0
  17. data/app/validators/devise_token_auth_email_validator.rb +23 -0
  18. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  19. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  20. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  21. data/app/views/devise_token_auth/omniauth_external_window.html.erb +38 -0
  22. data/config/locales/da-DK.yml +52 -0
  23. data/config/locales/de.yml +51 -0
  24. data/config/locales/en.yml +57 -0
  25. data/config/locales/es.yml +51 -0
  26. data/config/locales/fr.yml +51 -0
  27. data/config/locales/he.yml +52 -0
  28. data/config/locales/it.yml +48 -0
  29. data/config/locales/ja.yml +48 -0
  30. data/config/locales/nl.yml +32 -0
  31. data/config/locales/pl.yml +50 -0
  32. data/config/locales/pt-BR.yml +48 -0
  33. data/config/locales/pt.yml +50 -0
  34. data/config/locales/ro.yml +48 -0
  35. data/config/locales/ru.yml +52 -0
  36. data/config/locales/sq.yml +48 -0
  37. data/config/locales/sv.yml +52 -0
  38. data/config/locales/uk.yml +61 -0
  39. data/config/locales/vi.yml +52 -0
  40. data/config/locales/zh-CN.yml +48 -0
  41. data/config/locales/zh-HK.yml +50 -0
  42. data/config/locales/zh-TW.yml +50 -0
  43. data/lib/devise_tokens.rb +14 -0
  44. data/lib/devise_tokens/blacklist.rb +2 -0
  45. data/lib/devise_tokens/controllers/helpers.rb +161 -0
  46. data/lib/devise_tokens/controllers/url_helpers.rb +10 -0
  47. data/lib/devise_tokens/engine.rb +92 -0
  48. data/lib/devise_tokens/errors.rb +6 -0
  49. data/lib/devise_tokens/rails/routes.rb +116 -0
  50. data/lib/devise_tokens/token_factory.rb +126 -0
  51. data/lib/devise_tokens/url.rb +39 -0
  52. data/lib/devise_tokens/version.rb +3 -0
  53. data/lib/generators/devise_tokens/USAGE +31 -0
  54. data/lib/generators/devise_tokens/install_generator.rb +91 -0
  55. data/lib/generators/devise_tokens/install_generator_helpers.rb +98 -0
  56. data/lib/generators/devise_tokens/install_mongoid_generator.rb +46 -0
  57. data/lib/generators/devise_tokens/install_views_generator.rb +18 -0
  58. data/lib/generators/devise_tokens/templates/devise_tokens.rb +55 -0
  59. data/lib/generators/devise_tokens/templates/devise_tokens_create_users.rb.erb +49 -0
  60. data/lib/generators/devise_tokens/templates/user.rb.erb +9 -0
  61. data/lib/generators/devise_tokens/templates/user_mongoid.rb.erb +56 -0
  62. data/lib/tasks/devise_tokens_tasks.rake +6 -0
  63. metadata +208 -4
  64. data/lib/devise-tokens.rb +0 -5
@@ -0,0 +1,204 @@
1
+ module DeviseTokens
2
+ class PasswordsController < DeviseTokens::ApplicationController
3
+ before_action :validate_redirect_url_param, only: [:create, :edit]
4
+ skip_after_action :update_auth_header, only: [:create, :edit]
5
+
6
+ # this action is responsible for generating password reset tokens and sending emails
7
+ def create
8
+ return render_create_error_missing_email unless resource_params[:email]
9
+
10
+ @email = get_case_insensitive_field_from_resource_params(:email)
11
+ @resource = find_resource(:uid, @email)
12
+
13
+ if @resource
14
+ yield @resource if block_given?
15
+ @resource.send_reset_password_instructions(
16
+ email: @email,
17
+ provider: 'email',
18
+ redirect_url: @redirect_url,
19
+ client_config: params[:config_name]
20
+ )
21
+
22
+ if @resource.errors.empty?
23
+ return render_create_success
24
+ else
25
+ render_create_error @resource.errors
26
+ end
27
+ else
28
+ render_not_found_error
29
+ end
30
+ end
31
+
32
+ # this is where users arrive after visiting the password reset confirmation link
33
+ def edit
34
+ # if a user is not found, return nil
35
+ @resource = resource_class.with_reset_password_token(resource_params[:reset_password_token])
36
+
37
+ if @resource && @resource.reset_password_period_valid?
38
+ token = @resource.create_token unless require_client_password_reset_token?
39
+
40
+ # ensure that user is confirmed
41
+ @resource.skip_confirmation! if confirmable_enabled? && !@resource.confirmed_at
42
+ # allow user to change password once without current_password
43
+ @resource.allow_password_change = true if recoverable_enabled?
44
+
45
+ @resource.save!
46
+
47
+ yield @resource if block_given?
48
+
49
+ if require_client_password_reset_token?
50
+ redirect_to DeviseTokens::Url.generate(@redirect_url, reset_password_token: resource_params[:reset_password_token])
51
+ else
52
+ redirect_header_options = { reset_password: true }
53
+ redirect_headers = build_redirect_headers(token.token,
54
+ token.client,
55
+ redirect_header_options)
56
+ redirect_to(@resource.build_auth_url(@redirect_url,
57
+ redirect_headers))
58
+ end
59
+ else
60
+ render_edit_error
61
+ end
62
+ end
63
+
64
+ def update
65
+ # make sure user is authorized
66
+ if require_client_password_reset_token? && resource_params[:reset_password_token]
67
+ @resource = resource_class.with_reset_password_token(resource_params[:reset_password_token])
68
+ return render_update_error_unauthorized unless @resource
69
+
70
+ @token = @resource.create_token
71
+ else
72
+ @resource = set_user_by_token
73
+ end
74
+
75
+ return render_update_error_unauthorized unless @resource
76
+
77
+ # make sure account doesn't use oauth2 provider
78
+ unless @resource.provider == 'email'
79
+ return render_update_error_password_not_required
80
+ end
81
+
82
+ # ensure that password params were sent
83
+ unless password_resource_params[:password] && password_resource_params[:password_confirmation]
84
+ return render_update_error_missing_password
85
+ end
86
+
87
+ if @resource.send(resource_update_method, password_resource_params)
88
+ @resource.allow_password_change = false if recoverable_enabled?
89
+ @resource.save!
90
+
91
+ yield @resource if block_given?
92
+ return render_update_success
93
+ else
94
+ return render_update_error
95
+ end
96
+ end
97
+
98
+ protected
99
+
100
+ def resource_update_method
101
+ allow_password_change = recoverable_enabled? && @resource.allow_password_change == true || require_client_password_reset_token?
102
+ if DeviseTokens.check_current_password_before_update == false || allow_password_change
103
+ 'update'
104
+ else
105
+ 'update_with_password'
106
+ end
107
+ end
108
+
109
+ def render_create_error_missing_email
110
+ render_error(401, I18n.t('devise_tokens.passwords.missing_email'))
111
+ end
112
+
113
+ def render_create_error_missing_redirect_url
114
+ render_error(401, I18n.t('devise_tokens.passwords.missing_redirect_url'))
115
+ end
116
+
117
+ def render_error_not_allowed_redirect_url
118
+ response = {
119
+ status: 'error',
120
+ data: resource_data
121
+ }
122
+ message = I18n.t('devise_tokens.passwords.not_allowed_redirect_url', redirect_url: @redirect_url)
123
+ render_error(422, message, response)
124
+ end
125
+
126
+ def render_create_success
127
+ render json: {
128
+ success: true,
129
+ message: I18n.t('devise_tokens.passwords.sended', email: @email)
130
+ }
131
+ end
132
+
133
+ def render_create_error(errors)
134
+ render json: {
135
+ success: false,
136
+ errors: errors
137
+ }, status: 400
138
+ end
139
+
140
+ def render_edit_error
141
+ raise ActionController::RoutingError, 'Not Found'
142
+ end
143
+
144
+ def render_update_error_unauthorized
145
+ render_error(401, 'Unauthorized')
146
+ end
147
+
148
+ def render_update_error_password_not_required
149
+ render_error(422, I18n.t('devise_tokens.passwords.password_not_required', provider: @resource.provider.humanize))
150
+ end
151
+
152
+ def render_update_error_missing_password
153
+ render_error(422, I18n.t('devise_tokens.passwords.missing_passwords'))
154
+ end
155
+
156
+ def render_update_success
157
+ render json: {
158
+ success: true,
159
+ data: resource_data,
160
+ message: I18n.t('devise_tokens.passwords.successfully_updated')
161
+ }
162
+ end
163
+
164
+ def render_update_error
165
+ render json: {
166
+ success: false,
167
+ errors: resource_errors
168
+ }, status: 422
169
+ end
170
+
171
+ private
172
+
173
+ def resource_params
174
+ params.permit(:email, :reset_password_token)
175
+ end
176
+
177
+ def password_resource_params
178
+ params.permit(*params_for_resource(:account_update))
179
+ end
180
+
181
+ def render_not_found_error
182
+ render_error(404, I18n.t('devise_tokens.passwords.user_not_found', email: @email))
183
+ end
184
+
185
+ def validate_redirect_url_param
186
+ # give redirect value from params priority
187
+ @redirect_url = params.fetch(
188
+ :redirect_url,
189
+ DeviseTokens.default_password_reset_url
190
+ )
191
+
192
+ return render_create_error_missing_redirect_url unless @redirect_url
193
+ return render_error_not_allowed_redirect_url if blacklisted_redirect_url?(@redirect_url)
194
+ end
195
+
196
+ def reset_password_token_as_raw?(recoverable)
197
+ recoverable && recoverable.reset_password_token.present? && !require_client_password_reset_token?
198
+ end
199
+
200
+ def require_client_password_reset_token?
201
+ DeviseTokens.require_client_password_reset_token
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,203 @@
1
+ module DeviseTokens
2
+ class RegistrationsController < DeviseTokens::ApplicationController
3
+ before_action :set_user_by_token, only: [:destroy, :update]
4
+ before_action :validate_sign_up_params, only: :create
5
+ before_action :validate_account_update_params, only: :update
6
+ skip_after_action :update_auth_header, only: [:create, :destroy]
7
+
8
+ def create
9
+ build_resource
10
+
11
+ unless @resource.present?
12
+ raise DeviseTokens::Errors::NoResourceDefinedError,
13
+ "#{self.class.name} #build_resource does not define @resource,"\
14
+ ' execution stopped.'
15
+ end
16
+
17
+ # give redirect value from params priority
18
+ @redirect_url = params.fetch(
19
+ :confirm_success_url,
20
+ DeviseTokens.default_confirm_success_url
21
+ )
22
+
23
+ # success redirect url is required
24
+ if confirmable_enabled? && !@redirect_url
25
+ return render_create_error_missing_confirm_success_url
26
+ end
27
+
28
+ # if whitelist is set, validate redirect_url against whitelist
29
+ return render_create_error_redirect_url_not_allowed if blacklisted_redirect_url?(@redirect_url)
30
+
31
+ # override email confirmation, must be sent manually from ctrl
32
+ callback_name = defined?(ActiveRecord) && resource_class < ActiveRecord::Base ? :commit : :create
33
+ resource_class.set_callback(callback_name, :after, :send_on_create_confirmation_instructions)
34
+ resource_class.skip_callback(callback_name, :after, :send_on_create_confirmation_instructions)
35
+
36
+ if @resource.respond_to? :skip_confirmation_notification!
37
+ # Fix duplicate e-mails by disabling Devise confirmation e-mail
38
+ @resource.skip_confirmation_notification!
39
+ end
40
+
41
+ if @resource.save
42
+ yield @resource if block_given?
43
+
44
+ unless @resource.confirmed?
45
+ # user will require email authentication
46
+ @resource.send_confirmation_instructions({
47
+ client_config: params[:config_name],
48
+ redirect_url: @redirect_url
49
+ })
50
+ end
51
+
52
+ if active_for_authentication?
53
+ # email auth has been bypassed, authenticate user
54
+ @token = @resource.create_token
55
+ @resource.save!
56
+ update_auth_header
57
+ end
58
+
59
+ render_create_success
60
+ else
61
+ clean_up_passwords @resource
62
+ render_create_error
63
+ end
64
+ end
65
+
66
+ def update
67
+ if @resource
68
+ if @resource.send(resource_update_method, account_update_params)
69
+ yield @resource if block_given?
70
+ render_update_success
71
+ else
72
+ render_update_error
73
+ end
74
+ else
75
+ render_update_error_user_not_found
76
+ end
77
+ end
78
+
79
+ def destroy
80
+ if @resource
81
+ @resource.destroy
82
+ yield @resource if block_given?
83
+ render_destroy_success
84
+ else
85
+ render_destroy_error
86
+ end
87
+ end
88
+
89
+ def sign_up_params
90
+ params.permit(*params_for_resource(:sign_up))
91
+ end
92
+
93
+ def account_update_params
94
+ params.permit(*params_for_resource(:account_update))
95
+ end
96
+
97
+ protected
98
+
99
+ def build_resource
100
+ @resource = resource_class.new(sign_up_params)
101
+ @resource.provider = provider
102
+
103
+ # honor devise configuration for case_insensitive_keys
104
+ if resource_class.case_insensitive_keys.include?(:email)
105
+ @resource.email = sign_up_params[:email].try(:downcase)
106
+ else
107
+ @resource.email = sign_up_params[:email]
108
+ end
109
+ end
110
+
111
+ def render_create_error_missing_confirm_success_url
112
+ response = {
113
+ status: 'error',
114
+ data: resource_data
115
+ }
116
+ message = I18n.t('devise_tokens.registrations.missing_confirm_success_url')
117
+ render_error(422, message, response)
118
+ end
119
+
120
+ def render_create_error_redirect_url_not_allowed
121
+ response = {
122
+ status: 'error',
123
+ data: resource_data
124
+ }
125
+ message = I18n.t('devise_tokens.registrations.redirect_url_not_allowed', redirect_url: @redirect_url)
126
+ render_error(422, message, response)
127
+ end
128
+
129
+ def render_create_success
130
+ render json: {
131
+ status: 'success',
132
+ data: resource_data
133
+ }
134
+ end
135
+
136
+ def render_create_error
137
+ render json: {
138
+ status: 'error',
139
+ data: resource_data,
140
+ errors: resource_errors
141
+ }, status: 422
142
+ end
143
+
144
+ def render_update_success
145
+ render json: {
146
+ status: 'success',
147
+ data: resource_data
148
+ }
149
+ end
150
+
151
+ def render_update_error
152
+ render json: {
153
+ status: 'error',
154
+ errors: resource_errors
155
+ }, status: 422
156
+ end
157
+
158
+ def render_update_error_user_not_found
159
+ render_error(404, I18n.t('devise_tokens.registrations.user_not_found'), status: 'error')
160
+ end
161
+
162
+ def render_destroy_success
163
+ render json: {
164
+ status: 'success',
165
+ message: I18n.t('devise_tokens.registrations.account_with_uid_destroyed', uid: @resource.uid)
166
+ }
167
+ end
168
+
169
+ def render_destroy_error
170
+ render_error(404, I18n.t('devise_tokens.registrations.account_to_destroy_not_found'), status: 'error')
171
+ end
172
+
173
+ private
174
+
175
+ def resource_update_method
176
+ if DeviseTokens.check_current_password_before_update == :attributes
177
+ 'update_with_password'
178
+ elsif DeviseTokens.check_current_password_before_update == :password && account_update_params.key?(:password)
179
+ 'update_with_password'
180
+ elsif account_update_params.key?(:current_password)
181
+ 'update_with_password'
182
+ else
183
+ 'update'
184
+ end
185
+ end
186
+
187
+ def validate_sign_up_params
188
+ validate_post_data sign_up_params, I18n.t('errors.messages.validate_sign_up_params')
189
+ end
190
+
191
+ def validate_account_update_params
192
+ validate_post_data account_update_params, I18n.t('errors.messages.validate_account_update_params')
193
+ end
194
+
195
+ def validate_post_data which, message
196
+ render_error(:unprocessable_entity, message, status: 'error') if which.empty?
197
+ end
198
+
199
+ def active_for_authentication?
200
+ !@resource.respond_to?(:active_for_authentication?) || @resource.active_for_authentication?
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,128 @@
1
+ module DeviseTokens
2
+ class SessionsController < DeviseTokens::ApplicationController
3
+ before_action :set_user_by_token, only: [:destroy]
4
+ after_action :reset_session, only: [:destroy]
5
+
6
+ def new
7
+ render_new_error
8
+ end
9
+
10
+ def create
11
+ # Check
12
+ field = (resource_params.keys.map(&:to_sym) & resource_class.authentication_keys).first
13
+
14
+ @resource = nil
15
+ if field
16
+ q_value = get_case_insensitive_field_from_resource_params(field)
17
+
18
+ @resource = find_resource(field, q_value)
19
+ end
20
+
21
+ if @resource && valid_params?(field, q_value) && (!@resource.respond_to?(:active_for_authentication?) || @resource.active_for_authentication?)
22
+ valid_password = @resource.valid_password?(resource_params[:password])
23
+ if (@resource.respond_to?(:valid_for_authentication?) && !@resource.valid_for_authentication? { valid_password }) || !valid_password
24
+ return render_create_error_bad_credentials
25
+ end
26
+ @token = @resource.create_token
27
+ @resource.save
28
+
29
+ sign_in(:user, @resource, store: false, bypass: false)
30
+
31
+ yield @resource if block_given?
32
+
33
+ render_create_success
34
+ elsif @resource && !(!@resource.respond_to?(:active_for_authentication?) || @resource.active_for_authentication?)
35
+ if @resource.respond_to?(:locked_at) && @resource.locked_at
36
+ render_create_error_account_locked
37
+ else
38
+ render_create_error_not_confirmed
39
+ end
40
+ else
41
+ render_create_error_bad_credentials
42
+ end
43
+ end
44
+
45
+ def destroy
46
+ # remove auth instance variables so that after_action does not run
47
+ user = remove_instance_variable(:@resource) if @resource
48
+ client = @token.client if @token.client
49
+ @token.clear!
50
+
51
+ if user && client && user.tokens[client]
52
+ user.tokens.delete(client)
53
+ user.save!
54
+
55
+ yield user if block_given?
56
+
57
+ render_destroy_success
58
+ else
59
+ render_destroy_error
60
+ end
61
+ end
62
+
63
+ protected
64
+
65
+ def valid_params?(key, val)
66
+ resource_params[:password] && key && val
67
+ end
68
+
69
+ def get_auth_params
70
+ auth_key = nil
71
+ auth_val = nil
72
+
73
+ # iterate thru allowed auth keys, use first found
74
+ resource_class.authentication_keys.each do |k|
75
+ if resource_params[k]
76
+ auth_val = resource_params[k]
77
+ auth_key = k
78
+ break
79
+ end
80
+ end
81
+
82
+ # honor devise configuration for case_insensitive_keys
83
+ if resource_class.case_insensitive_keys.include?(auth_key)
84
+ auth_val.downcase!
85
+ end
86
+
87
+ { key: auth_key, val: auth_val }
88
+ end
89
+
90
+ def render_new_error
91
+ render_error(405, I18n.t('devise_tokens.sessions.not_supported'))
92
+ end
93
+
94
+ def render_create_success
95
+ render json: {
96
+ data: resource_data(resource_json: @resource.token_validation_response)
97
+ }
98
+ end
99
+
100
+ def render_create_error_not_confirmed
101
+ render_error(401, I18n.t('devise_tokens.sessions.not_confirmed', email: @resource.email))
102
+ end
103
+
104
+ def render_create_error_account_locked
105
+ render_error(401, I18n.t('devise.mailer.unlock_instructions.account_lock_msg'))
106
+ end
107
+
108
+ def render_create_error_bad_credentials
109
+ render_error(401, I18n.t('devise_tokens.sessions.bad_credentials'))
110
+ end
111
+
112
+ def render_destroy_success
113
+ render json: {
114
+ success:true
115
+ }, status: 200
116
+ end
117
+
118
+ def render_destroy_error
119
+ render_error(404, I18n.t('devise_tokens.sessions.user_not_found'))
120
+ end
121
+
122
+ private
123
+
124
+ def resource_params
125
+ params.permit(*params_for_resource(:sign_in))
126
+ end
127
+ end
128
+ end