rls_multi_tenant 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +59 -5
- data/lib/rls_multi_tenant/concerns/multi_tenant.rb +5 -0
- data/lib/rls_multi_tenant/concerns/tenant_context.rb +1 -0
- data/lib/rls_multi_tenant/generators/install/install_generator.rb +11 -0
- data/lib/rls_multi_tenant/generators/install/templates/rls_multi_tenant.rb +7 -0
- data/lib/rls_multi_tenant/generators/migration/templates/enable_rls.rb +0 -6
- data/lib/rls_multi_tenant/generators/model/templates/migration.rb +1 -10
- data/lib/rls_multi_tenant/generators/setup/setup_generator.rb +0 -9
- data/lib/rls_multi_tenant/generators/shared/templates/create_tenant.rb +2 -0
- data/lib/rls_multi_tenant/middleware/subdomain_tenant_selector.rb +79 -0
- data/lib/rls_multi_tenant/railtie.rb +6 -0
- data/lib/rls_multi_tenant/version.rb +1 -1
- data/lib/rls_multi_tenant.rb +12 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ef549a91c89a2d4c0b4ee20af9711d31fb807b3b61d115c6655e491a35ef1bcc
|
|
4
|
+
data.tar.gz: 4aabdf36264d22878785a8e737b67c7dca87a4700989d149dda0e72b13cbc6be
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 31152dc5b94a7f4a9c12ec3eaf3aed96ca8fc8e1080e2918b68b85a65b9d9d8fa34f7ae8c7472b2daa77dafa5d00f368a362d2473732c940c26e860bc4a93155
|
|
7
|
+
data.tar.gz: 1bbab04fd97a40d5f07254f0f75e1ed113950309d1029840238dc572a5739a4f76e808b1e14b95f936334079c1776112401be9bdbff76ece4e794d2d30c8ad8a
|
data/README.md
CHANGED
|
@@ -10,6 +10,7 @@ A Rails gem that provides PostgreSQL Row Level Security (RLS) based multi-tenanc
|
|
|
10
10
|
- 📦 **Auto-inclusion**: Automatic model configuration
|
|
11
11
|
- 🚀 **Generators**: Rails generators for quick setup
|
|
12
12
|
- ⚙️ **Configurable**: Flexible configuration options
|
|
13
|
+
- 🌐 **Subdomain Middleware**: Automatic tenant switching based on subdomain
|
|
13
14
|
|
|
14
15
|
## Installation
|
|
15
16
|
|
|
@@ -40,6 +41,8 @@ bundle install
|
|
|
40
41
|
config.tenant_id_column = :tenant_id # Tenant ID column name
|
|
41
42
|
config.app_user_env_var = "POSTGRES_APP_USER" # Environment variable for app user
|
|
42
43
|
config.enable_security_validation = true # Enable security checks
|
|
44
|
+
config.enable_subdomain_middleware = true # Enable subdomain-based tenant switching (default: true)
|
|
45
|
+
config.subdomain_field = :subdomain # Field to use for subdomain matching (default: :subdomain)
|
|
43
46
|
end
|
|
44
47
|
```
|
|
45
48
|
|
|
@@ -75,32 +78,78 @@ Your models automatically include the `MultiTenant` concern:
|
|
|
75
78
|
```ruby
|
|
76
79
|
class User < ApplicationRecord
|
|
77
80
|
# Automatically includes MultiTenant concern
|
|
78
|
-
|
|
81
|
+
include RlsMultiTenant::Concerns::MultiTenant
|
|
79
82
|
end
|
|
80
83
|
```
|
|
81
84
|
|
|
82
85
|
### Tenant Context Switching
|
|
83
86
|
|
|
84
87
|
```ruby
|
|
85
|
-
# Create a new tenant
|
|
86
|
-
tenant = Tenant.create!(name: "
|
|
88
|
+
# Create a new tenant with subdomain
|
|
89
|
+
tenant = Tenant.create!(name: "Company A", subdomain: "company-a")
|
|
87
90
|
```
|
|
88
91
|
|
|
89
92
|
```ruby
|
|
90
93
|
# Switch tenant context for a block
|
|
91
94
|
Tenant.switch(tenant) do
|
|
92
|
-
User.create!(name: "User from
|
|
95
|
+
User.create!(name: "User from Company A", email: "user@company-a.com") # Automatically assigned to current tenant
|
|
93
96
|
end
|
|
94
97
|
|
|
95
98
|
# Switch tenant context permanently
|
|
96
99
|
Tenant.switch!(tenant)
|
|
97
|
-
User.create!(name: "User from
|
|
100
|
+
User.create!(name: "User from Company A", email: "user@company-a.com")
|
|
98
101
|
Tenant.reset! # Reset context
|
|
99
102
|
|
|
100
103
|
# Get current tenant
|
|
101
104
|
current_tenant = Tenant.current
|
|
102
105
|
```
|
|
103
106
|
|
|
107
|
+
### Automatic Subdomain-Based Tenant Switching
|
|
108
|
+
|
|
109
|
+
The gem includes middleware that automatically switches tenants based on the request subdomain. This is enabled by default and works seamlessly with your tenant model.
|
|
110
|
+
|
|
111
|
+
**The middleware automatically:**
|
|
112
|
+
- Extracts the subdomain from the request host
|
|
113
|
+
- Finds the matching tenant by the subdomain field
|
|
114
|
+
- Switches the tenant context for the duration of the request
|
|
115
|
+
- Resets the context after the request completes
|
|
116
|
+
|
|
117
|
+
**Usage:**
|
|
118
|
+
```ruby
|
|
119
|
+
# Create tenants with subdomains
|
|
120
|
+
tenant1 = Tenant.create!(name: "Company A", subdomain: "company-a")
|
|
121
|
+
tenant2 = Tenant.create!(name: "Company B", subdomain: "company-b")
|
|
122
|
+
|
|
123
|
+
# Users visiting company-a.yourdomain.com will automatically be in tenant1's context
|
|
124
|
+
# Users visiting company-b.yourdomain.com will automatically be in tenant2's context
|
|
125
|
+
# Users visiting yourdomain.com (no subdomain) will have no tenant context
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Public Access (Non-Tenanted Models)
|
|
129
|
+
|
|
130
|
+
Models that don't include `RlsMultiTenant::Concerns::TenantContext` are automatically treated as public models and can be accessed without tenant context. This provides a secure, explicit way to separate tenant-specific and public models.
|
|
131
|
+
|
|
132
|
+
**Example:**
|
|
133
|
+
```ruby
|
|
134
|
+
# Public models (no tenant association)
|
|
135
|
+
class PublicPost < ApplicationRecord
|
|
136
|
+
# No TenantContext concern included
|
|
137
|
+
# These models are accessible without tenant context
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Tenant-specific models (automatically generated)
|
|
141
|
+
class User < ApplicationRecord
|
|
142
|
+
# Automatically includes MultiTenant concern
|
|
143
|
+
# These models require tenant context and are constrained by RLS
|
|
144
|
+
include RlsMultiTenant::Concerns::MultiTenant
|
|
145
|
+
end
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Security Benefits:**
|
|
149
|
+
- **Explicit Intent**: Models must explicitly include `TenantContext` to be tenant-constrained
|
|
150
|
+
- **Fail-Safe**: Public models are clearly separated from tenant models
|
|
151
|
+
- **No Configuration Drift**: Can't accidentally expose tenant data through misconfiguration
|
|
152
|
+
|
|
104
153
|
## Configuration
|
|
105
154
|
|
|
106
155
|
The gem is configured in `config/initializers/rls_multi_tenant.rb` (created by the install generator). You can customize the following options:
|
|
@@ -111,6 +160,8 @@ RlsMultiTenant.configure do |config|
|
|
|
111
160
|
config.tenant_id_column = :tenant_id # Tenant ID column name
|
|
112
161
|
config.app_user_env_var = "POSTGRES_APP_USER" # Environment variable for app user
|
|
113
162
|
config.enable_security_validation = true # Enable security checks (prevents running with superuser privileges)
|
|
163
|
+
config.enable_subdomain_middleware = true # Enable subdomain-based tenant switching (default: true)
|
|
164
|
+
config.subdomain_field = :subdomain # Field to use for subdomain matching (default: :subdomain)
|
|
114
165
|
end
|
|
115
166
|
```
|
|
116
167
|
|
|
@@ -126,6 +177,9 @@ rails db_as:admin[seed]
|
|
|
126
177
|
|
|
127
178
|
# Create database with admin privileges
|
|
128
179
|
rails db_as:admin[create]
|
|
180
|
+
|
|
181
|
+
# Drop database with admin privileges
|
|
182
|
+
rails db_as:admin[drop]
|
|
129
183
|
```
|
|
130
184
|
|
|
131
185
|
## Security Features
|
|
@@ -16,8 +16,13 @@ module RlsMultiTenant
|
|
|
16
16
|
|
|
17
17
|
def set_tenant_id
|
|
18
18
|
current_tenant = RlsMultiTenant.tenant_class.current
|
|
19
|
+
|
|
19
20
|
if current_tenant && self.send(RlsMultiTenant.tenant_id_column).blank?
|
|
20
21
|
self.send("#{RlsMultiTenant.tenant_id_column}=", current_tenant.id)
|
|
22
|
+
elsif current_tenant.nil?
|
|
23
|
+
raise RlsMultiTenant::Error,
|
|
24
|
+
"Cannot create #{self.class.name} without tenant context. " \
|
|
25
|
+
"This model requires a tenant context. "
|
|
21
26
|
end
|
|
22
27
|
end
|
|
23
28
|
end
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'rails/generators'
|
|
4
|
+
require 'rls_multi_tenant/generators/shared/template_helper'
|
|
4
5
|
|
|
5
6
|
module RlsMultiTenant
|
|
6
7
|
module Generators
|
|
7
8
|
class InstallGenerator < Rails::Generators::Base
|
|
9
|
+
include Shared::TemplateHelper
|
|
10
|
+
|
|
8
11
|
source_root File.expand_path("templates", __dir__)
|
|
9
12
|
|
|
10
13
|
desc "Install RLS Multi-tenant gem configuration"
|
|
@@ -13,6 +16,14 @@ module RlsMultiTenant
|
|
|
13
16
|
template "rls_multi_tenant.rb", "config/initializers/rls_multi_tenant.rb"
|
|
14
17
|
end
|
|
15
18
|
|
|
19
|
+
def create_db_admin_task
|
|
20
|
+
unless File.exist?(File.join(destination_root, "lib/tasks/db_admin.rake"))
|
|
21
|
+
copy_shared_template "db_admin.rake", "lib/tasks/db_admin.rake"
|
|
22
|
+
else
|
|
23
|
+
say "Database admin task already exists, skipping creation", :yellow
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
16
27
|
def show_instructions
|
|
17
28
|
say "\n" + "="*60, :green
|
|
18
29
|
say "RLS Multi-tenant gem configuration installed successfully!", :green
|
|
@@ -12,4 +12,11 @@ RlsMultiTenant.configure do |config|
|
|
|
12
12
|
|
|
13
13
|
# Enable/disable security validation
|
|
14
14
|
config.enable_security_validation = true
|
|
15
|
+
|
|
16
|
+
# Enable/disable subdomain-based tenant switching middleware
|
|
17
|
+
config.enable_subdomain_middleware = true
|
|
18
|
+
|
|
19
|
+
# Configure the field to use for subdomain matching (default: :subdomain)
|
|
20
|
+
# This should be a field on your tenant model that contains the subdomain
|
|
21
|
+
config.subdomain_field = :subdomain
|
|
15
22
|
end
|
|
@@ -7,15 +7,9 @@ class EnableRlsFor<%= table_name.camelize %> < ActiveRecord::Migration[<%= Rails
|
|
|
7
7
|
|
|
8
8
|
# Create RLS policy
|
|
9
9
|
execute "CREATE POLICY <%= table_name %>_app_user ON <%= table_name %> TO #{ENV['<%= RlsMultiTenant.app_user_env_var %>']} USING (<%= RlsMultiTenant.tenant_id_column %> = NULLIF(current_setting('rls.<%= RlsMultiTenant.tenant_id_column %>', TRUE), '')::uuid)"
|
|
10
|
-
|
|
11
|
-
# Grant permissions
|
|
12
|
-
execute "GRANT SELECT, INSERT, UPDATE, DELETE ON <%= table_name %> TO #{ENV['<%= RlsMultiTenant.app_user_env_var %>']}"
|
|
13
10
|
end
|
|
14
11
|
|
|
15
12
|
dir.down do
|
|
16
|
-
# Revoke permissions
|
|
17
|
-
execute "REVOKE SELECT, INSERT, UPDATE, DELETE ON <%= table_name %> FROM #{ENV['<%= RlsMultiTenant.app_user_env_var %>']}"
|
|
18
|
-
|
|
19
13
|
# Drop policy
|
|
20
14
|
execute "DROP POLICY <%= table_name %>_app_user ON <%= table_name %>"
|
|
21
15
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
class <%= migration_class_name %> < ActiveRecord::Migration[<%= Rails.version.to_f %>]
|
|
2
2
|
def change
|
|
3
3
|
# Create the table
|
|
4
|
-
create_table :<%= table_name
|
|
4
|
+
create_table :<%= table_name %> do |t|
|
|
5
5
|
t.references :<%= tenant_id_column.to_s.gsub('_id', '') %>, null: false, foreign_key: { to_table: :<%= tenant_class_name.underscore.pluralize %> }, type: :uuid
|
|
6
6
|
<% @attributes.each do |attribute| -%>
|
|
7
7
|
t.<%= attribute.type %> :<%= attribute.name %>
|
|
@@ -13,15 +13,6 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= Rails.version.to
|
|
|
13
13
|
# Enable Row Level Security
|
|
14
14
|
execute "ALTER TABLE <%= table_name %> ENABLE ROW LEVEL SECURITY"
|
|
15
15
|
|
|
16
|
-
reversible do |dir|
|
|
17
|
-
dir.up do
|
|
18
|
-
execute "GRANT SELECT, INSERT, UPDATE, DELETE ON <%= table_name %> TO #{ENV['<%= RlsMultiTenant.app_user_env_var %>']}"
|
|
19
|
-
end
|
|
20
|
-
dir.down do
|
|
21
|
-
execute "REVOKE SELECT, INSERT, UPDATE, DELETE ON <%= table_name %> FROM #{ENV['<%= RlsMultiTenant.app_user_env_var %>']}"
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
16
|
# Define RLS policy
|
|
26
17
|
reversible do |dir|
|
|
27
18
|
dir.up do
|
|
@@ -23,14 +23,6 @@ module RlsMultiTenant
|
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
def create_db_admin_task
|
|
27
|
-
unless File.exist?(File.join(destination_root, "lib/tasks/db_admin.rake"))
|
|
28
|
-
copy_shared_template "db_admin.rake", "lib/tasks/db_admin.rake"
|
|
29
|
-
else
|
|
30
|
-
say "Database admin task already exists, skipping creation", :yellow
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
26
|
def create_uuid_migration
|
|
35
27
|
unless Dir.glob(File.join(destination_root, "db/migrate/*_enable_uuid_extension.rb")).any?
|
|
36
28
|
create_migration_with_timestamp("enable_uuid", 1)
|
|
@@ -61,7 +53,6 @@ module RlsMultiTenant
|
|
|
61
53
|
say "="*60, :green
|
|
62
54
|
say "\nCreated:", :yellow
|
|
63
55
|
say "• #{tenant_class_name} model", :green
|
|
64
|
-
say "• Database admin task", :green
|
|
65
56
|
say "• UUID extension migration", :green
|
|
66
57
|
say "• App user migration(s)", :green
|
|
67
58
|
say "• #{tenant_class_name} migration", :green
|
|
@@ -2,10 +2,12 @@ class Create<%= RlsMultiTenant.tenant_class_name.pluralize %> < ActiveRecord::Mi
|
|
|
2
2
|
def change
|
|
3
3
|
create_table :<%= RlsMultiTenant.tenant_class_name.underscore.pluralize %>, id: :uuid do |t|
|
|
4
4
|
t.string :name, null: false
|
|
5
|
+
t.string :subdomain, null: false
|
|
5
6
|
|
|
6
7
|
t.timestamps
|
|
7
8
|
end
|
|
8
9
|
|
|
9
10
|
add_index :<%= RlsMultiTenant.tenant_class_name.underscore.pluralize %>, :name, unique: true
|
|
11
|
+
add_index :<%= RlsMultiTenant.tenant_class_name.underscore.pluralize %>, :subdomain, unique: true
|
|
10
12
|
end
|
|
11
13
|
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RlsMultiTenant
|
|
4
|
+
module Middleware
|
|
5
|
+
class SubdomainTenantSelector
|
|
6
|
+
def initialize(app)
|
|
7
|
+
@app = app
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def call(env)
|
|
11
|
+
request = ActionDispatch::Request.new(env)
|
|
12
|
+
tenant = resolve_tenant_from_subdomain(request)
|
|
13
|
+
|
|
14
|
+
if tenant
|
|
15
|
+
# Switch tenant context for the duration of the request
|
|
16
|
+
Rails.logger.info "[RLS Multi-Tenant] #{request.method} #{request.path} -> Tenant: #{tenant.name} (#{tenant.id})" if defined?(Rails)
|
|
17
|
+
RlsMultiTenant.tenant_class.switch(tenant) do
|
|
18
|
+
@app.call(env)
|
|
19
|
+
end
|
|
20
|
+
else
|
|
21
|
+
# No tenant found - check if we need tenant context
|
|
22
|
+
subdomain = extract_subdomain(request.host)
|
|
23
|
+
if subdomain.present? && subdomain != 'www'
|
|
24
|
+
# Subdomain exists but no tenant found - this is an error
|
|
25
|
+
Rails.logger.warn "[RLS Multi-Tenant] #{request.method} #{request.path} -> No tenant found for subdomain '#{subdomain}'" if defined?(Rails)
|
|
26
|
+
raise RlsMultiTenant::Error, "No tenant found for subdomain '#{subdomain}'. Please ensure the tenant exists with the correct subdomain."
|
|
27
|
+
end
|
|
28
|
+
# If no subdomain, allow access to public models (models without TenantContext)
|
|
29
|
+
# Models that include TenantContext will automatically be constrained by RLS
|
|
30
|
+
Rails.logger.info "[RLS Multi-Tenant] #{request.method} #{request.path} -> Public access (no subdomain)" if defined?(Rails)
|
|
31
|
+
@app.call(env)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def resolve_tenant_from_subdomain(request)
|
|
38
|
+
subdomain = extract_subdomain(request.host)
|
|
39
|
+
return nil if subdomain.blank? || subdomain == 'www'
|
|
40
|
+
|
|
41
|
+
# Look up tenant by subdomain only
|
|
42
|
+
tenant_class = RlsMultiTenant.tenant_class
|
|
43
|
+
subdomain_field = RlsMultiTenant.subdomain_field
|
|
44
|
+
|
|
45
|
+
# Only allow subdomain-based lookup
|
|
46
|
+
unless tenant_class.column_names.include?(subdomain_field.to_s)
|
|
47
|
+
raise RlsMultiTenant::ConfigurationError,
|
|
48
|
+
"Subdomain field '#{subdomain_field}' not found on #{tenant_class.name}. " \
|
|
49
|
+
"Please add a '#{subdomain_field}' column to your tenant model or configure a different subdomain_field."
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
tenant_class.find_by(subdomain_field => subdomain)
|
|
53
|
+
rescue => e
|
|
54
|
+
Rails.logger.error "Failed to resolve tenant from subdomain '#{subdomain}': #{e.message}" if defined?(Rails)
|
|
55
|
+
nil
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def extract_subdomain(host)
|
|
59
|
+
return nil if host.blank?
|
|
60
|
+
|
|
61
|
+
# Remove port if present
|
|
62
|
+
host = host.split(':').first
|
|
63
|
+
|
|
64
|
+
# Split by dots and get the first part (subdomain)
|
|
65
|
+
parts = host.split('.')
|
|
66
|
+
|
|
67
|
+
# Handle localhost development (e.g., foo.localhost:3000)
|
|
68
|
+
if parts.length == 2 && parts.last == 'localhost'
|
|
69
|
+
parts.first
|
|
70
|
+
# Handle standard domains (e.g., foo.example.com)
|
|
71
|
+
elsif parts.length >= 3
|
|
72
|
+
parts.first
|
|
73
|
+
else
|
|
74
|
+
nil
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -34,5 +34,11 @@ module RlsMultiTenant
|
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
|
+
|
|
38
|
+
initializer "rls_multi_tenant.middleware", after: :load_config_initializers do |app|
|
|
39
|
+
if RlsMultiTenant.enable_subdomain_middleware
|
|
40
|
+
app.config.middleware.use RlsMultiTenant::Middleware::SubdomainTenantSelector
|
|
41
|
+
end
|
|
42
|
+
end
|
|
37
43
|
end
|
|
38
44
|
end
|
data/lib/rls_multi_tenant.rb
CHANGED
|
@@ -5,6 +5,7 @@ require "rls_multi_tenant/concerns/multi_tenant"
|
|
|
5
5
|
require "rls_multi_tenant/concerns/tenant_context"
|
|
6
6
|
require "rls_multi_tenant/security_validator"
|
|
7
7
|
require "rls_multi_tenant/rls_helper"
|
|
8
|
+
require "rls_multi_tenant/middleware/subdomain_tenant_selector"
|
|
8
9
|
require "rls_multi_tenant/generators/shared/template_helper"
|
|
9
10
|
require "rls_multi_tenant/railtie" if defined?(Rails)
|
|
10
11
|
|
|
@@ -15,7 +16,7 @@ module RlsMultiTenant
|
|
|
15
16
|
|
|
16
17
|
# Configuration options
|
|
17
18
|
class << self
|
|
18
|
-
attr_accessor :tenant_class_name, :tenant_id_column, :app_user_env_var, :enable_security_validation
|
|
19
|
+
attr_accessor :tenant_class_name, :tenant_id_column, :app_user_env_var, :enable_security_validation, :enable_subdomain_middleware, :subdomain_field
|
|
19
20
|
|
|
20
21
|
def configure
|
|
21
22
|
yield self
|
|
@@ -36,6 +37,14 @@ module RlsMultiTenant
|
|
|
36
37
|
def enable_security_validation
|
|
37
38
|
@enable_security_validation.nil? ? true : @enable_security_validation
|
|
38
39
|
end
|
|
40
|
+
|
|
41
|
+
def enable_subdomain_middleware
|
|
42
|
+
@enable_subdomain_middleware.nil? ? false : @enable_subdomain_middleware
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def subdomain_field
|
|
46
|
+
@subdomain_field ||= :subdomain
|
|
47
|
+
end
|
|
39
48
|
end
|
|
40
49
|
|
|
41
50
|
# Default configuration
|
|
@@ -43,4 +52,6 @@ module RlsMultiTenant
|
|
|
43
52
|
self.tenant_id_column = :tenant_id
|
|
44
53
|
self.app_user_env_var = "POSTGRES_APP_USER"
|
|
45
54
|
self.enable_security_validation = true
|
|
55
|
+
self.enable_subdomain_middleware = true
|
|
56
|
+
self.subdomain_field = :subdomain
|
|
46
57
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rls_multi_tenant
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Coding Ways
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-09-
|
|
11
|
+
date: 2025-09-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -177,6 +177,7 @@ files:
|
|
|
177
177
|
- lib/rls_multi_tenant/generators/shared/templates/db_admin.rake
|
|
178
178
|
- lib/rls_multi_tenant/generators/shared/templates/enable_uuid_extension.rb
|
|
179
179
|
- lib/rls_multi_tenant/generators/task/task_generator.rb
|
|
180
|
+
- lib/rls_multi_tenant/middleware/subdomain_tenant_selector.rb
|
|
180
181
|
- lib/rls_multi_tenant/railtie.rb
|
|
181
182
|
- lib/rls_multi_tenant/rls_helper.rb
|
|
182
183
|
- lib/rls_multi_tenant/rls_multi_tenant.rb
|