careacademy-acl9 3.3.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 +7 -0
- data/.gitignore +24 -0
- data/.ruby-version +1 -0
- data/.travis.yml +26 -0
- data/Appraisals +23 -0
- data/CHANGELOG.md +122 -0
- data/CONTRIBUTING.md +62 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +167 -0
- data/LICENSE +9 -0
- data/MIT-LICENSE +20 -0
- data/README.md +326 -0
- data/Rakefile +20 -0
- data/TODO +42 -0
- data/acl9.gemspec +27 -0
- data/bin/appraisal +16 -0
- data/bin/bundler +16 -0
- data/bin/cc-tddium-post-worker +16 -0
- data/bin/erubis +16 -0
- data/bin/rackup +16 -0
- data/bin/rails +16 -0
- data/bin/rake +16 -0
- data/bin/sprockets +16 -0
- data/bin/tapout +16 -0
- data/bin/thor +16 -0
- data/bin/tilt +16 -0
- data/bin/yard +16 -0
- data/bin/yardoc +16 -0
- data/bin/yri +16 -0
- data/gemfiles/.bundle/config +2 -0
- data/gemfiles/rails_5.0.gemfile +10 -0
- data/gemfiles/rails_5.1.gemfile +10 -0
- data/gemfiles/rails_5.2.gemfile +9 -0
- data/gemfiles/rails_6.0.gemfile +9 -0
- data/gemfiles/rails_6.1.gemfile +9 -0
- data/gemfiles/rails_7.0.gemfile +9 -0
- data/lib/acl9/controller_extensions/dsl_base.rb +212 -0
- data/lib/acl9/controller_extensions/generators.rb +166 -0
- data/lib/acl9/controller_extensions.rb +85 -0
- data/lib/acl9/helpers.rb +49 -0
- data/lib/acl9/model_extensions/for_object.rb +74 -0
- data/lib/acl9/model_extensions/for_subject.rb +232 -0
- data/lib/acl9/model_extensions.rb +136 -0
- data/lib/acl9/prepositions.rb +18 -0
- data/lib/acl9/version.rb +3 -0
- data/lib/acl9.rb +78 -0
- data/lib/generators/acl9/setup/USAGE +35 -0
- data/lib/generators/acl9/setup/setup_generator.rb +122 -0
- data/lib/generators/acl9/setup/templates/create_role_tables.rb +31 -0
- data/lib/generators/acl9/setup/templates/role.rb +3 -0
- data/test/config_test.rb +55 -0
- data/test/controller_extensions/actions_test.rb +199 -0
- data/test/controller_extensions/anon_test.rb +39 -0
- data/test/controller_extensions/base.rb +96 -0
- data/test/controller_extensions/basics_test.rb +44 -0
- data/test/controller_extensions/conditions_test.rb +48 -0
- data/test/controller_extensions/method_test.rb +70 -0
- data/test/controller_extensions/multi_match_test.rb +142 -0
- data/test/controller_extensions/multiple_role_arguments_test.rb +136 -0
- data/test/controller_extensions/prepositions_test.rb +108 -0
- data/test/controller_extensions/pseudo_role_test.rb +26 -0
- data/test/controller_extensions/role_test.rb +75 -0
- data/test/controllers/acl_action_override_test.rb +24 -0
- data/test/controllers/acl_arguments_test.rb +5 -0
- data/test/controllers/acl_block_test.rb +5 -0
- data/test/controllers/acl_boolean_method_test.rb +5 -0
- data/test/controllers/acl_helper_method_test.rb +29 -0
- data/test/controllers/acl_ivars_test.rb +15 -0
- data/test/controllers/acl_method2_test.rb +6 -0
- data/test/controllers/acl_method_test.rb +6 -0
- data/test/controllers/acl_object_hash_test.rb +18 -0
- data/test/controllers/acl_query_method_named_test.rb +9 -0
- data/test/controllers/acl_query_method_test.rb +9 -0
- data/test/controllers/acl_query_method_with_lambda_test.rb +9 -0
- data/test/controllers/acl_query_mixin.rb +54 -0
- data/test/controllers/acl_subject_method_test.rb +15 -0
- data/test/controllers/arguments_checking_test.rb +43 -0
- data/test/dummy/app/assets/config/manifest.js +0 -0
- data/test/dummy/app/controllers/acl_action_override.rb +15 -0
- data/test/dummy/app/controllers/acl_arguments.rb +10 -0
- data/test/dummy/app/controllers/acl_block.rb +6 -0
- data/test/dummy/app/controllers/acl_boolean_method.rb +23 -0
- data/test/dummy/app/controllers/acl_helper_method.rb +11 -0
- data/test/dummy/app/controllers/acl_ivars.rb +17 -0
- data/test/dummy/app/controllers/acl_method.rb +6 -0
- data/test/dummy/app/controllers/acl_method2.rb +6 -0
- data/test/dummy/app/controllers/acl_objects_hash.rb +10 -0
- data/test/dummy/app/controllers/acl_query_method.rb +9 -0
- data/test/dummy/app/controllers/acl_query_method_named.rb +15 -0
- data/test/dummy/app/controllers/acl_query_method_with_lambda.rb +9 -0
- data/test/dummy/app/controllers/acl_subject_method.rb +16 -0
- data/test/dummy/app/controllers/application_controller.rb +13 -0
- data/test/dummy/app/controllers/empty_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/helpers/some_helper.rb +8 -0
- data/test/dummy/app/models/.keep +0 -0
- data/test/dummy/app/models/access.rb +3 -0
- data/test/dummy/app/models/account.rb +3 -0
- data/test/dummy/app/models/bar.rb +3 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/models/foo.rb +3 -0
- data/test/dummy/app/models/foo_bar.rb +3 -0
- data/test/dummy/app/models/other/foo.rb +5 -0
- data/test/dummy/app/models/other/role.rb +5 -0
- data/test/dummy/app/models/other/user.rb +5 -0
- data/test/dummy/app/models/role.rb +3 -0
- data/test/dummy/app/models/string_object_role.rb +3 -0
- data/test/dummy/app/models/string_user.rb +3 -0
- data/test/dummy/app/models/user.rb +3 -0
- data/test/dummy/app/models/uuid.rb +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +4 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/test.rb +40 -0
- data/test/dummy/config/initializers/assets.rb +8 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/secrets.rb +1 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/db/migrate/20141117132218_create_tables.rb +149 -0
- data/test/helpers/helper_test.rb +89 -0
- data/test/models/roles_test.rb +369 -0
- data/test/models/roles_with_custom_association_names_test.rb +28 -0
- data/test/models/roles_with_custom_class_names_test.rb +28 -0
- data/test/models/system_roles_test.rb +22 -0
- data/test/models/users_roles_and_subjects_with_namespaced_class_names_test.rb +30 -0
- data/test/test_helper.rb +94 -0
- data/test/version_test.rb +7 -0
- metadata +321 -0
data/README.md
ADDED
@@ -0,0 +1,326 @@
|
|
1
|
+
# acl9
|
2
|
+
|
3
|
+
[](https://travis-ci.org/be9/acl9)
|
4
|
+
|
5
|
+
Acl9 is a role-based authorization system that provides a concise DSL for
|
6
|
+
securing your Rails application.
|
7
|
+
|
8
|
+
Access control is pointless if you're not sure you've done it right. The
|
9
|
+
fundamental goal of acl9 is to ensure that your rules are easy to understand and
|
10
|
+
easy to test - in other words acl9 makes it easy to ensure you've got your
|
11
|
+
permissions correct.
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Acl9 is [Semantically Versioned](http://semver.org/), so just add this to your
|
16
|
+
`Gemfile` (note that you need 3.2 for Rails 6+ support):
|
17
|
+
|
18
|
+
### Rails 7 - stick with 2.7
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
gem 'acl9', '~> 4.0'
|
22
|
+
```
|
23
|
+
|
24
|
+
You will need Ruby 2.7.x
|
25
|
+
|
26
|
+
### Rails 5,6 - stick with 2.x
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
gem 'acl9', '~> 3.2'
|
30
|
+
```
|
31
|
+
|
32
|
+
You will need Ruby > 2.0
|
33
|
+
|
34
|
+
### Rails 4 - stick with 2.x
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
gem 'acl9', '~> 2.0'
|
38
|
+
```
|
39
|
+
|
40
|
+
### Rails < 4 - upgrade Rails!
|
41
|
+
|
42
|
+
We dropped support for Rails < 4 in the 1.x releases, so if you're still using
|
43
|
+
Rails 2.x or 3.x then you'll want this:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
gem 'acl9', '~> 0.12'
|
47
|
+
```
|
48
|
+
|
49
|
+
## Getting Started
|
50
|
+
|
51
|
+
The simplest way to demonstrate this is with some examples.
|
52
|
+
|
53
|
+
### Access Control
|
54
|
+
|
55
|
+
You declare the access control directly in your controller, so it's visible and
|
56
|
+
obvious for any developer looking at the controller:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
class Admin::SchoolsController < ApplicationController
|
60
|
+
access_control do
|
61
|
+
allow :support, :of => School
|
62
|
+
allow :admins, :managers, :teachers, :of => :school
|
63
|
+
deny :teachers, :only => :destroy
|
64
|
+
|
65
|
+
action :index do
|
66
|
+
allow anonymous, logged_in
|
67
|
+
end
|
68
|
+
|
69
|
+
allow logged_in, :only => :show
|
70
|
+
deny :students
|
71
|
+
end
|
72
|
+
|
73
|
+
def index
|
74
|
+
# ...
|
75
|
+
end
|
76
|
+
|
77
|
+
# ...
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
81
|
+
You can see more about all this stuff in the wiki under [Access Control
|
82
|
+
Subsystem](//github.com/be9/acl9/wiki/Access-Control-Subsystem)
|
83
|
+
|
84
|
+
### Roles
|
85
|
+
|
86
|
+
The other side of acl9 is where you give and remove roles to and from a user. As
|
87
|
+
you're looking through these examples refer back to the [Access
|
88
|
+
Control](#access-control) example and you should be able to see which access
|
89
|
+
control rule each role corresponds to.
|
90
|
+
|
91
|
+
Let's say we want to create an admin of a given school, not a global admin, just
|
92
|
+
the admin for a particular school:
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
user.has_role! :admin, school
|
96
|
+
user.has_role! :admin, of: school
|
97
|
+
```
|
98
|
+
|
99
|
+
Then let's say we have some support people in our organization who are dedicated
|
100
|
+
to supporting all the schools. We could do two things, either we could come up
|
101
|
+
with a new role name like `:school_support` or we can use the fact that we can
|
102
|
+
assign roles to any object, including a class, and do this:
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
user.has_role! :support, School
|
106
|
+
user.has_role! :support, for: School
|
107
|
+
```
|
108
|
+
|
109
|
+
You can see the `allow` line in our `access_control` block that this corresponds
|
110
|
+
with. If we had used `:school_support` instead then that line would have to be:
|
111
|
+
`allow :school_support`
|
112
|
+
|
113
|
+
Now, when a support person leaves that team, we need to remove that role:
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
user.has_no_role! :support, School
|
117
|
+
user.has_no_role! :support, at: School
|
118
|
+
```
|
119
|
+
|
120
|
+
You can see more about all this stuff in the wiki under [Role
|
121
|
+
Subsystem](//github.com/be9/acl9/wiki/Role-Subsystem)
|
122
|
+
|
123
|
+
## Database Setup
|
124
|
+
|
125
|
+
As mentioned in [Role Subsystem](//github.com/be9/acl9/wiki/Role-Subsystem) you
|
126
|
+
don't have to use these, if your role system is very simple all you need is a
|
127
|
+
`has_role?` method in your subject model that returns a boolean and the Access
|
128
|
+
Control part of Acl9 will work from that.
|
129
|
+
|
130
|
+
However, most commonly, the roles and role assignments are stored in two new
|
131
|
+
tables that you create specifically for Acl9. There's a rails generator for
|
132
|
+
creating the migrations, role model and updating the subject model and
|
133
|
+
optionally any number of object models.
|
134
|
+
|
135
|
+
You can view the USAGE for this generator by running the following in your app
|
136
|
+
directory:
|
137
|
+
|
138
|
+
```sh
|
139
|
+
bin/rails g acl9:setup -h
|
140
|
+
```
|
141
|
+
|
142
|
+
## Configuration
|
143
|
+
|
144
|
+
There are five configurable settings. These all have sensible defaults which can
|
145
|
+
be easily overridden in `config/initializers/acl9.rb`
|
146
|
+
|
147
|
+
You can also override each of the `:default_*` settings (dropping the "default_"
|
148
|
+
prefix) in your models/controllers - see below for more detail:
|
149
|
+
|
150
|
+
### :default_role_class_name
|
151
|
+
|
152
|
+
Set to `'Role'` and can be overridden in your "user" model, [see the wiki for more](//github.com/be9/acl9/wiki/Role-Subsystem#custom-class-names).
|
153
|
+
|
154
|
+
### :default_association_name
|
155
|
+
|
156
|
+
Set to `:role_objects` and can be overridden in
|
157
|
+
your "user" model, [see the wiki for more](//github.com/be9/acl9/wiki/Role-Subsystem#subject-model).
|
158
|
+
We chose a name for this association that was unlikely to conflict with
|
159
|
+
existing models but a lot of people override this to be just `:roles`
|
160
|
+
|
161
|
+
### :default_subject_class_name
|
162
|
+
|
163
|
+
Set to `'User'` and can be overridden in your
|
164
|
+
"role" model, [see the wiki for more](//github.com/be9/acl9/wiki/Role-Subsystem#custom-class-names).
|
165
|
+
|
166
|
+
### :default_subject_method
|
167
|
+
|
168
|
+
Set to `:current_user` and can be overridden in
|
169
|
+
your controllers, [see the wiki for more](//github.com/be9/acl9/wiki/Access-Control-Subsystem#subject_method).
|
170
|
+
|
171
|
+
### :default_join_table_name
|
172
|
+
|
173
|
+
This is set to `nil` by default, which will mean it will use the Rails method of
|
174
|
+
calculating the join table name for a `has_and_belongs_to_many` (eg.
|
175
|
+
`users_roles`). Remember that if you override this value, either do it before
|
176
|
+
you run `rails g acl9:setup` or be sure to update your migration or database.
|
177
|
+
|
178
|
+
### :normalize_role_names
|
179
|
+
|
180
|
+
Set to `true` (see "Upgrade Notes" below if you're upgrading) and can only be
|
181
|
+
changed by setting it in `Acl9.config`. When true this causes Acl9 to normalize
|
182
|
+
your role names, normalization is `.to_s.underscore.singularize`. This is done
|
183
|
+
on both the setter and getter.
|
184
|
+
|
185
|
+
### :protect_global_roles
|
186
|
+
|
187
|
+
Set to `true` (see "Upgrade Notes" below if you're upgrading) and can only be
|
188
|
+
changed by merging into `Acl9.config`. This setting changes how global roles
|
189
|
+
(ie. roles with no object) are treated.
|
190
|
+
|
191
|
+
Say we set a role like so:
|
192
|
+
|
193
|
+
```ruby
|
194
|
+
user.has_role! :admin, school
|
195
|
+
```
|
196
|
+
|
197
|
+
When `:protect_global_roles` is `true` (as is the default) then `user.has_role?
|
198
|
+
:admin` is `false`. Ie. changing the role on a specific instance doesn't impact
|
199
|
+
the global role (hence the name).
|
200
|
+
|
201
|
+
When `:protect_global_roles` is `false` then `user.has_role? :admin` is `true`.
|
202
|
+
Ie. setting a role on a specific instance makes that person a global one of
|
203
|
+
those roles.
|
204
|
+
|
205
|
+
Basically these are just two different ways of working with roles, if you're
|
206
|
+
protecting your global roles then you can use them as sort of a superuser
|
207
|
+
version of a given role. So you can have an admin of a school **and** a global
|
208
|
+
admin with different privileges.
|
209
|
+
|
210
|
+
If you don't protect your global roles then you can use them as a catch-all for
|
211
|
+
any specific roles, so then the admins of schools, classrooms and students can
|
212
|
+
all be granted a privilege by allowing the global `:admin` role.
|
213
|
+
|
214
|
+
### Example
|
215
|
+
|
216
|
+
```ruby
|
217
|
+
# config/initializers/acl9.rb
|
218
|
+
Acl9.config.default_association_name = :roles
|
219
|
+
|
220
|
+
# or...
|
221
|
+
Acl9.configure do |c|
|
222
|
+
c.default_association_name = :roles
|
223
|
+
end
|
224
|
+
```
|
225
|
+
|
226
|
+
### Reset Defaults
|
227
|
+
|
228
|
+
On the off chance that you ever need to reset the config back to its default you
|
229
|
+
can use:
|
230
|
+
|
231
|
+
```ruby
|
232
|
+
Acl9.config.reset!
|
233
|
+
```
|
234
|
+
|
235
|
+
## Upgrade Notes
|
236
|
+
|
237
|
+
### Acl9 now protects global roles by default
|
238
|
+
|
239
|
+
Please, PLEASE, **PLEASE** note. If you're upgrading from the `0.x` series of acl9
|
240
|
+
then there's an important change in one of the defaults for `1.x`. We flipped
|
241
|
+
the default value of `:protect_global_roles` from `false` to `true`.
|
242
|
+
|
243
|
+
Say you had a role on an object:
|
244
|
+
|
245
|
+
```ruby
|
246
|
+
user.has_role! :manager, department
|
247
|
+
```
|
248
|
+
|
249
|
+
We all know that this means:
|
250
|
+
|
251
|
+
```ruby
|
252
|
+
user.has_role? :manager, department # => true
|
253
|
+
user.has_role? :manager, in: department # => true
|
254
|
+
```
|
255
|
+
|
256
|
+
With `:protect_global_roles` set to `false`, as it was in `0.x` then the above
|
257
|
+
role would mean that the global `:manager` role would also be `true`.
|
258
|
+
|
259
|
+
Ie. this is how `0.x` behaved:
|
260
|
+
|
261
|
+
```ruby
|
262
|
+
user.has_role? :manager # => true
|
263
|
+
```
|
264
|
+
|
265
|
+
Now in `1.x` we default `:protect_global_roles` to `true` which means that the
|
266
|
+
global `:manager` role is protected, ie:
|
267
|
+
|
268
|
+
```ruby
|
269
|
+
user.has_role? :manager # => false
|
270
|
+
```
|
271
|
+
|
272
|
+
In words, in 1.x just because you're the `:manager` of a `department` that
|
273
|
+
doesn't make you a global `:manager` (anymore).
|
274
|
+
|
275
|
+
### Acl9 now normalizes role names by default
|
276
|
+
|
277
|
+
So basically we downcase, underscore, and singularize your role names, so:
|
278
|
+
|
279
|
+
```ruby
|
280
|
+
user.has_role! 'FooBars'
|
281
|
+
|
282
|
+
user.has_role? 'FooBars' # => true
|
283
|
+
user.has_role? :foo_bar # => true
|
284
|
+
|
285
|
+
user.has_role! :foo_bar # => nil, because it was already set above
|
286
|
+
```
|
287
|
+
|
288
|
+
If you're upgrading then you will want to do something like this:
|
289
|
+
|
290
|
+
```ruby
|
291
|
+
Role.all.each do |role|
|
292
|
+
role.update! name: role.name.underscore.singularize
|
293
|
+
end
|
294
|
+
```
|
295
|
+
|
296
|
+
**Then check for any duplicates** and resolve those manually.
|
297
|
+
|
298
|
+
### Acl9 now raises ArgumentError on bad args to `allow`/`deny`
|
299
|
+
|
300
|
+
In 2.x and above we now try to help the developer by raising ArgumentError if
|
301
|
+
they mess up with the options they pass to `allow`/`deny`, this prevents people
|
302
|
+
doing things that they think are going to work but actually aren't like:
|
303
|
+
|
304
|
+
```ruby
|
305
|
+
allow all, actions: [ :index, :show ] # <---- BROKEN!!
|
306
|
+
```
|
307
|
+
|
308
|
+
## Community
|
309
|
+
|
310
|
+
**Gitter:** [Join the gitter chat here](https://gitter.im/be9/acl9)
|
311
|
+
|
312
|
+
**docs:** Rdocs are available [here](http://rdoc.info/projects/be9/acl9).
|
313
|
+
|
314
|
+
**StackOverflow:** Go ask (or answer) a question [on
|
315
|
+
StackOverflow](http://stackoverflow.com/questions/tagged/acl9)
|
316
|
+
|
317
|
+
**Mailing list:** We have an old skule mailing list as well [acl9-discuss
|
318
|
+
group](http://groups.google.com/group/acl9-discuss)
|
319
|
+
|
320
|
+
**Contributing:** Last but not least, check out the [Contributing
|
321
|
+
Guide](./CONTRIBUTING.md) if you want to get even more involved
|
322
|
+
|
323
|
+
## Acknowledgements
|
324
|
+
|
325
|
+
[All these people are awesome!](//github.com/be9/acl9/graphs/contributors) as are all the
|
326
|
+
people who have raised or investigated issues.
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
|
5
|
+
desc 'Default: run tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
require 'rake/testtask'
|
9
|
+
|
10
|
+
Rake::TestTask.new(:test) do |test|
|
11
|
+
test.libs << 'lib' << 'test'
|
12
|
+
test.pattern = 'test/**/*_test.rb'
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'yard'
|
16
|
+
|
17
|
+
YARD::Rake::YardocTask.new do |t|
|
18
|
+
t.files = ['lib/**/*.rb']
|
19
|
+
end
|
20
|
+
|
data/TODO
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
* Complex roles with ANDing.
|
2
|
+
|
3
|
+
Something like:
|
4
|
+
|
5
|
+
access_control do
|
6
|
+
allow all, :except => :destroy
|
7
|
+
allow complex_role, :to => :destroy do
|
8
|
+
is :strong
|
9
|
+
is :decisive
|
10
|
+
is :owner, :of => :object
|
11
|
+
is_not :banned
|
12
|
+
is_not :fake
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
* Acl9-based menu generator.
|
17
|
+
|
18
|
+
If you get Access Denied on /secrets/index, probably you shouldn't see "Secrets" item
|
19
|
+
in the menu at all.
|
20
|
+
|
21
|
+
It can be very DRY. Say, we introduce :menu => true option to access_control method which
|
22
|
+
will make it register a lambda (can see/cannot see) in some global hash (indexed by controller name).
|
23
|
+
|
24
|
+
Then, given an URL, you'll be able to check it against this hash. /secrets/index is mapped to
|
25
|
+
SecretsController#index, so you run access_control_hash['SecretsController'].call('index') and
|
26
|
+
show the link only if true is returned.
|
27
|
+
|
28
|
+
The problem here is with objects. SecretsController's access_control block can reference instance
|
29
|
+
variables during the permission check, but we have only current instantiated controller which can be any.
|
30
|
+
|
31
|
+
Another option is to distinguish visible part from access control part.
|
32
|
+
|
33
|
+
menu do
|
34
|
+
item 'Home', home_path
|
35
|
+
item 'Secrets', secrets_path do
|
36
|
+
allow :trusted
|
37
|
+
end
|
38
|
+
|
39
|
+
# ...
|
40
|
+
end
|
41
|
+
|
42
|
+
Here only "trusted" users will see "Secrets" item.
|
data/acl9.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.unshift File.expand_path("../lib", __FILE__)
|
3
|
+
require "acl9/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.authors = ["oleg dashevskii", "Jason King"]
|
7
|
+
s.email = ["olegdashevskii@gmail.com", "jk@handle.it"]
|
8
|
+
s.description = "Role-based authorization system for Rails with a concise DSL for securing your Rails application. Acl9 makes it easy to get security right for your app, the access control code sits right in your controller, the syntax is very easy to understand, and acl9 makes it easy to test your access rules."
|
9
|
+
s.summary = "Role-based authorization system for Rails with a concise DSL for securing your Rails application."
|
10
|
+
s.homepage = "http://github.com/careacademy/acl9"
|
11
|
+
|
12
|
+
s.files = `git ls-files`.split($\)
|
13
|
+
s.test_files = s.files.grep(%r{^test/})
|
14
|
+
s.name = "careacademy-acl9"
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
s.version = Acl9::VERSION
|
17
|
+
s.license = 'MIT'
|
18
|
+
|
19
|
+
s.required_ruby_version = ">= 2"
|
20
|
+
|
21
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
22
|
+
|
23
|
+
s.add_dependency "rails", '> 5.0', '< 8.0'
|
24
|
+
|
25
|
+
s.add_development_dependency "yard"
|
26
|
+
s.add_development_dependency 'sqlite3'
|
27
|
+
end
|
data/bin/appraisal
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'appraisal' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('appraisal', 'appraisal')
|
data/bin/bundler
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'bundler' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('bundler', 'bundler')
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'cc-tddium-post-worker' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('codeclimate-test-reporter', 'cc-tddium-post-worker')
|
data/bin/erubis
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'erubis' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('erubis', 'erubis')
|
data/bin/rackup
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'rackup' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('rack', 'rackup')
|
data/bin/rails
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'rails' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('railties', 'rails')
|
data/bin/rake
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'rake' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('rake', 'rake')
|
data/bin/sprockets
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'sprockets' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('sprockets', 'sprockets')
|
data/bin/tapout
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'tapout' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('tapout', 'tapout')
|
data/bin/thor
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'thor' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('thor', 'thor')
|
data/bin/tilt
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'tilt' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('tilt', 'tilt')
|
data/bin/yard
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'yard' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('yard', 'yard')
|
data/bin/yardoc
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'yardoc' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('yard', 'yardoc')
|
data/bin/yri
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'yri' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('yard', 'yri')
|