rbacan 0.3.1 → 0.4.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.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/CHANGELOG.md +28 -0
- data/CLAUDE.md +51 -0
- data/Gemfile.lock +54 -22
- data/app/models/rbacan/role.rb +22 -9
- data/app/models/rbacan/user_role.rb +8 -5
- data/lib/generators/install/templates/create_permissions.rb +1 -1
- data/lib/generators/install/templates/create_role_permissions.rb +3 -3
- data/lib/generators/install/templates/create_roles.rb +10 -1
- data/lib/generators/install/templates/create_user_roles.rb +11 -4
- data/lib/generators/install/templates/rbacan.rb +15 -0
- data/lib/generators/rbacan/install_generator.rb +26 -7
- data/lib/rbacan/permittable.rb +53 -26
- data/lib/rbacan/version.rb +1 -1
- data/lib/rbacan.rb +37 -10
- data/rbacan.gemspec +26 -29
- metadata +51 -32
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 066e77f9b2f426249a569e679c9c1348e28b2f3af5f19f480a9059ce237b5258
|
|
4
|
+
data.tar.gz: 83cb20bd2b2e97c558f0f97f2c0452417f01668f73cc3bccbf48eddde3e7cd81
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5b2c8e3ac69a2fc9ea125022eb1d8ac2fd63ee702c2b6e8b1300e6c5dc317ae9db8b5dc1fd96167ea418b1a1cded3f2b7282edd6f09a2ec4fd19783556b4eb4d
|
|
7
|
+
data.tar.gz: f1a0312c57018c184383266dfeab2b9c2fe216431e63558996d14162e1c56291c85edee0ab00bab716498da4bd34f7d3dd56232ded31e48947b1c932078ac72a
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,34 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.4.0] - 2026-04-13
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `primary_key_type` config option — auto-detects host app's primary key type (supports `:uuid` and `:bigint`)
|
|
10
|
+
- `tenant_scoped` config option — when `true`, adds `tenant_id` to `roles` and `user_roles` tables
|
|
11
|
+
- `tenant_class` config option — configurable tenant model class name (default: `"Tenant"`)
|
|
12
|
+
- `Rbacan.resolve_primary_key_type` — helper to resolve the effective PK type at runtime
|
|
13
|
+
- Tenant-aware methods on `Permittable`:
|
|
14
|
+
- `roles_for_tenant(tenant_id)` — returns roles assigned in a specific tenant (+ global)
|
|
15
|
+
- `has_role_in_tenant?(role_name, tenant_id)` — checks role in tenant context
|
|
16
|
+
- `can_in_tenant?(permission_name, tenant_id)` — checks permission in tenant context
|
|
17
|
+
- `assign_role` now accepts optional `tenant_id:` keyword argument for tenant-scoped assignments
|
|
18
|
+
- `remove_role` now accepts optional `tenant_id:` keyword argument
|
|
19
|
+
- `Role` scopes: `.global` (where tenant_id IS NULL), `.for_tenant(tenant_id)` (tenant + global roles)
|
|
20
|
+
- `Role` model: conditional `belongs_to :tenant` when `tenant_scoped` is enabled
|
|
21
|
+
- `UserRole` model: conditional `belongs_to :tenant` when `tenant_scoped` is enabled
|
|
22
|
+
- Initializer template now documents all new configuration options
|
|
23
|
+
- Migration templates now use explicit `type:` on `t.references` for FK columns
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- `t.bigint :user_id` was hardcoded in `create_user_roles` migration — now uses `t.references :user` with proper type detection matching the host app's PK type
|
|
28
|
+
- Migration templates now conditionally pass `id: :uuid` to `create_table` based on host app configuration
|
|
29
|
+
- `create_role_permissions` migration now specifies explicit `type:` on foreign key references
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
5
33
|
## [0.3.0] - 2026-03-31
|
|
6
34
|
|
|
7
35
|
### Added
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bin/setup # install dependencies
|
|
9
|
+
rake spec # run all tests
|
|
10
|
+
bundle exec rspec spec/rbacan_spec.rb # run a single spec file
|
|
11
|
+
bundle exec rake install # install gem locally
|
|
12
|
+
bundle exec rake release # tag, push commits/tags, push .gem to RubyGems
|
|
13
|
+
gem build rbacan.gemspec # build .gem file manually
|
|
14
|
+
gem push rbacan-<version>.gem # push to RubyGems manually
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Architecture
|
|
18
|
+
|
|
19
|
+
This is a Rails engine gem that provides Role-Based Access Control (RBAC).
|
|
20
|
+
|
|
21
|
+
**Data model** — four tables managed by the gem's migrations:
|
|
22
|
+
- `roles` / `permissions` — named entities
|
|
23
|
+
- `role_permissions` — join table linking roles to permissions
|
|
24
|
+
- `user_roles` — join table linking the host app's user model to roles
|
|
25
|
+
|
|
26
|
+
**Entry points:**
|
|
27
|
+
- `lib/rbacan.rb` — main module; holds `mattr_accessor` config accessors and a `configure` block. All class names and table names are configurable here (defaults to `User`, `Rbacan::Role`, etc.).
|
|
28
|
+
- `lib/rbacan/permittable.rb` — `ActiveSupport::Concern` included in the host app's user model via `include Rbacan::Permittable`. Adds `assign_role`, `remove_role`, and `can?` instance methods.
|
|
29
|
+
- `lib/rbacan/roles_and_permissions.rb` — utility module (`RolesAndPermissions`) used in seeds to bulk-create roles/permissions and assign permissions to roles.
|
|
30
|
+
- `lib/rbacan/engine.rb` — Rails engine that auto-loads `app/models`.
|
|
31
|
+
|
|
32
|
+
**Generator** (`rails generate rbacan:install`) copies four migration files, `db/copy_to_seeds.rb`, and `config/initializers/rbacan.rb` into the host app.
|
|
33
|
+
|
|
34
|
+
**Configuration** (host app's `config/initializers/rbacan.rb`):
|
|
35
|
+
```ruby
|
|
36
|
+
Rbacan.configure do |config|
|
|
37
|
+
config.permittable_class = "User" # change if your user model has a different name
|
|
38
|
+
end
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Releasing a new version
|
|
42
|
+
|
|
43
|
+
1. Bump `lib/rbacan/version.rb`
|
|
44
|
+
2. `gem build rbacan.gemspec`
|
|
45
|
+
3. `gem push rbacan-<version>.gem`
|
|
46
|
+
|
|
47
|
+
RubyGems push host is `https://rubygems.org`. GitHub repo: `https://github.com/hamdi777/RBACan`.
|
|
48
|
+
|
|
49
|
+
## Known state
|
|
50
|
+
|
|
51
|
+
The spec suite has a placeholder test (`expect(false).to eq(true)`) in `spec/rbacan_spec.rb` that intentionally fails — it was never replaced with real tests.
|
data/Gemfile.lock
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
rbacan (0.
|
|
5
|
-
rails (>= 5.2)
|
|
4
|
+
rbacan (0.4.0)
|
|
5
|
+
rails (>= 5.2, < 9)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: https://rubygems.org/
|
|
@@ -82,7 +82,7 @@ GEM
|
|
|
82
82
|
tzinfo (~> 2.0, >= 2.0.5)
|
|
83
83
|
uri (>= 0.13.1)
|
|
84
84
|
base64 (0.3.0)
|
|
85
|
-
bigdecimal (4.1.
|
|
85
|
+
bigdecimal (4.1.1)
|
|
86
86
|
builder (3.3.0)
|
|
87
87
|
concurrent-ruby (1.3.6)
|
|
88
88
|
connection_pool (3.0.2)
|
|
@@ -118,8 +118,7 @@ GEM
|
|
|
118
118
|
net-smtp
|
|
119
119
|
marcel (1.1.0)
|
|
120
120
|
mini_mime (1.1.5)
|
|
121
|
-
|
|
122
|
-
minitest (6.0.2)
|
|
121
|
+
minitest (6.0.3)
|
|
123
122
|
drb (~> 2.0)
|
|
124
123
|
prism (~> 1.5)
|
|
125
124
|
net-imap (0.6.3)
|
|
@@ -132,11 +131,22 @@ GEM
|
|
|
132
131
|
net-smtp (0.5.1)
|
|
133
132
|
net-protocol
|
|
134
133
|
nio4r (2.7.5)
|
|
135
|
-
nokogiri (1.19.2)
|
|
136
|
-
|
|
134
|
+
nokogiri (1.19.2-aarch64-linux-gnu)
|
|
135
|
+
racc (~> 1.4)
|
|
136
|
+
nokogiri (1.19.2-aarch64-linux-musl)
|
|
137
|
+
racc (~> 1.4)
|
|
138
|
+
nokogiri (1.19.2-arm-linux-gnu)
|
|
139
|
+
racc (~> 1.4)
|
|
140
|
+
nokogiri (1.19.2-arm-linux-musl)
|
|
141
|
+
racc (~> 1.4)
|
|
142
|
+
nokogiri (1.19.2-arm64-darwin)
|
|
143
|
+
racc (~> 1.4)
|
|
144
|
+
nokogiri (1.19.2-x86_64-darwin)
|
|
137
145
|
racc (~> 1.4)
|
|
138
146
|
nokogiri (1.19.2-x86_64-linux-gnu)
|
|
139
147
|
racc (~> 1.4)
|
|
148
|
+
nokogiri (1.19.2-x86_64-linux-musl)
|
|
149
|
+
racc (~> 1.4)
|
|
140
150
|
pp (0.6.3)
|
|
141
151
|
prettyprint
|
|
142
152
|
prettyprint (0.2.0)
|
|
@@ -146,7 +156,7 @@ GEM
|
|
|
146
156
|
stringio
|
|
147
157
|
racc (1.8.1)
|
|
148
158
|
rack (3.2.6)
|
|
149
|
-
rack-session (2.1.
|
|
159
|
+
rack-session (2.1.2)
|
|
150
160
|
base64 (>= 0.1.0)
|
|
151
161
|
rack (>= 3.0.0)
|
|
152
162
|
rack-test (2.2.0)
|
|
@@ -204,9 +214,14 @@ GEM
|
|
|
204
214
|
rspec-support (~> 3.13.0)
|
|
205
215
|
rspec-support (3.13.7)
|
|
206
216
|
securerandom (0.4.1)
|
|
207
|
-
sqlite3 (2.9.2)
|
|
208
|
-
|
|
217
|
+
sqlite3 (2.9.2-aarch64-linux-gnu)
|
|
218
|
+
sqlite3 (2.9.2-aarch64-linux-musl)
|
|
219
|
+
sqlite3 (2.9.2-arm-linux-gnu)
|
|
220
|
+
sqlite3 (2.9.2-arm-linux-musl)
|
|
221
|
+
sqlite3 (2.9.2-arm64-darwin)
|
|
222
|
+
sqlite3 (2.9.2-x86_64-darwin)
|
|
209
223
|
sqlite3 (2.9.2-x86_64-linux-gnu)
|
|
224
|
+
sqlite3 (2.9.2-x86_64-linux-musl)
|
|
210
225
|
stringio (3.2.0)
|
|
211
226
|
thor (1.5.0)
|
|
212
227
|
timeout (0.6.1)
|
|
@@ -222,18 +237,24 @@ GEM
|
|
|
222
237
|
zeitwerk (2.7.5)
|
|
223
238
|
|
|
224
239
|
PLATFORMS
|
|
225
|
-
|
|
226
|
-
|
|
240
|
+
aarch64-linux-gnu
|
|
241
|
+
aarch64-linux-musl
|
|
242
|
+
arm-linux-gnu
|
|
243
|
+
arm-linux-musl
|
|
244
|
+
arm64-darwin
|
|
245
|
+
x86_64-darwin
|
|
246
|
+
x86_64-linux-gnu
|
|
247
|
+
x86_64-linux-musl
|
|
227
248
|
|
|
228
249
|
DEPENDENCIES
|
|
229
|
-
activerecord (>= 5.2)
|
|
250
|
+
activerecord (>= 5.2, < 9)
|
|
230
251
|
bundler (>= 2.0)
|
|
231
252
|
generator_spec (~> 0.9.4)
|
|
232
|
-
railties (>= 5.2)
|
|
253
|
+
railties (>= 5.2, < 9)
|
|
233
254
|
rake (~> 13.0)
|
|
234
255
|
rbacan!
|
|
235
256
|
rspec (~> 3.0)
|
|
236
|
-
sqlite3
|
|
257
|
+
sqlite3
|
|
237
258
|
|
|
238
259
|
CHECKSUMS
|
|
239
260
|
action_text-trix (2.1.18) sha256=3fdb83f8bff4145d098be283cdd47ac41caf5110bfa6df4695ed7127d7fb3642
|
|
@@ -249,7 +270,7 @@ CHECKSUMS
|
|
|
249
270
|
activestorage (8.1.3) sha256=0564ce9309143951a67615e1bb4e090ee54b8befed417133cae614479b46384d
|
|
250
271
|
activesupport (8.1.3) sha256=21a5e0dfbd4c3ddd9e1317ec6a4d782fa226e7867dc70b0743acda81a1dca20e
|
|
251
272
|
base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
|
|
252
|
-
bigdecimal (4.1.
|
|
273
|
+
bigdecimal (4.1.1) sha256=1c09efab961da45203c8316b0cdaec0ff391dfadb952dd459584b63ebf8054ca
|
|
253
274
|
builder (3.3.0) sha256=497918d2f9dca528fdca4b88d84e4ef4387256d984b8154e9d5d3fe5a9c8835f
|
|
254
275
|
concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab
|
|
255
276
|
connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a
|
|
@@ -270,22 +291,27 @@ CHECKSUMS
|
|
|
270
291
|
mail (2.9.0) sha256=6fa6673ecd71c60c2d996260f9ee3dd387d4673b8169b502134659ece6d34941
|
|
271
292
|
marcel (1.1.0) sha256=fdcfcfa33cc52e93c4308d40e4090a5d4ea279e160a7f6af988260fa970e0bee
|
|
272
293
|
mini_mime (1.1.5) sha256=8681b7e2e4215f2a159f9400b5816d85e9d8c6c6b491e96a12797e798f8bccef
|
|
273
|
-
|
|
274
|
-
minitest (6.0.2) sha256=db6e57956f6ecc6134683b4c87467d6dd792323c7f0eea7b93f66bd284adbc3d
|
|
294
|
+
minitest (6.0.3) sha256=88ac8a1de36c00692420e7cb3cc11a0773bbcb126aee1c249f320160a7d11411
|
|
275
295
|
net-imap (0.6.3) sha256=9bab75f876596d09ee7bf911a291da478e0cd6badc54dfb82874855ccc82f2ad
|
|
276
296
|
net-pop (0.1.2) sha256=848b4e982013c15b2f0382792268763b748cce91c9e91e36b0f27ed26420dff3
|
|
277
297
|
net-protocol (0.2.2) sha256=aa73e0cba6a125369de9837b8d8ef82a61849360eba0521900e2c3713aa162a8
|
|
278
298
|
net-smtp (0.5.1) sha256=ed96a0af63c524fceb4b29b0d352195c30d82dd916a42f03c62a3a70e5b70736
|
|
279
299
|
nio4r (2.7.5) sha256=6c90168e48fb5f8e768419c93abb94ba2b892a1d0602cb06eef16d8b7df1dca1
|
|
280
|
-
nokogiri (1.19.2) sha256=
|
|
300
|
+
nokogiri (1.19.2-aarch64-linux-gnu) sha256=c34d5c8208025587554608e98fd88ab125b29c80f9352b821964e9a5d5cfbd19
|
|
301
|
+
nokogiri (1.19.2-aarch64-linux-musl) sha256=7f6b4b0202d507326841a4f790294bf75098aef50c7173443812e3ac5cb06515
|
|
302
|
+
nokogiri (1.19.2-arm-linux-gnu) sha256=b7fa1139016f3dc850bda1260988f0d749934a939d04ef2da13bec060d7d5081
|
|
303
|
+
nokogiri (1.19.2-arm-linux-musl) sha256=61114d44f6742ff72194a1b3020967201e2eb982814778d130f6471c11f9828c
|
|
304
|
+
nokogiri (1.19.2-arm64-darwin) sha256=58d8ea2e31a967b843b70487a44c14c8ba1866daa1b9da9be9dbdf1b43dee205
|
|
305
|
+
nokogiri (1.19.2-x86_64-darwin) sha256=7d9af11fda72dfaa2961d8c4d5380ca0b51bc389dc5f8d4b859b9644f195e7a4
|
|
281
306
|
nokogiri (1.19.2-x86_64-linux-gnu) sha256=fa8feca882b73e871a9845f3817a72e9734c8e974bdc4fbad6e4bc6e8076b94f
|
|
307
|
+
nokogiri (1.19.2-x86_64-linux-musl) sha256=93128448e61a9383a30baef041bf1f5817e22f297a1d400521e90294445069a8
|
|
282
308
|
pp (0.6.3) sha256=2951d514450b93ccfeb1df7d021cae0da16e0a7f95ee1e2273719669d0ab9df6
|
|
283
309
|
prettyprint (0.2.0) sha256=2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193
|
|
284
310
|
prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
|
|
285
311
|
psych (5.3.1) sha256=eb7a57cef10c9d70173ff74e739d843ac3b2c019a003de48447b2963d81b1974
|
|
286
312
|
racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
|
|
287
313
|
rack (3.2.6) sha256=5ed78e1f73b2e25679bec7d45ee2d4483cc4146eb1be0264fc4d94cb5ef212c2
|
|
288
|
-
rack-session (2.1.
|
|
314
|
+
rack-session (2.1.2) sha256=595434f8c0c3473ae7d7ac56ecda6cc6dfd9d37c0b2b5255330aa1576967ffe8
|
|
289
315
|
rack-test (2.2.0) sha256=005a36692c306ac0b4a9350355ee080fd09ddef1148a5f8b2ac636c720f5c463
|
|
290
316
|
rackup (2.3.1) sha256=6c79c26753778e90983761d677a48937ee3192b3ffef6bc963c0950f94688868
|
|
291
317
|
rails (8.1.3) sha256=6d017ba5348c98fc909753a8169b21d44de14d2a0b92d140d1a966834c3c9cd3
|
|
@@ -293,7 +319,7 @@ CHECKSUMS
|
|
|
293
319
|
rails-html-sanitizer (1.7.0) sha256=28b145cceaf9cc214a9874feaa183c3acba036c9592b19886e0e45efc62b1e89
|
|
294
320
|
railties (8.1.3) sha256=913eb0e0cb520aac687ffd74916bd726d48fa21f47833c6292576ef6a286de22
|
|
295
321
|
rake (13.3.1) sha256=8c9e89d09f66a26a01264e7e3480ec0607f0c497a861ef16063604b1b08eb19c
|
|
296
|
-
rbacan (0.
|
|
322
|
+
rbacan (0.4.0)
|
|
297
323
|
rdoc (7.2.0) sha256=8650f76cd4009c3b54955eb5d7e3a075c60a57276766ebf36f9085e8c9f23192
|
|
298
324
|
reline (0.6.3) sha256=1198b04973565b36ec0f11542ab3f5cfeeec34823f4e54cebde90968092b1835
|
|
299
325
|
rspec (3.13.2) sha256=206284a08ad798e61f86d7ca3e376718d52c0bc944626b2349266f239f820587
|
|
@@ -302,8 +328,14 @@ CHECKSUMS
|
|
|
302
328
|
rspec-mocks (3.13.8) sha256=086ad3d3d17533f4237643de0b5c42f04b66348c28bf6b9c2d3f4a3b01af1d47
|
|
303
329
|
rspec-support (3.13.7) sha256=0640e5570872aafefd79867901deeeeb40b0c9875a36b983d85f54fb7381c47c
|
|
304
330
|
securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1
|
|
305
|
-
sqlite3 (2.9.2) sha256=
|
|
331
|
+
sqlite3 (2.9.2-aarch64-linux-gnu) sha256=eeb86db55645b85327ba75129e3614658d974bf4da8fdc87018a0d42c59f6e42
|
|
332
|
+
sqlite3 (2.9.2-aarch64-linux-musl) sha256=4feff91fb8c2b13688da34b5627c9d1ed9cedb3ee87a7114ec82209147f07a6d
|
|
333
|
+
sqlite3 (2.9.2-arm-linux-gnu) sha256=1ee2eb06b5301aaf5ce343a6e88d99ac932d95202d7b350f0e7b6d8d588580d7
|
|
334
|
+
sqlite3 (2.9.2-arm-linux-musl) sha256=8ca0de6aceede968de0394e22e95d549834c4d8e318f69a92a52f049878a0057
|
|
335
|
+
sqlite3 (2.9.2-arm64-darwin) sha256=d15bd9609a05f9d54930babe039585efc8cadd57517c15b64ec7dfa75158a5e9
|
|
336
|
+
sqlite3 (2.9.2-x86_64-darwin) sha256=ed691b5021674d72582d03c5a38e89634b961902735fb6225273892805421d13
|
|
306
337
|
sqlite3 (2.9.2-x86_64-linux-gnu) sha256=dce83ffcb7e72f9f7aeb6e5404f15d277a45332fe18ccce8a8b3ed51e8d23aee
|
|
338
|
+
sqlite3 (2.9.2-x86_64-linux-musl) sha256=e8dd906a613f13b60f6d47ae9dda376384d9de1ab3f7e3f2fdf2fd18a871a2d7
|
|
307
339
|
stringio (3.2.0) sha256=c37cb2e58b4ffbd33fe5cd948c05934af997b36e0b6ca6fdf43afa234cf222e1
|
|
308
340
|
thor (1.5.0) sha256=e3a9e55fe857e44859ce104a84675ab6e8cd59c650a49106a05f55f136425e73
|
|
309
341
|
timeout (0.6.1) sha256=78f57368a7e7bbadec56971f78a3f5ecbcfb59b7fcbb0a3ed6ddc08a5094accb
|
data/app/models/rbacan/role.rb
CHANGED
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
module Rbacan
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
class Role < ApplicationRecord
|
|
3
|
+
self.table_name = Rbacan.role_table
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
has_many :permissions, class_name: Rbacan.permission_class, through: :role_permissions
|
|
5
|
+
validates :name, presence: true
|
|
6
|
+
validates :name, uniqueness: true, unless: -> { Rbacan.tenant_scoped && tenant_id.present? }
|
|
7
|
+
validates :name, uniqueness: { scope: :tenant_id }, if: -> { Rbacan.tenant_scoped && tenant_id.present? }
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
has_many :role_permissions, class_name: Rbacan.role_permission_class, dependent: :destroy
|
|
10
|
+
has_many :permissions, class_name: Rbacan.permission_class, through: :role_permissions
|
|
11
|
+
|
|
12
|
+
has_many :user_roles, class_name: Rbacan.user_role_class, dependent: :destroy
|
|
13
|
+
has_many :users, class_name: Rbacan.permittable_class, through: :user_roles
|
|
14
|
+
|
|
15
|
+
# Tenant association — only meaningful when tenant_scoped is enabled.
|
|
16
|
+
# The column must exist in the database; it is added by the migration
|
|
17
|
+
# when tenant_scoped is true.
|
|
18
|
+
belongs_to :tenant, class_name: Rbacan.tenant_class, optional: true if Rbacan.tenant_scoped
|
|
19
|
+
|
|
20
|
+
# Global roles have no tenant (tenant_id IS NULL).
|
|
21
|
+
scope :global, -> { where(tenant_id: nil) }
|
|
22
|
+
|
|
23
|
+
# Returns roles available for a specific tenant: its own roles plus global roles.
|
|
24
|
+
scope :for_tenant, ->(tenant_id) { where(tenant_id: [tenant_id, nil]) }
|
|
25
|
+
end
|
|
13
26
|
end
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
module Rbacan
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
class UserRole < ApplicationRecord
|
|
3
|
+
self.table_name = Rbacan.user_role_table
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
belongs_to :role, class_name: Rbacan.role_class
|
|
6
|
+
belongs_to :user, class_name: Rbacan.permittable_class
|
|
7
|
+
|
|
8
|
+
# Tenant association — only meaningful when tenant_scoped is enabled.
|
|
9
|
+
belongs_to :tenant, class_name: Rbacan.tenant_class, optional: true if Rbacan.tenant_scoped
|
|
10
|
+
end
|
|
8
11
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
class CreatePermissions < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
|
|
2
2
|
def change
|
|
3
|
-
create_table :permissions do |t|
|
|
3
|
+
create_table :permissions<%= ", id: :uuid" if primary_key_type == :uuid %> do |t|
|
|
4
4
|
t.string :name, null: false
|
|
5
5
|
|
|
6
6
|
t.timestamps
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
class CreateRolePermissions < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
|
|
2
2
|
def change
|
|
3
|
-
create_table :role_permissions do |t|
|
|
4
|
-
t.references :role, null: false, index: true, foreign_key: { to_table: :roles, on_delete: :cascade }
|
|
5
|
-
t.references :permission, null: false, index: true, foreign_key: { to_table: :permissions, on_delete: :cascade }
|
|
3
|
+
create_table :role_permissions<%= ", id: :uuid" if primary_key_type == :uuid %> do |t|
|
|
4
|
+
t.references :role, null: false, type: :<%= primary_key_type %>, index: true, foreign_key: { to_table: :roles, on_delete: :cascade }
|
|
5
|
+
t.references :permission, null: false, type: :<%= primary_key_type %>, index: true, foreign_key: { to_table: :permissions, on_delete: :cascade }
|
|
6
6
|
|
|
7
7
|
t.timestamps
|
|
8
8
|
end
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
class CreateRoles < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
|
|
2
2
|
def change
|
|
3
|
-
create_table :roles do |t|
|
|
3
|
+
create_table :roles<%= ", id: :uuid" if primary_key_type == :uuid %> do |t|
|
|
4
4
|
t.string :name, null: false
|
|
5
|
+
<% if tenant_scoped? %>
|
|
6
|
+
t.references :tenant, null: true, type: :<%= primary_key_type %>, index: true
|
|
7
|
+
<% end %>
|
|
5
8
|
|
|
6
9
|
t.timestamps
|
|
7
10
|
end
|
|
11
|
+
<% if tenant_scoped? %>
|
|
12
|
+
|
|
13
|
+
add_index :roles, :name, unique: true, where: "tenant_id IS NULL", name: "index_roles_on_name_global"
|
|
14
|
+
add_index :roles, [:tenant_id, :name], unique: true, name: "index_roles_on_tenant_id_and_name"
|
|
15
|
+
<% else %>
|
|
8
16
|
|
|
9
17
|
add_index :roles, :name, unique: true
|
|
18
|
+
<% end %>
|
|
10
19
|
end
|
|
11
20
|
end
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
class CreateUserRoles < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
|
|
2
2
|
def change
|
|
3
|
-
create_table :user_roles do |t|
|
|
4
|
-
t.references :role, null: false, index: true, foreign_key: { to_table: :roles, on_delete: :cascade }
|
|
5
|
-
t.
|
|
3
|
+
create_table :user_roles<%= ", id: :uuid" if primary_key_type == :uuid %> do |t|
|
|
4
|
+
t.references :role, null: false, type: :<%= primary_key_type %>, index: true, foreign_key: { to_table: :roles, on_delete: :cascade }
|
|
5
|
+
t.references :user, null: false, type: :<%= primary_key_type %>, index: true
|
|
6
|
+
<% if tenant_scoped? %>
|
|
7
|
+
t.references :tenant, null: true, type: :<%= primary_key_type %>, index: true
|
|
8
|
+
<% end %>
|
|
6
9
|
|
|
7
10
|
t.timestamps
|
|
8
11
|
end
|
|
12
|
+
<% if tenant_scoped? %>
|
|
13
|
+
|
|
14
|
+
add_index :user_roles, [:user_id, :role_id, :tenant_id], unique: true, name: "index_user_roles_unique"
|
|
15
|
+
<% else %>
|
|
9
16
|
|
|
10
|
-
add_index :user_roles, :user_id
|
|
11
17
|
add_index :user_roles, [:user_id, :role_id], unique: true
|
|
18
|
+
<% end %>
|
|
12
19
|
end
|
|
13
20
|
end
|
|
@@ -14,6 +14,21 @@ Rbacan.configure do |config|
|
|
|
14
14
|
# config.user_role_table = "user_roles"
|
|
15
15
|
# config.role_permission_table = "role_permissions"
|
|
16
16
|
|
|
17
|
+
# Primary key type for generated migrations.
|
|
18
|
+
# Set to :uuid if your app uses UUID primary keys.
|
|
19
|
+
# When nil, auto-detects from your Rails generator config (primary_key_type).
|
|
20
|
+
# config.primary_key_type = :uuid
|
|
21
|
+
|
|
22
|
+
# Enable tenant scoping for roles and user_roles.
|
|
23
|
+
# When true, adds tenant_id to the roles and user_roles tables,
|
|
24
|
+
# allowing tenant-specific roles and role assignments.
|
|
25
|
+
# Permissions always remain global regardless of this setting.
|
|
26
|
+
# config.tenant_scoped = false
|
|
27
|
+
|
|
28
|
+
# The name of your tenant model class (default: "Tenant").
|
|
29
|
+
# Only used when tenant_scoped is true.
|
|
30
|
+
# config.tenant_class = "Tenant"
|
|
31
|
+
|
|
17
32
|
# Authorization failure handling:
|
|
18
33
|
# :raise — raises Rbacan::NotAuthorized (default)
|
|
19
34
|
# :redirect — redirects to unauthorized_redirect_path
|
|
@@ -5,8 +5,8 @@ module Rbacan
|
|
|
5
5
|
module Generators
|
|
6
6
|
class InstallGenerator < ::Rails::Generators::Base
|
|
7
7
|
include Rails::Generators::Migration
|
|
8
|
-
source_root File.expand_path('
|
|
9
|
-
desc
|
|
8
|
+
source_root File.expand_path('../install/templates', __dir__)
|
|
9
|
+
desc 'Add the migrations for roles and permissions'
|
|
10
10
|
|
|
11
11
|
def self.next_migration_number(path)
|
|
12
12
|
next_migration_number = current_migration_number(path) + 1
|
|
@@ -14,19 +14,38 @@ module Rbacan
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def copy_migrations
|
|
17
|
-
migration_template
|
|
18
|
-
migration_template
|
|
19
|
-
migration_template
|
|
20
|
-
migration_template
|
|
17
|
+
migration_template 'create_permissions.rb', 'db/migrate/create_permissions.rb'
|
|
18
|
+
migration_template 'create_roles.rb', 'db/migrate/create_roles.rb'
|
|
19
|
+
migration_template 'create_role_permissions.rb', 'db/migrate/create_role_permissions.rb'
|
|
20
|
+
migration_template 'create_user_roles.rb', 'db/migrate/create_user_roles.rb'
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def copy_seed
|
|
24
|
-
copy_file 'copy_to_seeds.rb',
|
|
24
|
+
copy_file 'copy_to_seeds.rb', 'db/copy_to_seeds.rb'
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def copy_initializer
|
|
28
28
|
copy_file 'rbacan.rb', 'config/initializers/rbacan.rb'
|
|
29
29
|
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
# Resolves the primary key type for migration templates.
|
|
34
|
+
# Checks the explicit Rbacan config first, then the Rails generator config.
|
|
35
|
+
def primary_key_type
|
|
36
|
+
configured = Rbacan.primary_key_type
|
|
37
|
+
configured ||= begin
|
|
38
|
+
Rails.configuration.generators.options.dig(:active_record, :primary_key_type)
|
|
39
|
+
rescue StandardError
|
|
40
|
+
nil
|
|
41
|
+
end
|
|
42
|
+
configured || :bigint
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Whether tenant scoping is enabled.
|
|
46
|
+
def tenant_scoped?
|
|
47
|
+
Rbacan.tenant_scoped
|
|
48
|
+
end
|
|
30
49
|
end
|
|
31
50
|
end
|
|
32
51
|
end
|
data/lib/rbacan/permittable.rb
CHANGED
|
@@ -7,72 +7,99 @@ module Rbacan
|
|
|
7
7
|
included do
|
|
8
8
|
has_many :user_roles,
|
|
9
9
|
class_name: Rbacan.user_role_class,
|
|
10
|
-
dependent:
|
|
10
|
+
dependent: :destroy
|
|
11
11
|
accepts_nested_attributes_for :user_roles
|
|
12
12
|
has_many :roles,
|
|
13
13
|
class_name: Rbacan.role_class,
|
|
14
|
-
through:
|
|
14
|
+
through: :user_roles
|
|
15
15
|
|
|
16
16
|
# Returns users that have the given role (by name).
|
|
17
|
-
scope :with_role,
|
|
17
|
+
scope :with_role, lambda { |role_name|
|
|
18
18
|
joins(:roles).where(Rbacan.role_table => { name: role_name.to_s })
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
# Returns users that have the given permission via any of their roles.
|
|
22
|
-
scope :with_permission,
|
|
22
|
+
scope :with_permission, lambda { |permission_name|
|
|
23
23
|
joins(roles: { role_permissions: :permission })
|
|
24
24
|
.where(Rbacan.permission_table => { name: permission_name.to_s })
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
# Assigns a role to the user. Idempotent — safe to call multiple times.
|
|
28
|
-
#
|
|
29
|
-
def assign_role(role_name)
|
|
28
|
+
# When tenant_scoped is enabled, pass tenant_id: to scope the assignment.
|
|
29
|
+
def assign_role(role_name, tenant_id: nil)
|
|
30
30
|
assigned_role = Rbacan.role_class.constantize.find_by_name(role_name.to_s)
|
|
31
31
|
raise ArgumentError, "Role '#{role_name}' not found" unless assigned_role
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
attrs = { role_id: assigned_role.id }
|
|
34
|
+
attrs[:tenant_id] = tenant_id if Rbacan.tenant_scoped
|
|
35
|
+
user_roles.find_or_create_by(attrs)
|
|
34
36
|
end
|
|
35
37
|
|
|
36
38
|
# Removes a role from the user.
|
|
37
|
-
#
|
|
38
|
-
|
|
39
|
-
def remove_role(role_name)
|
|
39
|
+
# When tenant_scoped is enabled, pass tenant_id: to remove from a specific tenant.
|
|
40
|
+
def remove_role(role_name, tenant_id: nil)
|
|
40
41
|
removed_role = Rbacan.role_class.constantize.find_by_name(role_name.to_s)
|
|
41
42
|
return unless removed_role
|
|
42
43
|
|
|
43
|
-
|
|
44
|
+
scope = user_roles.where(role_id: removed_role.id)
|
|
45
|
+
scope = scope.where(tenant_id: tenant_id) if Rbacan.tenant_scoped
|
|
46
|
+
scope.destroy_all
|
|
44
47
|
end
|
|
45
48
|
|
|
46
49
|
# Returns true if the user has the named permission via any of their roles.
|
|
47
|
-
# Fix: was two queries; now a single EXISTS query via association joins.
|
|
48
50
|
def can?(permission_name)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
roles
|
|
52
|
+
.joins(role_permissions: :permission)
|
|
53
|
+
.where(Rbacan.permission_table => { name: permission_name.to_s })
|
|
54
|
+
.exists?
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Returns true if the user has the named permission in a specific tenant context.
|
|
58
|
+
# Checks both global role assignments (tenant_id NULL) and tenant-specific ones.
|
|
59
|
+
def can_in_tenant?(permission_name, tenant_id)
|
|
60
|
+
roles
|
|
61
|
+
.joins(role_permissions: :permission)
|
|
62
|
+
.where(Rbacan.permission_table => { name: permission_name.to_s })
|
|
63
|
+
.where(Rbacan.user_role_table => { tenant_id: [tenant_id, nil] })
|
|
64
|
+
.exists?
|
|
53
65
|
end
|
|
54
66
|
|
|
55
67
|
# Returns true if the user has the named role.
|
|
56
68
|
def has_role?(role_name)
|
|
57
|
-
|
|
69
|
+
roles.where(name: role_name.to_s).exists?
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Returns true if the user has the named role in a specific tenant context.
|
|
73
|
+
# Checks both global role assignments (tenant_id NULL) and tenant-specific ones.
|
|
74
|
+
def has_role_in_tenant?(role_name, tenant_id)
|
|
75
|
+
user_roles
|
|
76
|
+
.joins(:role)
|
|
77
|
+
.where(Rbacan.role_table => { name: role_name.to_s })
|
|
78
|
+
.where(Rbacan.user_role_table => { tenant_id: [tenant_id, nil] })
|
|
79
|
+
.exists?
|
|
58
80
|
end
|
|
59
81
|
|
|
60
82
|
# Returns true if the user has ANY of the listed roles.
|
|
61
83
|
def has_any_role?(*role_names)
|
|
62
|
-
|
|
84
|
+
roles.where(name: role_names.map(&:to_s)).exists?
|
|
63
85
|
end
|
|
64
86
|
|
|
65
87
|
# Returns true if the user has ALL of the listed permissions.
|
|
66
|
-
# Uses a single query: counts distinct matching permissions and compares
|
|
67
|
-
# to the requested set size.
|
|
68
88
|
def can_all?(*permission_names)
|
|
69
89
|
names = permission_names.map(&:to_s)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
90
|
+
roles
|
|
91
|
+
.joins(role_permissions: :permission)
|
|
92
|
+
.where(Rbacan.permission_table => { name: names })
|
|
93
|
+
.select("#{Rbacan.permission_table}.name")
|
|
94
|
+
.distinct
|
|
95
|
+
.count == names.uniq.size
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Returns roles assigned to this user for a specific tenant.
|
|
99
|
+
# Includes global role assignments (tenant_id NULL).
|
|
100
|
+
def roles_for_tenant(tenant_id)
|
|
101
|
+
roles
|
|
102
|
+
.where(Rbacan.user_role_table => { tenant_id: [tenant_id, nil] })
|
|
76
103
|
end
|
|
77
104
|
end
|
|
78
105
|
end
|
data/lib/rbacan/version.rb
CHANGED
data/lib/rbacan.rb
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
6
|
-
require
|
|
7
|
-
require
|
|
8
|
-
require
|
|
1
|
+
require 'rbacan/version'
|
|
2
|
+
require 'rbacan/not_authorized'
|
|
3
|
+
require 'rbacan/permittable'
|
|
4
|
+
require 'rbacan/engine'
|
|
5
|
+
require 'rbacan/roles_and_permissions'
|
|
6
|
+
require 'rbacan/authorization'
|
|
7
|
+
require 'rbacan/view_helpers'
|
|
8
|
+
require 'rbacan/route_constraint'
|
|
9
9
|
|
|
10
10
|
module Rbacan
|
|
11
11
|
mattr_accessor :permittable_class
|
|
@@ -39,6 +39,33 @@ module Rbacan
|
|
|
39
39
|
mattr_accessor :unauthorized_redirect_path
|
|
40
40
|
@@unauthorized_redirect_path = '/'
|
|
41
41
|
|
|
42
|
+
# Primary key type for generated migrations.
|
|
43
|
+
# nil = auto-detect from Rails generator config (primary_key_type).
|
|
44
|
+
# Set to :uuid for UUID primary keys, or :bigint for standard integer keys.
|
|
45
|
+
mattr_accessor :primary_key_type
|
|
46
|
+
@@primary_key_type = nil
|
|
47
|
+
|
|
48
|
+
# When true, adds tenant_id to roles and user_roles tables,
|
|
49
|
+
# enabling tenant-scoped roles and role assignments.
|
|
50
|
+
# Permissions remain global (no tenant_id) regardless of this setting.
|
|
51
|
+
mattr_accessor :tenant_scoped
|
|
52
|
+
@@tenant_scoped = false
|
|
53
|
+
|
|
54
|
+
# The name of your tenant model class (default: "Tenant").
|
|
55
|
+
# Only used when tenant_scoped is true.
|
|
56
|
+
mattr_accessor :tenant_class
|
|
57
|
+
@@tenant_class = 'Tenant'
|
|
58
|
+
|
|
59
|
+
# Resolves the effective primary key type.
|
|
60
|
+
# Checks the explicit config first, then falls back to the Rails generator config.
|
|
61
|
+
def self.resolve_primary_key_type
|
|
62
|
+
return primary_key_type if primary_key_type.present?
|
|
63
|
+
|
|
64
|
+
Rails.configuration.generators.options.dig(:active_record, :primary_key_type)
|
|
65
|
+
rescue StandardError
|
|
66
|
+
nil
|
|
67
|
+
end
|
|
68
|
+
|
|
42
69
|
def self.create_role(role_name)
|
|
43
70
|
@@role_class.constantize.create(name: role_name)
|
|
44
71
|
end
|
|
@@ -51,12 +78,12 @@ module Rbacan
|
|
|
51
78
|
chosen_role = @@role_class.constantize.find_by_name(role_name)
|
|
52
79
|
given_permission = @@permission_class.constantize.find_by_name(permission_name)
|
|
53
80
|
@@role_permission_class.constantize.create(
|
|
54
|
-
role_id:
|
|
81
|
+
role_id: chosen_role.id,
|
|
55
82
|
permission_id: given_permission.id
|
|
56
83
|
)
|
|
57
84
|
end
|
|
58
85
|
|
|
59
|
-
def self.configure
|
|
86
|
+
def self.configure
|
|
60
87
|
yield self
|
|
61
88
|
end
|
|
62
89
|
|
data/rbacan.gemspec
CHANGED
|
@@ -1,42 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
lib = File.expand_path("../lib", __FILE__)
|
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
-
require
|
|
3
|
+
require 'rbacan/version'
|
|
5
4
|
|
|
6
5
|
Gem::Specification.new do |spec|
|
|
7
|
-
spec.name =
|
|
6
|
+
spec.name = 'rbacan'
|
|
8
7
|
spec.version = Rbacan::VERSION
|
|
9
|
-
spec.authors = [
|
|
10
|
-
spec.email = [
|
|
8
|
+
spec.authors = ['hamdi']
|
|
9
|
+
spec.email = ['hamdi_amiche@outlook.fr']
|
|
11
10
|
|
|
12
|
-
spec.summary =
|
|
13
|
-
spec.description =
|
|
14
|
-
spec.homepage =
|
|
15
|
-
spec.licenses = [
|
|
11
|
+
spec.summary = 'A gem to give permission access to users based on their roles'
|
|
12
|
+
spec.description = 'RBACan is a Role-Based Access Control tool to control user access to the functionalities of your application'
|
|
13
|
+
spec.homepage = 'https://github.com/hamdi777/RBACan'
|
|
14
|
+
spec.licenses = ['MIT']
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
|
23
|
-
end
|
|
16
|
+
raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.' unless spec.respond_to?(:metadata)
|
|
17
|
+
|
|
18
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
|
19
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
20
|
+
spec.metadata['changelog_uri'] = 'https://github.com/hamdi777/RBACan/blob/master/CHANGELOG.md'
|
|
24
21
|
|
|
25
|
-
spec.files
|
|
22
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
26
23
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
27
24
|
end
|
|
28
|
-
spec.bindir =
|
|
25
|
+
spec.bindir = 'exe'
|
|
29
26
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
30
|
-
spec.require_paths = [
|
|
31
|
-
spec.required_ruby_version =
|
|
27
|
+
spec.require_paths = ['lib']
|
|
28
|
+
spec.required_ruby_version = '>= 3.0'
|
|
32
29
|
|
|
33
|
-
spec.add_dependency 'rails', '
|
|
30
|
+
spec.add_dependency 'rails', '>= 5.2', '< 9'
|
|
34
31
|
|
|
35
|
-
spec.add_development_dependency
|
|
36
|
-
spec.add_development_dependency
|
|
37
|
-
spec.add_development_dependency
|
|
38
|
-
spec.add_development_dependency
|
|
39
|
-
spec.add_development_dependency
|
|
40
|
-
spec.add_development_dependency
|
|
41
|
-
spec.add_development_dependency
|
|
32
|
+
spec.add_development_dependency 'activerecord', '>= 5.2', '< 9'
|
|
33
|
+
spec.add_development_dependency 'bundler', '>= 2.0'
|
|
34
|
+
spec.add_development_dependency 'generator_spec', '~> 0.9.4'
|
|
35
|
+
spec.add_development_dependency 'railties', '>= 5.2', '< 9'
|
|
36
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
|
37
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
38
|
+
spec.add_development_dependency 'sqlite3'
|
|
42
39
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rbacan
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- hamdi
|
|
@@ -13,114 +13,132 @@ dependencies:
|
|
|
13
13
|
name: rails
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
15
15
|
requirements:
|
|
16
|
-
- - "
|
|
16
|
+
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
18
|
version: '5.2'
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '9'
|
|
19
22
|
type: :runtime
|
|
20
23
|
prerelease: false
|
|
21
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
25
|
requirements:
|
|
23
|
-
- - "
|
|
26
|
+
- - ">="
|
|
24
27
|
- !ruby/object:Gem::Version
|
|
25
28
|
version: '5.2'
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '9'
|
|
26
32
|
- !ruby/object:Gem::Dependency
|
|
27
|
-
name:
|
|
33
|
+
name: activerecord
|
|
28
34
|
requirement: !ruby/object:Gem::Requirement
|
|
29
35
|
requirements:
|
|
30
|
-
- - "
|
|
36
|
+
- - ">="
|
|
31
37
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '2
|
|
38
|
+
version: '5.2'
|
|
39
|
+
- - "<"
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '9'
|
|
33
42
|
type: :development
|
|
34
43
|
prerelease: false
|
|
35
44
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
45
|
requirements:
|
|
37
|
-
- - "
|
|
46
|
+
- - ">="
|
|
38
47
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '2
|
|
48
|
+
version: '5.2'
|
|
49
|
+
- - "<"
|
|
50
|
+
- !ruby/object:Gem::Version
|
|
51
|
+
version: '9'
|
|
40
52
|
- !ruby/object:Gem::Dependency
|
|
41
|
-
name:
|
|
53
|
+
name: bundler
|
|
42
54
|
requirement: !ruby/object:Gem::Requirement
|
|
43
55
|
requirements:
|
|
44
|
-
- - "
|
|
56
|
+
- - ">="
|
|
45
57
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '
|
|
58
|
+
version: '2.0'
|
|
47
59
|
type: :development
|
|
48
60
|
prerelease: false
|
|
49
61
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
62
|
requirements:
|
|
51
|
-
- - "
|
|
63
|
+
- - ">="
|
|
52
64
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '
|
|
65
|
+
version: '2.0'
|
|
54
66
|
- !ruby/object:Gem::Dependency
|
|
55
|
-
name:
|
|
67
|
+
name: generator_spec
|
|
56
68
|
requirement: !ruby/object:Gem::Requirement
|
|
57
69
|
requirements:
|
|
58
70
|
- - "~>"
|
|
59
71
|
- !ruby/object:Gem::Version
|
|
60
|
-
version:
|
|
72
|
+
version: 0.9.4
|
|
61
73
|
type: :development
|
|
62
74
|
prerelease: false
|
|
63
75
|
version_requirements: !ruby/object:Gem::Requirement
|
|
64
76
|
requirements:
|
|
65
77
|
- - "~>"
|
|
66
78
|
- !ruby/object:Gem::Version
|
|
67
|
-
version:
|
|
79
|
+
version: 0.9.4
|
|
68
80
|
- !ruby/object:Gem::Dependency
|
|
69
|
-
name:
|
|
81
|
+
name: railties
|
|
70
82
|
requirement: !ruby/object:Gem::Requirement
|
|
71
83
|
requirements:
|
|
72
|
-
- - "
|
|
84
|
+
- - ">="
|
|
73
85
|
- !ruby/object:Gem::Version
|
|
74
|
-
version:
|
|
86
|
+
version: '5.2'
|
|
87
|
+
- - "<"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '9'
|
|
75
90
|
type: :development
|
|
76
91
|
prerelease: false
|
|
77
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
78
93
|
requirements:
|
|
79
|
-
- - "
|
|
94
|
+
- - ">="
|
|
80
95
|
- !ruby/object:Gem::Version
|
|
81
|
-
version:
|
|
96
|
+
version: '5.2'
|
|
97
|
+
- - "<"
|
|
98
|
+
- !ruby/object:Gem::Version
|
|
99
|
+
version: '9'
|
|
82
100
|
- !ruby/object:Gem::Dependency
|
|
83
|
-
name:
|
|
101
|
+
name: rake
|
|
84
102
|
requirement: !ruby/object:Gem::Requirement
|
|
85
103
|
requirements:
|
|
86
104
|
- - "~>"
|
|
87
105
|
- !ruby/object:Gem::Version
|
|
88
|
-
version: '
|
|
106
|
+
version: '13.0'
|
|
89
107
|
type: :development
|
|
90
108
|
prerelease: false
|
|
91
109
|
version_requirements: !ruby/object:Gem::Requirement
|
|
92
110
|
requirements:
|
|
93
111
|
- - "~>"
|
|
94
112
|
- !ruby/object:Gem::Version
|
|
95
|
-
version: '
|
|
113
|
+
version: '13.0'
|
|
96
114
|
- !ruby/object:Gem::Dependency
|
|
97
|
-
name:
|
|
115
|
+
name: rspec
|
|
98
116
|
requirement: !ruby/object:Gem::Requirement
|
|
99
117
|
requirements:
|
|
100
118
|
- - "~>"
|
|
101
119
|
- !ruby/object:Gem::Version
|
|
102
|
-
version: '
|
|
120
|
+
version: '3.0'
|
|
103
121
|
type: :development
|
|
104
122
|
prerelease: false
|
|
105
123
|
version_requirements: !ruby/object:Gem::Requirement
|
|
106
124
|
requirements:
|
|
107
125
|
- - "~>"
|
|
108
126
|
- !ruby/object:Gem::Version
|
|
109
|
-
version: '
|
|
127
|
+
version: '3.0'
|
|
110
128
|
- !ruby/object:Gem::Dependency
|
|
111
129
|
name: sqlite3
|
|
112
130
|
requirement: !ruby/object:Gem::Requirement
|
|
113
131
|
requirements:
|
|
114
|
-
- - "
|
|
132
|
+
- - ">="
|
|
115
133
|
- !ruby/object:Gem::Version
|
|
116
|
-
version: '
|
|
134
|
+
version: '0'
|
|
117
135
|
type: :development
|
|
118
136
|
prerelease: false
|
|
119
137
|
version_requirements: !ruby/object:Gem::Requirement
|
|
120
138
|
requirements:
|
|
121
|
-
- - "
|
|
139
|
+
- - ">="
|
|
122
140
|
- !ruby/object:Gem::Version
|
|
123
|
-
version: '
|
|
141
|
+
version: '0'
|
|
124
142
|
description: RBACan is a Role-Based Access Control tool to control user access to
|
|
125
143
|
the functionalities of your application
|
|
126
144
|
email:
|
|
@@ -133,6 +151,7 @@ files:
|
|
|
133
151
|
- ".rspec"
|
|
134
152
|
- ".travis.yml"
|
|
135
153
|
- CHANGELOG.md
|
|
154
|
+
- CLAUDE.md
|
|
136
155
|
- CODE_OF_CONDUCT.md
|
|
137
156
|
- Gemfile
|
|
138
157
|
- Gemfile.lock
|
|
@@ -184,7 +203,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
184
203
|
- !ruby/object:Gem::Version
|
|
185
204
|
version: '0'
|
|
186
205
|
requirements: []
|
|
187
|
-
rubygems_version: 3.6.
|
|
206
|
+
rubygems_version: 3.6.9
|
|
188
207
|
specification_version: 4
|
|
189
208
|
summary: A gem to give permission access to users based on their roles
|
|
190
209
|
test_files: []
|