Files
grecia/app/models/tenant.rb
Javi Martín 5983006657 Use a custom method to detect the current tenant
The subdomain elevator we were using, which is included in apartment,
didn't work on hosts already including a subdomain (like
demo.consul.dev, for instance). In those cases, we would manually add
the subdomain to the list of excluded subdomains. Since these subdomains
will be different for different CONSUL installations, it meant each
installation had to customize the code. Furthermore, existing
installations using subdomains would stop working.

So we're using a custom method to find the current tenant, based on the
host defined in `default_url_options`.

In order to avoid any side-effects on single-tenant applications, we're
adding a new configuration option to enable multitenancy

We're enabling two ways to handle this configuration option:

a) Change the application_custom.rb file, which is under version control
b) Change the secrets.yml file, which is not under version control

This way people prefering to handle configuration options through
version control can do so, while people who prefer handling
configuration options through te secrets.yml file can do so as well.

We're also disabling the super-annoying warnings mentioning there are no
tenants which we got every time we run migrations on single-tenant
applications. These messages will only be enabled when the multitenancy
feature is enabled too. For this reason, we're also disabling the
multitenancy feature in the development environment by default.
2022-11-09 18:19:20 +01:00

56 lines
1.4 KiB
Ruby

class Tenant < ApplicationRecord
validates :schema,
presence: true,
uniqueness: true,
exclusion: { in: ->(*) { excluded_subdomains }},
format: { with: URI::DEFAULT_PARSER.regexp[:HOST] }
validates :name, presence: true, uniqueness: true
after_create :create_schema
after_update :rename_schema
after_destroy :destroy_schema
def self.resolve_host(host)
return nil unless Rails.application.config.multitenancy.present?
return nil if host.blank? || host.match?(Resolv::AddressRegex)
host_domain = allowed_domains.find { |domain| host == domain || host.ends_with?(".#{domain}") }
host.delete_prefix("www.").sub(/\.?#{host_domain}\Z/, "").presence
end
def self.allowed_domains
dev_domains = %w[localhost lvh.me example.com]
dev_domains + [default_host]
end
def self.excluded_subdomains
%w[mail public shared_extensions www]
end
def self.default_host
ActionMailer::Base.default_url_options[:host]
end
def self.switch(...)
Apartment::Tenant.switch(...)
end
private
def create_schema
Apartment::Tenant.create(schema)
end
def rename_schema
if saved_change_to_schema?
ActiveRecord::Base.connection.execute(
"ALTER SCHEMA \"#{schema_before_last_save}\" RENAME TO \"#{schema}\";"
)
end
end
def destroy_schema
Apartment::Tenant.drop(schema)
end
end