mongoid-multitenancy-2 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9dc6399d5cdbff8bba0cc3dd03e423a7659882add4cc6f26f17baa54e0afcd2c
4
+ data.tar.gz: 241541c0d0fd6317eccbe4400468ff8f0bc947957b4d62901e52f76ecf4321a6
5
+ SHA512:
6
+ metadata.gz: 1501beb088b83f3a11a209b50f69a2652fe699f767b10cec66c161b877e3a10af2872765a7773d6e90c5278a2e986f024ec34288e2d431ec7431052533f3ff99
7
+ data.tar.gz: a18f045711297c9946029334a60e335becf76e53d86af16a4ebb6381219f8f26b4029a367d47350d034e2cb0e95135d6aceeac4b028db8b18988123ace7a0cac
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
19
+ Gemfile*.lock
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --order random
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ - 2.3.0
5
+ - 2.4.1
6
+ gemfile:
7
+ - gemfiles/Gemfile.mongoid-6
8
+ - gemfiles/Gemfile.mongoid-7
9
+ - Gemfile
10
+ services:
11
+ - mongodb
12
+ sudo: false
@@ -0,0 +1,54 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
+ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [2.0.3] - 2020-06-23
8
+ ### Added
9
+
10
+ ## [2.0.2] - 2018-08-23
11
+ ### Added
12
+
13
+ * Support of mongoid 7
14
+
15
+ ## [2.0.1] - 2017-12-14
16
+ ### Changed
17
+
18
+ * Add ensure block in method with_tenant
19
+
20
+ ## [2.0] - 2017-07-21
21
+ ### New Features
22
+
23
+ * Add support for mongoid 6
24
+ * Remove support for mongoid 4 & 5
25
+
26
+ ## 1.2
27
+
28
+ ### New Features
29
+
30
+ * Add *exclude_shared* option for the TenantUniquenessValidator
31
+
32
+ ## 1.1
33
+
34
+ ### New Features
35
+
36
+ * Add scopes *shared* and *unshared* (1b5c420)
37
+
38
+ ### Fixes
39
+
40
+ * When a tenant is optional, do not override the tenant during persisted document initialization (81a9b45)
41
+
42
+ ## 1.0.0
43
+
44
+ ### New Features
45
+
46
+ * Add support for mongoid 5
47
+
48
+ ### Major Changes (Backwards Incompatible)
49
+
50
+ * Drops support for mongoid 3
51
+
52
+ * An optional tenant is now automatically set if a current tenant is defined.
53
+
54
+ * A unique constraint with an optional tenant now uses the client scoping. An item cannot be shared if another client item has the same value.
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rake'
4
+
5
+ group :test do
6
+ gem 'database_cleaner'
7
+ gem 'coveralls', require: false
8
+ gem 'rspec', '~> 3.1'
9
+ gem 'yard'
10
+ gem 'mongoid-rspec', git: 'https://github.com/mongoid-rspec/mongoid-rspec.git'
11
+ gem 'rubocop', require: false
12
+ end
13
+
14
+ # Specify your gem's dependencies in mongoid-multitenancy.gemspec
15
+ gemspec
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Perfect Memory
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,283 @@
1
+ # mongoid-multitenancy [![Build Status](https://api.travis-ci.org/PerfectMemory/mongoid-multitenancy.png?branch=master)](https://travis-ci.org/PerfectMemory/mongoid-multitenancy) [![Coverage Status](https://coveralls.io/repos/github/PerfectMemory/mongoid-multitenancy/badge.svg?branch=master)](https://coveralls.io/github/PerfectMemory/mongoid-multitenancy?branch=master) [![Code Climate](https://codeclimate.com/github/PerfectMemory/mongoid-multitenancy.png)](https://codeclimate.com/github/PerfectMemory/mongoid-multitenancy)
2
+
3
+ This gem is the rebooted version of abandoned [mongoid multitenancy](https://github.com/PerfectMemory/mongoid-multitenancy)
4
+
5
+ mongoid-multitenancy adds the ability to scope [Mongoid](https://github.com/mongoid/mongoid) models to a tenant in a **shared database strategy**. Tenants are represented by a tenant model, such as `Client`. mongoid-multitenancy will help you set the current tenant on each request and ensures that all 'tenant models' are always properly scoped to the current tenant: when viewing, searching and creating.
6
+
7
+ It is directly inspired by the [acts_as_tenant gem](https://github.com/ErwinM/acts_as_tenant) for Active Record.
8
+
9
+ In addition, mongoid-multitenancy:
10
+
11
+ * allows you to set the current tenant
12
+ * allows shared items between the tenants
13
+ * allows you to define an immutable tenant field once it is persisted
14
+ * is thread safe
15
+ * redefines some mongoid functions like `index`, `validates_with` and `delete_all` to take in account the multitenancy.
16
+
17
+ Compatibility
18
+ ===============
19
+
20
+ mongoid-multitenancy 2.0 is compatible with mongoid 6/7. For mongoid 4/5 compatiblity, use mongoid-multitenancy 1.2.
21
+
22
+ Installation
23
+ ===============
24
+
25
+ Add this line to your application's Gemfile:
26
+
27
+ gem 'mongoid-multitenancy', '~> 2.0'
28
+
29
+ And then execute:
30
+
31
+ $ bundle
32
+
33
+ Or install it yourself as:
34
+
35
+ $ gem install mongoid-multitenancy
36
+
37
+ Usage
38
+ ===============
39
+
40
+ There are two steps to add multi-tenancy to your app with mongoid-multitenancy:
41
+
42
+ 1. setting the current tenant and
43
+ 2. scoping your models.
44
+
45
+ Setting the current tenant
46
+ --------------------------
47
+ There are two ways to set the current tenant: (1) by setting the current tenant manually, or (2) by setting the current tenant for a block.
48
+
49
+ **Setting the current tenant in a controller, manually**
50
+
51
+ ```ruby
52
+ Mongoid::Multitenancy.current_tenant = client_instance
53
+ ```
54
+
55
+ Setting the current_tenant yourself requires you to use a before_filter to set the Mongoid::Multitenancy.current_tenant variable.
56
+
57
+ **Setting the current tenant for a block**
58
+
59
+ ```ruby
60
+ Mongoid::Multitenancy.with_tenant(client_instance) do
61
+ # Current tenant is set for all code in this block
62
+ end
63
+ ```
64
+
65
+ This approach is useful when running background processes for a specified tenant. For example, by putting this in your worker's run method,
66
+ any code in this block will be scoped to the current tenant. All methods that set the current tenant are thread safe.
67
+
68
+ **Note:** If the current tenant is not set by one of these methods, mongoid-multitenancy will apply a global scope to your models, not related to any tenant. So make sure you use one of the two methods to tell mongoid-multitenancy about the current tenant.
69
+
70
+ Scoping your models
71
+ -------------------
72
+ ```ruby
73
+ class Client
74
+ include Mongoid::Document
75
+
76
+ field :name, :type => String
77
+ validates_uniqueness_of :name
78
+ end
79
+
80
+ class Article
81
+ include Mongoid::Document
82
+ include Mongoid::Multitenancy::Document
83
+
84
+ tenant(:tenant)
85
+
86
+ field :title, :type => String
87
+ end
88
+ ```
89
+
90
+ Adding `tenant` to your model declaration will scope that model to the current tenant **BUT ONLY if a current tenant has been set**.
91
+ The association passed to the `tenant` function must be valid.
92
+
93
+ `tenant` accepts several options:
94
+
95
+ | Option | Default | Description |
96
+ | ------------- | ------------- | ------------- |
97
+ | :optional | false | set to true when the tenant is optional |
98
+ | :immutable | true | set to true when the tenant field is immutable |
99
+ | :full_indexes | true | set to true to add the tenant field automatically to all the indexes |
100
+ | :index | false | set to true to define an index for the tenant field |
101
+ | :scopes | true | set to true to define scopes :shared and :unshared |
102
+ | :class_name, etc. | | all the other options will be passed to the mongoid relation (belongs_to) |
103
+
104
+ Some examples to illustrate this behavior:
105
+
106
+ ```ruby
107
+ # This manually sets the current tenant for testing purposes. In your app this is handled by the gem.
108
+ Mongoid::Multitenancy.current_tenant = Client.find_by(:name => 'Perfect Memory') # => <#Client _id:50ca04b86c82bfc125000025, :name: "Perfect Memory">
109
+
110
+ # All searches are scoped by the tenant, the following searches will only return objects belonging to the current client.
111
+ Article.all # => all articles where tenant_id => 50ca04b86c82bfc125000025
112
+
113
+ # New objects are scoped to the current tenant
114
+ article = Article.new(:title => 'New blog')
115
+ article.save # => <#Article _id: 50ca04b86c82bfc125000044, title: 'New blog', tenant_id: 50ca04b86c82bfc125000025>
116
+
117
+ # It can make the tenant field immutable once it is persisted to avoid inconsistency
118
+ article.persisted? # => true
119
+ article.tenant = another_client
120
+ article.valid? # => false
121
+ ```
122
+
123
+ **Optional tenant**
124
+
125
+ When setting an optional tenant, for example to allow shared instances between all the tenants, the default scope will return both the tenant and the free-tenant items. That means that using `Article.delete_all` or `Article.destroy_all` will **remove the shared items too**.
126
+
127
+ Note: if a current tenant is set and you want to mark the item shared, you must explicitly set the tenant relation to nil after the initialization.
128
+
129
+ ```ruby
130
+ class Article
131
+ include Mongoid::Document
132
+ include Mongoid::Multitenancy::Document
133
+
134
+ tenant(:tenant, optional: true)
135
+
136
+ field :title, :type => String
137
+ end
138
+
139
+ Mongoid::Multitenancy.with_tenant(client_instance) do
140
+ Article.all # => all articles where tenant_id.in [50ca04b86c82bfc125000025, nil]
141
+ article = Article.new(:title => 'New article')
142
+ article.save # => <#Article _id: 50ca04b86c82bfc125000044, title: 'New blog', tenant_id: 50ca04b86c82bfc125000025>
143
+
144
+ # tenant needs to be set manually to nil
145
+ article = Article.new(:title => 'New article', :tenant => nil)
146
+ article.save # => <#Article _id: 50ca04b86c82bfc125000044, title: 'New blog', tenant_id: 50ca04b86c82bfc125000025>
147
+ article.tenant = nil
148
+ article.save => <#Article _id: 50ca04b86c82bfc125000044, title: 'New blog', tenant_id: nil>
149
+ end
150
+ ```
151
+
152
+ Rails
153
+ -------------------
154
+
155
+ If you are using Rails, you may want to set the current tenant at each request.
156
+
157
+ **Manually set the current tenant in ApplicationController using the host request**
158
+
159
+ ```ruby
160
+ class ApplicationController < ActionController::Base
161
+ before_filter :set_current_client
162
+
163
+ def set_current_client
164
+ current_client = Client.find_by_host(request.host)
165
+ Mongoid::Multitenancy.current_tenant = current_client
166
+ end
167
+ end
168
+ ```
169
+
170
+ Setting the current_tenant yourself requires you to use a before_filter to set the Mongoid::Multitenancy.current_tenant variable.
171
+
172
+ Mongoid Uniqueness validators
173
+ -------------------
174
+
175
+ mongoid-multitenancy brings a TenantUniqueness validator that will, depending on the tenant options, check that your uniqueness
176
+ constraints are respected:
177
+
178
+ * When used with a *mandatory* tenant, the uniqueness constraint is scoped to the current client.
179
+
180
+ In the following case, 2 articles can have the same slug if they belongs to 2 different clients.
181
+
182
+ ```ruby
183
+ class Article
184
+ include Mongoid::Document
185
+ include Mongoid::Multitenancy::Document
186
+
187
+ tenant :tenant
188
+
189
+ field :slug
190
+
191
+ validates_tenant_uniqueness_of :slug
192
+ end
193
+ ```
194
+
195
+ * When used with an *optional* tenant, the uniqueness constraint by default is not scoped if the item is shared, but is
196
+ scoped to the client new item otherwise. Note that by default in that case a private item cannot have a value if a shared item
197
+ already uses it. You can change that behaviour by setting the option `exclude_shared` to `true`.
198
+
199
+ In the following case, 2 private articles can have the same slug if they belongs to 2 different clients. But if a shared
200
+ article has the slug "slugA", no client will be able to use that slug again, like a standard `validates_uniqueness_of` does.
201
+
202
+ ```ruby
203
+ class Article
204
+ include Mongoid::Document
205
+ include Mongoid::Multitenancy::Document
206
+
207
+ tenant :tenant, optional: true
208
+
209
+ field :slug
210
+
211
+ validates_tenant_uniqueness_of :slug
212
+ end
213
+ ```
214
+
215
+ In the following case, 2 private articles can have the same slug if they belongs to 2 different clients even if a shared
216
+ article already uses that same slug, like a `validates_uniqueness_of scope: :tenant` does.
217
+
218
+ ```ruby
219
+ class Article
220
+ include Mongoid::Document
221
+ include Mongoid::Multitenancy::Document
222
+
223
+ tenant :tenant, optional: true
224
+
225
+ field :slug
226
+
227
+ validates_tenant_uniqueness_of :slug, exclude_shared: true
228
+ end
229
+ ```
230
+
231
+ Mongoid indexes
232
+ -------------------
233
+
234
+ mongoid-multitenancy automatically adds the tenant foreign key in all your mongoid indexes to avoid to redefine all your validators. If you prefer to define manually the indexes, you can use the option `full_indexes: false`.
235
+
236
+ To create a single index on the tenant field, you can use the option `index: true` like any `belongs_to` declaration (false by default)
237
+
238
+ On the example below, only one indexe will be created:
239
+
240
+ * { 'title_id' => 1, 'tenant_id' => 1 }
241
+
242
+ ```ruby
243
+ class Article
244
+ include Mongoid::Document
245
+ include Mongoid::Multitenancy::Document
246
+
247
+ tenant :tenant, full_indexes: true
248
+
249
+ field :title
250
+
251
+ index({ :title => 1 })
252
+ end
253
+ ```
254
+
255
+ On the example below, 2 indexes will be created:
256
+
257
+ * { 'tenant_id' => 1 }
258
+ * { 'title_id' => 1 }
259
+
260
+ ```ruby
261
+ class Article
262
+ include Mongoid::Document
263
+ include Mongoid::Multitenancy::Document
264
+
265
+ tenant :tenant, index: true
266
+
267
+ field :title
268
+
269
+ index({ :title => 1 })
270
+ end
271
+ ```
272
+
273
+ Author & Credits
274
+ ----------------
275
+ mongoid-multitenancy is written by [Aymeric Brisse](https://github.com/abrisse/), from [Perfect Memory](http://www.perfect-memory.com).
276
+
277
+ ## Contributing
278
+
279
+ 1. Fork it
280
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
281
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
282
+ 4. Push to the branch (`git push origin my-new-feature`)
283
+ 5. Create new Pull Request
@@ -0,0 +1,8 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'yard'
4
+
5
+ YARD::Rake::YardocTask.new
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'mongoid', '~> 6.0'
4
+
5
+ gem 'rake'
6
+
7
+ group :test do
8
+ gem 'database_cleaner'
9
+ gem 'coveralls', require: false
10
+ gem 'rspec', '~> 3.1'
11
+ gem 'yard'
12
+ gem 'mongoid-rspec', git: 'https://github.com/mongoid-rspec/mongoid-rspec.git'
13
+ gem 'rubocop', require: false
14
+ end