rodauth-rails 0.8.2 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +52 -0
  3. data/README.md +453 -223
  4. data/lib/generators/rodauth/install_generator.rb +26 -15
  5. data/lib/generators/rodauth/migration/base.erb +2 -2
  6. data/lib/generators/rodauth/templates/app/lib/rodauth_app.rb +50 -49
  7. data/lib/generators/rodauth/templates/app/mailers/rodauth_mailer.rb +3 -3
  8. data/lib/generators/rodauth/templates/app/views/rodauth/_global_logout_field.html.erb +1 -1
  9. data/lib/generators/rodauth/templates/app/views/rodauth/_login_confirm_field.html.erb +2 -2
  10. data/lib/generators/rodauth/templates/app/views/rodauth/_login_display.html.erb +2 -2
  11. data/lib/generators/rodauth/templates/app/views/rodauth/_login_field.html.erb +2 -2
  12. data/lib/generators/rodauth/templates/app/views/rodauth/_new_password_field.html.erb +2 -2
  13. data/lib/generators/rodauth/templates/app/views/rodauth/_otp_auth_code_field.html.erb +2 -2
  14. data/lib/generators/rodauth/templates/app/views/rodauth/_password_confirm_field.html.erb +2 -2
  15. data/lib/generators/rodauth/templates/app/views/rodauth/_password_field.html.erb +2 -2
  16. data/lib/generators/rodauth/templates/app/views/rodauth/_recovery_code_field.html.erb +2 -2
  17. data/lib/generators/rodauth/templates/app/views/rodauth/_sms_code_field.html.erb +2 -2
  18. data/lib/generators/rodauth/templates/app/views/rodauth/_sms_phone_field.html.erb +2 -2
  19. data/lib/generators/rodauth/templates/app/views/rodauth/_submit.html.erb +1 -1
  20. data/lib/generators/rodauth/templates/app/views/rodauth/otp_setup.html.erb +2 -2
  21. data/lib/generators/rodauth/templates/app/views/rodauth/remember.html.erb +1 -1
  22. data/lib/generators/rodauth/templates/app/views/rodauth/webauthn_remove.html.erb +1 -1
  23. data/lib/generators/rodauth/templates/app/views/rodauth_mailer/unlock_account.text.erb +1 -1
  24. data/lib/rodauth/rails.rb +20 -0
  25. data/lib/rodauth/rails/app.rb +23 -31
  26. data/lib/rodauth/rails/app/flash.rb +7 -11
  27. data/lib/rodauth/rails/app/middleware.rb +20 -10
  28. data/lib/rodauth/rails/auth.rb +40 -0
  29. data/lib/rodauth/rails/controller_methods.rb +1 -5
  30. data/lib/rodauth/rails/feature.rb +17 -202
  31. data/lib/rodauth/rails/feature/base.rb +62 -0
  32. data/lib/rodauth/rails/feature/callbacks.rb +61 -0
  33. data/lib/rodauth/rails/feature/csrf.rb +65 -0
  34. data/lib/rodauth/rails/feature/email.rb +30 -0
  35. data/lib/rodauth/rails/feature/instrumentation.rb +71 -0
  36. data/lib/rodauth/rails/feature/render.rb +41 -0
  37. data/lib/rodauth/rails/version.rb +1 -1
  38. data/rodauth-rails.gemspec +1 -1
  39. metadata +15 -9
  40. data/lib/generators/rodauth/mailer_generator.rb +0 -37
@@ -0,0 +1,61 @@
1
+ module Rodauth
2
+ module Rails
3
+ module Feature
4
+ module Callbacks
5
+ private
6
+
7
+ # Runs controller callbacks and rescue handlers around Rodauth actions.
8
+ def _around_rodauth(&block)
9
+ result = nil
10
+
11
+ rails_controller_rescue do
12
+ rails_controller_callbacks do
13
+ result = catch(:halt) { super(&block) }
14
+ end
15
+ end
16
+
17
+ result = handle_rails_controller_response(result)
18
+
19
+ throw :halt, result if result
20
+ end
21
+
22
+ # Runs any #(before|around|after)_action controller callbacks.
23
+ def rails_controller_callbacks(&block)
24
+ rails_controller_instance.run_callbacks(:process_action, &block)
25
+ end
26
+
27
+ # Runs any registered #rescue_from controller handlers.
28
+ def rails_controller_rescue
29
+ yield
30
+ rescue Exception => exception
31
+ rails_controller_instance.rescue_with_handler(exception) || raise
32
+
33
+ unless rails_controller_instance.performed?
34
+ raise Rodauth::Rails::Error, "rescue_from handler didn't write any response"
35
+ end
36
+ end
37
+
38
+ # Handles controller rendering a response or setting response headers.
39
+ def handle_rails_controller_response(result)
40
+ if rails_controller_instance.performed?
41
+ rails_controller_response
42
+ elsif result
43
+ result[1].merge!(rails_controller_instance.response.headers)
44
+ result
45
+ end
46
+ end
47
+
48
+ # Returns Roda response from controller response if set.
49
+ def rails_controller_response
50
+ controller_response = rails_controller_instance.response
51
+
52
+ response.status = controller_response.status
53
+ response.headers.merge! controller_response.headers
54
+ response.write controller_response.body
55
+
56
+ response.finish
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,65 @@
1
+ module Rodauth
2
+ module Rails
3
+ module Feature
4
+ module Csrf
5
+ def self.included(feature)
6
+ feature.auth_methods(
7
+ :rails_csrf_tag,
8
+ :rails_csrf_param,
9
+ :rails_csrf_token,
10
+ :rails_check_csrf!,
11
+ )
12
+ end
13
+
14
+ # Render Rails CSRF tags in Rodauth templates.
15
+ def csrf_tag(*)
16
+ rails_csrf_tag
17
+ end
18
+
19
+ # Verify Rails' authenticity token.
20
+ def check_csrf
21
+ rails_check_csrf!
22
+ end
23
+
24
+ # Have Rodauth call #check_csrf automatically.
25
+ def check_csrf?
26
+ true
27
+ end
28
+
29
+ private
30
+
31
+ def rails_controller_callbacks
32
+ return super if rails_api_controller?
33
+
34
+ # don't verify CSRF token as part of callbacks, Rodauth will do that
35
+ rails_controller_instance.allow_forgery_protection = false
36
+ super do
37
+ # turn the setting back to default so that form tags generate CSRF tags
38
+ rails_controller_instance.allow_forgery_protection = rails_controller.allow_forgery_protection
39
+ yield
40
+ end
41
+ end
42
+
43
+ # Calls the controller to verify the authenticity token.
44
+ def rails_check_csrf!
45
+ rails_controller_instance.send(:verify_authenticity_token)
46
+ end
47
+
48
+ # Hidden tag with Rails CSRF token inserted into Rodauth templates.
49
+ def rails_csrf_tag
50
+ %(<input type="hidden" name="#{rails_csrf_param}" value="#{rails_csrf_token}">)
51
+ end
52
+
53
+ # The request parameter under which to send the Rails CSRF token.
54
+ def rails_csrf_param
55
+ rails_controller.request_forgery_protection_token
56
+ end
57
+
58
+ # The Rails CSRF token value inserted into Rodauth templates.
59
+ def rails_csrf_token
60
+ rails_controller_instance.send(:form_authenticity_token)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,30 @@
1
+ module Rodauth
2
+ module Rails
3
+ module Feature
4
+ module Email
5
+ def self.included(feature)
6
+ feature.depends :email_base
7
+ end
8
+
9
+ private
10
+
11
+ # Create emails with ActionMailer which uses configured delivery method.
12
+ def create_email_to(to, subject, body)
13
+ Mailer.create_email(to: to, from: email_from, subject: "#{email_subject_prefix}#{subject}", body: body)
14
+ end
15
+
16
+ # Delivers the given email.
17
+ def send_email(email)
18
+ email.deliver_now
19
+ end
20
+
21
+ # ActionMailer subclass for correct email delivering.
22
+ class Mailer < ActionMailer::Base
23
+ def create_email(**options)
24
+ mail(**options)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,71 @@
1
+ module Rodauth
2
+ module Rails
3
+ module Feature
4
+ module Instrumentation
5
+ private
6
+
7
+ def _around_rodauth
8
+ rails_instrument_request { super }
9
+ end
10
+
11
+ def redirect(*)
12
+ rails_instrument_redirection { super }
13
+ end
14
+
15
+ def rails_render(*)
16
+ render_output = nil
17
+ rails_controller_instance.view_runtime = rails_controller_instance.send(:cleanup_view_runtime) do
18
+ Benchmark.ms { render_output = super }
19
+ end
20
+ render_output
21
+ end
22
+
23
+ def rails_instrument_request
24
+ request = rails_request
25
+
26
+ raw_payload = {
27
+ controller: scope.class.superclass.name,
28
+ action: "call",
29
+ request: request,
30
+ params: request.filtered_parameters,
31
+ headers: request.headers,
32
+ format: request.format.ref,
33
+ method: request.request_method,
34
+ path: request.fullpath
35
+ }
36
+
37
+ ActiveSupport::Notifications.instrument("start_processing.action_controller", raw_payload)
38
+
39
+ ActiveSupport::Notifications.instrument("process_action.action_controller", raw_payload) do |payload|
40
+ begin
41
+ result = catch(:halt) { yield }
42
+
43
+ response = ActionDispatch::Response.new *(result || [404, {}, []])
44
+ payload[:response] = response
45
+ payload[:status] = response.status
46
+
47
+ throw :halt, result if result
48
+ rescue => error
49
+ payload[:status] = ActionDispatch::ExceptionWrapper.status_code_for_exception(error.class.name)
50
+ raise
51
+ ensure
52
+ rails_controller_eval { append_info_to_payload(payload) }
53
+ end
54
+ end
55
+ end
56
+
57
+ def rails_instrument_redirection
58
+ ActiveSupport::Notifications.instrument("redirect_to.action_controller", request: rails_request) do |payload|
59
+ result = catch(:halt) { yield }
60
+
61
+ response = ActionDispatch::Response.new(*result)
62
+ payload[:status] = response.status
63
+ payload[:location] = response.filtered_location
64
+
65
+ throw :halt, result
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,41 @@
1
+ module Rodauth
2
+ module Rails
3
+ module Feature
4
+ module Render
5
+ def self.included(feature)
6
+ feature.auth_methods :rails_render
7
+ end
8
+
9
+ # Renders templates with layout. First tries to render a user-defined
10
+ # template, otherwise falls back to Rodauth's template.
11
+ def view(page, *)
12
+ rails_render(action: page.tr("-", "_"), layout: true) ||
13
+ rails_render(html: super.html_safe, layout: true)
14
+ end
15
+
16
+ # Renders templates without layout. First tries to render a user-defined
17
+ # template or partial, otherwise falls back to Rodauth's template.
18
+ def render(page)
19
+ rails_render(partial: page.tr("-", "_"), layout: false) ||
20
+ rails_render(action: page.tr("-", "_"), layout: false) ||
21
+ super.html_safe
22
+ end
23
+
24
+ def button(*)
25
+ super.html_safe
26
+ end
27
+
28
+ private
29
+
30
+ # Calls the Rails renderer, returning nil if a template is missing.
31
+ def rails_render(*args)
32
+ return if rails_api_controller?
33
+
34
+ rails_controller_instance.render_to_string(*args)
35
+ rescue ActionView::MissingTemplate
36
+ nil
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,5 +1,5 @@
1
1
  module Rodauth
2
2
  module Rails
3
- VERSION = "0.8.2"
3
+ VERSION = "0.12.0"
4
4
  end
5
5
  end
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
17
17
  spec.require_paths = ["lib"]
18
18
 
19
19
  spec.add_dependency "railties", ">= 4.2", "< 7"
20
- spec.add_dependency "rodauth", "~> 2.8"
20
+ spec.add_dependency "rodauth", "~> 2.11"
21
21
  spec.add_dependency "sequel-activerecord_connection", "~> 1.1"
22
22
  spec.add_dependency "tilt"
23
23
  spec.add_dependency "bcrypt"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rodauth-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janko Marohnić
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-10 00:00:00.000000000 Z
11
+ date: 2021-05-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -36,14 +36,14 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '2.8'
39
+ version: '2.11'
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '2.8'
46
+ version: '2.11'
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: sequel-activerecord_connection
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -111,7 +111,6 @@ files:
111
111
  - LICENSE.txt
112
112
  - README.md
113
113
  - lib/generators/rodauth/install_generator.rb
114
- - lib/generators/rodauth/mailer_generator.rb
115
114
  - lib/generators/rodauth/migration/account_expiration.erb
116
115
  - lib/generators/rodauth/migration/active_sessions.erb
117
116
  - lib/generators/rodauth/migration/audit_logging.erb
@@ -205,8 +204,15 @@ files:
205
204
  - lib/rodauth/rails/app.rb
206
205
  - lib/rodauth/rails/app/flash.rb
207
206
  - lib/rodauth/rails/app/middleware.rb
207
+ - lib/rodauth/rails/auth.rb
208
208
  - lib/rodauth/rails/controller_methods.rb
209
209
  - lib/rodauth/rails/feature.rb
210
+ - lib/rodauth/rails/feature/base.rb
211
+ - lib/rodauth/rails/feature/callbacks.rb
212
+ - lib/rodauth/rails/feature/csrf.rb
213
+ - lib/rodauth/rails/feature/email.rb
214
+ - lib/rodauth/rails/feature/instrumentation.rb
215
+ - lib/rodauth/rails/feature/render.rb
210
216
  - lib/rodauth/rails/middleware.rb
211
217
  - lib/rodauth/rails/railtie.rb
212
218
  - lib/rodauth/rails/tasks.rake
@@ -216,7 +222,7 @@ homepage: https://github.com/janko/rodauth-rails
216
222
  licenses:
217
223
  - MIT
218
224
  metadata: {}
219
- post_install_message:
225
+ post_install_message:
220
226
  rdoc_options: []
221
227
  require_paths:
222
228
  - lib
@@ -231,8 +237,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
231
237
  - !ruby/object:Gem::Version
232
238
  version: '0'
233
239
  requirements: []
234
- rubygems_version: 3.1.4
235
- signing_key:
240
+ rubygems_version: 3.2.3
241
+ signing_key:
236
242
  specification_version: 4
237
243
  summary: Provides Rails integration for Rodauth.
238
244
  test_files: []
@@ -1,37 +0,0 @@
1
- require "rails/generators/base"
2
-
3
- module Rodauth
4
- module Rails
5
- module Generators
6
- class MailerGenerator < ::Rails::Generators::Base
7
- source_root "#{__dir__}/templates"
8
- namespace "rodauth:mailer"
9
-
10
- VIEWS = %w[
11
- email_auth
12
- password_changed
13
- reset_password
14
- unlock_account
15
- verify_account
16
- verify_login_change
17
- ]
18
-
19
- class_option :name,
20
- desc: "The name for the mailer and the views directory",
21
- default: "rodauth"
22
-
23
- def copy_mailer
24
- template "app/mailers/rodauth_mailer.rb",
25
- "app/mailers/#{options[:name].underscore}_mailer.rb"
26
- end
27
-
28
- def copy_mailer_views
29
- VIEWS.each do |view|
30
- template "app/views/rodauth_mailer/#{view}.text.erb",
31
- "app/views/#{options[:name].underscore}_mailer/#{view}.text.erb"
32
- end
33
- end
34
- end
35
- end
36
- end
37
- end