role_core 0.0.12 → 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 161464a27b8e4e9f59ca62b95a6c975fec056196b48d1fe0a80e2d15618a368e
4
- data.tar.gz: 28f2cc4b103d2093893ce45a98ab91e63e878e4639889822eae5e710286660d3
3
+ metadata.gz: 2c75876caf7676f2733564e2f0657b8625c798d29ee7de9e45a21bc66312e54d
4
+ data.tar.gz: 8bfb27b3b34481cb4cf566d3ff336e9450b45020a9109a201d7ac21e1e81194f
5
5
  SHA512:
6
- metadata.gz: 4aaf5fe44a10e9448faec6c6ba0316ba446641238bd3c1d2e99fd29a950d43398e56ce1483edb7c0cb63d597fcccbf71dddb27aecd5e89e4dc0b3a6bb0999298
7
- data.tar.gz: 4a85faabeeccdd1b4b84459be9aea41459972edddddac5ce6dbcbb190084304f405380496cd731cf446ea2ae37a55ae04f02301b64e27fe997fa06e2b6d71412
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
- A Rails engine providing essential industry of Role-based access control.
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
- ## Usage
8
+ It's only provides the ability to define permissions and pre-made Role model.
9
9
 
10
- See demo for now.
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
- Or you may want to include the gem directly from GitHub:
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,2 @@
1
+ Description:
2
+ The role_core:config generator creates RoleCore initializer and locale in the config directory.
@@ -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,2 @@
1
+ Description:
2
+ The role_core:model generator creates Role model for customizing in the app/models directory.
@@ -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
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Role < RoleCore::Role
4
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RoleCore
4
- VERSION = "0.0.12"
4
+ VERSION = "0.0.14"
5
5
  end
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.12
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-22 00:00:00.000000000 Z
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: A Rails engine providing essential industry of Role-based access control
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: A Rails engine providing essential industry of Role-based access control
101
+ summary: RoleCore is a Rails engine which could provide essential industry of Role-based
102
+ access control.
94
103
  test_files: []