action_access 0.0.1

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.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/CONTRIBUTING.md +23 -0
  4. data/Gemfile +14 -0
  5. data/Gemfile.lock +87 -0
  6. data/LICENSE.txt +20 -0
  7. data/README.md +283 -0
  8. data/Rakefile +28 -0
  9. data/action_access.gemspec +24 -0
  10. data/lib/action_access.rb +14 -0
  11. data/lib/action_access/controller_additions.rb +75 -0
  12. data/lib/action_access/keeper.rb +90 -0
  13. data/lib/action_access/model_additions.rb +14 -0
  14. data/lib/action_access/railtie.rb +19 -0
  15. data/lib/action_access/user_utilities.rb +39 -0
  16. data/lib/action_access/version.rb +3 -0
  17. data/test/action_access_test.rb +21 -0
  18. data/test/controllers/articles_controller_test.rb +41 -0
  19. data/test/controllers/secrets_controller_test.rb +10 -0
  20. data/test/controllers/static_controller_test.rb +15 -0
  21. data/test/dummy/README.rdoc +28 -0
  22. data/test/dummy/Rakefile +6 -0
  23. data/test/dummy/app/assets/images/.keep +0 -0
  24. data/test/dummy/app/assets/javascripts/application.js +13 -0
  25. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  26. data/test/dummy/app/controllers/application_controller.rb +15 -0
  27. data/test/dummy/app/controllers/articles_controller.rb +36 -0
  28. data/test/dummy/app/controllers/concerns/.keep +0 -0
  29. data/test/dummy/app/controllers/secrets_controller.rb +4 -0
  30. data/test/dummy/app/controllers/static_controller.rb +6 -0
  31. data/test/dummy/app/helpers/application_helper.rb +2 -0
  32. data/test/dummy/app/mailers/.keep +0 -0
  33. data/test/dummy/app/models/.keep +0 -0
  34. data/test/dummy/app/models/concerns/.keep +0 -0
  35. data/test/dummy/app/models/user.rb +7 -0
  36. data/test/dummy/app/views/articles/edit.html.erb +1 -0
  37. data/test/dummy/app/views/articles/index.html.erb +1 -0
  38. data/test/dummy/app/views/articles/new.html.erb +1 -0
  39. data/test/dummy/app/views/articles/show.html.erb +3 -0
  40. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  41. data/test/dummy/app/views/static/home.html.erb +1 -0
  42. data/test/dummy/bin/bundle +3 -0
  43. data/test/dummy/bin/rails +4 -0
  44. data/test/dummy/bin/rake +4 -0
  45. data/test/dummy/config.ru +4 -0
  46. data/test/dummy/config/application.rb +23 -0
  47. data/test/dummy/config/boot.rb +5 -0
  48. data/test/dummy/config/database.yml +25 -0
  49. data/test/dummy/config/environment.rb +5 -0
  50. data/test/dummy/config/environments/development.rb +37 -0
  51. data/test/dummy/config/environments/production.rb +78 -0
  52. data/test/dummy/config/environments/test.rb +39 -0
  53. data/test/dummy/config/initializers/assets.rb +8 -0
  54. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  55. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  56. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  57. data/test/dummy/config/initializers/inflections.rb +16 -0
  58. data/test/dummy/config/initializers/mime_types.rb +4 -0
  59. data/test/dummy/config/initializers/session_store.rb +3 -0
  60. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  61. data/test/dummy/config/locales/en.yml +23 -0
  62. data/test/dummy/config/routes.rb +6 -0
  63. data/test/dummy/config/secrets.yml +22 -0
  64. data/test/dummy/db/migrate/20140926071026_create_users.rb +10 -0
  65. data/test/dummy/db/schema.rb +23 -0
  66. data/test/dummy/lib/assets/.keep +0 -0
  67. data/test/dummy/log/.keep +0 -0
  68. data/test/dummy/public/404.html +67 -0
  69. data/test/dummy/public/422.html +67 -0
  70. data/test/dummy/public/500.html +66 -0
  71. data/test/dummy/public/favicon.ico +0 -0
  72. data/test/models/user_test.rb +22 -0
  73. data/test/support/compact_environment.rb +9 -0
  74. data/test/test_helper.rb +8 -0
  75. metadata +203 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c3a922a62dc47428db03349b5ab4381c32d669ea
4
+ data.tar.gz: 639f7cf2ce63e3783f7d33970ea874624f8c7981
5
+ SHA512:
6
+ metadata.gz: 10c2835e378462860b56b636431ebb26ac196acd179c82703a72bb77cb61745352b97ed668d28f2999dc88a4deec16f0ac32d3c10794a42be1489dd103b37d94
7
+ data.tar.gz: 8a1b64c08c10887c41e55a1e8f16d2ed8677cd68a7f7ef42f050f8e04a7d517727e2651e7841c0cc8bfa84b195768ae7c43d99c168eaa0f6a6d61e2b96bf797a
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ test/dummy/db/*.sqlite3
5
+ test/dummy/db/*.sqlite3-journal
6
+ test/dummy/log/*.log
7
+ test/dummy/tmp/
8
+ test/dummy/.sass-cache
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,23 @@
1
+ ## Please read before contributing
2
+
3
+ 1. If you have questions about Action Access, use the
4
+ [Mailing List](https://groups.google.com/d/forum/action_access) or
5
+ [Stack Overflow](https://stackoverflow.com/questions/tagged/action_access).
6
+ Do not post questions here.
7
+
8
+ 2. If you find a security bug, **DO NOT** submit an issue here.
9
+ Please send an e-mail to [mgag.issues@gmail.com](mailto:mgag.issues@gmail.com)
10
+ instead.
11
+
12
+ 3. Do a small search on the issues tracker before submitting your issue to
13
+ see if it was already reported or fixed. In case it was not, create your report
14
+ with a **clear description** of the issue and a **code sample** that
15
+ demonstrates it. Include Rails and Action Access versions, and as much relevant
16
+ information as possible. Tests or a sample application showing how the
17
+ expected behavior is not occurring will be much appreciated.
18
+
19
+ The more information you give, the easier it becomes to track the issue and fix
20
+ it. Your goal should be to make it easy for yourself and others to replicate
21
+ the bug and figure out a fix.
22
+
23
+ Thanks for your time and support!
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Declare your gem's dependencies in action_access.gemspec.
4
+ # Bundler will treat runtime dependencies like base dependencies, and
5
+ # development dependencies will be added by default to the :development group.
6
+ gemspec
7
+
8
+ # Declare any dependencies that are still in development here instead of in
9
+ # your gemspec. These might include edge Rails or gems from your path or
10
+ # Git. Remember to move these dependencies to your gemspec before releasing
11
+ # your gem to rubygems.org.
12
+
13
+ # To use debugger
14
+ # gem 'debugger'
data/Gemfile.lock ADDED
@@ -0,0 +1,87 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ action_access (0.0.1)
5
+ rails (~> 4.1)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ actionmailer (4.1.6)
11
+ actionpack (= 4.1.6)
12
+ actionview (= 4.1.6)
13
+ mail (~> 2.5, >= 2.5.4)
14
+ actionpack (4.1.6)
15
+ actionview (= 4.1.6)
16
+ activesupport (= 4.1.6)
17
+ rack (~> 1.5.2)
18
+ rack-test (~> 0.6.2)
19
+ actionview (4.1.6)
20
+ activesupport (= 4.1.6)
21
+ builder (~> 3.1)
22
+ erubis (~> 2.7.0)
23
+ activemodel (4.1.6)
24
+ activesupport (= 4.1.6)
25
+ builder (~> 3.1)
26
+ activerecord (4.1.6)
27
+ activemodel (= 4.1.6)
28
+ activesupport (= 4.1.6)
29
+ arel (~> 5.0.0)
30
+ activesupport (4.1.6)
31
+ i18n (~> 0.6, >= 0.6.9)
32
+ json (~> 1.7, >= 1.7.7)
33
+ minitest (~> 5.1)
34
+ thread_safe (~> 0.1)
35
+ tzinfo (~> 1.1)
36
+ arel (5.0.1.20140414130214)
37
+ builder (3.2.2)
38
+ erubis (2.7.0)
39
+ hike (1.2.3)
40
+ i18n (0.6.11)
41
+ json (1.8.1)
42
+ mail (2.6.1)
43
+ mime-types (>= 1.16, < 3)
44
+ mime-types (2.3)
45
+ minitest (5.4.1)
46
+ multi_json (1.10.1)
47
+ rack (1.5.2)
48
+ rack-test (0.6.2)
49
+ rack (>= 1.0)
50
+ rails (4.1.6)
51
+ actionmailer (= 4.1.6)
52
+ actionpack (= 4.1.6)
53
+ actionview (= 4.1.6)
54
+ activemodel (= 4.1.6)
55
+ activerecord (= 4.1.6)
56
+ activesupport (= 4.1.6)
57
+ bundler (>= 1.3.0, < 2.0)
58
+ railties (= 4.1.6)
59
+ sprockets-rails (~> 2.0)
60
+ railties (4.1.6)
61
+ actionpack (= 4.1.6)
62
+ activesupport (= 4.1.6)
63
+ rake (>= 0.8.7)
64
+ thor (>= 0.18.1, < 2.0)
65
+ rake (10.3.2)
66
+ sprockets (2.12.2)
67
+ hike (~> 1.2)
68
+ multi_json (~> 1.0)
69
+ rack (~> 1.0)
70
+ tilt (~> 1.1, != 1.3.0)
71
+ sprockets-rails (2.1.4)
72
+ actionpack (>= 3.0)
73
+ activesupport (>= 3.0)
74
+ sprockets (~> 2.8)
75
+ sqlite3 (1.3.9)
76
+ thor (0.19.1)
77
+ thread_safe (0.3.4)
78
+ tilt (1.4.1)
79
+ tzinfo (1.2.2)
80
+ thread_safe (~> 0.1)
81
+
82
+ PLATFORMS
83
+ ruby
84
+
85
+ DEPENDENCIES
86
+ action_access!
87
+ sqlite3
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2014 Matías A. Gagliano
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,283 @@
1
+ # Action Access
2
+
3
+ Action Access is an access control system for Ruby on Rails. It provides a
4
+ modular and easy way to secure applications and handle permissions.
5
+
6
+ It works at controller level focusing on what **actions** are accessible for
7
+ the current user instead of handling models and their attributes.
8
+
9
+ It also provides utilities for thorough control and some useful view helpers.
10
+
11
+
12
+ ## Installation
13
+
14
+ Add `action_access` to the app's Gemfile, run the `bundle` command and restart
15
+ any running server.
16
+
17
+ ```ruby
18
+ # Gemfile
19
+ gem 'action_access'
20
+ ```
21
+
22
+
23
+ ## Basic configuration
24
+
25
+ The most important setting is the way to get the **clearance level** (role,
26
+ user group, etc.), other than that it works out of the box.
27
+
28
+ Action Access doesn't require users or authentication at all to function so
29
+ you can get creative with the way you set and identify clearance levels.
30
+
31
+ It only needs a `current_clearance_level` method that returns the proper
32
+ clearance level for the current request. It can be a string or symbol and
33
+ it doesn't matter if it's singular or plural, it'll be singularized.
34
+
35
+ * With `current_user`:
36
+
37
+ The default `current_clearance_level` method tests if it can get
38
+ `current_user.clearance_level` and defaults to `:guest` if not.
39
+
40
+ So, if you already have a `current_user` method you just need to add a
41
+ `clearance_level` method to the user. With a role based authorization you
42
+ may add the following to your `User` model:
43
+
44
+ ```ruby
45
+ class User < ActiveRecord::Base
46
+ belongs_to :role
47
+
48
+ def clearance_level
49
+ role.name
50
+ end
51
+ end
52
+ ```
53
+
54
+ * No `current_user`:
55
+
56
+ If there's no `current_user` you need to override `current_clearance_level`
57
+ with whatever logic that applies to your application.
58
+
59
+ Continuing with the role based example, you might do something like this:
60
+
61
+ ```ruby
62
+ class ApplicationController < ActionController::Base
63
+ def current_clearance_level
64
+ session[:role] || :guest
65
+ end
66
+ end
67
+ ```
68
+
69
+
70
+ ## Setting permissions
71
+
72
+ Permissions are set through authorization statements using the **let** class
73
+ method available in every controller. The first parameter is the clearance
74
+ level (plural or singular) and the second is the action or list of actions.
75
+
76
+ As a simple example, to allow administrators (and only administrators in this
77
+ case) to delete articles you'd add the following to `ArticlesController`:
78
+
79
+ ```ruby
80
+ class ArticlesController < ApplicationController
81
+ let :admins, :destroy
82
+
83
+ def destroy
84
+ # ...
85
+ end
86
+
87
+ # ...
88
+ end
89
+ ```
90
+
91
+ This will automatically **lock** the controller and only allow administrators
92
+ accessing the destroy action. **Every other request** pointing to the controller
93
+ **will be rejected** and redirected with an alert.
94
+
95
+ ### Real-life example:
96
+
97
+ ```ruby
98
+ class ArticlesController < ApplicationController
99
+ let :admins, :all
100
+ let :editors, [:index, :show, :edit, :update]
101
+ let :all, [:index, :show]
102
+
103
+ def index
104
+ # ...
105
+ end
106
+
107
+ # ...
108
+ end
109
+ ```
110
+
111
+ These statements lock the controller and set the following:
112
+ * _Administrators_ (admins) are authorized to access any action.
113
+ * _Editors_ can list, view and edit articles.
114
+ * _Anyone else_ can **only** list and view articles.
115
+
116
+ This case uses the special keyword `:all`, it means everyone if passed as the
117
+ first argument or every action if passed as the second one.
118
+
119
+ Again, any unauthorized request will be rejected and redirected with an alert.
120
+
121
+ ### Note about clearance levels
122
+
123
+ Notice that in the previous examples we didn't need to define clearance levels
124
+ or roles anywhere else in the application. With the authorization statement you
125
+ both **define** them and **set their permissions**. The only requirement is
126
+ that the clearance levels from the authorizations match the one returned by
127
+ `current_clearance_level`.
128
+
129
+
130
+ ## Advanced configuration
131
+
132
+ ### Locked by default
133
+
134
+ The `lock_access` class method forces controllers to be locked even if no
135
+ permissions are defined, in such case every request will be redirected.
136
+
137
+ This allows to ensure that an entire application or scope (e.g. `Admin`) is
138
+ **locked by default**. Simply call `lock_access` inside `ApplicationController`
139
+ or from a scope's base controller.
140
+
141
+ ```ruby
142
+ class ApplicationController < ActionController::Base
143
+ lock_access
144
+
145
+ # ...
146
+ end
147
+ ```
148
+
149
+ To **unlock** a single controller (to make it "public") add `let :all, :all`,
150
+ this will allow anyone to access any action in the controller.
151
+
152
+ ### Redirection path
153
+
154
+ By default any unauthorized (or not explicitly authorized) access will be
155
+ redirected to the **root path**.
156
+
157
+ You can set or choose a different path by overriding the somewhat long but
158
+ very clear `unauthorized_access_redirection_path` method.
159
+
160
+ ```ruby
161
+ class ApplicationController < ActionController::Base
162
+
163
+ def unathorized_access_redirection_path
164
+ case current_user.clearance_level.to_sym
165
+ when :admin then admin_root_path
166
+ when :user then user_root_path
167
+ else root_path
168
+ end
169
+ end
170
+
171
+ # ...
172
+ end
173
+ ```
174
+
175
+ ### Alert message
176
+
177
+ Redirections have a default alert message of "Not authorized.". To customize it
178
+ or use translations set `action_access.redirection_message` in your locales.
179
+
180
+ ```yml
181
+ # config/locales/en.yml
182
+ en:
183
+ action_access:
184
+ redirection_message: "You are not allowed to do this!"
185
+ ```
186
+
187
+
188
+ ## Utilities
189
+
190
+ ### Fine Grained Access Control
191
+
192
+ If further control is required, possibly because access depends on request
193
+ parameters or some result from the database, you can use the `not_authorized!`
194
+ method inside actions to reject the request and issue a redirection. It
195
+ optionally takes a redirection path and a custom alert message.
196
+
197
+ ```ruby
198
+ class ProfilesController < ApplicationController
199
+ let :user, [:edit, :update]
200
+
201
+ def update
202
+ unless params[:id] == current_user.profile_id
203
+ not_authorized! path: profile_path, message: "That's not your profile!"
204
+ end
205
+
206
+ # ...
207
+ end
208
+
209
+ # ...
210
+ end
211
+ ```
212
+
213
+ There are better ways to handle this particular case but it serves to outline
214
+ the use of `not_authorized!` inside actions.
215
+
216
+ ### Model additions
217
+
218
+ Action Access is bundled with some model utilities too. By calling
219
+ `add_access_utilities` in any model it will extend it with a `can?` instance
220
+ method that checks if the entity (commonly a user) is authorized to perform a
221
+ given action on a resource.
222
+
223
+ `can?` takes two arguments, the action and the resource, and a namespace option
224
+ if needed. The resource can be a string, symbol, controller class or model
225
+ instance. Action Access will do the possible to get the right controller out
226
+ of the resource and the namespace (optional). In the end it returns a boolean.
227
+
228
+ **Some examples:**
229
+
230
+ ```ruby
231
+ @user.can? :edit, :articles, namespace: :admin
232
+ @user.can? :edit, @admin_article # Admin::Article instance
233
+ @user.can? :edit, Admin::ArticlesController
234
+ # True if the user's clearance level allows her to access 'admin/articles#edit'.
235
+ ```
236
+
237
+ `can?` depends on a `clearance_level` method in the model so don't forget it.
238
+ Continuing with the `User` model from before:
239
+
240
+ ```ruby
241
+ class User < ActiveRecord::Base
242
+ add_access_utilities
243
+
244
+ belongs_to :role
245
+
246
+ def clearance_level
247
+ role.name
248
+ end
249
+ end
250
+ ```
251
+
252
+ ```erb
253
+ <% if current_user.can? :edit, :articles %>
254
+ <%= link_to 'Edit article', edit_article_path(@article) %>
255
+ <% end %>
256
+ ```
257
+
258
+ ### The keeper
259
+
260
+ The **keeper** is the core of Action Access, it's the one that registers
261
+ permissions and who decides if a clearance level grants access or not.
262
+
263
+ It's available as `keeper` within controllers and views and as
264
+ `ActionAccess::Keeper.instance` anywhere else. You can use it check permissions
265
+ with the `lets?` method that takes the clearance level as the first argument,
266
+ the rest are the same as `can?`.
267
+
268
+ ```ruby
269
+ # Filter a list of users to only those allowed to edit articles.
270
+ @users.select { |user| keeper.lets? user.role.name, :edit, :articles }
271
+ ```
272
+
273
+
274
+ ## License
275
+
276
+ Action Access is released under the [MIT License](http://opensource.org/licenses/MIT).
277
+
278
+ Copyright (c) 2014 Matías A. Gagliano.
279
+
280
+
281
+ ## Contributing
282
+
283
+ See [CONTRIBUTING.md](CONTRIBUTING.md).