rails_multisite 2.1.2 → 3.0.0

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.

Potentially problematic release.


This version of rails_multisite might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b3fe0041751b722c29731d43407a107d44873642fa1166d8c28f15a776c35ac9
4
- data.tar.gz: ed8fedef6ee6ae4e11725f88d0375f17abe62a94a04bb99417b69daad3a2887c
3
+ metadata.gz: ee4885d481591f47f16a367e206e103af5ef3ea1504d65e0c34f97fa8766b91f
4
+ data.tar.gz: b6dc6f7d07e5ced80e7da754f5940b30a42a60d02e859afc8c949ffdf24f8b60
5
5
  SHA512:
6
- metadata.gz: b17dd4868f46d9cddf9a7ec2156d0d7aacc1e359673440e15b723b26ec67750fac5f3da2028e2d1d31f9234979dbe3ef3bd03511d1ea19ecb7c9ec40f10c5fca
7
- data.tar.gz: e3de9e44f8f4a04b0be895472ad360a32877644f1c7ce2939a674556965070908c5b0dd65d70c7b2ea3962490d4fcccfbd2781798d928d3387c84395426ec2f8
6
+ metadata.gz: c9d34362e98ddce5e8f771233ad43a803cf66e71bcd546dedaee3ae4a06991149f2e07d9e6024cbc111ee3166db7c193772cfdf7c78bec729da772b5db06a5bf
7
+ data.tar.gz: 4c9fdee8046e62e40be983d6f28f8e0fc703f89129e3d41d7ee9003aefa1c344bd170b7d4a5c1575729b80363ee2a7cfb48ad6a299564db3aa52da2fef0090c4
data/README.md CHANGED
@@ -93,6 +93,19 @@ To get a Rails console that is connected to `some_database_1` database:
93
93
  RAILS_DB=db_one rails console
94
94
  ```
95
95
 
96
+ ### CDN origin support
97
+
98
+ To avoid needing to configure many origins you can consider using `RailsMultisite::ConnectionManagement.asset_hostnames`
99
+
100
+ When configured, requests to `asset_hostname`?__ws=another.host.name will be re-routed to the correct site. Cookies will
101
+ be stripped on all incoming requests.
102
+
103
+ Example:
104
+
105
+ - Multisite serves `sub.example.com` and `assets.example.com`
106
+ - `RailsMultisite::ConnectionManagement.asset_hostnames = ['assets.example.com']`
107
+ - Requests to `https://assets.example.com/route/?__ws=sub.example.com` will be routed to the `sub.example.com`
108
+
96
109
 
97
110
  ## Contributing
98
111
 
@@ -1,16 +1,24 @@
1
1
  # frozen_string_literal: true
2
- #
2
+
3
+ if Rails.version >= '6.1'
4
+ require 'rails_multisite/connection_management/rails_61_compat'
5
+ else
6
+ require 'rails_multisite/connection_management/rails_60_compat'
7
+ end
8
+
3
9
  module RailsMultisite
4
10
  class ConnectionManagement
5
-
6
11
  DEFAULT = 'default'
7
- SPEC_KLASS = ActiveRecord::ConnectionAdapters::ConnectionSpecification
8
12
 
9
13
  def self.default_config_filename
10
14
  File.absolute_path(Rails.root.to_s + "/config/multisite.yml")
11
15
  end
12
16
 
13
17
  def self.clear_settings!
18
+ @instance&.db_spec_cache&.each do |key, spec|
19
+ @instance.connection_handlers.delete(self.handler_key(spec))
20
+ end
21
+
14
22
  @instance = nil
15
23
  end
16
24
 
@@ -31,6 +39,14 @@ module RailsMultisite
31
39
  end
32
40
  end
33
41
 
42
+ def self.asset_hostnames
43
+ @asset_hostnames
44
+ end
45
+
46
+ def self.asset_hostnames=(h)
47
+ @asset_hostnames = h
48
+ end
49
+
34
50
  def self.config_filename
35
51
  @instance.config_filename
36
52
  end
@@ -92,16 +108,11 @@ module RailsMultisite
92
108
  end
93
109
 
94
110
  def self.current_hostname
95
- spec = @instance.connection_spec(db: self.current_db) if @instance
96
- spec ||= ActiveRecord::Base.connection_pool.spec
97
- config = spec.config
98
- config[:host_names].nil? ? config[:host] : config[:host_names].first
111
+ current_db_hostnames.first
99
112
  end
100
113
 
101
114
  def self.current_db_hostnames
102
- spec = @instance.connection_spec(db: self.current_db) if @instance
103
- spec ||= ActiveRecord::Base.connection_pool.spec
104
- config = spec.config
115
+ config = (@instance&.connection_spec(db: current_db) || ConnectionSpecification.current).config
105
116
  config[:host_names].nil? ? [config[:host]] : config[:host_names]
106
117
  end
107
118
 
@@ -109,7 +120,7 @@ module RailsMultisite
109
120
  if @instance
110
121
  @instance.connection_spec(opts)
111
122
  else
112
- ActiveRecord::Base.connection_pool.spec
123
+ ConnectionSpecification.current
113
124
  end
114
125
  end
115
126
 
@@ -121,17 +132,45 @@ module RailsMultisite
121
132
  end
122
133
  end
123
134
 
124
- attr_reader :config_filename
135
+ def self.handler_key(spec)
136
+ @handler_key_suffix ||= begin
137
+ if ActiveRecord::Base.respond_to?(:writing_role)
138
+ "_#{ActiveRecord::Base.writing_role}"
139
+ else
140
+ ""
141
+ end
142
+ end
143
+
144
+ :"#{spec.name}#{@handler_key_suffix}"
145
+ end
146
+
147
+ def self.default_connection_handler=(connection_handler)
148
+ if @instance
149
+ unless connection_handler.is_a?(ActiveRecord::ConnectionAdapters::ConnectionHandler)
150
+ raise ArgumentError.new("Invalid connection handler")
151
+ end
152
+
153
+ @instance.default_connection_handler = connection_handler
154
+ end
155
+ end
156
+
157
+ attr_reader :config_filename, :db_spec_cache, :connection_handlers
158
+ attr_writer :default_connection_handler
125
159
 
126
160
  def initialize(config_filename)
127
161
  @config_filename = config_filename
128
162
 
129
- @connection_handlers = {}
130
- @db_spec_cache = {}
163
+ @connection_handlers = begin
164
+ if ActiveRecord::Base.respond_to?(:connection_handlers)
165
+ ActiveRecord::Base.connection_handlers
166
+ else
167
+ {}
168
+ end
169
+ end
131
170
 
132
- @default_spec = SPEC_KLASS::Resolver.new(ActiveRecord::Base.configurations).spec(Rails.env.to_sym)
171
+ @db_spec_cache = {}
172
+ @default_spec = ConnectionSpecification.default
133
173
  @default_connection_handler = ActiveRecord::Base.connection_handler
134
- @established_default = false
135
174
 
136
175
  @reload_mutex = Mutex.new
137
176
 
@@ -141,7 +180,7 @@ module RailsMultisite
141
180
  def load_config!
142
181
  configs = YAML::load(File.open(@config_filename))
143
182
 
144
- no_prepared_statements = ActiveRecord::Base.configurations[Rails.env]["prepared_statements"] == false
183
+ no_prepared_statements = @default_spec.config[:prepared_statements] == false
145
184
 
146
185
  configs.each do |k, v|
147
186
  raise ArgumentError.new("Please do not name any db default!") if k == DEFAULT
@@ -149,17 +188,8 @@ module RailsMultisite
149
188
  v[:prepared_statements] = false if no_prepared_statements
150
189
  end
151
190
 
152
- resolve_configs = configs
153
-
154
- # rails 6 needs to use a proper object for the resolver
155
- if defined?(ActiveRecord::DatabaseConfigurations)
156
- resolve_configs = ActiveRecord::DatabaseConfigurations.new(configs)
157
- end
158
-
159
- resolver = SPEC_KLASS::Resolver.new(resolve_configs)
160
-
161
191
  # Build a hash of db name => spec
162
- new_db_spec_cache = Hash[*configs.map { |k, _| [k, resolver.spec(k.to_sym)] }.flatten]
192
+ new_db_spec_cache = ConnectionSpecification.db_spec_cache(configs)
163
193
  new_db_spec_cache.each do |k, v|
164
194
  # If spec already existed, use the old version
165
195
  if v&.to_hash == @db_spec_cache[k]&.to_hash
@@ -177,7 +207,7 @@ module RailsMultisite
177
207
  end
178
208
 
179
209
  # Add the default hostnames as well
180
- ActiveRecord::Base.configurations[Rails.env]["host_names"].each do |host|
210
+ @default_spec.config[:host_names].each do |host|
181
211
  new_host_spec_cache[host] = @default_spec
182
212
  end
183
213
 
@@ -188,8 +218,7 @@ module RailsMultisite
188
218
  @db_spec_cache = new_db_spec_cache
189
219
 
190
220
  # Clean up connection handler cache.
191
- # (@connection_handlers is a hash of spec => handler)
192
- removed_specs.each { |s| @connection_handlers.delete(s) }
221
+ removed_specs.each { |s| @connection_handlers.delete(handler_key(s)) }
193
222
  end
194
223
 
195
224
  def reload
@@ -217,18 +246,14 @@ module RailsMultisite
217
246
  spec ||= @default_spec
218
247
  handler = nil
219
248
  if spec != @default_spec
220
- handler = @connection_handlers[spec]
249
+ handler = @connection_handlers[handler_key(spec)]
221
250
  unless handler
222
251
  handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
223
252
  handler_establish_connection(handler, spec)
224
- @connection_handlers[spec] = handler
253
+ @connection_handlers[handler_key(spec)] = handler
225
254
  end
226
255
  else
227
256
  handler = @default_connection_handler
228
- if !@established_default
229
- handler_establish_connection(handler, spec)
230
- @established_default = true
231
- end
232
257
  end
233
258
 
234
259
  ActiveRecord::Base.connection_handler = handler
@@ -330,7 +355,7 @@ module RailsMultisite
330
355
  end
331
356
 
332
357
  def current_db
333
- ActiveRecord::Base.connection_pool.spec.config[:db_key] || DEFAULT
358
+ ConnectionSpecification.current.config[:db_key] || DEFAULT
334
359
  end
335
360
 
336
361
  def current_hostname
@@ -343,7 +368,14 @@ module RailsMultisite
343
368
  end
344
369
 
345
370
  request = Rack::Request.new(env)
346
- host = request['__ws'] || request.host
371
+
372
+ host =
373
+ if request['__ws'] && self.class.asset_hostnames&.include?(request.host)
374
+ request.cookies.clear
375
+ request['__ws']
376
+ else
377
+ request.host
378
+ end
347
379
 
348
380
  env["RAILS_MULTISITE_HOST"] = host
349
381
  end
@@ -362,5 +394,9 @@ module RailsMultisite
362
394
  handler.establish_connection(spec.config)
363
395
  end
364
396
 
397
+ def handler_key(spec)
398
+ self.class.handler_key(spec)
399
+ end
400
+
365
401
  end
366
402
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMultisite
4
+ class ConnectionManagement
5
+ class ConnectionSpecification
6
+ class << self
7
+ def current
8
+ ActiveRecord::Base.connection_pool.spec
9
+ end
10
+
11
+ def db_spec_cache(configs)
12
+ resolve_configs = configs
13
+ # rails 6 needs to use a proper object for the resolver
14
+ if defined?(ActiveRecord::DatabaseConfigurations)
15
+ resolve_configs = ActiveRecord::DatabaseConfigurations.new(configs)
16
+ end
17
+ resolver = ActiveRecord::ConnectionAdapters::ConnectionSpecification::Resolver.new(resolve_configs)
18
+ configs.map { |k, _| [k, resolver.spec(k.to_sym)] }.to_h
19
+ end
20
+
21
+ def default
22
+ ActiveRecord::ConnectionAdapters::ConnectionSpecification::Resolver
23
+ .new(ActiveRecord::Base.configurations)
24
+ .spec(Rails.env.to_sym)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsMultisite
4
+ class ConnectionManagement
5
+ class ConnectionSpecification
6
+ class << self
7
+ def current
8
+ new(ActiveRecord::Base.connection_pool.db_config)
9
+ end
10
+
11
+ def db_spec_cache(configs)
12
+ resolve_configs = ActiveRecord::DatabaseConfigurations.new(configs)
13
+ configs.map { |k, _| [k, new(resolve_configs.resolve(k.to_sym))] }.to_h
14
+ end
15
+
16
+ def default
17
+ new(ActiveRecord::Base.configurations.resolve(Rails.env.to_sym))
18
+ end
19
+ end
20
+
21
+ attr_reader :spec
22
+
23
+ def initialize(spec)
24
+ @spec = spec
25
+ end
26
+
27
+ def name
28
+ spec.env_name
29
+ end
30
+
31
+ def to_hash
32
+ spec.configuration_hash
33
+ end
34
+ alias config to_hash
35
+ end
36
+ end
37
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  #
3
3
  module RailsMultisite
4
- VERSION = "2.1.2"
4
+ VERSION = "3.0.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_multisite
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.2
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-08 00:00:00.000000000 Z
11
+ date: 2021-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -61,6 +61,8 @@ files:
61
61
  - README.md
62
62
  - lib/rails_multisite.rb
63
63
  - lib/rails_multisite/connection_management.rb
64
+ - lib/rails_multisite/connection_management/rails_60_compat.rb
65
+ - lib/rails_multisite/connection_management/rails_61_compat.rb
64
66
  - lib/rails_multisite/formatter.rb
65
67
  - lib/rails_multisite/middleware.rb
66
68
  - lib/rails_multisite/railtie.rb
@@ -70,7 +72,7 @@ files:
70
72
  homepage: ''
71
73
  licenses: []
72
74
  metadata: {}
73
- post_install_message:
75
+ post_install_message:
74
76
  rdoc_options: []
75
77
  require_paths:
76
78
  - lib
@@ -85,8 +87,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
87
  - !ruby/object:Gem::Version
86
88
  version: '0'
87
89
  requirements: []
88
- rubygems_version: 3.1.2
89
- signing_key:
90
+ rubygems_version: 3.2.2
91
+ signing_key:
90
92
  specification_version: 4
91
93
  summary: Multi tenancy support for Rails
92
94
  test_files: []