Skip to content

Commit

Permalink
Allow overriding rodauth.rails_url_options
Browse files Browse the repository at this point in the history
This allows setting different URL options depending on the mailer's
default URL options, for example:

  class RodauthMailer < ApplicationMailer
    # ...
    private

    def rodauth(account_id, &block)
      instance = RodauthApp.rodauth.allocate
      instance.rails_url_options.merge!(default_url_options)
      # ...
    end

    def default_url_options
      { host: "subdomain.example.com" }
    end
  end

Resolves #306.
  • Loading branch information
janko committed Jun 25, 2024
1 parent f32020c commit b325e56
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 9 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## HEAD

* Allow overriding `rodauth.rails_url_options` in the mailer (@janko)

* Remove duplicate index on `account_id` in JWT refresh keys table (@janko)

* Rely on default index names in generated migrations (@thedumtechguy)
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,14 @@ Rodauth::Rails.rodauth(session: { two_factor_auth_setup: true })
Rodauth::Rails.rodauth(:admin, params: { "param" => "value" })
```

You can override default URL options ad-hoc by modifying `#rails_url_options`:

```rb
rodauth.base_url #=> "https://example.com"
rodauth.rails_url_options[:host] = "subdomain.example.com"
rodauth.base_url #=> "https://subdomain.example.com"
```

### Using as a library

Rodauth offers a [`Rodauth.lib`][library] method for when you want to use it as a library (via [internal requests][internal_request]), as opposed to having it route requests. This gem provides a `Rodauth::Rails.lib` counterpart that does the same but with Rails integration:
Expand Down Expand Up @@ -633,6 +641,7 @@ The `rails` feature rodauth-rails loads provides the following configuration met
| `rails_controller_instance` | Instance of the controller with the request env context. |
| `rails_controller` | Controller class to use for rendering and CSRF protection. |
| `rails_account_model` | Model class connected with the accounts table. |
| `rails_url_options` | Options used for generating URLs outside of a request (defaults to `config.action_mailer.default_url_options`) |

```rb
class RodauthMain < Rodauth::Rails::Auth
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class RodauthMailer < ApplicationMailer

private

# Default URL options are inherited from Action Mailer, but you can override them
# ad-hoc by modifying the `rodauth.rails_url_options` hash.
def rodauth(name, account_id, &block)
instance = RodauthApp.rodauth(name).allocate
instance.instance_eval { @account = account_ds(account_id).first! }
Expand Down
22 changes: 16 additions & 6 deletions lib/rodauth/rails/feature/internal_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@ module Feature
module InternalRequest
extend ActiveSupport::Concern

included do
auth_private_methods :rails_url_options
end

def domain
return super unless missing_host? && rails_url_options
return super unless missing_host? && rails_url_options!

rails_url_options.fetch(:host)
end

def base_url
return super unless missing_host? && domain && rails_url_options
return super unless missing_host? && domain && rails_url_options!

scheme = rails_url_options[:protocol] || "http"
port = rails_url_options[:port]
Expand All @@ -21,6 +25,11 @@ def base_url
url
end

def rails_url_options
return _rails_url_options if frozen? # handle path_class_methods feature
@rails_url_options ||= _rails_url_options
end

private

def rails_controller_around
Expand All @@ -44,11 +53,12 @@ def missing_host?
internal_request? && (request.host.nil? || request.host == INVALID_DOMAIN) || scope.nil?
end

def rails_url_options
return nil unless defined?(ActionMailer)
def rails_url_options!
rails_url_options.presence or fail Error, "There is no information to set the URL host from. Please set config.action_mailer.default_url_options in your Rails application, configure #domain and #base_url in your Rodauth configuration, or set #rails_url_options on the Rodauth instance."
end

::Rails.configuration.action_mailer.default_url_options or
fail Error, "There is no information to set the URL host from. Please set config.action_mailer.default_url_options in your Rails application, or configure #domain and #base_url in your Rodauth configuration."
def _rails_url_options
defined?(ActionMailer) ? ActionMailer::Base.default_url_options.dup : {}
end
end
end
Expand Down
14 changes: 11 additions & 3 deletions test/internal_request_test.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
require "test_helper"

class InternalRequestTest < UnitTest
test "inheriting URL options from config.action_mailer" do
test "inheriting URL options from Action Mailer" do
RodauthApp.rodauth.create_account(login: "[email protected]", password: "secret")
email = ActionMailer::Base.deliveries.last
assert_match %r{https://example\.com}, email.body.to_s
end

test "allowing overriding URL options" do
test "overriding URL options directly" do
rodauth = RodauthApp.rodauth.allocate
rodauth.rails_url_options[:host] = "sub.example.com"

assert_equal "https://sub.example.com", rodauth.base_url
assert_equal "example.com", ActionMailer::Base.default_url_options[:host]
end

test "overriding URL options via rack env" do
env = { "HTTP_HOST" => "foobar.com", "rack.url_scheme" => "http" }
RodauthApp.rodauth.create_account(login: "[email protected]", password: "secret", env: env)
email = ActionMailer::Base.deliveries.last
assert_match %r{http://foobar\.com}, email.body.to_s
end

test "missing config.action_mailer.default_url_options" do
test "missing Action Mailer default URL options" do
Rails.configuration.action_mailer.stub(:default_url_options, nil) do
assert_equal "/create-account", RodauthApp.rodauth.create_account_path
assert_raises Rodauth::Rails::Error do
Expand Down

0 comments on commit b325e56

Please sign in to comment.