access-granted 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +64 -25
- data/access-granted.gemspec +1 -1
- data/lib/access-granted.rb +0 -7
- data/lib/access-granted/permission.rb +1 -1
- data/lib/access-granted/policy.rb +5 -10
- data/lib/access-granted/role.rb +2 -4
- data/lib/access-granted/version.rb +1 -1
- data/spec/permission_spec.rb +23 -8
- data/spec/policy_spec.rb +61 -32
- data/spec/role_spec.rb +17 -21
- data/spec/spec_helper.rb +0 -1
- metadata +13 -16
- data/lib/access-granted/controller_methods.rb +0 -24
- data/spec/controller_methods_spec.rb +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ada45684334e5433ed3504e66d2183464bcf4203
|
4
|
+
data.tar.gz: b0c59ba381cc29461dcb70d13a771dd72c268495
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2db7e6b39316cffabd20ef32e1b93af44f86812af6e93fc4153a03355326608b4727b99b78ac7843a47d3f8c85b3995cae01dd81335f692900f043feeb396c31
|
7
|
+
data.tar.gz: 0c19dd7e52f3ccf791a00ae436cd983df5e64377bf2cf3a6dd1511805f4e62b8cf429b974a3c20b22eca4cd4b564c2fe7d5af5bad1c88c98f5d0fea0d4ee2054
|
data/README.md
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
# AccessGranted [![Build Status](https://travis-ci.org/
|
1
|
+
# AccessGranted [![Build Status](https://travis-ci.org/chaps-io/access-granted.svg?branch=master)](https://travis-ci.org/chaps-io/access-granted) [![Code Climate](https://codeclimate.com/github/pokonski/access-granted.png)](https://codeclimate.com/github/pokonski/access-granted)
|
2
|
+
|
3
|
+
## [![](http://i.imgur.com/ya8Wnyl.png)](https://chaps.io) proudly made by [Chaps](https://chaps.io)
|
4
|
+
|
2
5
|
|
3
6
|
Multi-role and whitelist based authorization gem for Rails. And it's lightweight (~300 lines of code)!
|
4
7
|
|
@@ -8,24 +11,27 @@ Guaranteed to work on MRI 1.9.3/2.0/2.1, Rubinius >= 2.1.1 and JRuby >= 1.7.6.
|
|
8
11
|
|
9
12
|
# Summary
|
10
13
|
|
11
|
-
AccessGranted is meant as replacement for CanCan to solve three major problems:
|
14
|
+
AccessGranted is meant as a replacement for CanCan to solve three major problems:
|
12
15
|
|
13
|
-
1. built-in support for roles
|
16
|
+
1. **built-in support for roles**
|
14
17
|
|
15
|
-
Easy to read access policy code where permissions are cleanly grouped into roles
|
16
|
-
Additionally permissions are forced to be unique in the scope a role.
|
17
|
-
|
18
|
+
Easy to read access policy code where permissions are cleanly grouped into roles.
|
19
|
+
Additionally, permissions are forced to be unique in the scope of a role. This greatly simplifies the resolving
|
20
|
+
permissions while substantially reducing the code-base.
|
18
21
|
|
19
|
-
2. white-list based
|
22
|
+
2. **white-list based**
|
20
23
|
|
21
|
-
This means that you define what a role **can** do,
|
22
|
-
|
24
|
+
This means that you define what a role **can** do, which results in clean, readable policies regardless of complexity.
|
25
|
+
You don't have to worry about juggling `can`s and `cannot`s in a very convoluted way!
|
23
26
|
|
24
|
-
|
27
|
+
_Note_: `cannot` is still available, but has a very specifc use. See [Usage](#usage) below.
|
25
28
|
|
26
|
-
3.
|
27
|
-
|
28
|
-
|
29
|
+
3. **framework agnostic**
|
30
|
+
|
31
|
+
Permissions can work on basically any object and AccessGranted is framework-agnostic,
|
32
|
+
But we offer extensions for your favourite frameworks as gems:
|
33
|
+
- Rails: [access-granted-rails](https://github.com/pokonski/access-granted-rails)
|
34
|
+
- ... more to come!
|
29
35
|
|
30
36
|
See [Usage](#usage) for an example of a complete AccessPolicy file.
|
31
37
|
|
@@ -41,11 +47,8 @@ This gem was created as a replacement for CanCan and therefore it requires minim
|
|
41
47
|
I decided to not implement this functionality as it was mostly ignored by CanCan users.
|
42
48
|
|
43
49
|
2. Both `can?`/`cannot?` and `authorize!` methods work in Rails controllers and views, just like in CanCan.
|
44
|
-
The only change you have to make is replace all `can? :manage, Class` with
|
45
|
-
`can :manage` is
|
46
|
-
in one line.
|
47
|
-
|
48
|
-
Due to introduction of Roles checking for generic `:manage` permission is very complicated and also confusing for developers.
|
50
|
+
The only change you have to make is to replace all `can? :manage, Class` with the exact action to check against.
|
51
|
+
`can :manage` is still available for **defining** methods and serves as a shortcut for defining `:read`, `:create`, `:update`, `:destroy` all in one line.
|
49
52
|
|
50
53
|
3. Syntax for defining permissions in AccessPolicy file (Ability in CanCan) is exactly the same,
|
51
54
|
with added roles on top. See [Usage](#usage) below.
|
@@ -53,17 +56,15 @@ This gem was created as a replacement for CanCan and therefore it requires minim
|
|
53
56
|
|
54
57
|
## Installation
|
55
58
|
|
56
|
-
|
59
|
+
### Rails
|
57
60
|
|
58
|
-
|
59
|
-
|
60
|
-
And then execute:
|
61
|
+
This includes Rails-specific integration (`can?`, `cannot?`, `current_policy` helpers and more):
|
61
62
|
|
62
|
-
|
63
|
+
gem 'access-granted-rails'
|
63
64
|
|
64
|
-
|
65
|
+
### Others
|
65
66
|
|
66
|
-
|
67
|
+
gem 'access-granted'
|
67
68
|
|
68
69
|
## Usage
|
69
70
|
|
@@ -126,6 +127,44 @@ class Policy
|
|
126
127
|
end
|
127
128
|
```
|
128
129
|
|
130
|
+
## Common examples
|
131
|
+
|
132
|
+
### Extracting roles to separate files
|
133
|
+
|
134
|
+
Let's say your app is getting bigger and more complex. This means your policy file is also getting longer.
|
135
|
+
|
136
|
+
Below you can see an extracted `:member` role:
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
class AccessPolicy
|
140
|
+
include AccessGranted::Policy
|
141
|
+
|
142
|
+
def configure(user)
|
143
|
+
role :administrator, is_admin: true do
|
144
|
+
can :manage, User
|
145
|
+
end
|
146
|
+
|
147
|
+
role :member, MemberRole, lambda { |user| !u.guest? }
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
```
|
152
|
+
|
153
|
+
And roles should look like this
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
# app/roles/member_role.rb
|
157
|
+
|
158
|
+
class MemberRole < AccessGranted::Role
|
159
|
+
def configure(user)
|
160
|
+
can :create, Post
|
161
|
+
can :destroy, Post do |post|
|
162
|
+
post.author == user
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
```
|
167
|
+
|
129
168
|
|
130
169
|
## Contributing
|
131
170
|
|
data/access-granted.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["piotrek@okonski.org"]
|
11
11
|
spec.description = %q{Role based authorization gem}
|
12
12
|
spec.summary = %q{Elegant whitelist and role based authorization with ability to prioritize roles.}
|
13
|
-
spec.homepage = "https://github.com/
|
13
|
+
spec.homepage = "https://github.com/chaps-io/access-granted"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files`.split($/)
|
data/lib/access-granted.rb
CHANGED
@@ -2,15 +2,8 @@ require "access-granted/version"
|
|
2
2
|
require "access-granted/exceptions"
|
3
3
|
require "access-granted/policy"
|
4
4
|
require "access-granted/permission"
|
5
|
-
require "access-granted/controller_methods"
|
6
5
|
require "access-granted/role"
|
7
6
|
|
8
7
|
module AccessGranted
|
9
8
|
|
10
9
|
end
|
11
|
-
|
12
|
-
if defined? ActionController::Base
|
13
|
-
ActionController::Base.class_eval do
|
14
|
-
include AccessGranted::ControllerMethods
|
15
|
-
end
|
16
|
-
end
|
@@ -5,7 +5,6 @@ module AccessGranted
|
|
5
5
|
def initialize(user)
|
6
6
|
@user = user
|
7
7
|
@roles = []
|
8
|
-
@last_priority = 0
|
9
8
|
configure(@user)
|
10
9
|
end
|
11
10
|
|
@@ -17,19 +16,17 @@ module AccessGranted
|
|
17
16
|
if roles.select {|r| r.name == name }.any?
|
18
17
|
raise DuplicateRole, "Role '#{name}' already defined"
|
19
18
|
end
|
20
|
-
@last_priority += 1
|
21
19
|
r = if conditions_or_klass.is_a?(Class) && conditions_or_klass <= AccessGranted::Role
|
22
|
-
conditions_or_klass.new(name,
|
20
|
+
conditions_or_klass.new(name, conditions, @user, block)
|
23
21
|
else
|
24
|
-
Role.new(name,
|
22
|
+
Role.new(name, conditions_or_klass, @user, block)
|
25
23
|
end
|
26
24
|
roles << r
|
27
|
-
roles.sort_by! {|r| r.priority }
|
28
25
|
r
|
29
26
|
end
|
30
27
|
|
31
28
|
def can?(action, subject)
|
32
|
-
|
29
|
+
matching_roles.each do |role|
|
33
30
|
permission = role.find_permission(action, subject)
|
34
31
|
return permission.granted if permission
|
35
32
|
end
|
@@ -40,10 +37,8 @@ module AccessGranted
|
|
40
37
|
!can?(*args)
|
41
38
|
end
|
42
39
|
|
43
|
-
def
|
44
|
-
roles.select
|
45
|
-
role.applies_to?(user)
|
46
|
-
end
|
40
|
+
def matching_roles
|
41
|
+
roles.select { |role| role.applies_to?(@user) }
|
47
42
|
end
|
48
43
|
|
49
44
|
def authorize!(action, subject)
|
data/lib/access-granted/role.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
module AccessGranted
|
2
2
|
class Role
|
3
|
-
attr_reader :name, :user, :
|
3
|
+
attr_reader :name, :user, :conditions, :permissions
|
4
4
|
|
5
|
-
def initialize(name,
|
5
|
+
def initialize(name, conditions = nil, user = nil, block = nil)
|
6
6
|
@user = user
|
7
7
|
@name = name
|
8
|
-
@priority = priority
|
9
8
|
@conditions = conditions
|
10
9
|
@block = block
|
11
10
|
@permissions = []
|
@@ -45,7 +44,6 @@ module AccessGranted
|
|
45
44
|
end
|
46
45
|
end
|
47
46
|
|
48
|
-
|
49
47
|
def relevant_permissions(action, subject)
|
50
48
|
permissions_by_action(action).select do |perm|
|
51
49
|
perm.matches_subject?(subject)
|
data/spec/permission_spec.rb
CHANGED
@@ -6,51 +6,66 @@ describe AccessGranted::Permission do
|
|
6
6
|
describe "#matches_conditions?" do
|
7
7
|
it "matches when no conditions given" do
|
8
8
|
perm = subject.new(true, :read, String)
|
9
|
-
perm.matches_conditions?(String).
|
9
|
+
expect(perm.matches_conditions?(String)).to eq(true)
|
10
10
|
end
|
11
11
|
|
12
12
|
it "matches proc conditions" do
|
13
13
|
sub = double("Element", published?: true)
|
14
14
|
perm = subject.new(true, :read, sub.class, {}, proc {|el| el.published? })
|
15
|
-
perm.matches_conditions?(sub).
|
15
|
+
expect(perm.matches_conditions?(sub)).to eq(true)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
19
|
describe "#matches_hash_conditions?" do
|
20
20
|
it "matches condition hash is empty" do
|
21
21
|
perm = subject.new(true, :read, String)
|
22
|
-
perm.matches_hash_conditions?(String).
|
22
|
+
expect(perm.matches_hash_conditions?(String)).to eq(true)
|
23
23
|
end
|
24
24
|
|
25
25
|
it "matches when conditions given" do
|
26
26
|
sub = double("Element", published: true)
|
27
27
|
perm = subject.new(true, :read, sub, { published: true })
|
28
|
-
perm.matches_hash_conditions?(sub).
|
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
33
|
perm = subject.new(true, :read, sub, { published: true, readable: true })
|
34
|
-
perm.matches_hash_conditions?(sub).
|
34
|
+
expect(perm.matches_hash_conditions?(sub)).to eq(false)
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
describe "#matches_action?" do
|
39
39
|
it "matches if actions are identical" do
|
40
40
|
perm = subject.new(true, :read, String)
|
41
|
-
perm.matches_action?(:read).
|
41
|
+
expect(perm.matches_action?(:read)).to_not be_nil
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
45
|
describe "#matches_subject?" do
|
46
46
|
it "matches if subjects are identical" do
|
47
47
|
perm = subject.new(true, :read, String)
|
48
|
-
expect(perm.matches_subject? String).to
|
48
|
+
expect(perm.matches_subject? String).to eq(true)
|
49
49
|
end
|
50
50
|
|
51
51
|
it "matches if class is equal to subject" do
|
52
52
|
perm = subject.new(true, :read, String)
|
53
|
-
expect(perm.matches_subject? "test").to
|
53
|
+
expect(perm.matches_subject? "test").to eq(true)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "matches if superclass is equal to subject" do
|
57
|
+
perm = subject.new(true, :read, Object)
|
58
|
+
expect(perm.matches_subject? "test").to eq(true)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "matches if any ancestor is equal to subject" do
|
62
|
+
perm = subject.new(true, :read, BasicObject)
|
63
|
+
expect(perm.matches_subject? "test").to eq(true)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "does not match if any descendant is equal to subject" do
|
67
|
+
perm = subject.new(true, :read, String)
|
68
|
+
expect(perm.matches_subject? Object.new).to eq(false)
|
54
69
|
end
|
55
70
|
end
|
56
71
|
end
|
data/spec/policy_spec.rb
CHANGED
@@ -1,11 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe AccessGranted::Policy do
|
4
|
-
|
5
|
-
|
6
|
-
include AccessGranted::Policy
|
7
|
-
end.new(nil)
|
8
|
-
end
|
4
|
+
let(:klass) { Class.new { include AccessGranted::Policy } }
|
5
|
+
subject(:policy) { klass.new(nil) }
|
9
6
|
|
10
7
|
describe "#configure" do
|
11
8
|
before :each do
|
@@ -33,14 +30,14 @@ describe AccessGranted::Policy do
|
|
33
30
|
end
|
34
31
|
end
|
35
32
|
end
|
36
|
-
klass.new(@admin).can?(:destroy, String).
|
37
|
-
klass.new(@admin).can?(:read, String).
|
33
|
+
expect(klass.new(@admin).can?(:destroy, String)).to eq(true)
|
34
|
+
expect(klass.new(@admin).can?(:read, String)).to eq(true)
|
38
35
|
|
39
|
-
klass.new(@member).cannot?(:destroy, String).
|
40
|
-
klass.new(@member).can?(:read, String).
|
36
|
+
expect(klass.new(@member).cannot?(:destroy, String)).to eq(true)
|
37
|
+
expect(klass.new(@member).can?(:read, String)).to eq(true)
|
41
38
|
|
42
|
-
klass.new(@mod).can?(:read, String).
|
43
|
-
klass.new(@mod).cannot?(:destroy, String).
|
39
|
+
expect(klass.new(@mod).can?(:read, String)).to eq(true)
|
40
|
+
expect(klass.new(@mod).cannot?(:destroy, String)).to eq(true)
|
44
41
|
end
|
45
42
|
|
46
43
|
context "when multiple roles define the same permission" do
|
@@ -62,9 +59,9 @@ describe AccessGranted::Policy do
|
|
62
59
|
end
|
63
60
|
end
|
64
61
|
|
65
|
-
|
66
|
-
|
67
|
-
|
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)
|
68
65
|
end
|
69
66
|
end
|
70
67
|
describe "#cannot" do
|
@@ -82,8 +79,28 @@ describe AccessGranted::Policy do
|
|
82
79
|
end
|
83
80
|
end
|
84
81
|
end
|
85
|
-
klass.new(@member).can?(:create, String).
|
86
|
-
klass.new(@banned).cannot?(:create, String).
|
82
|
+
expect(klass.new(@member).can?(:create, String)).to eq(true)
|
83
|
+
expect(klass.new(@banned).cannot?(:create, String)).to eq(true)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "#authorize!" do
|
88
|
+
let(:klass) do
|
89
|
+
Class.new do
|
90
|
+
include AccessGranted::Policy
|
91
|
+
|
92
|
+
def configure(user)
|
93
|
+
role(:member) { can :create, String }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it "raises AccessDenied if actions is not allowed" do
|
99
|
+
expect { klass.new(@member).authorize!(:create, Integer) }.to raise_error AccessGranted::AccessDenied
|
100
|
+
end
|
101
|
+
|
102
|
+
it "returns the subject if allowed" do
|
103
|
+
expect(klass.new(@member).authorize!(:create, String)).to equal String
|
87
104
|
end
|
88
105
|
end
|
89
106
|
end
|
@@ -95,39 +112,51 @@ describe AccessGranted::Policy do
|
|
95
112
|
can :read, String
|
96
113
|
end
|
97
114
|
end
|
98
|
-
|
99
|
-
|
115
|
+
subject.role(:member, klass_role)
|
116
|
+
expect(policy.roles.first.class).to eq(klass_role)
|
117
|
+
end
|
118
|
+
|
119
|
+
it "returns roles in the order of priority" do
|
120
|
+
policy.role(:admin)
|
121
|
+
policy.role(:moderator)
|
122
|
+
policy.role(:user)
|
123
|
+
policy.role(:guest)
|
124
|
+
|
125
|
+
expect(policy.roles.map(&:name)).to eq([:admin, :moderator, :user, :guest])
|
100
126
|
end
|
101
127
|
|
102
128
|
it "allows defining a default role" do
|
103
|
-
|
104
|
-
|
129
|
+
policy.role(:member)
|
130
|
+
expect(policy.roles.map(&:name)).to include(:member)
|
105
131
|
end
|
106
132
|
|
107
133
|
it "does not allow duplicate role names" do
|
108
|
-
|
109
|
-
expect {
|
134
|
+
policy.role(:member)
|
135
|
+
expect { policy.role(:member) }.to raise_error AccessGranted::DuplicateRole
|
110
136
|
end
|
111
137
|
|
112
138
|
it "allows nesting `can` calls inside a block" do
|
113
|
-
role =
|
139
|
+
role = policy.role(:member) do
|
114
140
|
can :read, String
|
115
141
|
end
|
116
142
|
|
117
|
-
role.find_permission(:read, String).granted.
|
143
|
+
expect(role.find_permission(:read, String).granted).to eq(true)
|
118
144
|
end
|
119
145
|
end
|
120
146
|
|
121
|
-
describe "#
|
122
|
-
|
123
|
-
user = double("User", is_moderator: true, is_admin: true)
|
147
|
+
describe "#matching_roles" do
|
148
|
+
let(:user) { double("User", is_moderator: true, is_admin: true) }
|
124
149
|
|
125
|
-
|
126
|
-
|
127
|
-
|
150
|
+
before do
|
151
|
+
policy.role(:administrator, { is_admin: true })
|
152
|
+
policy.role(:moderator, { is_moderator: true })
|
153
|
+
policy.role(:member)
|
154
|
+
end
|
128
155
|
|
129
|
-
|
156
|
+
shared_examples 'role matcher' do
|
157
|
+
it "returns all matching roles in the order of priority" do
|
158
|
+
expect(subject.map(&:name)).to eq([:administrator, :moderator, :member])
|
159
|
+
end
|
130
160
|
end
|
131
161
|
end
|
132
|
-
|
133
162
|
end
|
data/spec/role_spec.rb
CHANGED
@@ -7,52 +7,48 @@ describe AccessGranted::Role do
|
|
7
7
|
expect { subject.new }.to raise_error
|
8
8
|
end
|
9
9
|
|
10
|
-
it "requires priority" do
|
11
|
-
expect { subject.new(:member) }.to raise_error
|
12
|
-
end
|
13
|
-
|
14
10
|
it "creates a default role without conditions" do
|
15
|
-
subject.new(:member
|
11
|
+
expect(subject.new(:member).conditions).to be_nil
|
16
12
|
end
|
17
13
|
|
18
14
|
describe "#relevant_permissions?" do
|
19
15
|
it "returns only matching permissions" do
|
20
|
-
role = subject.new(:member
|
16
|
+
role = subject.new(:member)
|
21
17
|
role.can :read, String
|
22
18
|
role.can :read, Hash
|
23
|
-
role.relevant_permissions(:read, String).
|
19
|
+
expect(role.relevant_permissions(:read, String)).to eq([AccessGranted::Permission.new(true, :read, String)])
|
24
20
|
end
|
25
21
|
end
|
26
22
|
|
27
23
|
describe "#applies_to?" do
|
28
24
|
it "matches user when no conditions given" do
|
29
|
-
role = subject.new(:member
|
25
|
+
role = subject.new(:member)
|
30
26
|
user = double("User")
|
31
|
-
role.applies_to?(user).
|
27
|
+
expect(role.applies_to?(user)).to eq(true)
|
32
28
|
end
|
33
29
|
|
34
30
|
it "matches user by hash conditions" do
|
35
|
-
role = subject.new(:moderator,
|
31
|
+
role = subject.new(:moderator, { is_moderator: true })
|
36
32
|
user = double("User", is_moderator: true)
|
37
|
-
role.applies_to?(user).
|
33
|
+
expect(role.applies_to?(user)).to eq(true)
|
38
34
|
end
|
39
35
|
|
40
36
|
it "doesn't match user if any of hash conditions is not met" do
|
41
|
-
role = subject.new(:moderator,
|
37
|
+
role = subject.new(:moderator, { is_moderator: true, is_admin: true })
|
42
38
|
user = double("User", is_moderator: true, is_admin: false)
|
43
|
-
role.applies_to?(user).
|
39
|
+
expect(role.applies_to?(user)).to eq(false)
|
44
40
|
end
|
45
41
|
|
46
42
|
it "matches user by Proc conditions" do
|
47
|
-
role = subject.new(:moderator,
|
43
|
+
role = subject.new(:moderator, proc {|user| user.is_moderator? })
|
48
44
|
user = double("User", is_moderator?: true)
|
49
|
-
role.applies_to?(user).
|
45
|
+
expect(role.applies_to?(user)).to eq(true)
|
50
46
|
end
|
51
47
|
end
|
52
48
|
|
53
49
|
describe "#can" do
|
54
50
|
before :each do
|
55
|
-
@role = AccessGranted::Role.new(:member
|
51
|
+
@role = AccessGranted::Role.new(:member)
|
56
52
|
end
|
57
53
|
|
58
54
|
it "forbids creating actions with the same name" do
|
@@ -62,25 +58,25 @@ describe AccessGranted::Role do
|
|
62
58
|
|
63
59
|
it "accepts :manage shortcut for CRUD actions" do
|
64
60
|
@role.can :manage, String
|
65
|
-
@role.permissions.map(&:action).
|
61
|
+
expect(@role.permissions.map(&:action)).to include(:read, :create, :update, :destroy)
|
66
62
|
end
|
67
63
|
|
68
64
|
describe "when action is an Array" do
|
69
65
|
it "creates multiple permissions" do
|
70
66
|
@role.can [:read, :create], String
|
71
|
-
@role.permissions.
|
67
|
+
expect(@role.permissions.size).to eq(2)
|
72
68
|
end
|
73
69
|
end
|
74
70
|
|
75
71
|
describe "when no conditions given" do
|
76
72
|
it "should be able to read a class" do
|
77
73
|
@role.can :read, String
|
78
|
-
@role.find_permission(:read, String).
|
74
|
+
expect(@role.find_permission(:read, String)).to_not be_nil
|
79
75
|
end
|
80
76
|
|
81
77
|
it "should be able to read instance of class" do
|
82
78
|
@role.can :read, String
|
83
|
-
@role.find_permission(:read, "text").
|
79
|
+
expect(@role.find_permission(:read, "text")).to_not be_nil
|
84
80
|
end
|
85
81
|
end
|
86
82
|
|
@@ -88,7 +84,7 @@ describe AccessGranted::Role do
|
|
88
84
|
it "should be able to read when conditions match" do
|
89
85
|
sub = double("Element", published: true)
|
90
86
|
@role.can :read, sub.class, { published: true }
|
91
|
-
@role.find_permission(:read, sub).
|
87
|
+
expect(@role.find_permission(:read, sub)).to_not be_nil
|
92
88
|
end
|
93
89
|
end
|
94
90
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,41 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: access-granted
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.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:
|
11
|
+
date: 2015-07-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.3'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rspec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
description: Role based authorization gem
|
@@ -45,27 +45,25 @@ executables: []
|
|
45
45
|
extensions: []
|
46
46
|
extra_rdoc_files: []
|
47
47
|
files:
|
48
|
-
- .gitignore
|
49
|
-
- .rspec
|
50
|
-
- .travis.yml
|
48
|
+
- ".gitignore"
|
49
|
+
- ".rspec"
|
50
|
+
- ".travis.yml"
|
51
51
|
- Gemfile
|
52
52
|
- LICENSE.txt
|
53
53
|
- README.md
|
54
54
|
- Rakefile
|
55
55
|
- access-granted.gemspec
|
56
56
|
- lib/access-granted.rb
|
57
|
-
- lib/access-granted/controller_methods.rb
|
58
57
|
- lib/access-granted/exceptions.rb
|
59
58
|
- lib/access-granted/permission.rb
|
60
59
|
- lib/access-granted/policy.rb
|
61
60
|
- lib/access-granted/role.rb
|
62
61
|
- lib/access-granted/version.rb
|
63
|
-
- spec/controller_methods_spec.rb
|
64
62
|
- spec/permission_spec.rb
|
65
63
|
- spec/policy_spec.rb
|
66
64
|
- spec/role_spec.rb
|
67
65
|
- spec/spec_helper.rb
|
68
|
-
homepage: https://github.com/
|
66
|
+
homepage: https://github.com/chaps-io/access-granted
|
69
67
|
licenses:
|
70
68
|
- MIT
|
71
69
|
metadata: {}
|
@@ -75,23 +73,22 @@ require_paths:
|
|
75
73
|
- lib
|
76
74
|
required_ruby_version: !ruby/object:Gem::Requirement
|
77
75
|
requirements:
|
78
|
-
- -
|
76
|
+
- - ">="
|
79
77
|
- !ruby/object:Gem::Version
|
80
78
|
version: '0'
|
81
79
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
80
|
requirements:
|
83
|
-
- -
|
81
|
+
- - ">="
|
84
82
|
- !ruby/object:Gem::Version
|
85
83
|
version: '0'
|
86
84
|
requirements: []
|
87
85
|
rubyforge_project:
|
88
|
-
rubygems_version: 2.
|
86
|
+
rubygems_version: 2.4.5
|
89
87
|
signing_key:
|
90
88
|
specification_version: 4
|
91
89
|
summary: Elegant whitelist and role based authorization with ability to prioritize
|
92
90
|
roles.
|
93
91
|
test_files:
|
94
|
-
- spec/controller_methods_spec.rb
|
95
92
|
- spec/permission_spec.rb
|
96
93
|
- spec/policy_spec.rb
|
97
94
|
- spec/role_spec.rb
|
@@ -1,24 +0,0 @@
|
|
1
|
-
module AccessGranted
|
2
|
-
module ControllerMethods
|
3
|
-
def current_policy
|
4
|
-
@current_policy ||= ::Policy.new(current_user)
|
5
|
-
end
|
6
|
-
|
7
|
-
def self.included(base)
|
8
|
-
base.helper_method :can?, :cannot?, :current_policy
|
9
|
-
end
|
10
|
-
|
11
|
-
def can?(*args)
|
12
|
-
current_policy.can?(*args)
|
13
|
-
end
|
14
|
-
|
15
|
-
def cannot?(*args)
|
16
|
-
current_policy.cannot?(*args)
|
17
|
-
end
|
18
|
-
|
19
|
-
def authorize!(*args)
|
20
|
-
current_policy.authorize!(*args)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
@@ -1,42 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe AccessGranted::ControllerMethods do
|
4
|
-
before(:each) do
|
5
|
-
@current_user = double("User")
|
6
|
-
@controller_class = Class.new
|
7
|
-
@controller = @controller_class.new
|
8
|
-
@controller_class.stub(:helper_method).with(:can?, :cannot?, :current_policy)
|
9
|
-
@controller_class.send(:include, AccessGranted::ControllerMethods)
|
10
|
-
@controller.stub(:current_user).and_return(@current_user)
|
11
|
-
end
|
12
|
-
|
13
|
-
it "should have current_policy method returning Policy instance" do
|
14
|
-
@controller.current_policy.should be_kind_of(AccessGranted::Policy)
|
15
|
-
end
|
16
|
-
|
17
|
-
it "provides can? and cannot? method delegated to current_policy" do
|
18
|
-
@controller.can?(:read, String).should be_false
|
19
|
-
@controller.cannot?(:read, String).should be_true
|
20
|
-
end
|
21
|
-
|
22
|
-
describe "#authorize!" do
|
23
|
-
it "raises exception when authorization fails" do
|
24
|
-
expect { @controller.authorize!(:read, String) }.to raise_error(AccessGranted::AccessDenied)
|
25
|
-
end
|
26
|
-
|
27
|
-
it "returns subject if authorization succeeds" do
|
28
|
-
klass = Class.new do
|
29
|
-
include AccessGranted::Policy
|
30
|
-
|
31
|
-
def configure(user)
|
32
|
-
role :member, 1 do
|
33
|
-
can :read, String
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
policy = klass.new(@current_user)
|
38
|
-
@controller.stub(:current_policy).and_return(policy)
|
39
|
-
@controller.authorize!(:read, String).should == String
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|