authorize_if 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 (47) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +200 -0
  4. data/Rakefile +34 -0
  5. data/lib/authorize_if.rb +138 -0
  6. data/lib/authorize_if/version.rb +3 -0
  7. data/lib/tasks/authorize_if_tasks.rake +4 -0
  8. data/test/dummy/README.rdoc +28 -0
  9. data/test/dummy/Rakefile +6 -0
  10. data/test/dummy/app/assets/javascripts/application.js +13 -0
  11. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  12. data/test/dummy/app/controllers/application_controller.rb +9 -0
  13. data/test/dummy/app/controllers/articles_controller.rb +27 -0
  14. data/test/dummy/app/helpers/application_helper.rb +2 -0
  15. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  16. data/test/dummy/bin/bundle +3 -0
  17. data/test/dummy/bin/rails +4 -0
  18. data/test/dummy/bin/rake +4 -0
  19. data/test/dummy/bin/setup +29 -0
  20. data/test/dummy/config.ru +4 -0
  21. data/test/dummy/config/application.rb +13 -0
  22. data/test/dummy/config/boot.rb +5 -0
  23. data/test/dummy/config/environment.rb +5 -0
  24. data/test/dummy/config/environments/development.rb +35 -0
  25. data/test/dummy/config/environments/production.rb +72 -0
  26. data/test/dummy/config/environments/test.rb +37 -0
  27. data/test/dummy/config/initializers/assets.rb +11 -0
  28. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  29. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  30. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  31. data/test/dummy/config/initializers/inflections.rb +16 -0
  32. data/test/dummy/config/initializers/mime_types.rb +4 -0
  33. data/test/dummy/config/initializers/session_store.rb +3 -0
  34. data/test/dummy/config/initializers/wrap_parameters.rb +9 -0
  35. data/test/dummy/config/locales/en.yml +23 -0
  36. data/test/dummy/config/routes.rb +3 -0
  37. data/test/dummy/config/secrets.yml +22 -0
  38. data/test/dummy/db/test.sqlite3 +0 -0
  39. data/test/dummy/log/test.log +1784 -0
  40. data/test/dummy/public/404.html +67 -0
  41. data/test/dummy/public/422.html +67 -0
  42. data/test/dummy/public/500.html +66 -0
  43. data/test/dummy/public/favicon.ico +0 -0
  44. data/test/integration/authorize_if_integration_test.rb +41 -0
  45. data/test/test_helper.rb +19 -0
  46. data/test/unit/authorize_if_unit_test.rb +113 -0
  47. metadata +170 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fea95712c0006a402eef0bff57366a89a7b6cb67
4
+ data.tar.gz: b667cf8c07496f7fa6b1970107e5de1e44b53db2
5
+ SHA512:
6
+ metadata.gz: 34aff8dfa5ddeeea9ca00539a375c3e97c719b11d86b0367b2bbfdfcbc8d0cd0d58038040ba42f5b108cd4c96fe4e20524779962366e61bae31096840f999d08
7
+ data.tar.gz: 761953381f50d9842b22183bbe2582ea680a8650d28848a0dc37bbf2f54eabc0f4c16afa5f58316c700e4e2e3458fe1dcd0aac7d916ca64e82c0a40acac736f4
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Vladimir Rybas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,200 @@
1
+ # authorize_if
2
+
3
+ Minimalistic authorization library for Ruby on Rails applications. It
4
+ defines controller methods `authorize` and `authorize_if`, which accept
5
+ authorization rules and raise exception if rule evaluates to `false`.
6
+
7
+ And that's it.
8
+
9
+ ## Installation
10
+
11
+ Add gem to your application's `Gemfile`:
12
+
13
+ gem 'authorize_if'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install authorize_if
22
+
23
+ ## Usage
24
+
25
+ #### `authorize_if`
26
+
27
+ Accepts any `truthy` or `falsey` Ruby object.
28
+
29
+ ```ruby
30
+ class ArticlesController
31
+ def index
32
+ authorize_if current_user
33
+ # ...
34
+ end
35
+
36
+ def show
37
+ article = Article.find(params[:id])
38
+
39
+ authorize_if article.authored_by?(current_user) ||
40
+ article.group.members.include?(current_user)
41
+ # ...
42
+ end
43
+
44
+ def edit
45
+ article = Article.find(params[:id])
46
+
47
+ authorize_if can_manage?(article)
48
+ # ...
49
+ end
50
+
51
+ private
52
+
53
+ def can_manage?(article)
54
+ # ...
55
+ end
56
+ end
57
+ ```
58
+
59
+ It raises `AuthorizeIf::NotAuthorizedError` exception, which you can
60
+ rescue right in the controller method
61
+
62
+ ```ruby
63
+ class ArticlesController
64
+ def index
65
+ authorize_if current_user
66
+ # ...
67
+
68
+ rescue AuthorizeIf::NotAuthorizedError
69
+ head 403
70
+
71
+ end
72
+ end
73
+ ```
74
+
75
+ or with `rescue_from` in `ApplicaitonController`:
76
+
77
+ ```ruby
78
+ class ApplicationController < ActionController::Base
79
+ rescue_from "AuthorizeIf::NotAuthorizedError" do |exception|
80
+ head 403
81
+ end
82
+ end
83
+ ```
84
+
85
+ You can set custom error message by using configuration block
86
+
87
+ ```ruby
88
+ class ArticlesController
89
+ def index
90
+ authorize_if(current_user) do |config|
91
+ config.error_message = "You are not authorized!"
92
+ end
93
+ # ...
94
+ end
95
+ end
96
+
97
+ class ApplicationController < ActionController::Base
98
+ rescue_from "AuthorizeIf::NotAuthorizedError" do |exception|
99
+ render text: exception.message, status: 403
100
+ end
101
+ end
102
+ ```
103
+
104
+ #### `authorize`
105
+
106
+ This method helps to extract authorization rules out of controller. It
107
+ expects corresponding authorization rule to exist.
108
+
109
+ ```ruby
110
+ class ArticlesController
111
+ def index
112
+ authorize
113
+
114
+ # ...
115
+ end
116
+
117
+ private
118
+
119
+ def authorize_index?
120
+ current_user.present?
121
+ end
122
+ end
123
+ ```
124
+
125
+ You can extract those rules into a module and include them to the
126
+ controller.
127
+
128
+ ```ruby
129
+ module AuthorizationRules
130
+ def authorize_index?
131
+ current_user.present?
132
+ end
133
+ end
134
+
135
+ class ArticlesController
136
+ include AuthorizationRules
137
+
138
+ def index
139
+ authorize
140
+
141
+ # ...
142
+ end
143
+ end
144
+ ```
145
+
146
+ `authorize` accepts any parameters and passes them to authorization
147
+ rule.
148
+
149
+ ```ruby
150
+ class ArticlesController
151
+ def edit
152
+ article = Article.find(params[:id])
153
+
154
+ authorize(article)
155
+
156
+ # ...
157
+ end
158
+
159
+ private
160
+
161
+ def authorize_edit?(article)
162
+ article.author == current_user
163
+ end
164
+ end
165
+ ```
166
+
167
+ It can also be customized by using configuration block.
168
+
169
+ ```ruby
170
+ class ArticlesController
171
+ def edit
172
+ article = Article.find(params[:id])
173
+
174
+ authorize(article) do |config|
175
+ config.error_message = "You are not authorized!"
176
+ end
177
+
178
+ # ...
179
+ end
180
+
181
+ private
182
+
183
+ def authorize_edit?(article)
184
+ article.author == current_user
185
+ end
186
+ end
187
+ ```
188
+
189
+ ## Contributing
190
+
191
+ 1. Fork it ( https://github.com/vrybas/authorize_if/fork )
192
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
193
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
194
+ 4. Push to the branch (`git push origin my-new-feature`)
195
+ 5. Create a new Pull Request
196
+
197
+ ## License
198
+
199
+ Copyright 2016 Vladimir Rybas. MIT License (see LICENSE for details).
200
+
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'AuthorizeIf'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+
34
+ task default: :test
@@ -0,0 +1,138 @@
1
+ # Provides a set of methods to handle authorization scenarios.
2
+ # It is included to ActionController::Base on load.
3
+ #
4
+ module AuthorizeIf
5
+ NotAuthorizedError = Class.new(StandardError)
6
+ MissingAuthorizationRuleError = Class.new(StandardError)
7
+
8
+ Configuration = Class.new do
9
+ attr_accessor :error_message
10
+ end
11
+
12
+ # Evaluates given object as boolean. Returns 'true' if object
13
+ # evaluates to 'true'. Raises `AuthorizeIf::NotAuthorizedError`
14
+ # if object evaluates to 'false'.
15
+ #
16
+ # Also accepts block and calls it with `AuthorizeIf::Configuration`
17
+ # object as parameter. Behavior can be customized by calling methods
18
+ # on configuraiton object.
19
+ #
20
+ # @param [Object] rule
21
+ # The authorization rule. Any "truthy" or "falsey" Ruby object.
22
+ #
23
+ # @param [Proc] block
24
+ # The configuration block. Supported configuration:
25
+ # `error_message=()` - custom error message, which will be raised
26
+ # along with `AuthorizeIf::NotAuthorizedError`
27
+ # exception.
28
+ #
29
+ # @example
30
+ # class ArticlesController
31
+ # def index
32
+ # authorize_if current_user
33
+ # # => true
34
+ #
35
+ # ...
36
+ # end
37
+ #
38
+ # def edit
39
+ # @article = Article.find(params[:id])
40
+ #
41
+ # authorize_if @article.authors.include?(current_user) do |config|
42
+ # config.error_message = "You are not authorized!"
43
+ # end
44
+ # # => AuthorizeIf::NotAuthorizedError: You are not authorized!
45
+ #
46
+ # ...
47
+ # end
48
+ # end
49
+ #
50
+ #
51
+ # @return [Boolean]
52
+ # Returns 'true' if given object evaluates to 'true'.
53
+ #
54
+ # @raise [AuthorizeIf::NotAuthorizedError]
55
+ # Raised if given object evaluates to 'false'.
56
+ #
57
+ def authorize_if(rule, &block)
58
+ config = Configuration.new
59
+ block.call(config) if block
60
+
61
+ !!rule || raise(NotAuthorizedError, config.error_message)
62
+ end
63
+
64
+ # Accepts any arguments and configuration block. Calls corresponding
65
+ # authorization rule method with given arguments, except block.
66
+ #
67
+ # Then calls `#authorize_if` with the returning value of corresponding
68
+ # authorization rule as first argument, and with given configuration block.
69
+ #
70
+ # @param *args
71
+ # Any arguments, which will be given to corresponding
72
+ # authorization rule.
73
+ #
74
+ # @param [Proc] block
75
+ # The configuration block. See `#authorize_if` for complete list of
76
+ # configuration options.
77
+ #
78
+ # @example
79
+ # class ArticlesController
80
+ # def index
81
+ # authorize
82
+ # # => true
83
+ #
84
+ # ...
85
+ # end
86
+ #
87
+ # def edit
88
+ # @article = Article.find(params[:id])
89
+ #
90
+ # authorize(@article) do |config|
91
+ # config.error_message = "You are not authorized!"
92
+ # end
93
+ # # => AuthorizeIf::NotAuthorizedError: You are not authorized!
94
+ #
95
+ # ...
96
+ # end
97
+ #
98
+ # def destroy
99
+ # authorize
100
+ # # => AuthorizeIf::MissingAuthorizationRuleError: No authorization
101
+ # rule defined for action articles#destroy. Please define
102
+ # method #authorize_destroy? for ArticlesController
103
+ #
104
+ # ...
105
+ # end
106
+ #
107
+ # private
108
+ #
109
+ # def authorize_index?
110
+ # current_user.present?
111
+ # end
112
+ #
113
+ # def authorize_edit?(article)
114
+ # article.author == current_user
115
+ # end
116
+ # end
117
+ #
118
+ def authorize(*args, &block)
119
+ rule_method_name = "authorize_#{action_name}?"
120
+
121
+ unless self.respond_to?(rule_method_name, true)
122
+ msg = [
123
+ "No authorization rule defined for action",
124
+ "#{controller_name}##{action_name}.",
125
+ "Please define method ##{rule_method_name} for",
126
+ self.class.name
127
+ ].join(' ')
128
+
129
+ raise(MissingAuthorizationRuleError, msg)
130
+ end
131
+
132
+ authorize_if(self.send(rule_method_name, *args), &block)
133
+ end
134
+ end
135
+
136
+ ActiveSupport.on_load :action_controller do
137
+ include AuthorizeIf
138
+ end
@@ -0,0 +1,3 @@
1
+ module AuthorizeIf
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :authorize_if do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,28 @@
1
+ == README
2
+
3
+ This README would normally document whatever steps are necessary to get the
4
+ application up and running.
5
+
6
+ Things you may want to cover:
7
+
8
+ * Ruby version
9
+
10
+ * System dependencies
11
+
12
+ * Configuration
13
+
14
+ * Database creation
15
+
16
+ * Database initialization
17
+
18
+ * How to run the test suite
19
+
20
+ * Services (job queues, cache servers, search engines, etc.)
21
+
22
+ * Deployment instructions
23
+
24
+ * ...
25
+
26
+
27
+ Please feel free to use a different markup language if you do not plan to run
28
+ <tt>rake doc:app</tt>.