authority 2.2.0 → 2.3.0
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.
- data/CHANGELOG.markdown +6 -0
- data/Gemfile +1 -1
- data/README.markdown +27 -11
- data/TODO.markdown +5 -6
- data/lib/authority.rb +12 -21
- data/lib/authority/abilities.rb +3 -1
- data/lib/authority/controller.rb +31 -22
- data/lib/authority/security_violation.rb +15 -0
- data/lib/authority/user_abilities.rb +4 -0
- data/lib/authority/version.rb +1 -1
- data/spec/authority/abilities_spec.rb +76 -61
- data/spec/authority/authorizer_spec.rb +43 -39
- data/spec/authority/configuration_spec.rb +11 -11
- data/spec/authority/controller_spec.rb +151 -86
- data/spec/authority/integration_spec.rb +34 -29
- data/spec/authority/user_abilities_spec.rb +30 -20
- data/spec/authority_spec.rb +37 -41
- data/spec/spec_helper.rb +1 -0
- data/spec/support/{example_model.rb → example_classes.rb} +5 -1
- metadata +6 -7
- data/spec/support/example_controllers.rb +0 -22
- data/spec/support/user.rb +0 -3
@@ -1,13 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'support/
|
3
|
-
require 'support/user'
|
2
|
+
require 'support/example_classes'
|
4
3
|
|
5
4
|
describe "integration from user through model to authorizer" do
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
6
|
+
let(:user) { ExampleUser.new }
|
7
|
+
let(:resource_class) { ExampleResource }
|
8
|
+
let(:resource_instance) { resource_class.new }
|
11
9
|
|
12
10
|
describe "class methods" do
|
13
11
|
|
@@ -16,20 +14,24 @@ describe "integration from user through model to authorizer" do
|
|
16
14
|
adjective = Authority.abilities[verb]
|
17
15
|
adjective_method = "#{adjective}_by?"
|
18
16
|
|
19
|
-
describe "
|
17
|
+
describe "#{adjective_method}" do
|
18
|
+
|
19
|
+
describe "if given an options hash" do
|
20
|
+
|
21
|
+
it "delegates `#{adjective_method}` to its authorizer class, passing the options" do
|
22
|
+
resource_class.authorizer.should_receive(adjective_method).with(user, :lacking => 'nothing')
|
23
|
+
user.send(verb_method, resource_class, :lacking => 'nothing')
|
24
|
+
end
|
20
25
|
|
21
|
-
it "should delegate `#{adjective_method}` to its authorizer class, passing the options" do
|
22
|
-
ExampleModel.authorizer.should_receive(adjective_method).with(@user, :lacking => 'nothing')
|
23
|
-
@user.send(verb_method, ExampleModel, :lacking => 'nothing')
|
24
26
|
end
|
25
27
|
|
26
|
-
|
28
|
+
describe "if not given an options hash" do
|
27
29
|
|
28
|
-
|
30
|
+
it "delegates `#{adjective_method}` to its authorizer class, passing no options" do
|
31
|
+
resource_class.authorizer.should_receive(adjective_method).with(user)
|
32
|
+
user.send(verb_method, resource_instance)
|
33
|
+
end
|
29
34
|
|
30
|
-
it "should delegate `#{adjective_method}` to its authorizer class, passing no options" do
|
31
|
-
ExampleModel.authorizer.should_receive(adjective_method).with(@user)
|
32
|
-
@user.send(verb_method, @example_model)
|
33
35
|
end
|
34
36
|
|
35
37
|
end
|
@@ -40,11 +42,10 @@ describe "integration from user through model to authorizer" do
|
|
40
42
|
|
41
43
|
describe "instance methods" do
|
42
44
|
|
45
|
+
let!(:authorizer_instance) { resource_class.authorizer.new(resource_instance) }
|
46
|
+
|
43
47
|
before :each do
|
44
|
-
|
45
|
-
@example_model = ExampleModel.new
|
46
|
-
@authorizer = ExampleModel.authorizer.new(@example_model)
|
47
|
-
ExampleModel.authorizer.stub(:new).and_return(@authorizer)
|
48
|
+
resource_class.authorizer.stub(:new).and_return(authorizer_instance)
|
48
49
|
end
|
49
50
|
|
50
51
|
Authority.verbs.each do |verb|
|
@@ -52,20 +53,24 @@ describe "integration from user through model to authorizer" do
|
|
52
53
|
adjective = Authority.abilities[verb]
|
53
54
|
adjective_method = "#{adjective}_by?"
|
54
55
|
|
55
|
-
describe "
|
56
|
+
describe "#{adjective_method}" do
|
57
|
+
|
58
|
+
describe "if given an options hash" do
|
59
|
+
|
60
|
+
it "delegates `#{adjective_method}` to a new authorizer instance, passing the options" do
|
61
|
+
authorizer_instance.should_receive(adjective_method).with(user, :consistency => 'mushy')
|
62
|
+
user.send(verb_method, resource_instance, :consistency => 'mushy')
|
63
|
+
end
|
56
64
|
|
57
|
-
it "should delegate `#{adjective_method}` to a new authorizer instance, passing the options" do
|
58
|
-
@authorizer.should_receive(adjective_method).with(@user, :consistency => 'mushy')
|
59
|
-
@user.send(verb_method, @example_model, :consistency => 'mushy')
|
60
65
|
end
|
61
66
|
|
62
|
-
|
67
|
+
describe "if not given an options hash" do
|
68
|
+
|
69
|
+
it "delegates `#{adjective_method}` to a new authorizer instance, passing no options" do
|
70
|
+
authorizer_instance.should_receive(adjective_method).with(user)
|
71
|
+
user.send(verb_method, resource_instance)
|
72
|
+
end
|
63
73
|
|
64
|
-
describe "if not given an options hash" do
|
65
|
-
|
66
|
-
it "should delegate `#{adjective_method}` to a new authorizer instance, passing no options" do
|
67
|
-
@authorizer.should_receive(adjective_method).with(@user)
|
68
|
-
@user.send(verb_method, @example_model)
|
69
74
|
end
|
70
75
|
|
71
76
|
end
|
@@ -1,39 +1,49 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'support/
|
3
|
-
require 'support/user'
|
2
|
+
require 'support/example_classes'
|
4
3
|
|
5
4
|
describe Authority::UserAbilities do
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
@user = User.new
|
10
|
-
end
|
6
|
+
let(:resource_instance) { ExampleResource.new }
|
7
|
+
let(:user) { ExampleUser.new }
|
11
8
|
|
12
|
-
|
13
|
-
method_name = "can_#{verb}?"
|
9
|
+
describe "using `can_{verb}?` methods to check permissions on a resource" do
|
14
10
|
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
Authority.verbs.each do |verb|
|
12
|
+
method_name = "can_#{verb}?"
|
13
|
+
|
14
|
+
it "defines the `#{method_name}` method" do
|
15
|
+
expect(user).to respond_to(method_name)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "if given options" do
|
18
19
|
|
19
|
-
|
20
|
+
it "delegates the authorization check to the resource, passing the options" do
|
21
|
+
resource_instance.should_receive("#{Authority.abilities[verb]}_by?").with(user, :size => 'wee')
|
22
|
+
user.send(method_name, resource_instance, :size => 'wee')
|
23
|
+
end
|
20
24
|
|
21
|
-
it "should delegate the authorization check to the resource, passing the options" do
|
22
|
-
@example_model.should_receive("#{Authority.abilities[verb]}_by?").with(@user, :size => 'wee')
|
23
|
-
@user.send(method_name, @example_model, :size => 'wee')
|
24
25
|
end
|
25
26
|
|
26
|
-
|
27
|
+
describe "if not given options" do
|
27
28
|
|
28
|
-
|
29
|
+
it "delegates the authorization check to the resource, passing no options" do
|
30
|
+
resource_instance.should_receive("#{Authority.abilities[verb]}_by?").with(user)
|
31
|
+
user.send(method_name, resource_instance)
|
32
|
+
end
|
29
33
|
|
30
|
-
it "should delegate the authorization check to the resource, passing no options" do
|
31
|
-
@example_model.should_receive("#{Authority.abilities[verb]}_by?").with(@user)
|
32
|
-
@user.send(method_name, @example_model)
|
33
34
|
end
|
34
35
|
|
35
36
|
end
|
36
37
|
|
37
38
|
end
|
38
39
|
|
40
|
+
describe "using `can?` for non-resource-specific checks" do
|
41
|
+
|
42
|
+
it "checks with ApplicationAuthorizer" do
|
43
|
+
ApplicationAuthorizer.should_receive(:can_mimic_lemurs?).with(user)
|
44
|
+
user.can?(:mimic_lemurs)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
39
49
|
end
|
data/spec/authority_spec.rb
CHANGED
@@ -1,38 +1,37 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'support/
|
3
|
-
require 'support/user'
|
2
|
+
require 'support/example_classes'
|
4
3
|
|
5
4
|
describe Authority do
|
6
5
|
|
7
|
-
it "
|
8
|
-
Authority.abilities.
|
6
|
+
it "has a default list of abilities" do
|
7
|
+
expect(Authority.abilities).to be_a(Hash)
|
9
8
|
end
|
10
9
|
|
11
|
-
it "
|
10
|
+
it "does not allow modification of the Authority.abilities hash directly" do
|
12
11
|
expect { Authority.abilities[:exchange] = 'fungible' }.to raise_error(
|
13
12
|
StandardError, /modify frozen/
|
14
13
|
) # can't modify frozen hash - exact error type and message depends on Ruby version
|
15
14
|
end
|
16
15
|
|
17
|
-
it "
|
18
|
-
Authority.verbs.map(&:to_s).sort.
|
16
|
+
it "has a convenience accessor for the ability verbs" do
|
17
|
+
expect(Authority.verbs.map(&:to_s).sort).to eq(%w[create delete read update])
|
19
18
|
end
|
20
19
|
|
21
|
-
it "
|
22
|
-
Authority.adjectives.sort.
|
20
|
+
it "has a convenience accessor for the ability adjectives" do
|
21
|
+
expect(Authority.adjectives.sort).to eq(%w[creatable deletable readable updatable])
|
23
22
|
end
|
24
23
|
|
25
24
|
describe "configuring Authority" do
|
26
25
|
|
27
|
-
it "
|
28
|
-
Authority.
|
26
|
+
it "has a configuration accessor" do
|
27
|
+
expect(Authority).to respond_to(:configuration)
|
29
28
|
end
|
30
29
|
|
31
|
-
it "
|
32
|
-
Authority.
|
30
|
+
it "has a `configure` method" do
|
31
|
+
expect(Authority).to respond_to(:configure)
|
33
32
|
end
|
34
33
|
|
35
|
-
it "
|
34
|
+
it "requires the remainder of library internals after configuration" do
|
36
35
|
Authority.should_receive(:require_authority_internals!)
|
37
36
|
Authority.configure
|
38
37
|
end
|
@@ -40,62 +39,59 @@ describe Authority do
|
|
40
39
|
|
41
40
|
describe "enforcement" do
|
42
41
|
|
43
|
-
|
44
|
-
|
45
|
-
end
|
42
|
+
let(:user) { ExampleUser.new }
|
43
|
+
let(:resource_class) { ExampleResource }
|
46
44
|
|
47
45
|
describe "if given options" do
|
48
46
|
|
49
|
-
it "
|
47
|
+
it "checks the user's authorization, passing along the options" do
|
50
48
|
options = { :for => 'context' }
|
51
|
-
|
52
|
-
Authority.enforce(:delete,
|
49
|
+
user.should_receive(:can_delete?).with(resource_class, options).and_return(true)
|
50
|
+
Authority.enforce(:delete, resource_class, user, options)
|
53
51
|
end
|
54
52
|
|
55
53
|
end
|
56
54
|
|
57
55
|
describe "if not given options" do
|
58
56
|
|
59
|
-
it "
|
60
|
-
|
61
|
-
Authority.enforce(:delete,
|
57
|
+
it "checks the user's authorization, passing no options" do
|
58
|
+
user.should_receive(:can_delete?).with(resource_class).and_return(true)
|
59
|
+
Authority.enforce(:delete, resource_class, user)
|
62
60
|
end
|
63
61
|
|
64
62
|
end
|
65
63
|
|
66
|
-
it "
|
67
|
-
expect { Authority.enforce(:update,
|
64
|
+
it "raises a SecurityViolation if the action is unauthorized" do
|
65
|
+
expect { Authority.enforce(:update, resource_class, user) }.to raise_error(Authority::SecurityViolation)
|
68
66
|
end
|
69
67
|
|
70
|
-
it "
|
71
|
-
expect { Authority.enforce(:read,
|
68
|
+
it "doesn't raise a SecurityViolation if the action is authorized" do
|
69
|
+
expect { Authority.enforce(:read, resource_class, user) }.not_to raise_error(Authority::SecurityViolation)
|
72
70
|
end
|
73
71
|
|
74
72
|
end
|
75
73
|
|
76
74
|
describe Authority::SecurityViolation do
|
77
75
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
@security_violation = Authority::SecurityViolation.new(@user, @action, @resource)
|
83
|
-
end
|
76
|
+
let(:user) { :"Cap'n Ned" }
|
77
|
+
let(:action) { :keelhaul }
|
78
|
+
let(:resource) { :houseplant }
|
79
|
+
let(:security_violation) { Authority::SecurityViolation.new(user, action, resource) }
|
84
80
|
|
85
|
-
it "
|
86
|
-
|
81
|
+
it "has a reader for the user" do
|
82
|
+
expect(security_violation.user).to eq(user)
|
87
83
|
end
|
88
84
|
|
89
|
-
it "
|
90
|
-
|
85
|
+
it "has a reader for the action" do
|
86
|
+
expect(security_violation.action).to eq(action)
|
91
87
|
end
|
92
88
|
|
93
|
-
it "
|
94
|
-
|
89
|
+
it "has a reader for the resource" do
|
90
|
+
expect(security_violation.resource).to eq(resource)
|
95
91
|
end
|
96
92
|
|
97
|
-
it "
|
98
|
-
|
93
|
+
it "uses them all in its message" do
|
94
|
+
expect(security_violation.message).to eq("#{user} is not authorized to #{action} this resource: #{resource}")
|
99
95
|
end
|
100
96
|
|
101
97
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: authority
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-12-09 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rails
|
17
|
-
requirement: &
|
17
|
+
requirement: &69990830 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,7 +22,7 @@ dependencies:
|
|
22
22
|
version: 3.0.0
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *69990830
|
26
26
|
description: Authority helps you authorize actions in your Rails app. It's ORM-neutral
|
27
27
|
and has very little fancy syntax; just group your models under one or more Authorizer
|
28
28
|
classes and write plain Ruby methods on them.
|
@@ -53,6 +53,7 @@ files:
|
|
53
53
|
- lib/authority/configuration.rb
|
54
54
|
- lib/authority/controller.rb
|
55
55
|
- lib/authority/railtie.rb
|
56
|
+
- lib/authority/security_violation.rb
|
56
57
|
- lib/authority/user_abilities.rb
|
57
58
|
- lib/authority/version.rb
|
58
59
|
- lib/generators/authority/install_generator.rb
|
@@ -67,10 +68,8 @@ files:
|
|
67
68
|
- spec/authority/user_abilities_spec.rb
|
68
69
|
- spec/authority_spec.rb
|
69
70
|
- spec/spec_helper.rb
|
70
|
-
- spec/support/
|
71
|
-
- spec/support/example_model.rb
|
71
|
+
- spec/support/example_classes.rb
|
72
72
|
- spec/support/mock_rails.rb
|
73
|
-
- spec/support/user.rb
|
74
73
|
homepage: https://github.com/nathanl/authority
|
75
74
|
licenses: []
|
76
75
|
post_install_message:
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module MockController
|
2
|
-
def rescue_from(*args) ; end
|
3
|
-
def before_filter(*args) ; end
|
4
|
-
end
|
5
|
-
|
6
|
-
# this controller will have `authority_actions_for` called on it
|
7
|
-
class ExampleController
|
8
|
-
extend MockController
|
9
|
-
include Authority::Controller
|
10
|
-
end
|
11
|
-
|
12
|
-
class DummyController < ExampleController
|
13
|
-
end
|
14
|
-
|
15
|
-
class InstanceController < ExampleController
|
16
|
-
end
|
17
|
-
|
18
|
-
# this controller will not have `authority_actions_for` called on it but will
|
19
|
-
# have `authority_action_for` called on it
|
20
|
-
class SampleController
|
21
|
-
extend MockController
|
22
|
-
end
|
data/spec/support/user.rb
DELETED