lib/rodauth/rails/feature.rb in rodauth-rails-0.5.0 vs lib/rodauth/rails/feature.rb in rodauth-rails-0.6.0
- old
+ new
@@ -7,14 +7,15 @@
:rails_render,
:rails_csrf_tag,
:rails_csrf_param,
:rails_csrf_token,
:rails_check_csrf!,
- :rails_controller_instance,
:rails_controller,
)
+ auth_cached_method :rails_controller_instance
+
# Renders templates with layout. First tries to render a user-defined
# template, otherwise falls back to Rodauth's template.
def view(page, *)
rails_render(action: page.tr("-", "_"), layout: true) ||
rails_render(html: super.html_safe, layout: true)
@@ -26,32 +27,85 @@
rails_render(partial: page.tr("-", "_"), layout: false) ||
rails_render(action: page.tr("-", "_"), layout: false) ||
super
end
+ # Render Rails CSRF tags in Rodauth templates.
+ def csrf_tag(*)
+ rails_csrf_tag
+ end
+
# Verify Rails' authenticity token.
def check_csrf
rails_check_csrf!
end
# Have Rodauth call #check_csrf automatically.
def check_csrf?
true
end
- # Render Rails CSRF tags in Rodauth templates.
- def csrf_tag(*)
- rails_csrf_tag
- end
-
# Default the flash error key to Rails' default :alert.
def flash_error_key
:alert
end
private
+ # Runs controller callbacks and rescue handlers around Rodauth actions.
+ def _around_rodauth(&block)
+ result = nil
+
+ rails_controller_rescue do
+ rails_controller_callbacks do
+ result = catch(:halt) { super(&block) }
+ end
+ end
+
+ if rails_controller_instance.performed?
+ rails_controller_response
+ else
+ result[1].merge!(rails_controller_instance.response.headers)
+ throw :halt, result
+ end
+ end
+
+ # Runs any #(before|around|after)_action controller callbacks.
+ def rails_controller_callbacks
+ # don't verify CSRF token as part of callbacks, Rodauth will do that
+ rails_controller_instance.allow_forgery_protection = false
+
+ rails_controller_instance.run_callbacks(:process_action) do
+ # turn the setting back to default so that form tags generate CSRF tags
+ rails_controller_instance.allow_forgery_protection = rails_controller.allow_forgery_protection
+
+ yield
+ end
+ end
+
+ # Runs any registered #rescue_from controller handlers.
+ def rails_controller_rescue
+ yield
+ rescue Exception => exception
+ rails_controller_instance.rescue_with_handler(exception) || raise
+
+ unless rails_controller_instance.performed?
+ raise Rodauth::Rails::Error, "rescue_from handler didn't write any response"
+ end
+ end
+
+ # Returns Roda response from controller response if set.
+ def rails_controller_response
+ controller_response = rails_controller_instance.response
+
+ response.status = controller_response.status
+ response.headers.merge! controller_response.headers
+ response.write controller_response.body
+
+ request.halt
+ end
+
# Create emails with ActionMailer which uses configured delivery method.
def create_email_to(to, subject, body)
Mailer.create_email(to: to, from: email_from, subject: "#{email_subject_prefix}#{subject}", body: body)
end
@@ -62,17 +116,20 @@
# Calls the Rails renderer, returning nil if a template is missing.
def rails_render(*args)
return if only_json?
- begin
- rails_controller_instance.render_to_string(*args)
- rescue ActionView::MissingTemplate
- nil
- end
+ rails_controller_instance.render_to_string(*args)
+ rescue ActionView::MissingTemplate
+ nil
end
+ # Calls the controller to verify the authenticity token.
+ def rails_check_csrf!
+ rails_controller_instance.send(:verify_authenticity_token)
+ end
+
# Hidden tag with Rails CSRF token inserted into Rodauth templates.
def rails_csrf_tag
%(<input type="hidden" name="#{rails_csrf_param}" value="#{rails_csrf_token}">)
end
@@ -84,16 +141,11 @@
# The Rails CSRF token value inserted into Rodauth templates.
def rails_csrf_token
rails_controller_instance.send(:form_authenticity_token)
end
- # Calls the controller to verify the authenticity token.
- def rails_check_csrf!
- rails_controller_instance.send(:verify_authenticity_token)
- end
-
# Instances of the configured controller with current request's env hash.
- def rails_controller_instance
+ def _rails_controller_instance
request = ActionDispatch::Request.new(scope.env)
instance = rails_controller.new
if ActionPack.version >= Gem::Version.new("5.0")
instance.set_request! request