role_core 0.0.25 → 0.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +28 -36
- data/Rakefile +1 -1
- data/lib/generators/role_core/config/config_generator.rb +1 -1
- data/lib/generators/role_core/model/model_generator.rb +1 -1
- data/lib/role_core/computed_permissions.rb +4 -4
- data/lib/role_core/concerns/models/role.rb +1 -1
- data/lib/role_core/contrib/can_can_can_permission.rb +1 -1
- data/lib/role_core/mapper.rb +3 -3
- data/lib/role_core/permission.rb +4 -8
- data/lib/role_core/permission_set.rb +11 -12
- data/lib/role_core/version.rb +1 -1
- data/lib/role_core.rb +2 -6
- metadata +16 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39af11ea76fcb0c8a0ff489e44f929ed64fbdd18ae64f5f59f6768a000f8895a
|
4
|
+
data.tar.gz: 4d7b1901033d603da7c7f2b6247f19f120cc18ee1ccf3dbab5045a7b2a385098
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8649c664d4da57eb8665308dd58d2b1795dd619ff6b5e9be9611904b816e66ecbb28482bf25fa857e51a2b964966f655f2e9bddfb55a2c6c36a3506f86b927ab
|
7
|
+
data.tar.gz: d020474094ece60f11a0a8aa350acfa97598eecd492d106799327a10942966d4287fc0ffe4792658143a7d269b7e023e130b6d478723857be273151e95ffd000
|
data/README.md
CHANGED
@@ -76,8 +76,8 @@ In fact, the essence of permissions is Hash, keys are permissions, and values ar
|
|
76
76
|
|
77
77
|
### Management UI
|
78
78
|
|
79
|
-
Building a management UI is difficult,
|
80
|
-
but virtual model technique will translates permissions to a virtual model's (a class that conforms to ActiveModel) attributes,
|
79
|
+
Building a management UI is difficult,
|
80
|
+
but virtual model technique will translates permissions to a virtual model's (a class that conforms to ActiveModel) attributes,
|
81
81
|
and groups will translates to nested virtual models,
|
82
82
|
that means you can use all Rails view helpers including the mighty form builder,
|
83
83
|
and can benefit to Strong Parameter.
|
@@ -98,7 +98,13 @@ RoleCore can be working with CanCanCan, Pundit easily and happily.
|
|
98
98
|
Add this line to your Gemfile:
|
99
99
|
|
100
100
|
```ruby
|
101
|
-
gem
|
101
|
+
gem "role_core"
|
102
|
+
```
|
103
|
+
|
104
|
+
if your Rails < 7 or met `visit_Psych_Nodes_Alias': Unknown alias: redis (Psych::BadAlias)`, add this line:
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
gem "psych", "~> 3.3"
|
102
108
|
```
|
103
109
|
|
104
110
|
Then execute:
|
@@ -138,6 +144,8 @@ $ bin/rails g role_core:model
|
|
138
144
|
Permissions are defined in `config/initializers/role_core.rb`,
|
139
145
|
checking it to know how to define permissions.
|
140
146
|
|
147
|
+
(If you want to define permissions in runtime, check [Dynamic Permissions](https://github.com/rails-engine/role_core#dynamic-permissions))
|
148
|
+
|
141
149
|
In addition, there also includes a directive about how to integrate with CanCanCan.
|
142
150
|
|
143
151
|
#### I18n
|
@@ -305,7 +313,7 @@ class PostPolicy
|
|
305
313
|
def update?
|
306
314
|
user.permissions.post.update?
|
307
315
|
end
|
308
|
-
|
316
|
+
|
309
317
|
def update_my_own?
|
310
318
|
return true if user.permissions.post.update?
|
311
319
|
return unless user.permissions.post.update_my_own?
|
@@ -325,7 +333,7 @@ Open your User model:
|
|
325
333
|
Add a delegate to User model:
|
326
334
|
|
327
335
|
```ruby
|
328
|
-
|
336
|
+
delegate :computed_permissions, to: :role
|
329
337
|
```
|
330
338
|
|
331
339
|
- For a user who has multiple roles:
|
@@ -340,6 +348,20 @@ Open your User model:
|
|
340
348
|
|
341
349
|
Open `app/models/ability.rb`, add `user.computed_permissions.call(self, user)` to `initialize` method.
|
342
350
|
|
351
|
+
```ruby
|
352
|
+
class Ability
|
353
|
+
include CanCan::Ability
|
354
|
+
|
355
|
+
def initialize(user)
|
356
|
+
# Apply RoleCole managing permissions
|
357
|
+
user.computed_permissions.call(self, user)
|
358
|
+
|
359
|
+
# You still can add other permissions
|
360
|
+
can :read_public, :all
|
361
|
+
end
|
362
|
+
end
|
363
|
+
```
|
364
|
+
|
343
365
|
You can check dummy app for better understanding.
|
344
366
|
|
345
367
|
### Management UI
|
@@ -366,37 +388,7 @@ You can archive this goal by:
|
|
366
388
|
|
367
389
|
By design, RoleCore is for static permissions, but dynamic permissions is easy to support.
|
368
390
|
|
369
|
-
|
370
|
-
|
371
|
-
Here's an example:
|
372
|
-
|
373
|
-
- Design a model to persisting dynamic permissions, e.g `DynamicPermission(id: bigint, name: string, default: bool)`
|
374
|
-
- Add `dynamic_permissions` column (`text` type) to Role model to persisting dynamic permissions' configuration, and in your model `serialize :dynamic_permissions, Hash`
|
375
|
-
- Generate dynamic permissions set in runtime
|
376
|
-
```ruby
|
377
|
-
# Create a new permission set to containerize dynamic permissions
|
378
|
-
# `"Dynamic"` can be named to other but must be a valid Ruby class name,
|
379
|
-
# that's a hacking for `ActiveModel::Naming`,
|
380
|
-
# and can be used as I18n key, in this case, the key is `role_core/models/dynamic`.
|
381
|
-
dynamic_permission_set_class = PermissionSet.derive "Dynamic"
|
382
|
-
|
383
|
-
# Fetching dynamic permissions
|
384
|
-
dynamic_permissions = DynamicPermission.all
|
385
|
-
|
386
|
-
# Mapping dynamic permissions to permission set
|
387
|
-
dynamic_permission_set_class.draw do
|
388
|
-
dynamic_permissions.each do |p|
|
389
|
-
permission p.name, default: p.default
|
390
|
-
end
|
391
|
-
end
|
392
|
-
```
|
393
|
-
- Create a instance of this dynamic permission set
|
394
|
-
```ruby
|
395
|
-
dynamic_permissions = dynamic_permission_set_class.new(role.dynamic_permissions)
|
396
|
-
```
|
397
|
-
- You can use the `dynamic_permissions` now
|
398
|
-
|
399
|
-
Rails' `serialize` is static so you must do serialize and deserialize manually, you can wrap these logic into model.
|
391
|
+
See [example](test/dummy/app/models/team.rb) in dummy app and relates [view](test/dummy/app/views/teams/_permissions.html.erb) for details.
|
400
392
|
|
401
393
|
## Contributing
|
402
394
|
|
data/Rakefile
CHANGED
@@ -16,7 +16,7 @@ RDoc::Task.new(:rdoc) do |rdoc|
|
|
16
16
|
rdoc.rdoc_files.include("lib/**/*.rb")
|
17
17
|
end
|
18
18
|
|
19
|
-
APP_RAKEFILE = File.expand_path("
|
19
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
20
20
|
load "rails/tasks/engine.rake"
|
21
21
|
|
22
22
|
load "rails/tasks/statistics.rake"
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RoleCore
|
4
4
|
module Generators
|
5
5
|
class ConfigGenerator < Rails::Generators::Base
|
6
|
-
source_root File.expand_path("
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
7
7
|
|
8
8
|
def generate_config
|
9
9
|
copy_file "role_core.rb", "config/initializers/role_core.rb"
|
@@ -11,7 +11,7 @@ module RoleCore
|
|
11
11
|
@model_name = options[:model_name]
|
12
12
|
@subject = options[:subject]
|
13
13
|
@action = options[:action] || name
|
14
|
-
@options = options.except(:model, :model_name, :subject, :action)
|
14
|
+
@options = options.except(:model, :model_name, :subject, :action, :_namespace, :_priority, :_callable)
|
15
15
|
@block = block
|
16
16
|
end
|
17
17
|
|
data/lib/role_core/mapper.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module RoleCore
|
4
4
|
class Mapper
|
5
|
-
def initialize(set,
|
5
|
+
def initialize(set, constraints = {}) # :nodoc:
|
6
6
|
@constraints = constraints
|
7
7
|
@constraints[:_namespace] ||= []
|
8
8
|
@set = set
|
@@ -13,7 +13,7 @@ module RoleCore
|
|
13
13
|
self
|
14
14
|
end
|
15
15
|
|
16
|
-
def group(name,
|
16
|
+
def group(name, constraints = {}, &block)
|
17
17
|
raise ArgumentError, "`name` can't be blank" if name.blank?
|
18
18
|
raise ArgumentError, "must provide a block" unless block_given?
|
19
19
|
|
@@ -21,7 +21,7 @@ module RoleCore
|
|
21
21
|
constraints[:_namespace] << name
|
22
22
|
|
23
23
|
sub_permission_set_class =
|
24
|
-
if @set.nested_classes.
|
24
|
+
if @set.nested_classes.key?(name)
|
25
25
|
@set.nested_classes[name]
|
26
26
|
else
|
27
27
|
klass_name = constraints[:_namespace].map { |n| n.to_s.classify }.join("::")
|
data/lib/role_core/permission.rb
CHANGED
@@ -4,25 +4,21 @@ module RoleCore
|
|
4
4
|
class Permission
|
5
5
|
attr_reader :name, :namespace, :priority, :callable
|
6
6
|
|
7
|
-
def initialize(name, _namespace: [], _priority: 0, _callable: false, **
|
7
|
+
def initialize(name, _namespace: [], _priority: 0, _callable: false, **_options, &_block)
|
8
8
|
@name = name
|
9
9
|
@namespace = _namespace
|
10
10
|
@priority = _priority
|
11
11
|
@callable = _callable
|
12
12
|
end
|
13
13
|
|
14
|
-
def call(
|
14
|
+
def call(_context, *)
|
15
15
|
raise NotImplementedError
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
instance_values.hash
|
20
|
-
end
|
18
|
+
delegate :hash, to: :instance_values
|
21
19
|
|
22
20
|
def ==(other)
|
23
|
-
unless other.is_a?(RoleCore::Permission)
|
24
|
-
return false
|
25
|
-
end
|
21
|
+
return false unless other.is_a?(RoleCore::Permission)
|
26
22
|
|
27
23
|
instance_values == other.instance_values
|
28
24
|
end
|
@@ -8,9 +8,7 @@ module RoleCore
|
|
8
8
|
|
9
9
|
def computed_permissions(include_nesting: true)
|
10
10
|
permissions = self.class.registered_permissions.slice(*permitted_permission_names).values
|
11
|
-
if include_nesting && nested_attributes.any?
|
12
|
-
permissions.concat nested_attributes.values.map(&:computed_permissions).flatten!
|
13
|
-
end
|
11
|
+
permissions.concat nested_attributes.values.map(&:computed_permissions).flatten! if include_nesting && nested_attributes.any?
|
14
12
|
|
15
13
|
ComputedPermissions.new(permissions)
|
16
14
|
end
|
@@ -29,17 +27,13 @@ module RoleCore
|
|
29
27
|
end
|
30
28
|
|
31
29
|
def permission_class=(klass)
|
32
|
-
unless klass && klass < Permission
|
33
|
-
raise ArgumentError, "#{klass} should be sub-class of #{Permission}."
|
34
|
-
end
|
30
|
+
raise ArgumentError, "#{klass} should be sub-class of #{Permission}." unless klass && klass < Permission
|
35
31
|
|
36
32
|
@permission_class = klass
|
37
33
|
end
|
38
34
|
|
39
|
-
def draw(
|
40
|
-
unless block_given?
|
41
|
-
raise ArgumentError, "must provide a block"
|
42
|
-
end
|
35
|
+
def draw(constraints = {}, &block)
|
36
|
+
raise ArgumentError, "must provide a block" unless block_given?
|
43
37
|
|
44
38
|
Mapper.new(self, constraints).instance_exec(&block)
|
45
39
|
|
@@ -50,11 +44,16 @@ module RoleCore
|
|
50
44
|
@registered_permissions ||= ActiveSupport::HashWithIndifferentAccess.new
|
51
45
|
end
|
52
46
|
|
53
|
-
def register_permission(name, default = false,
|
47
|
+
def register_permission(name, default = false, options = {}, &block)
|
54
48
|
raise ArgumentError, "`name` can't be blank" if name.blank?
|
55
49
|
|
56
50
|
attribute name, :boolean, default: default
|
57
|
-
registered_permissions[name] = permission_class.new name, options, &block
|
51
|
+
registered_permissions[name] = permission_class.new name, **options, &block
|
52
|
+
end
|
53
|
+
|
54
|
+
PERMITTED_ATTRIBUTE_CLASSES = [Symbol].freeze
|
55
|
+
def permitted_attribute_classes
|
56
|
+
PERMITTED_ATTRIBUTE_CLASSES
|
58
57
|
end
|
59
58
|
end
|
60
59
|
end
|
data/lib/role_core/version.rb
CHANGED
data/lib/role_core.rb
CHANGED
@@ -17,9 +17,7 @@ module RoleCore
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def permission_set_class=(klass)
|
20
|
-
unless klass && klass < PermissionSet
|
21
|
-
raise ArgumentError, "#{klass} should be sub-class of #{PermissionSet}."
|
22
|
-
end
|
20
|
+
raise ArgumentError, "#{klass} should be sub-class of #{PermissionSet}." unless klass && klass < PermissionSet
|
23
21
|
|
24
22
|
@permission_set_class = klass.derive "Global"
|
25
23
|
end
|
@@ -29,9 +27,7 @@ module RoleCore
|
|
29
27
|
end
|
30
28
|
|
31
29
|
def permission_class=(klass)
|
32
|
-
unless klass && klass < Permission
|
33
|
-
raise ArgumentError, "#{klass} should be sub-class of #{Permission}."
|
34
|
-
end
|
30
|
+
raise ArgumentError, "#{klass} should be sub-class of #{Permission}." unless klass && klass < Permission
|
35
31
|
|
36
32
|
@permission_class = klass
|
37
33
|
end
|
metadata
CHANGED
@@ -1,55 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: role_core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.28
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jasl
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-03-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: options_model
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 0.0.15
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '1.0'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
29
|
+
version: 0.0.15
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '1.0'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
|
-
name:
|
34
|
+
name: rails
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
37
|
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version:
|
39
|
+
version: '5'
|
40
40
|
- - "<"
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version: '
|
42
|
+
version: '8'
|
43
43
|
type: :runtime
|
44
44
|
prerelease: false
|
45
45
|
version_requirements: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
47
|
- - ">="
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version:
|
49
|
+
version: '5'
|
50
50
|
- - "<"
|
51
51
|
- !ruby/object:Gem::Version
|
52
|
-
version: '
|
52
|
+
version: '8'
|
53
53
|
description: RoleCore is a Rails engine which could provide essential industry of
|
54
54
|
Role-based access control.
|
55
55
|
email:
|
@@ -85,7 +85,7 @@ homepage: https://github.com/rails-engine/role_core
|
|
85
85
|
licenses:
|
86
86
|
- MIT
|
87
87
|
metadata: {}
|
88
|
-
post_install_message:
|
88
|
+
post_install_message:
|
89
89
|
rdoc_options: []
|
90
90
|
require_paths:
|
91
91
|
- lib
|
@@ -100,8 +100,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
100
|
- !ruby/object:Gem::Version
|
101
101
|
version: '0'
|
102
102
|
requirements: []
|
103
|
-
rubygems_version: 3.
|
104
|
-
signing_key:
|
103
|
+
rubygems_version: 3.3.4
|
104
|
+
signing_key:
|
105
105
|
specification_version: 4
|
106
106
|
summary: RoleCore is a Rails engine which could provide essential industry of Role-based
|
107
107
|
access control.
|