access-granted 0.2.1 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d6d610eeb4a1e57538d942c6f1cd0bfe6958a852
4
- data.tar.gz: 50ce2232aa01528cb8478a38e578a8424ca0e801
3
+ metadata.gz: 1655a3217918c74b918dc7f52cf474a554fe3857
4
+ data.tar.gz: e589678196a86628ae844a6fa920824311a4025a
5
5
  SHA512:
6
- metadata.gz: 0768c9dd24d77292180d8574f9155312c3a4028b2259d8125d8db36754e8a26c7bb448f88452f2b7588fa72edd9e46d68522ea1a3eb6e3a2b185ef766ecc292d
7
- data.tar.gz: 7852d05613d5afa58e5cf6aa23a0432efab48ba0b7badc812047a107543e1c9784492ed591547e5f3cb649a0f58e2f53f75b8c1f964741451053eaea72111c49
6
+ metadata.gz: e4091466b976765cd9486124cc1daff3339918c985e02c76fe33093456c98cf41e842444e000a591b2262dc9210c0ae828f3f7bd6078b7a875462cb00ab9400b
7
+ data.tar.gz: c984daf5257a27d91c025b9b5e6955b1442da76f452f3344fa7d9d9f7036ebb6c4e25aab3c6cf3230ccd5fe61f02a0174e42d04aca0024516608c33668d583f3
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013 Piotrek Okoński
1
+ Copyright (c) 2015 Chaps sp. z o.o.
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -26,7 +26,7 @@ AccessGranted is meant as a replacement for CanCan to solve major problems:
26
26
  2. Roles
27
27
 
28
28
  Adds support for roles, so no more `if`'s and `else`'s in your Policy file. This makes it extremely easy to maintain and read the code.
29
-
29
+
30
30
  3. white-lists
31
31
 
32
32
  This means that you define what the user **can** do, which results in clean, readable policies regardless of app complexity.
@@ -58,8 +58,7 @@ Let's start with a complete example of what can be achieved:
58
58
  class AccessPolicy
59
59
  include AccessGranted::Policy
60
60
 
61
- def configure(user)
62
-
61
+ def configure
63
62
  # The most important admin role, gets checked first
64
63
 
65
64
  role :admin, { is_admin: true } do
@@ -77,8 +76,8 @@ class AccessPolicy
77
76
  role :member do
78
77
  can :create, Post
79
78
 
80
- can [:update, :destroy], Post do |post|
81
- post.user_id == user.id && post.comments.empty?
79
+ can [:update, :destroy], Post do |post, user|
80
+ post.author == user && post.comments.empty?
82
81
  end
83
82
  end
84
83
  end
@@ -133,12 +132,12 @@ end
133
132
 
134
133
  #### Block conditions
135
134
 
136
- "But wait! User should also be able to edit his posts, and only his posts!", you are wondering.
137
- This can be done using a block condition in `can` method, like so:
135
+ Sometimes you may need to dynamically check for ownership or other conditions,
136
+ this can be done using a block condition in `can` method, like so:
138
137
 
139
138
  ```ruby
140
139
  role :member do
141
- can :update, Post do |post|
140
+ can :update, Post do |post, user|
142
141
  post.author_id == user.id
143
142
  end
144
143
  end
@@ -157,7 +156,7 @@ role :admin, { is_admin: true } do
157
156
  end
158
157
 
159
158
  role :member do
160
- can :update, Post do |post|
159
+ can :update, Post do |post, user|
161
160
  post.author_id == user.id
162
161
  end
163
162
  end
@@ -284,7 +283,7 @@ Below you can see an extracted `:member` role:
284
283
  class AccessPolicy
285
284
  include AccessGranted::Policy
286
285
 
287
- def configure(user)
286
+ def configure
288
287
  role :administrator, is_admin: true do
289
288
  can :manage, User
290
289
  end
@@ -301,9 +300,9 @@ And roles should look like this
301
300
  # app/roles/member_role.rb
302
301
 
303
302
  class MemberRole < AccessGranted::Role
304
- def configure(user)
303
+ def configure
305
304
  can :create, Post
306
- can :destroy, Post do |post|
305
+ can :destroy, Post do |post, user|
307
306
  post.author == user
308
307
  end
309
308
  end
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "access-granted"
7
- spec.version = "0.2.1"
7
+ spec.version = "1.0.1"
8
8
  spec.authors = ["Piotrek Okoński"]
9
9
  spec.email = ["piotrek@okonski.org"]
10
10
  spec.description = %q{Role based authorization gem}
@@ -2,8 +2,9 @@ module AccessGranted
2
2
  class Permission
3
3
  attr_reader :action, :subject, :granted, :conditions
4
4
 
5
- def initialize(granted, action, subject, conditions = {}, block = nil)
5
+ def initialize(granted, action, subject, user = nil, conditions = {}, block = nil)
6
6
  @action = action
7
+ @user = user
7
8
  @granted = granted
8
9
  @subject = subject
9
10
  @conditions = conditions
@@ -20,7 +21,7 @@ module AccessGranted
20
21
 
21
22
  def matches_conditions?(subject)
22
23
  if @block
23
- @block.call(subject)
24
+ @block.call(subject, @user)
24
25
  else
25
26
  matches_hash_conditions?(subject)
26
27
  end
@@ -5,10 +5,10 @@ module AccessGranted
5
5
  def initialize(user)
6
6
  @user = user
7
7
  @roles = []
8
- configure(@user)
8
+ configure
9
9
  end
10
10
 
11
- def configure(user)
11
+ def configure
12
12
  end
13
13
 
14
14
  def role(name, conditions_or_klass = nil, conditions = nil, &block)
@@ -25,7 +25,7 @@ module AccessGranted
25
25
  r
26
26
  end
27
27
 
28
- def can?(action, subject)
28
+ def can?(action, subject = nil)
29
29
  roles.each do |role|
30
30
  next unless role.applies_to?(@user)
31
31
  permission = role.find_permission(action, subject)
@@ -12,14 +12,14 @@ module AccessGranted
12
12
  if @block
13
13
  instance_eval(&@block)
14
14
  else
15
- configure(@user)
15
+ configure
16
16
  end
17
17
  end
18
18
 
19
- def configure(user)
19
+ def configure
20
20
  end
21
21
 
22
- def can(action, subject, conditions = {}, &block)
22
+ def can(action, subject = nil, conditions = {}, &block)
23
23
  add_permission(true, action, subject, conditions, block)
24
24
  end
25
25
 
@@ -53,7 +53,7 @@ module AccessGranted
53
53
  def add_permission(granted, action, subject, conditions, block)
54
54
  prepare_actions(action).each do |a|
55
55
  raise DuplicatePermission if permission_exists?(a, subject)
56
- @permissions << Permission.new(granted, a, subject, conditions, block)
56
+ @permissions << Permission.new(granted, a, subject, @user, conditions, block)
57
57
  @permissions_by_action[a] ||= []
58
58
  @permissions_by_action[a] << @permissions.size - 1
59
59
  end
@@ -0,0 +1,16 @@
1
+ require 'rails/generators/base'
2
+
3
+ module Accessgranted
4
+ module Generators
5
+ class PolicyGenerator < Rails::Generators::Base
6
+ source_root File.expand_path("../../templates", __FILE__)
7
+
8
+ namespace "access_granted:policy"
9
+ desc "Creates an Access Granted policy."
10
+
11
+ def copy_policy
12
+ template "access_policy.rb", "app/policies/access_policy.rb"
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,40 @@
1
+ class AccessPolicy
2
+ include AccessGranted::Policy
3
+
4
+ def configure(user)
5
+ # Example policy for AccessGranted.
6
+ # For more details check the README at
7
+ #
8
+ # https://github.com/chaps-io/access-granted/blob/master/README.md
9
+ #
10
+ # Roles inherit from less important roles, so:
11
+ # - :admin has permissions defined in :member, :guest and himself
12
+ # - :member has permissions from :guest and himself
13
+ # - :guest has only its own permissions since it's the first role.
14
+ #
15
+ # The most important role should be at the top.
16
+ # In this case an administrator.
17
+ #
18
+ # role :admin, proc { |user| user.admin? } do
19
+ # can :destroy, User
20
+ # end
21
+
22
+ # More privileged role, applies to registered users.
23
+ #
24
+ # role :member, proc { |user| user.registered? } do
25
+ # can :create, Post
26
+ # can :create, Comment
27
+ # can [:update, :destroy], Post do |post|
28
+ # post.author == user
29
+ # end
30
+ # end
31
+
32
+ # The base role with no additional conditions.
33
+ # Applies to every user.
34
+ #
35
+ # role :guest do
36
+ # can :read, Post
37
+ # can :read, Comment
38
+ # end
39
+ end
40
+ end
@@ -28,7 +28,7 @@ describe AccessGranted::Rails::ControllerMethods do
28
28
  klass = Class.new do
29
29
  include AccessGranted::Policy
30
30
 
31
- def configure(user)
31
+ def configure
32
32
  role :member, 1 do
33
33
  can :read, String
34
34
  end
@@ -11,7 +11,7 @@ describe AccessGranted::Permission do
11
11
 
12
12
  it "matches proc conditions" do
13
13
  sub = double("Element", published?: true)
14
- perm = subject.new(true, :read, sub.class, {}, proc {|el| el.published? })
14
+ perm = subject.new(true, :read, sub.class, nil, {}, proc {|el| el.published? })
15
15
  expect(perm.matches_conditions?(sub)).to eq(true)
16
16
  end
17
17
  end
@@ -24,13 +24,13 @@ describe AccessGranted::Permission do
24
24
 
25
25
  it "matches when conditions given" do
26
26
  sub = double("Element", published: true)
27
- perm = subject.new(true, :read, sub, { published: true })
27
+ perm = subject.new(true, :read, sub, nil, { published: true })
28
28
  expect(perm.matches_hash_conditions?(sub)).to eq(true)
29
29
  end
30
30
 
31
31
  it "does not match if one of the conditions mismatches" do
32
32
  sub = double("Element", published: true, readable: false)
33
- perm = subject.new(true, :read, sub, { published: true, readable: true })
33
+ perm = subject.new(true, :read, sub, nil, { published: true, readable: true })
34
34
  expect(perm.matches_hash_conditions?(sub)).to eq(false)
35
35
  end
36
36
  end
@@ -12,11 +12,32 @@ describe AccessGranted::Policy do
12
12
  @banned = double("banned", id: 4, is_moderator: false, is_admin: true, is_banned: true)
13
13
  end
14
14
 
15
+ it "passes user object to permission block" do
16
+ post_owner = double(id: 123)
17
+ other_user = double(id: 5)
18
+ post = FakePost.new(post_owner.id)
19
+
20
+ klass = Class.new do
21
+ include AccessGranted::Policy
22
+
23
+ def configure
24
+ role :member do
25
+ can :destroy, FakePost do |post, user|
26
+ post.user_id == user.id
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ expect(klass.new(post_owner).can?(:destroy, post)).to eq(true)
33
+ expect(klass.new(other_user).can?(:destroy, post)).to eq(false)
34
+ end
35
+
15
36
  it "selects permission based on role priority" do
16
37
  klass = Class.new do
17
38
  include AccessGranted::Policy
18
39
 
19
- def configure(user)
40
+ def configure
20
41
  role :administrator, { is_admin: true } do
21
42
  can :destroy, String
22
43
  end
@@ -48,28 +69,47 @@ describe AccessGranted::Policy do
48
69
  klass = Class.new do
49
70
  include AccessGranted::Policy
50
71
 
51
- def configure(user)
72
+ def configure
52
73
  role :administrator, { is_admin: true } do
53
74
  can :destroy, FakePost
54
75
  end
55
76
 
56
77
  role :member do
57
- can :destroy, FakePost, user_id: user.id
78
+ can :destroy, FakePost do |post, user|
79
+ post.user_id == user.id
80
+ end
58
81
  end
59
82
  end
60
83
  end
61
84
 
62
- expect(klass.new(@admin).can?(:destroy, user_post)).to eq(true)
63
- expect(klass.new(@member).can?(:destroy, user_post)).to eq(true)
64
- expect(klass.new(@member).cannot?(:destroy, other_post)).to eq(true)
85
+ expect(klass.new(@admin).can?(:destroy, user_post)).to eq(true)
86
+ expect(klass.new(@admin).can?(:destroy, other_post)).to eq(true)
87
+
88
+ expect(klass.new(@member).can?(:destroy, user_post)).to eq(true)
89
+ expect(klass.new(@member).cannot?(:destroy, other_post)).to eq(true)
90
+ end
91
+ end
92
+
93
+ it "resolves permissions without subject" do
94
+ klass = Class.new do
95
+ include AccessGranted::Policy
96
+
97
+ def configure
98
+ role :member do
99
+ can :vague_action
100
+ end
101
+ end
65
102
  end
103
+
104
+ expect(klass.new(@member).can?(:vague_action)).to eq(true)
66
105
  end
106
+
67
107
  describe "#cannot" do
68
108
  it "forbids action when used in superior role" do
69
109
  klass = Class.new do
70
110
  include AccessGranted::Policy
71
111
 
72
- def configure(user)
112
+ def configure
73
113
  role :banned, { is_banned: true } do
74
114
  cannot :create, String
75
115
  end
@@ -89,13 +129,13 @@ describe AccessGranted::Policy do
89
129
  Class.new do
90
130
  include AccessGranted::Policy
91
131
 
92
- def configure(user)
132
+ def configure
93
133
  role(:member) { can :create, String }
94
134
  end
95
135
  end
96
136
  end
97
137
 
98
- it "raises AccessDenied if actions is not allowed" do
138
+ it "raises AccessDenied if action is not allowed" do
99
139
  expect { klass.new(@member).authorize!(:create, Integer) }.to raise_error AccessGranted::AccessDenied
100
140
  end
101
141
 
@@ -108,7 +148,7 @@ describe AccessGranted::Policy do
108
148
  describe "#role" do
109
149
  it "allows passing role class" do
110
150
  klass_role = Class.new AccessGranted::Role do
111
- def configure(user)
151
+ def configure
112
152
  can :read, String
113
153
  end
114
154
  end
@@ -42,6 +42,11 @@ describe AccessGranted::Role do
42
42
  @role = AccessGranted::Role.new(:member)
43
43
  end
44
44
 
45
+ it "allows adding permission without subject" do
46
+ @role.can :vague_action
47
+ expect(@role.find_permission(:vague_action, nil)).to_not be_nil
48
+ end
49
+
45
50
  it "forbids creating actions with the same name" do
46
51
  @role.can :read, String
47
52
  expect { @role.can :read, String }.to raise_error AccessGranted::DuplicatePermission
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: access-granted
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotrek Okoński
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-13 00:00:00.000000000 Z
11
+ date: 2015-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -62,6 +62,8 @@ files:
62
62
  - lib/access-granted/policy.rb
63
63
  - lib/access-granted/rails/controller_methods.rb
64
64
  - lib/access-granted/role.rb
65
+ - lib/generators/access_granted/policy_generator.rb
66
+ - lib/generators/templates/access_policy.rb
65
67
  - spec/controller_methods_spec.rb
66
68
  - spec/permission_spec.rb
67
69
  - spec/policy_spec.rb