pundit 0.2.2 → 0.2.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6dc0e920a5482e8b695a1cc1afd205fdc7752ad2
4
- data.tar.gz: 1354dab74c79e3673cc034ccccea04688e4cb07a
3
+ metadata.gz: 7cddd41b1da668bb3ff0c192972c1e69a590a66a
4
+ data.tar.gz: 3d21909c8ce034f4e5253045e10407b1a275bd01
5
5
  SHA512:
6
- metadata.gz: 0b745c98f6c3aa8376e97f3270ae6f3358339f13eb2fdd57c8adfc0e47f2dee073138866b7df986317d3bd19f6d23c80f7ffb6311a99b97c4f2fe46cb6924e93
7
- data.tar.gz: bad3e8cb1c9c8888abf4b93521100ae0122eeebb19dbaaf1790e6beb20189dac55a7e60c017bf525ea5b7091ff9c2a07b3126bd928e6f8d22ded5b0b1f3e9ab2
6
+ metadata.gz: 7498ab09942c960b5acc81c7ab9b081e7013007621ed53968d52815abd33e9a67310ac46810b1f3ae754755df01b40d90936b99d247854bcebef16b4b4976e9c
7
+ data.tar.gz: de605bb11eed39677a26ec2426347205e134e1cad09044870705ca73dadf26a152328750387cce44b721add47a8992a700020a0bf4b63f940406e5dfa99a0d2d
data/.travis.yml CHANGED
@@ -4,4 +4,4 @@ rvm:
4
4
  - 2.0.0
5
5
  - 2.1.0
6
6
  - jruby-19mode
7
- - rbx-2.2.3
7
+ - rbx
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # Pundit
2
+
3
+ ## 0.2.3 (unreleased)
4
+
5
+ - Add CHANGELOG (#107)
6
+
7
+ ## 0.2.2 (2014-02-07)
8
+
9
+ - Add [`pundit_user`](https://github.com/elabs/pundit#customize-pundit-user) (#42)
data/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  [![Build Status](https://secure.travis-ci.org/elabs/pundit.png?branch=master)](https://travis-ci.org/elabs/pundit)
4
4
  [![Code Climate](https://codeclimate.com/github/elabs/pundit.png)](https://codeclimate.com/github/elabs/pundit)
5
+ [![Inline docs](http://inch-pages.github.io/github/elabs/pundit.png)](http://inch-pages.github.io/github/elabs/pundit)
5
6
 
6
7
  Pundit provides a set of helpers which guide you in leveraging regular Ruby
7
8
  classes and object oriented design patterns to build a simple, robust and
@@ -57,13 +58,16 @@ As you can see, this is just a plain Ruby class. As a convenience, we can inheri
57
58
  from Struct or use Struct.new to define the policy class:
58
59
 
59
60
  ``` ruby
60
- PostPolicy = Struct.new(:user, :post) do
61
+ class PostPolicy < Struct.new(:user, :post)
61
62
  def update?
62
63
  user.admin? or not post.published?
63
64
  end
64
65
  end
65
66
  ```
66
67
 
68
+ You could also use the convenient
69
+ [attr_extras](https://github.com/barsoom/attr_extras) gem.
70
+
67
71
  Pundit makes the following assumptions about this class:
68
72
 
69
73
  - The class has the same name as some kind of model class, only suffixed
@@ -157,8 +161,8 @@ particular user has access to. When using Pundit, you are expected to
157
161
  define a class called a policy scope. It can look something like this:
158
162
 
159
163
  ``` ruby
160
- PostPolicy = Struct.new(:user, :post) do
161
- self::Scope = Struct.new(:user, :scope) do
164
+ class PostPolicy < Struct.new(:user, :post)
165
+ class Scope < Struct.new(:user, :scope)
162
166
  def resolve
163
167
  if user.admin?
164
168
  scope.all
@@ -271,7 +275,10 @@ end
271
275
 
272
276
  ## Rescuing a denied Authorization in Rails
273
277
 
274
- Pundit raises a `Pundit::NotAuthorizedError` you can [rescue_from](http://guides.rubyonrails.org/action_controller_overview.html#rescue-from) in your `ApplicationController`. You can customize the `user_not_authorized` method in every controller.
278
+ Pundit raises a `Pundit::NotAuthorizedError` you can
279
+ [rescue_from](http://guides.rubyonrails.org/action_controller_overview.html#rescue-from)
280
+ in your `ApplicationController`. You can customize the `user_not_authorized`
281
+ method in every controller.
275
282
 
276
283
  ```ruby
277
284
  class ApplicationController < ActionController::Base
@@ -284,11 +291,48 @@ class ApplicationController < ActionController::Base
284
291
 
285
292
  def user_not_authorized
286
293
  flash[:error] = "You are not authorized to perform this action."
287
- redirect_to request.headers["Referer"] || root_path
294
+ redirect_to(request.referrer || root_path)
288
295
  end
289
296
  end
290
297
  ```
291
298
 
299
+ ### Creating custom error messages
300
+
301
+ `NotAuthorizedError`s provide information on what query (e.g. `:create?`), what
302
+ record (e.g. an instance of `Post`), and what policy (e.g. an instance of
303
+ `PostPolicy`) caused the error to be raised.
304
+
305
+ One way to use these `query`, `record`, and `policy` properties is to connect
306
+ them with `I18n` to generate error messages. Here's how you might go about doing
307
+ that.
308
+
309
+ ```ruby
310
+ class ApplicationController < ActionController::Base
311
+ rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
312
+
313
+ private
314
+
315
+ def user_not_authorized(exception)
316
+ policy_name = exception.policy.class.to_s.underscore
317
+
318
+ flash[:error] = I18n.t "pundit.#{policy_name}.#{exception.query}",
319
+ default: 'You cannot perform this action.'
320
+ redirect_to(request.referrer || root_path)
321
+ end
322
+ end
323
+ ```
324
+
325
+ ```yaml
326
+ en:
327
+ pundit:
328
+ post_policy:
329
+ update?: 'You cannot edit this post!'
330
+ create?: 'You cannot create posts!'
331
+ ```
332
+
333
+ Of course, this is just an example. Pundit is agnostic as to how you implement
334
+ your error messaging.
335
+
292
336
  ## Manually retrieving policies and scopes
293
337
 
294
338
  Sometimes you want to retrieve a policy for a record outside the controller or
@@ -422,6 +466,7 @@ based on what is or is not authorized.
422
466
 
423
467
  # External Resources
424
468
 
469
+ - [RailsApps Example Application: Pundit and Devise](https://github.com/RailsApps/rails-devise-pundit)
425
470
  - [Migrating to Pundit from CanCan](http://blog.carbonfive.com/2013/10/21/migrating-to-pundit-from-cancan/)
426
471
  - [Testing Pundit Policies with RSpec](http://thunderboltlabs.com/blog/2013/03/27/testing-pundit-policies-with-rspec/)
427
472
 
data/lib/pundit.rb CHANGED
@@ -5,7 +5,10 @@ require "active_support/core_ext/string/inflections"
5
5
  require "active_support/core_ext/object/blank"
6
6
 
7
7
  module Pundit
8
- class NotAuthorizedError < StandardError; end
8
+ class NotAuthorizedError < StandardError
9
+ attr_accessor :query, :record, :policy
10
+ end
11
+ class AuthorizationNotPerformedError < StandardError; end
9
12
  class NotDefinedError < StandardError; end
10
13
 
11
14
  extend ActiveSupport::Concern
@@ -37,6 +40,10 @@ module Pundit
37
40
  helper_method :pundit_user
38
41
  end
39
42
  if respond_to?(:hide_action)
43
+ hide_action :policy_scope
44
+ hide_action :policy_scope=
45
+ hide_action :policy
46
+ hide_action :policy=
40
47
  hide_action :authorize
41
48
  hide_action :verify_authorized
42
49
  hide_action :verify_policy_scoped
@@ -45,19 +52,25 @@ module Pundit
45
52
  end
46
53
 
47
54
  def verify_authorized
48
- raise NotAuthorizedError unless @_policy_authorized
55
+ raise AuthorizationNotPerformedError unless @_policy_authorized
49
56
  end
50
57
 
51
58
  def verify_policy_scoped
52
- raise NotAuthorizedError unless @_policy_scoped
59
+ raise AuthorizationNotPerformedError unless @_policy_scoped
53
60
  end
54
61
 
55
62
  def authorize(record, query=nil)
56
63
  query ||= params[:action].to_s + "?"
57
64
  @_policy_authorized = true
58
- unless policy(record).public_send(query)
59
- raise NotAuthorizedError, "not allowed to #{query} this #{record}"
65
+
66
+ policy = policy(record)
67
+ unless policy.public_send(query)
68
+ error = NotAuthorizedError.new("not allowed to #{query} this #{record}")
69
+ error.query, error.record, error.policy = query, record, policy
70
+
71
+ raise error
60
72
  end
73
+
61
74
  true
62
75
  end
63
76
 
data/lib/pundit/rspec.rb CHANGED
@@ -21,7 +21,8 @@ module Pundit
21
21
  end
22
22
 
23
23
  def permissions
24
- example.metadata[:permissions]
24
+ current_example = ::RSpec.respond_to?(:current_example) ? ::RSpec.current_example : example
25
+ current_example.metadata[:permissions]
25
26
  end
26
27
  end
27
28
  end
@@ -1,3 +1,3 @@
1
1
  module Pundit
2
- VERSION = "0.2.2"
2
+ VERSION = "0.2.3"
3
3
  end
data/pundit.gemspec CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |gem|
21
21
  gem.add_dependency "activesupport", ">= 3.0.0"
22
22
  gem.add_development_dependency "activerecord", ">= 3.0.0"
23
23
  gem.add_development_dependency "bundler", "~> 1.3"
24
- gem.add_development_dependency "rspec", "~>2.0"
24
+ gem.add_development_dependency "rspec", "~>3.0.0.beta1"
25
25
  gem.add_development_dependency "pry"
26
26
  gem.add_development_dependency "rake"
27
27
  gem.add_development_dependency "yard"
data/spec/pundit_spec.rb CHANGED
@@ -66,25 +66,25 @@ describe Pundit do
66
66
 
67
67
  describe ".policy_scope" do
68
68
  it "returns an instantiated policy scope given a plain model class" do
69
- Pundit.policy_scope(user, Post).should == :published
69
+ expect(Pundit.policy_scope(user, Post)).to eq :published
70
70
  end
71
71
 
72
72
  it "returns an instantiated policy scope given an active model class" do
73
- Pundit.policy_scope(user, Comment).should == Comment
73
+ expect(Pundit.policy_scope(user, Comment)).to eq Comment
74
74
  end
75
75
 
76
76
  it "returns nil if the given policy scope can't be found" do
77
- Pundit.policy_scope(user, Article).should be_nil
77
+ expect(Pundit.policy_scope(user, Article)).to be_nil
78
78
  end
79
79
  end
80
80
 
81
81
  describe ".policy_scope!" do
82
82
  it "returns an instantiated policy scope given a plain model class" do
83
- Pundit.policy_scope!(user, Post).should == :published
83
+ expect(Pundit.policy_scope!(user, Post)).to eq :published
84
84
  end
85
85
 
86
86
  it "returns an instantiated policy scope given an active model class" do
87
- Pundit.policy_scope!(user, Comment).should == Comment
87
+ expect(Pundit.policy_scope!(user, Comment)).to eq Comment
88
88
  end
89
89
 
90
90
  it "throws an exception if the given policy scope can't be found" do
@@ -99,56 +99,56 @@ describe Pundit do
99
99
  describe ".policy" do
100
100
  it "returns an instantiated policy given a plain model instance" do
101
101
  policy = Pundit.policy(user, post)
102
- policy.user.should == user
103
- policy.post.should == post
102
+ expect(policy.user).to eq user
103
+ expect(policy.post).to eq post
104
104
  end
105
105
 
106
106
  it "returns an instantiated policy given an active model instance" do
107
107
  policy = Pundit.policy(user, comment)
108
- policy.user.should == user
109
- policy.comment.should == comment
108
+ expect(policy.user).to eq user
109
+ expect(policy.comment).to eq comment
110
110
  end
111
111
 
112
112
  it "returns an instantiated policy given a plain model class" do
113
113
  policy = Pundit.policy(user, Post)
114
- policy.user.should == user
115
- policy.post.should == Post
114
+ expect(policy.user).to eq user
115
+ expect(policy.post).to eq Post
116
116
  end
117
117
 
118
118
  it "returns an instantiated policy given an active model class" do
119
119
  policy = Pundit.policy(user, Comment)
120
- policy.user.should == user
121
- policy.comment.should == Comment
120
+ expect(policy.user).to eq user
121
+ expect(policy.comment).to eq Comment
122
122
  end
123
123
 
124
124
  it "returns nil if the given policy can't be found" do
125
- Pundit.policy(user, article).should be_nil
126
- Pundit.policy(user, Article).should be_nil
125
+ expect(Pundit.policy(user, article)).to be_nil
126
+ expect(Pundit.policy(user, Article)).to be_nil
127
127
  end
128
128
 
129
129
  describe "with .policy_class set on the model" do
130
130
  it "returns an instantiated policy given a plain model instance" do
131
131
  policy = Pundit.policy(user, artificial_blog)
132
- policy.user.should == user
133
- policy.blog.should == artificial_blog
132
+ expect(policy.user).to eq user
133
+ expect(policy.blog).to eq artificial_blog
134
134
  end
135
135
 
136
136
  it "returns an instantiated policy given a plain model class" do
137
137
  policy = Pundit.policy(user, ArtificialBlog)
138
- policy.user.should == user
139
- policy.blog.should == ArtificialBlog
138
+ expect(policy.user).to eq user
139
+ expect(policy.blog).to eq ArtificialBlog
140
140
  end
141
141
 
142
142
  it "returns an instantiated policy given a plain model instance providing an anonymous class" do
143
143
  policy = Pundit.policy(user, article_tag)
144
- policy.user.should == user
145
- policy.tag.should == article_tag
144
+ expect(policy.user).to eq user
145
+ expect(policy.tag).to eq article_tag
146
146
  end
147
147
 
148
148
  it "returns an instantiated policy given a plain model class providing an anonymous class" do
149
149
  policy = Pundit.policy(user, ArticleTag)
150
- policy.user.should == user
151
- policy.tag.should == ArticleTag
150
+ expect(policy.user).to eq user
151
+ expect(policy.tag).to eq ArticleTag
152
152
  end
153
153
  end
154
154
  end
@@ -156,26 +156,26 @@ describe Pundit do
156
156
  describe ".policy!" do
157
157
  it "returns an instantiated policy given a plain model instance" do
158
158
  policy = Pundit.policy!(user, post)
159
- policy.user.should == user
160
- policy.post.should == post
159
+ expect(policy.user).to eq user
160
+ expect(policy.post).to eq post
161
161
  end
162
162
 
163
163
  it "returns an instantiated policy given an active model instance" do
164
164
  policy = Pundit.policy!(user, comment)
165
- policy.user.should == user
166
- policy.comment.should == comment
165
+ expect(policy.user).to eq user
166
+ expect(policy.comment).to eq comment
167
167
  end
168
168
 
169
169
  it "returns an instantiated policy given a plain model class" do
170
170
  policy = Pundit.policy!(user, Post)
171
- policy.user.should == user
172
- policy.post.should == Post
171
+ expect(policy.user).to eq user
172
+ expect(policy.post).to eq Post
173
173
  end
174
174
 
175
175
  it "returns an instantiated policy given an active model class" do
176
176
  policy = Pundit.policy!(user, Comment)
177
- policy.user.should == user
178
- policy.comment.should == Comment
177
+ expect(policy.user).to eq user
178
+ expect(policy.comment).to eq Comment
179
179
  end
180
180
 
181
181
  it "throws an exception if the given policy can't be found" do
@@ -191,7 +191,7 @@ describe Pundit do
191
191
  end
192
192
 
193
193
  it "raises an exception when not authorized" do
194
- expect { controller.verify_authorized }.to raise_error(Pundit::NotAuthorizedError)
194
+ expect { controller.verify_authorized }.to raise_error(Pundit::AuthorizationNotPerformedError)
195
195
  end
196
196
  end
197
197
 
@@ -202,41 +202,49 @@ describe Pundit do
202
202
  end
203
203
 
204
204
  it "raises an exception when policy_scope is not used" do
205
- expect { controller.verify_policy_scoped }.to raise_error(Pundit::NotAuthorizedError)
205
+ expect { controller.verify_policy_scoped }.to raise_error(Pundit::AuthorizationNotPerformedError)
206
206
  end
207
207
  end
208
208
 
209
209
  describe "#authorize" do
210
210
  it "infers the policy name and authorized based on it" do
211
- controller.authorize(post).should be_true
211
+ expect(controller.authorize(post)).to be_truthy
212
212
  end
213
213
 
214
214
  it "can be given a different permission to check" do
215
- controller.authorize(post, :show?).should be_true
215
+ expect(controller.authorize(post, :show?)).to be_truthy
216
216
  expect { controller.authorize(post, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
217
217
  end
218
218
 
219
219
  it "works with anonymous class policies" do
220
- controller.authorize(article_tag, :show?).should be_true
220
+ expect(controller.authorize(article_tag, :show?)).to be_truthy
221
221
  expect { controller.authorize(article_tag, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
222
222
  end
223
223
 
224
224
  it "raises an error when the permission check fails" do
225
225
  expect { controller.authorize(Post.new) }.to raise_error(Pundit::NotAuthorizedError)
226
226
  end
227
+
228
+ it "raises an error with a query and action" do
229
+ expect { controller.authorize(post, :destroy?) }.to raise_error do |error|
230
+ expect(error.query).to eq :destroy?
231
+ expect(error.record).to eq post
232
+ expect(error.policy).to eq controller.policy(post)
233
+ end
234
+ end
227
235
  end
228
236
 
229
237
  describe "#pundit_user" do
230
238
  it 'returns the same thing as current_user' do
231
- controller.pundit_user.should eq controller.current_user
239
+ expect(controller.pundit_user).to eq controller.current_user
232
240
  end
233
241
  end
234
242
 
235
243
  describe ".policy" do
236
244
  it "returns an instantiated policy" do
237
245
  policy = controller.policy(post)
238
- policy.user.should == user
239
- policy.post.should == post
246
+ expect(policy.user).to eq user
247
+ expect(policy.post).to eq post
240
248
  end
241
249
 
242
250
  it "throws an exception if the given policy can't be found" do
@@ -247,13 +255,13 @@ describe Pundit do
247
255
  new_policy = OpenStruct.new
248
256
  controller.policy = new_policy
249
257
 
250
- controller.policy(post).should == new_policy
258
+ expect(controller.policy(post)).to eq new_policy
251
259
  end
252
260
  end
253
261
 
254
262
  describe ".policy_scope" do
255
263
  it "returns an instantiated policy scope" do
256
- controller.policy_scope(Post).should == :published
264
+ expect(controller.policy_scope(Post)).to eq :published
257
265
  end
258
266
 
259
267
  it "throws an exception if the given policy can't be found" do
@@ -264,7 +272,7 @@ describe Pundit do
264
272
  new_scope = OpenStruct.new
265
273
  controller.policy_scope = new_scope
266
274
 
267
- controller.policy_scope(post).should == new_scope
275
+ expect(controller.policy_scope(post)).to eq new_scope
268
276
  end
269
277
  end
270
278
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pundit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonas Nicklas
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-02-07 00:00:00.000000000 Z
12
+ date: 2014-04-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -59,14 +59,14 @@ dependencies:
59
59
  requirements:
60
60
  - - ~>
61
61
  - !ruby/object:Gem::Version
62
- version: '2.0'
62
+ version: 3.0.0.beta1
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
67
  - - ~>
68
68
  - !ruby/object:Gem::Version
69
- version: '2.0'
69
+ version: 3.0.0.beta1
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: pry
72
72
  requirement: !ruby/object:Gem::Requirement
@@ -119,6 +119,7 @@ extra_rdoc_files: []
119
119
  files:
120
120
  - .gitignore
121
121
  - .travis.yml
122
+ - CHANGELOG.md
122
123
  - Gemfile
123
124
  - LICENSE.txt
124
125
  - README.md