multi-tenant-support 1.1.0 → 1.3.1
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 +71 -0
- data/lib/generators/multi_tenant_support/templates/initializer.rb.tt +4 -0
- data/lib/multi-tenant-support.rb +5 -0
- data/lib/multi_tenant_support/active_job.rb +55 -1
- data/lib/multi_tenant_support/concern/controller_concern.rb +6 -6
- data/lib/multi_tenant_support/config/console.rb +21 -0
- data/lib/multi_tenant_support/minitest.rb +7 -0
- data/lib/multi_tenant_support/railtie.rb +8 -0
- data/lib/multi_tenant_support/rspec.rb +13 -0
- data/lib/multi_tenant_support/test/capybara.rb +57 -0
- data/lib/multi_tenant_support/test/integration.rb +29 -0
- data/lib/multi_tenant_support/test/system.rb +38 -0
- data/lib/multi_tenant_support/version.rb +1 -1
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d9a0f7c5067f07151a631c2b67b7b4ab6fb65da04f5b67c8020fec6d89ffe0f6
|
4
|
+
data.tar.gz: dbde15d968752339fbc72ec3aed925fa706863c88cdf5f06cb0036fda4c8679c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 38e715d1ad5361a4db0cbb2b4b8cde6df8572a72186be05a54949649aad6460e69ef13e2080dbbbe678c64caeb6d7e71e7b9bafc86734266dabe957b947493ca
|
7
|
+
data.tar.gz: 3bf0ff4690f643d531b897d487e3ca519df588ea2e08cd7036d3ba65dbbad3e68f129c0c6596b92bf222833112ac59d1ba6eb2c042ac8db8e990fc0267656c67
|
data/README.md
CHANGED
@@ -237,6 +237,12 @@ MultiTenantSupport.under_tenant amazon do
|
|
237
237
|
end
|
238
238
|
```
|
239
239
|
|
240
|
+
### Set current tenant global
|
241
|
+
|
242
|
+
```ruby
|
243
|
+
MultiTenantSupport::Current.tenant_account = account
|
244
|
+
```
|
245
|
+
|
240
246
|
### Disallow read across tenant by default
|
241
247
|
|
242
248
|
This gem disallow read across tenant by default. You can check current state through:
|
@@ -306,6 +312,67 @@ Currently, we don't have a good way to protect this method. So please use `upser
|
|
306
312
|
|
307
313
|
This gem has override `unscoped` to prevent the default tenant scope be scoped out. But if you really want to scope out the default tenant scope, you can use `unscope_tenant`.
|
308
314
|
|
315
|
+
### Console
|
316
|
+
|
317
|
+
Console does not allow read across tenant by default. But you have several ways to change that:
|
318
|
+
|
319
|
+
1. Set `allow_read_across_tenant_by_default` in the initialize file
|
320
|
+
|
321
|
+
```ruby
|
322
|
+
console do |config|
|
323
|
+
config.allow_read_across_tenant_by_default = true
|
324
|
+
end
|
325
|
+
```
|
326
|
+
2. Set the environment variable `ALLOW_READ_ACROSS_TENANT` when call consoel command
|
327
|
+
|
328
|
+
```bash
|
329
|
+
ALLOW_READ_ACROSS_TENANT=1 rails console
|
330
|
+
```
|
331
|
+
3. Manual change it in console
|
332
|
+
|
333
|
+
```ruby
|
334
|
+
$ rails c
|
335
|
+
$ irb(main):001:0> MultiTenantSupport.allow_read_across_tenant
|
336
|
+
```
|
337
|
+
|
338
|
+
## Testing
|
339
|
+
### Minitest (Rails default)
|
340
|
+
|
341
|
+
```ruby
|
342
|
+
# test/test_helper.rb
|
343
|
+
require 'multi_tenant_support/minitet'
|
344
|
+
```
|
345
|
+
### RSpec (with Capybara)
|
346
|
+
|
347
|
+
```ruby
|
348
|
+
# spec/rails_helper.rb or spec/spec_helper.rb
|
349
|
+
require 'multi_tenant_support/rspec'
|
350
|
+
```
|
351
|
+
|
352
|
+
Above code will make sure the `MultiTenantSupport.current_tenant` won't accidentally be reset during integration and system tests. For example:
|
353
|
+
|
354
|
+
With above testing requre code
|
355
|
+
|
356
|
+
```ruby
|
357
|
+
# Integration test
|
358
|
+
test "a integration test" do
|
359
|
+
host! "apple.example.com"
|
360
|
+
|
361
|
+
assert_no_changes "MultiTenantSupport.current_tenant" do
|
362
|
+
get users_path
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
# System test
|
367
|
+
test "a system test" do
|
368
|
+
Capybara.app_host = "http://apple.example.com"
|
369
|
+
|
370
|
+
assert_no_changes "MultiTenantSupport.current_tenant" do
|
371
|
+
visit users_path
|
372
|
+
end
|
373
|
+
end
|
374
|
+
```
|
375
|
+
|
309
376
|
## Code Example
|
310
377
|
|
311
378
|
### Database Schema
|
@@ -340,6 +407,10 @@ MultiTenantSupport.configure do
|
|
340
407
|
config.excluded_subdomains = ['www']
|
341
408
|
config.host = 'example.com'
|
342
409
|
end
|
410
|
+
|
411
|
+
console do |config|
|
412
|
+
config.allow_read_across_tenant_by_default = false
|
413
|
+
end
|
343
414
|
end
|
344
415
|
```
|
345
416
|
|
@@ -12,6 +12,10 @@ MultiTenantSupport.configure do
|
|
12
12
|
config.excluded_subdomains = ['www']
|
13
13
|
config.host = 'REPLACE.ME'
|
14
14
|
end
|
15
|
+
|
16
|
+
console do |config|
|
17
|
+
config.allow_read_across_tenant_by_default = false
|
18
|
+
end
|
15
19
|
end
|
16
20
|
|
17
21
|
# Uncomment if you are using sidekiq without ActiveJob
|
data/lib/multi-tenant-support.rb
CHANGED
@@ -4,6 +4,7 @@ require "multi_tenant_support/errors"
|
|
4
4
|
require "multi_tenant_support/config/app"
|
5
5
|
require "multi_tenant_support/config/controller"
|
6
6
|
require "multi_tenant_support/config/model"
|
7
|
+
require "multi_tenant_support/config/console"
|
7
8
|
require "multi_tenant_support/current"
|
8
9
|
require "multi_tenant_support/find_tenant_account"
|
9
10
|
require "multi_tenant_support/concern/controller_concern"
|
@@ -33,6 +34,10 @@ module MultiTenantSupport
|
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
37
|
+
def allow_read_across_tenant?
|
38
|
+
!disallow_read_across_tenant?
|
39
|
+
end
|
40
|
+
|
36
41
|
def disallow_read_across_tenant?
|
37
42
|
!Current.allow_read_across_tenant
|
38
43
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
module MultiTenantSupport
|
2
|
+
|
2
3
|
module ActiveJob
|
3
4
|
extend ActiveSupport::Concern
|
4
5
|
|
@@ -6,6 +7,40 @@ module MultiTenantSupport
|
|
6
7
|
attr_accessor :current_tenant
|
7
8
|
end
|
8
9
|
|
10
|
+
class_methods do
|
11
|
+
|
12
|
+
if Gem::Version.new(Rails.version) < Gem::Version.new("7.0.0.alpha1")
|
13
|
+
def perform_now(*args)
|
14
|
+
job = job_or_instantiate(*args)
|
15
|
+
job.current_tenant = MultiTenantSupport.current_tenant
|
16
|
+
job.perform_now
|
17
|
+
end
|
18
|
+
else
|
19
|
+
eval("
|
20
|
+
def perform_now(...)
|
21
|
+
job = job_or_instantiate(...)
|
22
|
+
job.current_tenant = MultiTenantSupport.current_tenant
|
23
|
+
job.perform_now
|
24
|
+
end
|
25
|
+
")
|
26
|
+
end
|
27
|
+
|
28
|
+
def execute(job_data)
|
29
|
+
keep_current_tenant_unchange do
|
30
|
+
super(job_data)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def keep_current_tenant_unchange
|
37
|
+
_current_tenant = MultiTenantSupport::Current.tenant_account
|
38
|
+
yield
|
39
|
+
ensure
|
40
|
+
MultiTenantSupport::Current.tenant_account = _current_tenant
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
9
44
|
def perform_now
|
10
45
|
MultiTenantSupport.under_tenant(current_tenant) do
|
11
46
|
super
|
@@ -43,6 +78,25 @@ module MultiTenantSupport
|
|
43
78
|
tenant_klass.find tenant_id
|
44
79
|
end
|
45
80
|
end
|
81
|
+
|
82
|
+
module ConfiguredJob
|
83
|
+
if Gem::Version.new(Rails.version) < Gem::Version.new("7.0.0.alpha1")
|
84
|
+
def perform_now(*args)
|
85
|
+
job = @job_class.new(*args)
|
86
|
+
job.current_tenant = MultiTenantSupport.current_tenant
|
87
|
+
job.perform_now
|
88
|
+
end
|
89
|
+
else
|
90
|
+
eval("
|
91
|
+
def perform_now(...)
|
92
|
+
job = @job_class.new(...)
|
93
|
+
job.current_tenant = MultiTenantSupport.current_tenant
|
94
|
+
job.perform_now
|
95
|
+
end
|
96
|
+
")
|
97
|
+
end
|
98
|
+
end
|
46
99
|
end
|
47
100
|
|
48
|
-
ActiveJob::Base.include(MultiTenantSupport::ActiveJob)
|
101
|
+
ActiveJob::Base.include(MultiTenantSupport::ActiveJob)
|
102
|
+
ActiveJob::ConfiguredJob.prepend(MultiTenantSupport::ConfiguredJob)
|
@@ -10,10 +10,6 @@ module MultiTenantSupport
|
|
10
10
|
|
11
11
|
private
|
12
12
|
|
13
|
-
define_method(MultiTenantSupport.current_tenant_account_method) do
|
14
|
-
instance_variable_get("@#{MultiTenantSupport.current_tenant_account_method}")
|
15
|
-
end
|
16
|
-
|
17
13
|
def set_current_tenant_account
|
18
14
|
tenant_account = find_current_tenant_account
|
19
15
|
MultiTenantSupport::Current.tenant_account = tenant_account
|
@@ -31,8 +27,12 @@ module MultiTenantSupport
|
|
31
27
|
end
|
32
28
|
|
33
29
|
module ViewHelper
|
34
|
-
|
35
|
-
|
30
|
+
extend ActiveSupport::Concern
|
31
|
+
|
32
|
+
included do
|
33
|
+
define_method(MultiTenantSupport.current_tenant_account_method) do
|
34
|
+
instance_variable_get("@#{MultiTenantSupport.current_tenant_account_method}")
|
35
|
+
end
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module MultiTenantSupport
|
2
|
+
|
3
|
+
module Config
|
4
|
+
class Console
|
5
|
+
attr_writer :allow_read_across_tenant_by_default
|
6
|
+
|
7
|
+
def allow_read_across_tenant_by_default
|
8
|
+
@allow_read_across_tenant_by_default ||= false
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module_function
|
14
|
+
def console
|
15
|
+
@console ||= Config::Console.new
|
16
|
+
return @console unless block_given?
|
17
|
+
|
18
|
+
yield @console
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
require_relative "./test/integration"
|
2
|
+
require_relative "./test/system"
|
3
|
+
require_relative "./test/capybara"
|
4
|
+
|
5
|
+
ActionDispatch::IntegrationTest.prepend(MultiTenantSupport::Test::Integration)
|
6
|
+
ActionDispatch::SystemTestCase.prepend(MultiTenantSupport::Test::System)
|
7
|
+
Capybara::Node::Element.prepend(MultiTenantSupport::Test::Capybara)
|
@@ -9,5 +9,13 @@ module MultiTenantSupport
|
|
9
9
|
config.app_generators.templates.unshift(active_record_templates)
|
10
10
|
end
|
11
11
|
|
12
|
+
console do
|
13
|
+
if ENV["ALLOW_READ_ACROSS_TENANT"] || MultiTenantSupport.console.allow_read_across_tenant_by_default
|
14
|
+
MultiTenantSupport.allow_read_across_tenant
|
15
|
+
else
|
16
|
+
MultiTenantSupport.disallow_read_across_tenant
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
12
20
|
end
|
13
21
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative "./test/integration"
|
2
|
+
require_relative "./test/system"
|
3
|
+
require_relative "./test/capybara"
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
config.include MultiTenantSupport::Test::Integration, type: :request
|
7
|
+
config.include MultiTenantSupport::Test::Integration, type: :controller
|
8
|
+
|
9
|
+
config.include MultiTenantSupport::Test::System, type: :system
|
10
|
+
config.include MultiTenantSupport::Test::System, type: :feature
|
11
|
+
end
|
12
|
+
|
13
|
+
Capybara::Node::Element.prepend(MultiTenantSupport::Test::Capybara)
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module MultiTenantSupport
|
2
|
+
module Test
|
3
|
+
module Capybara
|
4
|
+
|
5
|
+
def set(value, **options)
|
6
|
+
keep_context_tenant_unchange do
|
7
|
+
super(value, **options)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def select_option(wait: nil)
|
12
|
+
keep_context_tenant_unchange do
|
13
|
+
super(wait: wait)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def unselect_option(wait: nil)
|
18
|
+
keep_context_tenant_unchange do
|
19
|
+
super(wait: wait)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def perform_click_action(keys, wait: nil, **options)
|
24
|
+
keep_context_tenant_unchange do
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def trigger(event)
|
30
|
+
keep_context_tenant_unchange do
|
31
|
+
super
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def evaluate_script(script, *args)
|
36
|
+
keep_context_tenant_unchange do
|
37
|
+
super
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def evaluate_async_script(script, *args)
|
42
|
+
keep_context_tenant_unchange do
|
43
|
+
super
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def keep_context_tenant_unchange
|
48
|
+
_current_tenant = MultiTenantSupport::Current.tenant_account
|
49
|
+
MultiTenantSupport::Current.tenant_account = nil # Simulate real circumstance
|
50
|
+
yield
|
51
|
+
ensure
|
52
|
+
MultiTenantSupport::Current.tenant_account = _current_tenant
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module MultiTenantSupport
|
2
|
+
module Test
|
3
|
+
module Integration
|
4
|
+
|
5
|
+
%i[get post patch put delete head options].each do |method|
|
6
|
+
define_method method do |path, **args|
|
7
|
+
keep_context_tenant_unchange do
|
8
|
+
super(path, **args)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def follow_redirect(**args)
|
14
|
+
keep_context_tenant_unchange do
|
15
|
+
super(**args)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def keep_context_tenant_unchange
|
20
|
+
_current_tenant = MultiTenantSupport::Current.tenant_account
|
21
|
+
MultiTenantSupport::Current.tenant_account = nil # Simulate real circumstance
|
22
|
+
yield
|
23
|
+
ensure
|
24
|
+
MultiTenantSupport::Current.tenant_account = _current_tenant
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module MultiTenantSupport
|
2
|
+
module Test
|
3
|
+
module System
|
4
|
+
|
5
|
+
%i[
|
6
|
+
visit refresh click_on go_back go_forward
|
7
|
+
check choose click_button click_link
|
8
|
+
fill_in uncheck check unselect select
|
9
|
+
execute_script evaluate_script
|
10
|
+
].each do |method|
|
11
|
+
if RUBY_VERSION >= '2.7'
|
12
|
+
class_eval <<~METHOD, __FILE__, __LINE__ + 1
|
13
|
+
def #{method}(...)
|
14
|
+
keep_context_tenant_unchange do
|
15
|
+
super(...)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
METHOD
|
19
|
+
else
|
20
|
+
define_method method do |*args, &block|
|
21
|
+
keep_context_tenant_unchange do
|
22
|
+
super(*args, &block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def keep_context_tenant_unchange
|
29
|
+
_current_tenant = MultiTenantSupport::Current.tenant_account
|
30
|
+
MultiTenantSupport::Current.tenant_account = nil # Simulate real circumstance
|
31
|
+
yield
|
32
|
+
ensure
|
33
|
+
MultiTenantSupport::Current.tenant_account = _current_tenant
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: multi-tenant-support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1
|
4
|
+
version: 1.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hopper Gee
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-10-
|
11
|
+
date: 2021-10-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -45,13 +45,19 @@ files:
|
|
45
45
|
- lib/multi_tenant_support/concern/controller_concern.rb
|
46
46
|
- lib/multi_tenant_support/concern/model_concern.rb
|
47
47
|
- lib/multi_tenant_support/config/app.rb
|
48
|
+
- lib/multi_tenant_support/config/console.rb
|
48
49
|
- lib/multi_tenant_support/config/controller.rb
|
49
50
|
- lib/multi_tenant_support/config/model.rb
|
50
51
|
- lib/multi_tenant_support/current.rb
|
51
52
|
- lib/multi_tenant_support/errors.rb
|
52
53
|
- lib/multi_tenant_support/find_tenant_account.rb
|
54
|
+
- lib/multi_tenant_support/minitest.rb
|
53
55
|
- lib/multi_tenant_support/railtie.rb
|
56
|
+
- lib/multi_tenant_support/rspec.rb
|
54
57
|
- lib/multi_tenant_support/sidekiq.rb
|
58
|
+
- lib/multi_tenant_support/test/capybara.rb
|
59
|
+
- lib/multi_tenant_support/test/integration.rb
|
60
|
+
- lib/multi_tenant_support/test/system.rb
|
55
61
|
- lib/multi_tenant_support/version.rb
|
56
62
|
- lib/tasks/multi_tenant_support_tasks.rake
|
57
63
|
homepage: https://github.com/hoppergee/multi-tenant-support
|