ErwinM / acts_as_tenant

Easy multi-tenancy for Rails in a shared database setup.
MIT License
1.53k stars 263 forks source link

Can't figure out how to access tenant based on domain #259

Open DavidGeismarLtd opened 3 years ago

DavidGeismarLtd commented 3 years ago

I am using acts_as_tenant to build a multitenancy rails app that deploys customizable websites. In my application controller I have :

class ApplicationController < ActionController::Base
  set_current_tenant_by_subdomain_or_domain(:account, :subdomain, :domain)

Let's say my app is under platformdomain.io. When I create a new app, I can set a subdomain for it (let's say "me") and the new website will be accessible underme.platformdomain.io and this works perfectly fine. However I would also like my users to be able to deploy their app on their own custom domain like customdomain.io or shop.customdomain.io.

However when I try then to access the custom app at shop.mycustomdomain.io, I can see in the logs that my app is trying to load based on the subdomain shop.mycustomdomain:

Account Load (4.8ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."subdomain" = $1 LIMIT $2 [["subdomain", "shop.mycustomdomain"], ["LIMIT", 1]]

This can't work, as I guess the app should be trying to load the account with the domain of mycustomdomain. Am I missing something here ? Is this not how acts_as_tenant is supposed to work ? How can I achieve the described behavior ?

excid3 commented 3 years ago

You're using a subdomain AND a custom domain combined for shop.mycustomdomain.io. ActsAsTenant will only lookup using a subdomain OR a domain. Not both.

See: https://github.com/ErwinM/acts_as_tenant/blob/master/lib/acts_as_tenant/controller_extensions/subdomain_or_domain.rb#L15

I recommend you use set_current_tenant_through_filter. That way you can check the domain first before you decide to use a subdomain or not.

DavidGeismarLtd commented 3 years ago

Thanks for your answer @excid3. Following what you said I tried it with a naked domain (no subdomain) just mycustomdomain.co.uk. I would expect then acts_as_tenant to catch the right tenant based on the naked domain, right ? However the logs still show a search perform on the subdomain column : DEBUG -- : [69237831-ac24-491f-94a9-a575d0537844] Account Load (1.3ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."subdomain" = $1 LIMIT $2 [["subdomain", "mycustomdomain"], ["LIMIT", 1]]

excid3 commented 3 years ago

Because it thinks you have a subdomain since there are 2 periods. You have to configure Rails for a tld_length of 2 if you're using a TLD like .co.uk otherwise it thinks your domain is co.uk

config.action_dispatch.tld_length = 2

DavidGeismarLtd commented 3 years ago

@excid3 thanks for the info, before doing that I wanted to check if things would work with a domain with one period. So I used mycustomdomain.uk. However the search still performs on the subdomain column, on an empty string this time : SELECT "accounts".* FROM "accounts" WHERE "accounts"."subdomain" = $1 LIMIT $2 [["subdomain", ""], ["LIMIT", 1]] I checked and indeed Rails.application.action_dispatch.tld_length is equal to 1

firecall commented 2 years ago

Because it thinks you have a subdomain since there are 2 periods. You have to configure Rails for a tld_length of 2 if you're using a TLD like .co.uk otherwise it thinks your domain is co.uk

config.action_dispatch.tld_length = 2

Hi,

Could I please just clarify something around the TLD lemgth? :-)

I'm using Australian domains, like example.com.au

Im my Rails 6 app i have:

class ApplicationController < ActionController::Base set_current_tenant_by_subdomain_or_domain(:account, :domain)

I then have an Account table with a domain field:

domain: example.com.au

In production example.com.au wasn't working.

I thought I needed the full domain with the TLD, but realised that maybe I didn't! So I removed the .com.au TLD.

And now it is working!

In my prod logs (with log level debug) I can see the query:

SELECT accounts.* FROM accounts WHERE accounts.domain = example ORDER BY accounts.id ASC LIMIT 1

And that is working!

But based on what was indicated by Rails not understanding a TLD with a country code, it shouldn't work!

Have I totally misunderstood something here?

TIA! :-)