pundit 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Pundit
2
2
 
3
+ [![Build Status](https://secure.travis-ci.org/elabs/pundit.png?branch=master)](https://travis-ci.org/elabs/pundit)
4
+
3
5
  Pundit provides a set of helpers which guide you in leveraging regular Ruby
4
6
  classes and object oriented design patterns to build a simple, robust and
5
7
  scaleable authorization system.
@@ -193,6 +195,19 @@ You can, and are encouraged to, use this method in views:
193
195
  <% end %>
194
196
  ```
195
197
 
198
+ ## Manually specifying policy classes
199
+
200
+ Sometimes you might want to explicitly declare which policy to use for a given
201
+ class, instead of letting Pundit infer it. This can be done like so:
202
+
203
+ ``` ruby
204
+ class Post
205
+ def self.policy_class
206
+ PostablePolicyClass
207
+ end
208
+ end
209
+ ```
210
+
196
211
  ## Just plain old Ruby
197
212
 
198
213
  As you can see, Pundit doesn't do anything you couldn't have easily done
@@ -230,7 +245,7 @@ got through. This way you can fail more gracefully.
230
245
  ``` ruby
231
246
  class ApplicationPolicy
232
247
  def initialize(user, record)
233
- raise Pundit::NotAuthorized, "must be logged in" unless user
248
+ raise Pundit::NotAuthorizedError, "must be logged in" unless user
234
249
  @user = user
235
250
  @record = record
236
251
  end
@@ -6,44 +6,47 @@ module Pundit
6
6
  @object = object
7
7
  end
8
8
 
9
- def name
10
- if object.respond_to?(:model_name)
11
- object.model_name.to_s
12
- elsif object.class.respond_to?(:model_name)
13
- object.class.model_name.to_s
14
- elsif object.is_a?(Class)
15
- object.to_s
16
- else
17
- object.class.to_s
18
- end
19
- end
20
-
21
9
  def scope
22
- scope_name.constantize
10
+ policy::Scope if policy
23
11
  rescue NameError
24
12
  nil
25
13
  end
26
14
 
27
15
  def policy
28
- policy_name.constantize
16
+ klass = find
17
+ klass = klass.constantize if klass.is_a?(String)
18
+ klass
29
19
  rescue NameError
30
20
  nil
31
21
  end
32
22
 
33
23
  def scope!
34
- scope or raise NotDefinedError, "unable to find scope #{scope_name} for #{object}"
24
+ scope or raise NotDefinedError, "unable to find scope #{find}::Scope for #{object}"
35
25
  end
36
26
 
37
27
  def policy!
38
- policy or raise NotDefinedError, "unable to find policy #{policy_name} for #{object}"
28
+ policy or raise NotDefinedError, "unable to find policy #{find} for #{object}"
39
29
  end
40
30
 
41
- def scope_name
42
- "#{name}Policy::Scope"
43
- end
31
+ private
44
32
 
45
- def policy_name
46
- "#{name}Policy"
33
+ def find
34
+ if object.respond_to?(:policy_class)
35
+ object.policy_class
36
+ elsif object.class.respond_to?(:policy_class)
37
+ object.class.policy_class
38
+ else
39
+ klass = if object.respond_to?(:model_name)
40
+ object.model_name
41
+ elsif object.class.respond_to?(:model_name)
42
+ object.class.model_name
43
+ elsif object.is_a?(Class)
44
+ object
45
+ else
46
+ object.class
47
+ end
48
+ "#{klass}Policy"
49
+ end
47
50
  end
48
51
  end
49
52
  end
@@ -1,3 +1,3 @@
1
1
  module Pundit
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -34,12 +34,34 @@ class Comment; extend ActiveModel::Naming; end
34
34
 
35
35
  class Article; end
36
36
 
37
+ class BlogPolicy < Struct.new(:user, :blog); end
38
+ class Blog; end
39
+ class ArtificialBlog < Blog
40
+ def self.policy_class
41
+ BlogPolicy
42
+ end
43
+ end
44
+ class ArticleTag
45
+ def self.policy_class
46
+ Struct.new(:user, :tag) do
47
+ def show?
48
+ true
49
+ end
50
+ def destroy?
51
+ false
52
+ end
53
+ end
54
+ end
55
+ end
56
+
37
57
  describe Pundit do
38
58
  let(:user) { stub }
39
59
  let(:post) { Post.new(user) }
40
60
  let(:comment) { Comment.new }
41
61
  let(:article) { Article.new }
42
62
  let(:controller) { stub(:current_user => user, :params => { :action => "update" }).tap { |c| c.extend(Pundit) } }
63
+ let(:artificial_blog) { ArtificialBlog.new }
64
+ let(:article_tag) { ArticleTag.new }
43
65
 
44
66
  describe ".policy_scope" do
45
67
  it "returns an instantiated policy scope given a plain model class" do
@@ -67,6 +89,10 @@ describe Pundit do
67
89
  it "throws an exception if the given policy scope can't be found" do
68
90
  expect { Pundit.policy_scope!(user, Article) }.to raise_error(Pundit::NotDefinedError)
69
91
  end
92
+
93
+ it "throws an exception if the given policy scope can't be found" do
94
+ expect { Pundit.policy_scope!(user, ArticleTag) }.to raise_error(Pundit::NotDefinedError)
95
+ end
70
96
  end
71
97
 
72
98
  describe ".policy" do
@@ -98,6 +124,32 @@ describe Pundit do
98
124
  Pundit.policy(user, article).should be_nil
99
125
  Pundit.policy(user, Article).should be_nil
100
126
  end
127
+
128
+ describe "with .policy_class set on the model" do
129
+ it "returns an instantiated policy given a plain model instance" do
130
+ policy = Pundit.policy(user, artificial_blog)
131
+ policy.user.should == user
132
+ policy.blog.should == artificial_blog
133
+ end
134
+
135
+ it "returns an instantiated policy given a plain model class" do
136
+ policy = Pundit.policy(user, ArtificialBlog)
137
+ policy.user.should == user
138
+ policy.blog.should == ArtificialBlog
139
+ end
140
+
141
+ it "returns an instantiated policy given a plain model instance providing an anonymous class" do
142
+ policy = Pundit.policy(user, article_tag)
143
+ policy.user.should == user
144
+ policy.tag.should == article_tag
145
+ end
146
+
147
+ it "returns an instantiated policy given a plain model class providing an anonymous class" do
148
+ policy = Pundit.policy(user, ArticleTag)
149
+ policy.user.should == user
150
+ policy.tag.should == ArticleTag
151
+ end
152
+ end
101
153
  end
102
154
 
103
155
  describe ".policy!" do
@@ -152,6 +204,11 @@ describe Pundit do
152
204
  expect { controller.authorize(post, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
153
205
  end
154
206
 
207
+ it "works with anonymous class policies" do
208
+ controller.authorize(article_tag, :show?).should be_true
209
+ expect { controller.authorize(article_tag, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
210
+ end
211
+
155
212
  it "raises an error when the permission check fails" do
156
213
  expect { controller.authorize(Post.new) }.to raise_error(Pundit::NotAuthorizedError)
157
214
  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.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,88 +10,88 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-11-19 00:00:00.000000000 Z
13
+ date: 2013-01-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rails
17
+ prerelease: false
17
18
  requirement: !ruby/object:Gem::Requirement
18
- none: false
19
19
  requirements:
20
20
  - - ~>
21
21
  - !ruby/object:Gem::Version
22
22
  version: '3.0'
23
+ none: false
23
24
  type: :runtime
24
- prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
26
  requirements:
28
27
  - - ~>
29
28
  - !ruby/object:Gem::Version
30
29
  version: '3.0'
30
+ none: false
31
31
  - !ruby/object:Gem::Dependency
32
32
  name: rspec
33
+ prerelease: false
33
34
  requirement: !ruby/object:Gem::Requirement
34
- none: false
35
35
  requirements:
36
36
  - - ~>
37
37
  - !ruby/object:Gem::Version
38
38
  version: '2.0'
39
+ none: false
39
40
  type: :development
40
- prerelease: false
41
41
  version_requirements: !ruby/object:Gem::Requirement
42
- none: false
43
42
  requirements:
44
43
  - - ~>
45
44
  - !ruby/object:Gem::Version
46
45
  version: '2.0'
46
+ none: false
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: pry
49
+ prerelease: false
49
50
  requirement: !ruby/object:Gem::Requirement
50
- none: false
51
51
  requirements:
52
52
  - - ! '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ none: false
55
56
  type: :development
56
- prerelease: false
57
57
  version_requirements: !ruby/object:Gem::Requirement
58
- none: false
59
58
  requirements:
60
59
  - - ! '>='
61
60
  - !ruby/object:Gem::Version
62
61
  version: '0'
62
+ none: false
63
63
  - !ruby/object:Gem::Dependency
64
64
  name: rake
65
+ prerelease: false
65
66
  requirement: !ruby/object:Gem::Requirement
66
- none: false
67
67
  requirements:
68
68
  - - ! '>='
69
69
  - !ruby/object:Gem::Version
70
70
  version: '0'
71
+ none: false
71
72
  type: :development
72
- prerelease: false
73
73
  version_requirements: !ruby/object:Gem::Requirement
74
- none: false
75
74
  requirements:
76
75
  - - ! '>='
77
76
  - !ruby/object:Gem::Version
78
77
  version: '0'
78
+ none: false
79
79
  - !ruby/object:Gem::Dependency
80
80
  name: yard
81
+ prerelease: false
81
82
  requirement: !ruby/object:Gem::Requirement
82
- none: false
83
83
  requirements:
84
84
  - - ! '>='
85
85
  - !ruby/object:Gem::Version
86
86
  version: '0'
87
+ none: false
87
88
  type: :development
88
- prerelease: false
89
89
  version_requirements: !ruby/object:Gem::Requirement
90
- none: false
91
90
  requirements:
92
91
  - - ! '>='
93
92
  - !ruby/object:Gem::Version
94
93
  version: '0'
94
+ none: false
95
95
  description: Object oriented authorization for Rails applications
96
96
  email:
97
97
  - jonas.nicklas@gmail.com
@@ -125,17 +125,17 @@ rdoc_options: []
125
125
  require_paths:
126
126
  - lib
127
127
  required_ruby_version: !ruby/object:Gem::Requirement
128
- none: false
129
128
  requirements:
130
129
  - - ! '>='
131
130
  - !ruby/object:Gem::Version
132
131
  version: '0'
133
- required_rubygems_version: !ruby/object:Gem::Requirement
134
132
  none: false
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
134
  requirements:
136
135
  - - ! '>='
137
136
  - !ruby/object:Gem::Version
138
137
  version: '0'
138
+ none: false
139
139
  requirements: []
140
140
  rubyforge_project:
141
141
  rubygems_version: 1.8.24