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 +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +11 -12
- data/access-granted.gemspec +1 -1
- data/lib/access-granted/permission.rb +3 -2
- data/lib/access-granted/policy.rb +3 -3
- data/lib/access-granted/role.rb +4 -4
- data/lib/generators/access_granted/policy_generator.rb +16 -0
- data/lib/generators/templates/access_policy.rb +40 -0
- data/spec/controller_methods_spec.rb +1 -1
- data/spec/permission_spec.rb +3 -3
- data/spec/policy_spec.rb +50 -10
- data/spec/role_spec.rb +5 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1655a3217918c74b918dc7f52cf474a554fe3857
|
4
|
+
data.tar.gz: e589678196a86628ae844a6fa920824311a4025a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e4091466b976765cd9486124cc1daff3339918c985e02c76fe33093456c98cf41e842444e000a591b2262dc9210c0ae828f3f7bd6078b7a875462cb00ab9400b
|
7
|
+
data.tar.gz: c984daf5257a27d91c025b9b5e6955b1442da76f452f3344fa7d9d9f7036ebb6c4e25aab3c6cf3230ccd5fe61f02a0174e42d04aca0024516608c33668d583f3
|
data/LICENSE.txt
CHANGED
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
|
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.
|
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
|
-
|
137
|
-
|
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
|
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
|
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
|
data/access-granted.gemspec
CHANGED
@@ -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.
|
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
|
8
|
+
configure
|
9
9
|
end
|
10
10
|
|
11
|
-
def configure
|
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)
|
data/lib/access-granted/role.rb
CHANGED
@@ -12,14 +12,14 @@ module AccessGranted
|
|
12
12
|
if @block
|
13
13
|
instance_eval(&@block)
|
14
14
|
else
|
15
|
-
configure
|
15
|
+
configure
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
def configure
|
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
|
data/spec/permission_spec.rb
CHANGED
@@ -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
|
data/spec/policy_spec.rb
CHANGED
@@ -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
|
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
|
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,
|
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
|
63
|
-
expect(klass.new(@
|
64
|
-
|
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
|
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
|
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
|
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
|
151
|
+
def configure
|
112
152
|
can :read, String
|
113
153
|
end
|
114
154
|
end
|
data/spec/role_spec.rb
CHANGED
@@ -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.
|
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-
|
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
|