mongoid-multitenancy-forked 1.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 (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +12 -0
  5. data/CHANGELOG.md +56 -0
  6. data/Gemfile +15 -0
  7. data/LICENSE.TXT +20 -0
  8. data/README.md +284 -0
  9. data/Rakefile +8 -0
  10. data/gemfiles/Gemfile.mongoid-6 +14 -0
  11. data/gemfiles/Gemfile.mongoid-7 +14 -0
  12. data/lib/mongoid/multitenancy/document.rb +176 -0
  13. data/lib/mongoid/multitenancy/validators/tenancy.rb +36 -0
  14. data/lib/mongoid/multitenancy/validators/tenant_uniqueness.rb +67 -0
  15. data/lib/mongoid/multitenancy/version.rb +6 -0
  16. data/lib/mongoid/multitenancy.rb +34 -0
  17. data/lib/mongoid-multitenancy-forked.rb +1 -0
  18. data/mongoid-multitenancy-forked.gemspec +19 -0
  19. data/spec/immutable_spec.rb +46 -0
  20. data/spec/indexable_spec.rb +70 -0
  21. data/spec/inheritance_spec.rb +22 -0
  22. data/spec/mandatory_spec.rb +116 -0
  23. data/spec/models/account.rb +5 -0
  24. data/spec/models/immutable.rb +15 -0
  25. data/spec/models/indexable.rb +61 -0
  26. data/spec/models/mandatory.rb +15 -0
  27. data/spec/models/mutable.rb +15 -0
  28. data/spec/models/mutable_child.rb +9 -0
  29. data/spec/models/no_scopable.rb +11 -0
  30. data/spec/models/optional.rb +15 -0
  31. data/spec/models/optional_exclude.rb +15 -0
  32. data/spec/mongoid-multitenancy_spec.rb +37 -0
  33. data/spec/mutable_child_spec.rb +46 -0
  34. data/spec/mutable_spec.rb +50 -0
  35. data/spec/optional_exclude_spec.rb +71 -0
  36. data/spec/optional_spec.rb +207 -0
  37. data/spec/scopable_spec.rb +29 -0
  38. data/spec/spec_helper.rb +44 -0
  39. data/spec/support/mongoid_matchers.rb +17 -0
  40. data/spec/support/shared_examples.rb +80 -0
  41. metadata +125 -0
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutable do
4
+ let(:client) do
5
+ Account.create!(name: 'client')
6
+ end
7
+
8
+ let(:another_client) do
9
+ Account.create!(name: 'another client')
10
+ end
11
+
12
+ let(:item) do
13
+ Mutable.new(title: 'title X', slug: 'page-x')
14
+ end
15
+
16
+ it_behaves_like 'a tenantable model'
17
+
18
+ describe '#valid?' do
19
+ before do
20
+ Mongoid::Multitenancy.current_tenant = client
21
+ end
22
+
23
+ after do
24
+ Mongoid::Multitenancy.current_tenant = nil
25
+ end
26
+
27
+ context 'when the tenant has not changed' do
28
+ before do
29
+ item.save!
30
+ end
31
+
32
+ it 'is valid' do
33
+ item.title = 'title X (2)'
34
+ expect(item).to be_valid
35
+ end
36
+ end
37
+
38
+ context 'when the tenant has changed' do
39
+ before do
40
+ item.save!
41
+ Mongoid::Multitenancy.current_tenant = another_client
42
+ end
43
+
44
+ it 'is valid' do
45
+ item.tenant = another_client
46
+ expect(item).to be_valid
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe OptionalExclude do
4
+ let(:client) do
5
+ Account.create!(name: 'client')
6
+ end
7
+
8
+ let(:another_client) do
9
+ Account.create!(name: 'another client')
10
+ end
11
+
12
+ let(:item) do
13
+ OptionalExclude.new(title: 'title X', slug: 'page-x')
14
+ end
15
+
16
+ it_behaves_like 'a tenantable model'
17
+
18
+ describe '#valid?' do
19
+ context 'with a tenant' do
20
+ before do
21
+ Mongoid::Multitenancy.current_tenant = client
22
+ end
23
+
24
+ it 'is valid' do
25
+ expect(item).to be_valid
26
+ end
27
+
28
+ context 'with a uniqueness constraint' do
29
+ let(:duplicate) do
30
+ OptionalExclude.new(title: 'title Y', slug: 'page-x')
31
+ end
32
+
33
+ before do
34
+ item.save!
35
+ end
36
+
37
+ it 'does not allow duplicates on the same tenant' do
38
+ expect(duplicate).not_to be_valid
39
+ end
40
+
41
+ it 'allow duplicates on a different same tenant' do
42
+ Mongoid::Multitenancy.with_tenant(another_client) do
43
+ expect(duplicate).to be_valid
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ context 'without a tenant' do
50
+ it 'is valid' do
51
+ expect(item).to be_valid
52
+ end
53
+
54
+ context 'with a uniqueness constraint' do
55
+ let(:duplicate) do
56
+ OptionalExclude.new(title: 'title Y', slug: 'page-x')
57
+ end
58
+
59
+ before do
60
+ item.save!
61
+ end
62
+
63
+ it 'allow duplicates on any client' do
64
+ Mongoid::Multitenancy.with_tenant(client) do
65
+ expect(duplicate).to be_valid
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,207 @@
1
+ require 'spec_helper'
2
+
3
+ describe Optional do
4
+ let(:client) do
5
+ Account.create!(name: 'client')
6
+ end
7
+
8
+ let(:another_client) do
9
+ Account.create!(name: 'another client')
10
+ end
11
+
12
+ let(:item) do
13
+ Optional.new(title: 'title X', slug: 'page-x')
14
+ end
15
+
16
+ it_behaves_like 'a tenantable model'
17
+ it { is_expected.to validate_tenant_uniqueness_of(:slug) }
18
+
19
+ describe '#initialize' do
20
+ context 'within a client context' do
21
+ before do
22
+ Mongoid::Multitenancy.current_tenant = client
23
+ end
24
+
25
+ context 'when persisted' do
26
+ before do
27
+ item.tenant = nil
28
+ item.save!
29
+ end
30
+
31
+ it 'does not override the client' do
32
+ item.reload
33
+ expect(Optional.last.tenant).to be_nil
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ describe '.default_scope' do
40
+ let!(:item_a) do
41
+ Mongoid::Multitenancy.with_tenant(client) do
42
+ Optional.create!(title: 'title A', slug: 'article-a')
43
+ end
44
+ end
45
+
46
+ let!(:item_b) do
47
+ Mongoid::Multitenancy.with_tenant(another_client) do
48
+ Optional.create!(title: 'title B', slug: 'article-b')
49
+ end
50
+ end
51
+
52
+ let!(:shared_item) do
53
+ Optional.create!(title: 'title C', slug: 'article-c')
54
+ end
55
+
56
+ context 'with a current tenant' do
57
+ it 'filters on the current tenant / free-tenant items' do
58
+ Mongoid::Multitenancy.with_tenant(another_client) do
59
+ expect(Optional.all.to_a).to match_array [shared_item, item_b]
60
+ end
61
+ end
62
+ end
63
+
64
+ context 'without a current tenant' do
65
+ it 'does not filter on any tenant' do
66
+ expect(Optional.all.to_a).to match_array [item_a, item_b, shared_item]
67
+ end
68
+ end
69
+ end
70
+
71
+ describe '.shared' do
72
+ let!(:item_a) do
73
+ Mongoid::Multitenancy.with_tenant(client) do
74
+ Optional.create!(title: 'title A', slug: 'article-a')
75
+ end
76
+ end
77
+
78
+ let!(:item_b) do
79
+ Mongoid::Multitenancy.with_tenant(another_client) do
80
+ Optional.create!(title: 'title B', slug: 'article-b')
81
+ end
82
+ end
83
+
84
+ let!(:shared_item) do
85
+ Optional.create!(title: 'title C', slug: 'article-c')
86
+ end
87
+
88
+ it 'returns only the shared items' do
89
+ Mongoid::Multitenancy.with_tenant(another_client) do
90
+ expect(Optional.shared.to_a).to match_array [shared_item]
91
+ end
92
+ end
93
+ end
94
+
95
+ describe '.unshared' do
96
+ let!(:item_a) do
97
+ Mongoid::Multitenancy.with_tenant(client) do
98
+ Optional.create!(title: 'title A', slug: 'article-a')
99
+ end
100
+ end
101
+
102
+ let!(:item_b) do
103
+ Mongoid::Multitenancy.with_tenant(another_client) do
104
+ Optional.create!(title: 'title B', slug: 'article-b')
105
+ end
106
+ end
107
+
108
+ let!(:shared_item) do
109
+ Optional.create!(title: 'title C', slug: 'article-c')
110
+ end
111
+
112
+ it 'returns only the shared items' do
113
+ Mongoid::Multitenancy.with_tenant(another_client) do
114
+ expect(Optional.unshared.to_a).to match_array [item_b]
115
+ end
116
+ end
117
+ end
118
+
119
+ describe '#delete_all' do
120
+ let!(:item_a) do
121
+ Mongoid::Multitenancy.with_tenant(client) do
122
+ Optional.create!(title: 'title A', slug: 'article-a')
123
+ end
124
+ end
125
+
126
+ let!(:item_b) do
127
+ Mongoid::Multitenancy.with_tenant(another_client) do
128
+ Optional.create!(title: 'title B', slug: 'article-b')
129
+ end
130
+ end
131
+
132
+ let!(:shared_item) do
133
+ Optional.create!(title: 'title C', slug: 'article-c')
134
+ end
135
+
136
+ context 'with a current tenant' do
137
+ it 'only deletes the current tenant / free-tenant items' do
138
+ Mongoid::Multitenancy.with_tenant(another_client) do
139
+ Optional.delete_all
140
+ end
141
+
142
+ expect(Optional.all.to_a).to match_array [item_a]
143
+ end
144
+ end
145
+
146
+ context 'without a current tenant' do
147
+ it 'deletes all the pages' do
148
+ Optional.delete_all
149
+ expect(Optional.all.to_a).to be_empty
150
+ end
151
+ end
152
+ end
153
+
154
+ describe '#valid?' do
155
+ context 'with a tenant' do
156
+ before do
157
+ Mongoid::Multitenancy.current_tenant = client
158
+ end
159
+
160
+ it 'is valid' do
161
+ expect(item).to be_valid
162
+ end
163
+
164
+ context 'with a uniqueness constraint' do
165
+ let(:duplicate) do
166
+ Optional.new(title: 'title Y', slug: 'page-x')
167
+ end
168
+
169
+ before do
170
+ item.save!
171
+ end
172
+
173
+ it 'does not allow duplicates on the same tenant' do
174
+ expect(duplicate).not_to be_valid
175
+ end
176
+
177
+ it 'allow duplicates on a different same tenant' do
178
+ Mongoid::Multitenancy.with_tenant(another_client) do
179
+ expect(duplicate).to be_valid
180
+ end
181
+ end
182
+ end
183
+ end
184
+
185
+ context 'without a tenant' do
186
+ it 'is valid' do
187
+ expect(item).to be_valid
188
+ end
189
+
190
+ context 'with a uniqueness constraint' do
191
+ let(:duplicate) do
192
+ Optional.new(title: 'title Y', slug: 'page-x')
193
+ end
194
+
195
+ before do
196
+ item.save!
197
+ end
198
+
199
+ it 'does not allow duplicates on any client' do
200
+ Mongoid::Multitenancy.with_tenant(client) do
201
+ expect(duplicate).not_to be_valid
202
+ end
203
+ end
204
+ end
205
+ end
206
+ end
207
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe NoScopable do
4
+ it_behaves_like 'a tenantable model' do
5
+ let(:client) do
6
+ Account.create!(name: 'client')
7
+ end
8
+
9
+ let(:another_client) do
10
+ Account.create!(name: 'another client')
11
+ end
12
+
13
+ let(:item) do
14
+ NoScopable.new(title: 'title X', slug: 'page-x')
15
+ end
16
+ end
17
+
18
+ describe '.shared' do
19
+ it 'is not defined' do
20
+ expect(NoScopable).not_to respond_to(:shared)
21
+ end
22
+ end
23
+
24
+ describe '.unshared' do
25
+ it 'is not defined' do
26
+ expect(NoScopable).not_to respond_to(:unshared)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,44 @@
1
+ MODELS = File.join(File.dirname(__FILE__), 'models')
2
+
3
+ require 'simplecov'
4
+ require 'coveralls'
5
+ require 'database_cleaner-mongoid'
6
+
7
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
8
+ SimpleCov::Formatter::HTMLFormatter,
9
+ Coveralls::SimpleCov::Formatter
10
+ ]
11
+ SimpleCov.start
12
+
13
+ require 'rspec'
14
+ require 'mongoid'
15
+ require 'mongoid-multitenancy'
16
+ require 'mongoid-rspec'
17
+
18
+ require_relative 'support/shared_examples'
19
+ require_relative 'support/mongoid_matchers'
20
+
21
+ Dir["#{MODELS}/*.rb"].each { |f| require f }
22
+
23
+ Mongoid.configure do |config|
24
+ config.connect_to 'mongoid_multitenancy'
25
+ end
26
+
27
+ Mongoid.logger.level = Logger::INFO
28
+ Mongo::Logger.logger.level = Logger::INFO
29
+
30
+ RSpec.configure do |config|
31
+ config.include Mongoid::Matchers
32
+
33
+ config.expect_with :rspec do |c|
34
+ c.syntax = :expect
35
+ end
36
+
37
+ config.before(:each) do
38
+ DatabaseCleaner.clean
39
+ end
40
+
41
+ config.before(:each) do
42
+ Mongoid::Multitenancy.current_tenant = nil
43
+ end
44
+ end
@@ -0,0 +1,17 @@
1
+ module Mongoid
2
+ module Matchers
3
+ module Validations
4
+ class ValidateTenantUniquenessOfMatcher < ValidateUniquenessOfMatcher
5
+ def initialize(field)
6
+ @field = field.to_s
7
+ @type = 'tenant_uniqueness'
8
+ @options = {}
9
+ end
10
+ end
11
+
12
+ def validate_tenant_uniqueness_of(field)
13
+ ValidateTenantUniquenessOfMatcher.new(field)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,80 @@
1
+ shared_examples_for 'a tenantable model' do
2
+ it { is_expected.to belong_to(:tenant) }
3
+ it { is_expected.to have_index_for(tenant_id: 1, title: 1) }
4
+
5
+ describe '#initialize' do
6
+ context 'within a client context' do
7
+ before do
8
+ Mongoid::Multitenancy.current_tenant = client
9
+ end
10
+
11
+ it 'set the client' do
12
+ expect(item.tenant).to eq client
13
+ end
14
+ end
15
+
16
+ context 'without a client context' do
17
+ before do
18
+ Mongoid::Multitenancy.current_tenant = nil
19
+ end
20
+
21
+ it 'does not set any client' do
22
+ expect(item.tenant).to be_nil
23
+ end
24
+ end
25
+ end
26
+
27
+ describe '#valid?' do
28
+ context 'within a client context' do
29
+ before do
30
+ Mongoid::Multitenancy.current_tenant = client
31
+ end
32
+
33
+ context 'with the client id' do
34
+ before do
35
+ item.tenant = client
36
+ end
37
+
38
+ it 'is valid' do
39
+ expect(item).to be_valid
40
+ end
41
+ end
42
+
43
+ context 'with another client id' do
44
+ before do
45
+ item.tenant = another_client
46
+ end
47
+
48
+ it 'is not valid' do
49
+ expect(item).not_to be_valid
50
+ end
51
+ end
52
+ end
53
+
54
+ context 'without a client context' do
55
+ before do
56
+ Mongoid::Multitenancy.current_tenant = nil
57
+ end
58
+
59
+ context 'with the client id' do
60
+ before do
61
+ item.tenant = client
62
+ end
63
+
64
+ it 'is valid' do
65
+ expect(item).to be_valid
66
+ end
67
+ end
68
+
69
+ context 'with another client id' do
70
+ before do
71
+ item.tenant = another_client
72
+ end
73
+
74
+ it 'is valid' do
75
+ expect(item).to be_valid
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mongoid-multitenancy-forked
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Aymeric Brisse
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-05-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mongoid
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '6'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '10'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '6'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '10'
33
+ description: MultiTenancy with Mongoid - This is a fork for mongoid-multitenancy just
34
+ to allow mongoid version < 10
35
+ email:
36
+ - aymeric.brisse@mperfect-memory.com
37
+ executables: []
38
+ extensions: []
39
+ extra_rdoc_files: []
40
+ files:
41
+ - ".gitignore"
42
+ - ".rspec"
43
+ - ".travis.yml"
44
+ - CHANGELOG.md
45
+ - Gemfile
46
+ - LICENSE.TXT
47
+ - README.md
48
+ - Rakefile
49
+ - gemfiles/Gemfile.mongoid-6
50
+ - gemfiles/Gemfile.mongoid-7
51
+ - lib/mongoid-multitenancy-forked.rb
52
+ - lib/mongoid/multitenancy.rb
53
+ - lib/mongoid/multitenancy/document.rb
54
+ - lib/mongoid/multitenancy/validators/tenancy.rb
55
+ - lib/mongoid/multitenancy/validators/tenant_uniqueness.rb
56
+ - lib/mongoid/multitenancy/version.rb
57
+ - mongoid-multitenancy-forked.gemspec
58
+ - spec/immutable_spec.rb
59
+ - spec/indexable_spec.rb
60
+ - spec/inheritance_spec.rb
61
+ - spec/mandatory_spec.rb
62
+ - spec/models/account.rb
63
+ - spec/models/immutable.rb
64
+ - spec/models/indexable.rb
65
+ - spec/models/mandatory.rb
66
+ - spec/models/mutable.rb
67
+ - spec/models/mutable_child.rb
68
+ - spec/models/no_scopable.rb
69
+ - spec/models/optional.rb
70
+ - spec/models/optional_exclude.rb
71
+ - spec/mongoid-multitenancy_spec.rb
72
+ - spec/mutable_child_spec.rb
73
+ - spec/mutable_spec.rb
74
+ - spec/optional_exclude_spec.rb
75
+ - spec/optional_spec.rb
76
+ - spec/scopable_spec.rb
77
+ - spec/spec_helper.rb
78
+ - spec/support/mongoid_matchers.rb
79
+ - spec/support/shared_examples.rb
80
+ homepage: https://github.com/PerfectMemory/mongoid-multitenancy
81
+ licenses:
82
+ - MIT
83
+ metadata: {}
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubygems_version: 3.1.2
100
+ signing_key:
101
+ specification_version: 4
102
+ summary: Support of a multi-tenant database with Mongoid
103
+ test_files:
104
+ - spec/immutable_spec.rb
105
+ - spec/indexable_spec.rb
106
+ - spec/inheritance_spec.rb
107
+ - spec/mandatory_spec.rb
108
+ - spec/models/account.rb
109
+ - spec/models/immutable.rb
110
+ - spec/models/indexable.rb
111
+ - spec/models/mandatory.rb
112
+ - spec/models/mutable.rb
113
+ - spec/models/mutable_child.rb
114
+ - spec/models/no_scopable.rb
115
+ - spec/models/optional.rb
116
+ - spec/models/optional_exclude.rb
117
+ - spec/mongoid-multitenancy_spec.rb
118
+ - spec/mutable_child_spec.rb
119
+ - spec/mutable_spec.rb
120
+ - spec/optional_exclude_spec.rb
121
+ - spec/optional_spec.rb
122
+ - spec/scopable_spec.rb
123
+ - spec/spec_helper.rb
124
+ - spec/support/mongoid_matchers.rb
125
+ - spec/support/shared_examples.rb