tenantify 0.0.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.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +166 -0
  7. data/Rakefile +2 -0
  8. data/lib/tenantify.rb +57 -0
  9. data/lib/tenantify/configuration.rb +25 -0
  10. data/lib/tenantify/middleware.rb +40 -0
  11. data/lib/tenantify/middleware/builder.rb +63 -0
  12. data/lib/tenantify/middleware/strategies.rb +57 -0
  13. data/lib/tenantify/middleware/strategies/default.rb +46 -0
  14. data/lib/tenantify/middleware/strategies/header.rb +52 -0
  15. data/lib/tenantify/middleware/strategies/host.rb +57 -0
  16. data/lib/tenantify/resource.rb +28 -0
  17. data/lib/tenantify/tenant.rb +44 -0
  18. data/lib/tenantify/version.rb +5 -0
  19. data/spec/integration/manual_tenant_selection_spec.rb +16 -0
  20. data/spec/integration/middleware/custom_strategy.rb +40 -0
  21. data/spec/integration/middleware/many_strategies.rb +35 -0
  22. data/spec/integration/middleware/one_strategy_spec.rb +36 -0
  23. data/spec/integration/middleware/using_resources_spec.rb +48 -0
  24. data/spec/integration/resources_spec.rb +16 -0
  25. data/spec/spec_helper.rb +29 -0
  26. data/spec/tenantify/configuration_spec.rb +19 -0
  27. data/spec/tenantify/middleware/builder_spec.rb +66 -0
  28. data/spec/tenantify/middleware/strategies/default_spec.rb +17 -0
  29. data/spec/tenantify/middleware/strategies/header_spec.rb +27 -0
  30. data/spec/tenantify/middleware/strategies/host_spec.rb +32 -0
  31. data/spec/tenantify/middleware/strategies_spec.rb +41 -0
  32. data/spec/tenantify/middleware_spec.rb +37 -0
  33. data/spec/tenantify/resource_spec.rb +41 -0
  34. data/spec/tenantify/tenant_spec.rb +43 -0
  35. data/spec/tenantify/version_spec.rb +9 -0
  36. data/spec/tenantify_spec.rb +7 -0
  37. data/tenantify.gemspec +24 -0
  38. metadata +154 -0
@@ -0,0 +1,19 @@
1
+ require 'tenantify/configuration'
2
+
3
+ RSpec.describe Tenantify::Configuration do
4
+
5
+ subject { described_class.new }
6
+
7
+ describe '#strategy and #strategies' do
8
+ it 'stores all strategies and configuration' do
9
+ subject.strategy :strategy_1, :strategy_config_1
10
+ subject.strategy :strategy_2, :strategy_config_2
11
+
12
+ expect(subject.strategies).to eq [
13
+ [:strategy_1, :strategy_config_1],
14
+ [:strategy_2, :strategy_config_2]
15
+ ]
16
+ end
17
+ end
18
+
19
+ end
@@ -0,0 +1,66 @@
1
+ require 'tenantify/middleware/builder'
2
+
3
+ RSpec.describe Tenantify::Middleware::Builder do
4
+
5
+ let(:strategies_config) { [] }
6
+ let(:config) { double 'config', :strategies => strategies_config }
7
+
8
+ let(:known_strategies) { {} }
9
+
10
+ subject { described_class.new config, known_strategies: known_strategies }
11
+
12
+ let(:strategies_class) { Tenantify::Middleware::Strategies }
13
+ let(:strategies) { double 'strategies' }
14
+
15
+ describe '#call' do
16
+ context 'with a known strategy' do
17
+ let(:known_strategy_class) { double 'known_strategy_class' }
18
+ let(:known_strategy) { double 'known_strategy' }
19
+ let(:known_config) { double 'known_config' }
20
+
21
+ let(:strategies_config) { [[:known, known_config]] }
22
+ let(:known_strategies) { {:known => known_strategy_class} }
23
+
24
+ it 'builds it properly' do
25
+ expect(known_strategy_class).to receive(:new).
26
+ with(known_config).and_return(known_strategy)
27
+
28
+ expect(strategies_class).to receive :new do |arg|
29
+ expect(arg).to eq [known_strategy]
30
+ strategies
31
+ end
32
+
33
+ expect(subject.call).to eq strategies
34
+ end
35
+ end
36
+
37
+ context 'with a given strategy' do
38
+ let(:given_strategy_class) { Struct.new(:config) }
39
+ let(:given_config) { double 'given_config' }
40
+
41
+ let(:strategies_config) { [[given_strategy_class, given_config]] }
42
+
43
+ it 'builds it properly' do
44
+ expected_strategy = given_strategy_class.new(given_config)
45
+
46
+ expect(strategies_class).to receive :new do |arg|
47
+ expect(arg).to eq [expected_strategy]
48
+ strategies
49
+ end
50
+
51
+ expect(subject.call).to eq strategies
52
+ end
53
+ end
54
+
55
+ context 'with an unknown strategy' do
56
+ let(:strategies_config) { [[123, {}]] }
57
+
58
+ it 'raises error' do
59
+ expected_error = described_class::UnknownStrategyError
60
+
61
+ expect { subject.call }.to raise_error expected_error
62
+ end
63
+ end
64
+ end
65
+
66
+ end
@@ -0,0 +1,17 @@
1
+ require 'tenantify/middleware/strategies/default'
2
+
3
+ RSpec.describe Tenantify::Middleware::Strategies::Default do
4
+
5
+ let(:config) { {:tenant => 'the_tenant'} }
6
+
7
+ subject { described_class.new config }
8
+
9
+ describe '#tenant_for' do
10
+ let(:env) { double 'env' }
11
+
12
+ it 'returns the same tenant for any env' do
13
+ expect(subject.tenant_for(env)).to eq :the_tenant
14
+ end
15
+ end
16
+
17
+ end
@@ -0,0 +1,27 @@
1
+ require 'tenantify/middleware/strategies/header'
2
+
3
+ RSpec.describe Tenantify::Middleware::Strategies::Header do
4
+
5
+ let(:config) { {:name => 'X-Tenant'} }
6
+
7
+ subject { described_class.new config }
8
+
9
+ describe '#tenant_for' do
10
+ context 'when the header exists' do
11
+ let(:env) { {'X-Tenant' => 'the_tenant'} }
12
+
13
+ it 'returns the header content' do
14
+ expect(subject.tenant_for(env)).to eq :the_tenant
15
+ end
16
+ end
17
+
18
+ context 'when there is no header' do
19
+ let(:env) { {'Another-Header' => 'a_value'} }
20
+
21
+ it 'returns nil' do
22
+ expect(subject.tenant_for(env)).to be_nil
23
+ end
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,32 @@
1
+ require 'tenantify/middleware/strategies/host'
2
+
3
+ RSpec.describe Tenantify::Middleware::Strategies::Host do
4
+
5
+ let :config do
6
+ {
7
+ 'tenant_1' => ['www.host_a.com', 'www.host_b.com'],
8
+ 'tenant_2' => ['www.host_c.com', 'www.host_d.com']
9
+ }
10
+ end
11
+
12
+ subject { described_class.new config }
13
+
14
+ describe '#tenant_for' do
15
+ context 'with a valid host' do
16
+ let(:env) { {"SERVER_NAME" => 'www.host_c.com'} }
17
+
18
+ it 'chooses the proper tenant' do
19
+ expect(subject.tenant_for(env)).to eq :tenant_2
20
+ end
21
+ end
22
+
23
+ context 'with an invalid host' do
24
+ let(:env) { {"SERVER_NAME" => 'www.another_host.com'} }
25
+
26
+ it 'returns nil' do
27
+ expect(subject.tenant_for(env)).to be_nil
28
+ end
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,41 @@
1
+ require 'tenantify/middleware/strategies'
2
+
3
+ RSpec.describe Tenantify::Middleware::Strategies do
4
+
5
+ let(:strategies) { [] }
6
+
7
+ subject { described_class.new strategies }
8
+
9
+ describe '#tenant_for' do
10
+ let(:env) { double 'env' }
11
+
12
+ context 'when some strategy matches' do
13
+ let(:strategy_1) { double 'strategy_1' }
14
+ let(:strategy_2) { double 'strategy_2' }
15
+ let(:strategy_3) { double 'strategy_2' }
16
+
17
+ let(:strategies) { [strategy_1, strategy_2, strategy_3] }
18
+
19
+ it 'does not check remaining strategies' do
20
+ expect(strategy_1).to receive(:tenant_for).
21
+ with(env).and_return(nil)
22
+
23
+ expect(strategy_2).to receive(:tenant_for).
24
+ with(env).and_return(:a_tenant)
25
+
26
+ expect(strategy_3).not_to receive(:tenant_for)
27
+
28
+ expect(subject.tenant_for(env)).to eq :a_tenant
29
+ end
30
+ end
31
+
32
+ context 'when none strategy matches' do
33
+ let(:error) { described_class::NotMatchingStrategyError }
34
+
35
+ it 'raises error' do
36
+ expect{subject.tenant_for(env)}.to raise_error error
37
+ end
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,37 @@
1
+ require 'tenantify/middleware'
2
+
3
+ RSpec.describe Tenantify::Middleware do
4
+
5
+ let(:app) { double 'app' }
6
+ let(:config) { double 'config' }
7
+
8
+ subject { described_class.new app, config }
9
+
10
+ let(:strategies) { double 'strategies' }
11
+ let(:builder) { double 'builder', :call => strategies }
12
+
13
+ before do
14
+ allow(described_class::Builder).to receive(:new).
15
+ with(config).and_return(builder)
16
+ end
17
+
18
+ describe '#call' do
19
+ let(:env) { double 'env' }
20
+ let(:response) { double 'response' }
21
+
22
+ it 'calls the app with the proper tenant' do
23
+ expect(strategies).to receive(:tenant_for).
24
+ with(env).and_return(:a_tenant)
25
+
26
+ expect(app).to receive :call do |given_env|
27
+ expect(given_env).to eq env
28
+ expect(Tenantify::Tenant.current).to eq :a_tenant
29
+
30
+ response
31
+ end
32
+
33
+ expect(subject.call(env)).to eq response
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,41 @@
1
+ require 'tenantify/resource'
2
+
3
+ RSpec.describe Tenantify::Resource do
4
+
5
+ let(:tenant_1) { double 'tenant_1' }
6
+ let(:tenant_2) { double 'tenant_2' }
7
+
8
+ let(:resource_1) { double 'resource_1' }
9
+ let(:resource_2) { double 'resource_2' }
10
+
11
+ let :correspondence do
12
+ { tenant_1 => resource_1, tenant_2 => resource_2 }
13
+ end
14
+
15
+ subject { described_class.new correspondence }
16
+
17
+ describe '#current' do
18
+ it 'returns the current resource' do
19
+ Tenantify::Tenant.using tenant_2 do
20
+ expect(subject.current).to eq resource_2
21
+ end
22
+ end
23
+ end
24
+
25
+ describe '#all' do
26
+ it 'returns the correspondence' do
27
+ expect(subject.all).to eq correspondence
28
+ end
29
+ end
30
+
31
+ describe 'enumerable' do
32
+ let :expected_collection do
33
+ [ [tenant_1, resource_1], [tenant_2, resource_2] ]
34
+ end
35
+
36
+ it 'is a collection of resources' do
37
+ expect(subject.to_a).to eq expected_collection
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,43 @@
1
+ require 'tenantify/tenant'
2
+
3
+ RSpec.describe Tenantify::Tenant do
4
+
5
+ subject { Tenantify::Tenant }
6
+
7
+ def current_tenant
8
+ Thread.current.thread_variable_get(:tenant)
9
+ end
10
+
11
+ def set_tenant tenant
12
+ Thread.current.thread_variable_set(:tenant, tenant)
13
+ end
14
+
15
+ describe '.using' do
16
+ it 'changes the current tenant in the block' do
17
+ set_tenant 'original_value'
18
+
19
+ subject.using 'another_tenant' do
20
+ expect(current_tenant).to eq 'another_tenant'
21
+ end
22
+
23
+ expect(current_tenant).to eq 'original_value'
24
+ end
25
+ end
26
+
27
+ describe '.use!' do
28
+ it 'changes the current tenant permanently' do
29
+ subject.use! 'a_tenant'
30
+
31
+ expect(current_tenant).to eq 'a_tenant'
32
+ end
33
+ end
34
+
35
+ describe '.current' do
36
+ it 'returns the current tenant' do
37
+ set_tenant 'the_tenant'
38
+
39
+ expect(subject.current).to eq current_tenant
40
+ end
41
+ end
42
+
43
+ end
@@ -0,0 +1,9 @@
1
+ RSpec.describe Tenantify::VERSION do
2
+
3
+ subject { Tenantify::VERSION }
4
+
5
+ it 'has semantic format' do
6
+ expect(subject).to match /\A\d+\.\d+\.\d+\z/
7
+ end
8
+
9
+ end
@@ -0,0 +1,7 @@
1
+ require 'tenantify'
2
+
3
+ RSpec.describe Tenantify do
4
+
5
+ subject { Tenantify }
6
+
7
+ end
data/tenantify.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'tenantify/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "tenantify"
8
+ spec.version = Tenantify::VERSION
9
+ spec.authors = ["Jaime Cabot Campins"]
10
+ spec.email = ["jcabot@gmail.com"]
11
+ spec.summary = %q{It provides support for managing tenants on Rack applications}
12
+ spec.homepage = ""
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.7"
21
+ spec.add_development_dependency "rake", "~> 10.0"
22
+ spec.add_development_dependency "rspec"
23
+ spec.add_development_dependency "pry"
24
+ end
metadata ADDED
@@ -0,0 +1,154 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tenantify
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jaime Cabot Campins
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description:
70
+ email:
71
+ - jcabot@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - .rspec
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - lib/tenantify.rb
83
+ - lib/tenantify/configuration.rb
84
+ - lib/tenantify/middleware.rb
85
+ - lib/tenantify/middleware/builder.rb
86
+ - lib/tenantify/middleware/strategies.rb
87
+ - lib/tenantify/middleware/strategies/default.rb
88
+ - lib/tenantify/middleware/strategies/header.rb
89
+ - lib/tenantify/middleware/strategies/host.rb
90
+ - lib/tenantify/resource.rb
91
+ - lib/tenantify/tenant.rb
92
+ - lib/tenantify/version.rb
93
+ - spec/integration/manual_tenant_selection_spec.rb
94
+ - spec/integration/middleware/custom_strategy.rb
95
+ - spec/integration/middleware/many_strategies.rb
96
+ - spec/integration/middleware/one_strategy_spec.rb
97
+ - spec/integration/middleware/using_resources_spec.rb
98
+ - spec/integration/resources_spec.rb
99
+ - spec/spec_helper.rb
100
+ - spec/tenantify/configuration_spec.rb
101
+ - spec/tenantify/middleware/builder_spec.rb
102
+ - spec/tenantify/middleware/strategies/default_spec.rb
103
+ - spec/tenantify/middleware/strategies/header_spec.rb
104
+ - spec/tenantify/middleware/strategies/host_spec.rb
105
+ - spec/tenantify/middleware/strategies_spec.rb
106
+ - spec/tenantify/middleware_spec.rb
107
+ - spec/tenantify/resource_spec.rb
108
+ - spec/tenantify/tenant_spec.rb
109
+ - spec/tenantify/version_spec.rb
110
+ - spec/tenantify_spec.rb
111
+ - tenantify.gemspec
112
+ homepage: ''
113
+ licenses:
114
+ - MIT
115
+ metadata: {}
116
+ post_install_message:
117
+ rdoc_options: []
118
+ require_paths:
119
+ - lib
120
+ required_ruby_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - '>='
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ requirements: []
131
+ rubyforge_project:
132
+ rubygems_version: 2.2.2
133
+ signing_key:
134
+ specification_version: 4
135
+ summary: It provides support for managing tenants on Rack applications
136
+ test_files:
137
+ - spec/integration/manual_tenant_selection_spec.rb
138
+ - spec/integration/middleware/custom_strategy.rb
139
+ - spec/integration/middleware/many_strategies.rb
140
+ - spec/integration/middleware/one_strategy_spec.rb
141
+ - spec/integration/middleware/using_resources_spec.rb
142
+ - spec/integration/resources_spec.rb
143
+ - spec/spec_helper.rb
144
+ - spec/tenantify/configuration_spec.rb
145
+ - spec/tenantify/middleware/builder_spec.rb
146
+ - spec/tenantify/middleware/strategies/default_spec.rb
147
+ - spec/tenantify/middleware/strategies/header_spec.rb
148
+ - spec/tenantify/middleware/strategies/host_spec.rb
149
+ - spec/tenantify/middleware/strategies_spec.rb
150
+ - spec/tenantify/middleware_spec.rb
151
+ - spec/tenantify/resource_spec.rb
152
+ - spec/tenantify/tenant_spec.rb
153
+ - spec/tenantify/version_spec.rb
154
+ - spec/tenantify_spec.rb