role_core 0.0.12 → 0.0.14
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 +204 -10
- data/lib/generators/role_core/config/USAGE +2 -0
- data/lib/generators/role_core/config/config_generator.rb +14 -0
- data/lib/generators/role_core/config/templates/role_core.en.yml +20 -0
- data/lib/generators/role_core/config/templates/role_core.rb +70 -0
- data/lib/generators/role_core/model/USAGE +2 -0
- data/lib/generators/role_core/model/model_generator.rb +13 -0
- data/lib/generators/role_core/model/templates/role.rb +4 -0
- data/lib/role_core/version.rb +1 -1
- metadata +13 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c75876caf7676f2733564e2f0657b8625c798d29ee7de9e45a21bc66312e54d
|
4
|
+
data.tar.gz: 8bfb27b3b34481cb4cf566d3ff336e9450b45020a9109a201d7ac21e1e81194f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c4d3a8e2c38049412bc12f8e048093710ee3f929d9f6cac96525de98ecd6e1f8b4851792e905f8c0c2cc7a467a04cff9512c03d435d585b1c29c3e04b4fb437
|
7
|
+
data.tar.gz: fb14f0557dc1b7349b69e647297ebe3033b97138665b2c5314cccf5456933552aa6b0b6c906f258abf7a55be3f05e59e0e1a77ad26714151738e32e431da66bf
|
data/README.md
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
RoleCore
|
2
2
|
====
|
3
3
|
|
4
|
-
|
4
|
+
RoleCore is a Rails engine which could provide essential industry of Role-based access control.
|
5
5
|
|
6
6
|
<img width="550" alt="2018-03-12 10 12 21" src="https://user-images.githubusercontent.com/5518/37262401-e6c9d604-25dd-11e8-849d-7f7d923d5f18.png">
|
7
7
|
|
8
|
-
|
8
|
+
It's only provides the ability to define permissions and pre-made Role model.
|
9
9
|
|
10
|
-
|
10
|
+
In addition, it's not handle the authentication or authorization,
|
11
|
+
you should integrate with CanCanCan, Pundit or other solutions by yourself.
|
11
12
|
|
12
13
|
## Installation
|
13
14
|
|
@@ -17,13 +18,7 @@ Add this line to your Gemfile:
|
|
17
18
|
gem 'role_core'
|
18
19
|
```
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
```ruby
|
23
|
-
gem 'role_core', github: 'rails-engine/role_core'
|
24
|
-
```
|
25
|
-
|
26
|
-
And then execute:
|
21
|
+
Then execute:
|
27
22
|
|
28
23
|
```sh
|
29
24
|
$ bundle
|
@@ -41,8 +36,207 @@ Then do migrate
|
|
41
36
|
$ bin/rails db:migrate
|
42
37
|
```
|
43
38
|
|
39
|
+
Run config generator
|
40
|
+
|
41
|
+
```sh
|
42
|
+
$ bin/rails g role_core:config
|
43
|
+
```
|
44
|
+
|
45
|
+
Run model generator
|
46
|
+
|
47
|
+
```sh
|
48
|
+
$ bin/rails g role_core:model
|
49
|
+
```
|
50
|
+
|
51
|
+
## Getting Start
|
52
|
+
|
53
|
+
### Define permissions
|
54
|
+
|
55
|
+
Permissions are defined in `config/initializers/role_core.rb`,
|
56
|
+
checking it to know how to define permissions.
|
57
|
+
|
58
|
+
In addition, there also includes a directive about how to integrate with CanCanCan.
|
59
|
+
|
60
|
+
### Hook up to application
|
61
|
+
|
62
|
+
In order to obtain maximum customability, you need to hooking up role(s) to your user model by yourself.
|
63
|
+
|
64
|
+
#### For User who has single role
|
65
|
+
|
66
|
+
##### Create `one-to-many` relationship between Role and User
|
67
|
+
|
68
|
+
Generate `one-to-many` migration, adding `role_id` to `User` model
|
69
|
+
|
70
|
+
```sh
|
71
|
+
$ bin/rails g migration AddRoleToUsers role:references
|
72
|
+
```
|
73
|
+
|
74
|
+
Then do migrate
|
75
|
+
|
76
|
+
```sh
|
77
|
+
$ bin/rails db:migrate
|
78
|
+
```
|
79
|
+
|
80
|
+
Declare `a User belongs to a Role`
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
class User < ApplicationRecord
|
84
|
+
belongs_to :role
|
85
|
+
|
86
|
+
# ...
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
Declare `a Role has many Users`
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
class Role < RoleCore::Role
|
94
|
+
has_many :users
|
95
|
+
end
|
96
|
+
```
|
97
|
+
|
98
|
+
##### Check permission
|
99
|
+
|
100
|
+
Permssions you've defined will translate to a virtual model (a Class which implemented ActiveModel interface),
|
101
|
+
`permission` would be an attribute, `group` would be a nested virtual model (like ActiveRecord's `has_one` association).
|
102
|
+
|
103
|
+
So you can simply check permission like:
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
user.role.permissions.read_public?
|
107
|
+
user.role.permissions.project.read? # `project` is a `group`
|
108
|
+
```
|
109
|
+
|
110
|
+
For better usage, you may delegate the `permissions` from `Role` model to `User`:
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
class User < ApplicationRecord
|
114
|
+
belongs_to :role
|
115
|
+
|
116
|
+
delegate :permissions, to: :role
|
117
|
+
|
118
|
+
# ...
|
119
|
+
end
|
120
|
+
```
|
121
|
+
|
122
|
+
Then you can
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
user.permissions.read_public?
|
126
|
+
user.permissions.project.read?
|
127
|
+
```
|
128
|
+
|
129
|
+
_Keep in mind: fetching `role` will made a SQL query, you may need eager loading to avoid N+1 problem in some cases._
|
130
|
+
|
131
|
+
#### For User who has multiple roles
|
132
|
+
|
133
|
+
##### Create `many-to-many` relationship between Role and User
|
134
|
+
|
135
|
+
Generate a `many-to-many` intervening model
|
136
|
+
|
137
|
+
```sh
|
138
|
+
$ bin/rails g model RoleAssignment user:references role:references
|
139
|
+
```
|
140
|
+
|
141
|
+
Then do migrate
|
142
|
+
|
143
|
+
```sh
|
144
|
+
$ bin/rails db:migrate
|
145
|
+
```
|
146
|
+
|
147
|
+
Declare `a User has many Roles through RoleAssignments`
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
class User < ApplicationRecord
|
151
|
+
has_many :role_assignments, dependent: :destroy
|
152
|
+
has_many :roles, through: :role_assignments
|
153
|
+
|
154
|
+
# ...
|
155
|
+
end
|
156
|
+
```
|
157
|
+
|
158
|
+
Declare `a Role has many Users through RoleAssignments`
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
class Role < RoleCore::Role
|
162
|
+
has_many :role_assignments, dependent: :destroy
|
163
|
+
has_many :users, through: :role_assignments
|
164
|
+
end
|
165
|
+
```
|
166
|
+
|
167
|
+
##### Check permission
|
168
|
+
|
169
|
+
Permssions you've defined will translate to a virtual model (a Class which implemented ActiveModel interface),
|
170
|
+
`permission` would be an attribute, `group` would be a nested virtual model (like ActiveRecord's `has_one` association).
|
171
|
+
|
172
|
+
So you can simply check permission like:
|
173
|
+
|
174
|
+
```ruby
|
175
|
+
user.roles.any? { |role| role.permissions.read_public? }
|
176
|
+
user.roles.any? { |role| role.permissions.project.read? } # `project` is a `group`
|
177
|
+
```
|
178
|
+
|
179
|
+
For better usage, you could declare a `can?` helper method:
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
class User < ApplicationRecord
|
183
|
+
has_many :role_assignments, dependent: :destroy
|
184
|
+
has_many :roles, through: :role_assignments
|
185
|
+
|
186
|
+
def can?(&block)
|
187
|
+
roles.map(&:permissions).any?(&block)
|
188
|
+
end
|
189
|
+
|
190
|
+
# ...
|
191
|
+
end
|
192
|
+
```
|
193
|
+
|
194
|
+
Then you can
|
195
|
+
|
196
|
+
```ruby
|
197
|
+
user.can? { |permissions| permissions.read_public? }
|
198
|
+
user.can? { |permissions| permissions.project.read? }
|
199
|
+
```
|
200
|
+
|
201
|
+
_Keep in mind: fetching `roles` will made a SQL query, you may need eager loading to avoid N+1 problem in some cases._
|
202
|
+
|
203
|
+
### Integrate with CanCanCan
|
204
|
+
|
205
|
+
Open `config/initializers/role_core.rb`, uncomment CanCanCan integration codes and follows samples to define permissions for CanCanCan
|
206
|
+
|
207
|
+
Open your User model:
|
208
|
+
|
209
|
+
- For a user who has single role:
|
210
|
+
|
211
|
+
Add a delegate to User model:
|
212
|
+
|
213
|
+
```ruby
|
214
|
+
delegate :permitted_permissions, to: :role
|
215
|
+
```
|
216
|
+
|
217
|
+
- For a user who has multiple roles:
|
218
|
+
|
219
|
+
Add a `permitted_permissions` public method to User model:
|
220
|
+
|
221
|
+
```ruby
|
222
|
+
def permitted_permissions
|
223
|
+
roles.map(&:permitted_permissions).reduce(RoleCore::ComputedPermissions.new, &:concat)
|
224
|
+
end
|
225
|
+
```
|
226
|
+
|
227
|
+
Open `app/models/ability.rb`, add `user.permitted_permissions.call(self, user)` to `initialize` method.
|
228
|
+
|
229
|
+
You can check RoleCore's Demo (see below) for better understanding.
|
230
|
+
|
231
|
+
### Management UI
|
232
|
+
|
233
|
+
See [RolesController in dummy app](https://github.com/rails-engine/role_core/blob/master/test/dummy/app/controllers/roles_controller.rb)
|
234
|
+
and relates [view](https://github.com/rails-engine/role_core/blob/master/test/dummy/app/views/roles/_form.html.erb).
|
235
|
+
|
44
236
|
## Demo
|
45
237
|
|
238
|
+
The dummy app shows a simple multiple roles with CanCanCan integration includes management UI.
|
239
|
+
|
46
240
|
Clone the repository.
|
47
241
|
|
48
242
|
```sh
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RoleCore
|
4
|
+
module Generators
|
5
|
+
class ConfigGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path("../templates", __FILE__)
|
7
|
+
|
8
|
+
def generate_config
|
9
|
+
copy_file "role_core.rb", "config/initializers/role_core.rb"
|
10
|
+
copy_file "role_core.en.yml", "config/locales/role_core.en.yml"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
en:
|
2
|
+
role_core:
|
3
|
+
models: # Defined by `group` place here
|
4
|
+
# project: Project
|
5
|
+
# task: Task
|
6
|
+
attributes:
|
7
|
+
# global: # Top-level permissions
|
8
|
+
# foo: Foo
|
9
|
+
# bar: Bar
|
10
|
+
# project:
|
11
|
+
# create: New project
|
12
|
+
# destroy: Destroy project
|
13
|
+
# update: Edit project
|
14
|
+
# read: Read project
|
15
|
+
# read_public: Read public project
|
16
|
+
# task:
|
17
|
+
# create: New task
|
18
|
+
# destroy: Destroy task
|
19
|
+
# update: Edit task
|
20
|
+
# update_my_own: Edit my own task
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Uncomment below if you want to integrate with CanCanCan
|
4
|
+
#
|
5
|
+
# require "role_core/contrib/can_can_can_permission"
|
6
|
+
# RoleCore.permission_class = RoleCore::CanCanCanPermission
|
7
|
+
|
8
|
+
RoleCore.permission_set_class.draw do
|
9
|
+
# Define permissions for the application. For example:
|
10
|
+
#
|
11
|
+
# permission :foo, default: true # `default: true` means grant to user by default
|
12
|
+
# permission :bar
|
13
|
+
#
|
14
|
+
# You can also group permissions by using `group`:
|
15
|
+
#
|
16
|
+
# group :project do
|
17
|
+
# permission :create
|
18
|
+
# permission :destroy
|
19
|
+
# permission :update
|
20
|
+
# permission :read
|
21
|
+
# permission :read_public
|
22
|
+
#
|
23
|
+
# # `group` supports nesting
|
24
|
+
# group :task do
|
25
|
+
# permission :create
|
26
|
+
# permission :destroy
|
27
|
+
# permission :update
|
28
|
+
# permission :read
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# For CanCanCan integration, you can pass `model_name` for `group` or `permission`. For example:
|
33
|
+
#
|
34
|
+
# group :project, model_name: "Project" do
|
35
|
+
# permission :create
|
36
|
+
# permission :destroy, model_name: 'Plan'
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# That will translate to CanCanCan's abilities (if user has these permissions),
|
40
|
+
# the permission's name will be the action:
|
41
|
+
#
|
42
|
+
# can :create, Project
|
43
|
+
# can :destroy, Plan
|
44
|
+
#
|
45
|
+
# You can pass `priority` argument to `permission`
|
46
|
+
#
|
47
|
+
# group :project, model_name: "Project" do
|
48
|
+
# permission :read_public,
|
49
|
+
# permission :read, priority: 1
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# That will made 'read' prior than `read_public`.
|
53
|
+
#
|
54
|
+
# For CanCanCan's hash of conditions
|
55
|
+
# (see https://github.com/CanCanCommunity/cancancan/wiki/Defining-Abilities#hash-of-conditions)
|
56
|
+
# you can simply pass them as arguments for `permission` even with a block
|
57
|
+
#
|
58
|
+
# group :task, model_name: "Task" do
|
59
|
+
# permission :read_public, is_public: true
|
60
|
+
# permission :update_my_own, action: :update, default: true do |user, task|
|
61
|
+
# task.user_id == user.id
|
62
|
+
# end
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# Although permission's name will be CanCanCan's action by default,
|
66
|
+
# you can pass `action` argument to override it.
|
67
|
+
#
|
68
|
+
# permission :read_public, action: :read, is_public: true
|
69
|
+
#
|
70
|
+
end.finalize! # Call `finalize!` to freezing the definition, that's optional.
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RoleCore
|
4
|
+
module Generators
|
5
|
+
class ModelGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path("../templates", __FILE__)
|
7
|
+
|
8
|
+
def generate_model
|
9
|
+
copy_file "role.rb", "app/models/role.rb"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/role_core/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
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.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jasl
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-04-
|
11
|
+
date: 2018-04-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -44,7 +44,8 @@ dependencies:
|
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '0'
|
47
|
-
description:
|
47
|
+
description: RoleCore is a Rails engine which could provide essential industry of
|
48
|
+
Role-based access control.
|
48
49
|
email:
|
49
50
|
- jasl9187@hotmail.com
|
50
51
|
executables: []
|
@@ -57,6 +58,13 @@ files:
|
|
57
58
|
- app/models/role_core/application_record.rb
|
58
59
|
- app/models/role_core/role.rb
|
59
60
|
- db/migrate/20170705174003_create_roles.rb
|
61
|
+
- lib/generators/role_core/config/USAGE
|
62
|
+
- lib/generators/role_core/config/config_generator.rb
|
63
|
+
- lib/generators/role_core/config/templates/role_core.en.yml
|
64
|
+
- lib/generators/role_core/config/templates/role_core.rb
|
65
|
+
- lib/generators/role_core/model/USAGE
|
66
|
+
- lib/generators/role_core/model/model_generator.rb
|
67
|
+
- lib/generators/role_core/model/templates/role.rb
|
60
68
|
- lib/role_core.rb
|
61
69
|
- lib/role_core/computed_permissions.rb
|
62
70
|
- lib/role_core/concerns/models/role.rb
|
@@ -90,5 +98,6 @@ rubyforge_project:
|
|
90
98
|
rubygems_version: 2.7.6
|
91
99
|
signing_key:
|
92
100
|
specification_version: 4
|
93
|
-
summary:
|
101
|
+
summary: RoleCore is a Rails engine which could provide essential industry of Role-based
|
102
|
+
access control.
|
94
103
|
test_files: []
|