rddd 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +2 -0
- data/lib/rddd/authorization/authorize.rb +42 -0
- data/lib/rddd/authorization/rule.rb +45 -0
- data/lib/rddd/authorization/rules_builder.rb +44 -0
- data/lib/rddd/version.rb +1 -1
- data/spec/lib/authorization/authorize_spec.rb +55 -0
- data/spec/lib/authorization/integration_spec.rb +55 -0
- data/spec/lib/authorization/rule_spec.rb +57 -0
- data/spec/lib/authorization/rules_builder_spec.rb +29 -0
- metadata +12 -1
data/README.md
CHANGED
@@ -0,0 +1,42 @@
|
|
1
|
+
module Rddd
|
2
|
+
#
|
3
|
+
# Authorize plugin stores all the authorization rules
|
4
|
+
# and answers the question if specific user is or is
|
5
|
+
# not authorized to perform the action considering the
|
6
|
+
# parameters as well.
|
7
|
+
#
|
8
|
+
module Authorization
|
9
|
+
class Authorize
|
10
|
+
#
|
11
|
+
# Initialize.
|
12
|
+
#
|
13
|
+
# @param {Array} List of Rddd::Authorization::Rule.
|
14
|
+
# @param {Object} User we are gonna authorize.
|
15
|
+
#
|
16
|
+
def initialize(rules, user)
|
17
|
+
@rules = rules
|
18
|
+
@user = user
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Authorize given action.
|
23
|
+
#
|
24
|
+
# @param {Symbol} Action to be authorized.
|
25
|
+
# @param {Hash} Auxiliary attributes to decide authorization.
|
26
|
+
#
|
27
|
+
def can?(action, params = {})
|
28
|
+
rule = find_rule(action)
|
29
|
+
|
30
|
+
return true unless rule
|
31
|
+
|
32
|
+
rule.can?(@user, params)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def find_rule(action)
|
38
|
+
@rules.find { |rule| rule.is_for?(action) }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Rddd
|
2
|
+
module Authorization
|
3
|
+
#
|
4
|
+
# Representation of single authorization rule. It applies
|
5
|
+
# to a specific action and evaluates the given block to
|
6
|
+
# decide the outcome.
|
7
|
+
#
|
8
|
+
class Rule
|
9
|
+
InvalidEvaluationBlock = Class.new(RuntimeError)
|
10
|
+
|
11
|
+
#
|
12
|
+
# Initialize.
|
13
|
+
#
|
14
|
+
# @param {Symbol} Action to apply rule to.
|
15
|
+
# @param {Block} Block to be evaluated during authorization.
|
16
|
+
#
|
17
|
+
def initialize(action, &block)
|
18
|
+
# Block should take two arguments - user and params.
|
19
|
+
raise InvalidEvaluationBlock unless block.arity == 2
|
20
|
+
|
21
|
+
@action = action
|
22
|
+
@block = block
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# Is the Rule for given action?
|
27
|
+
#
|
28
|
+
# @param {Symbol} Action to be matched.
|
29
|
+
#
|
30
|
+
def is_for?(action)
|
31
|
+
@action == action
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Evalute the rule for a given user and params.
|
36
|
+
#
|
37
|
+
# @param {Object} User we are gonna authorize.
|
38
|
+
# @param {Hash} Auxiliary attributes to decide authorization.
|
39
|
+
#
|
40
|
+
def can?(user, params)
|
41
|
+
@block.call(user, params)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rddd/authorization/rule'
|
2
|
+
|
3
|
+
module Rddd
|
4
|
+
module Authorization
|
5
|
+
#
|
6
|
+
# Helper module for building list of authorization rules.
|
7
|
+
#
|
8
|
+
# Usage:
|
9
|
+
#
|
10
|
+
# builder = Object.new
|
11
|
+
# builder.extends Rddd::Authorization::RulesBuilder
|
12
|
+
#
|
13
|
+
# builder.can :create_project do |user, params|
|
14
|
+
# user.owner? && params[:account_id] == user.account_id
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
#
|
18
|
+
# # This part happens inside framework
|
19
|
+
# authorizer = Rddd::Authorization::Authorize.new(builder.rules, user)
|
20
|
+
# authorizer.can?(:create_project, {:account_id => 123})
|
21
|
+
#
|
22
|
+
#
|
23
|
+
# Call to can method define the rule for a given action. The block
|
24
|
+
# always takes the user instance and additional parameters which
|
25
|
+
# specify details for the performed action.
|
26
|
+
#
|
27
|
+
module RulesBuilder
|
28
|
+
attr_reader :rules
|
29
|
+
|
30
|
+
#
|
31
|
+
# Create new rule applied to specified action and perform the given
|
32
|
+
# block.
|
33
|
+
#
|
34
|
+
# @param {Symbol} Action the rule applies to.
|
35
|
+
# @param {Block} Block to be executed to evaluate authorization.
|
36
|
+
#
|
37
|
+
def can(action, &block)
|
38
|
+
@rules ||= []
|
39
|
+
|
40
|
+
@rules << Rule.new(action, &block)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/rddd/version.rb
CHANGED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rddd/authorization/authorize'
|
3
|
+
|
4
|
+
describe Rddd::Authorization::Authorize do
|
5
|
+
let(:authorize) do
|
6
|
+
Rddd::Authorization::Authorize.new(
|
7
|
+
rules, user
|
8
|
+
)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#can?' do
|
12
|
+
subject { authorize.can?(action, params) }
|
13
|
+
|
14
|
+
let(:rule) { stub('rule') }
|
15
|
+
let(:rules) { [rule] }
|
16
|
+
|
17
|
+
let(:user) { stub('user') }
|
18
|
+
|
19
|
+
let(:params) { {:foo => 'bar'} }
|
20
|
+
|
21
|
+
let(:action) { :foo }
|
22
|
+
|
23
|
+
context 'has no rule' do
|
24
|
+
let(:rules) { [] }
|
25
|
+
|
26
|
+
it { should be_true }
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'has aplicable rule which is positive' do
|
30
|
+
before do
|
31
|
+
rule.expects(:is_for?).with(:foo).returns(true)
|
32
|
+
rule.expects(:can?).with(user, params).returns(true)
|
33
|
+
end
|
34
|
+
|
35
|
+
it { should be_true }
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'has applicable rule which is negative' do
|
39
|
+
before do
|
40
|
+
rule.expects(:is_for?).with(:foo).returns(true)
|
41
|
+
rule.expects(:can?).with(user, params).returns(false)
|
42
|
+
end
|
43
|
+
|
44
|
+
it { should be_false }
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'has no applicable rule' do
|
48
|
+
before do
|
49
|
+
rule.expects(:is_for?).with(:foo).returns(false)
|
50
|
+
end
|
51
|
+
|
52
|
+
it { should be_true }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rddd/authorization/authorize'
|
3
|
+
require 'rddd/authorization/rules_builder'
|
4
|
+
|
5
|
+
describe Rddd::Authorization::Authorize do
|
6
|
+
let(:builder) do
|
7
|
+
Object.new.tap do |object|
|
8
|
+
object.extend Rddd::Authorization::RulesBuilder
|
9
|
+
|
10
|
+
object.can :create_project do |user, params|
|
11
|
+
user.owner? && user.account_id == params[:account_id]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'create_project' do
|
17
|
+
subject do
|
18
|
+
Rddd::Authorization::Authorize.new(builder.rules, user) \
|
19
|
+
.can?(:create_project, {:account_id => '1'})
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'user is owner' do
|
23
|
+
let(:user) do
|
24
|
+
stub('user',
|
25
|
+
:owner? => true,
|
26
|
+
:account_id => '1'
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
it { should be_true }
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'user is not owner' do
|
34
|
+
let(:user) do
|
35
|
+
stub('user',
|
36
|
+
:owner? => false,
|
37
|
+
:account_id => '1'
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
it { should be_false }
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'user is not on same account' do
|
45
|
+
let(:user) do
|
46
|
+
stub('user',
|
47
|
+
:owner? => true,
|
48
|
+
:account_id => '2'
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
it { should be_false }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rddd/authorization/rule'
|
3
|
+
|
4
|
+
describe Rddd::Authorization::Rule do
|
5
|
+
|
6
|
+
let(:action) { :foo }
|
7
|
+
|
8
|
+
let(:block) { lambda { |user, params| true } }
|
9
|
+
|
10
|
+
let(:authorize) do
|
11
|
+
Rddd::Authorization::Rule.new(
|
12
|
+
action, &block
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'should raise if rule block is invalid' do
|
17
|
+
let(:block) { lambda { |user| true } }
|
18
|
+
|
19
|
+
it { expect { authorize }.to raise_exception Rddd::Authorization::Rule::InvalidEvaluationBlock }
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#is_for?' do
|
23
|
+
subject { authorize.is_for?(questioned_action) }
|
24
|
+
|
25
|
+
context 'matching action' do
|
26
|
+
let(:questioned_action) { :foo }
|
27
|
+
|
28
|
+
it { should be_true }
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'not matching action' do
|
32
|
+
let(:questioned_action) { :bar }
|
33
|
+
|
34
|
+
it { should be_false }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#can?' do
|
39
|
+
let(:user) { stub('user, params') }
|
40
|
+
|
41
|
+
let(:params) { stub('user, params') }
|
42
|
+
|
43
|
+
subject { authorize.can?(user, params) }
|
44
|
+
|
45
|
+
describe 'passing right params to block' do
|
46
|
+
before do
|
47
|
+
block.expects(:call).with(user, params).returns(false)
|
48
|
+
end
|
49
|
+
|
50
|
+
it { should be_false }
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should return true as lambda does' do
|
54
|
+
should be_true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rddd/authorization/rules_builder'
|
3
|
+
|
4
|
+
describe Rddd::Authorization::RulesBuilder do
|
5
|
+
let(:builder) do
|
6
|
+
Object.new.tap do |object|
|
7
|
+
object.extend Rddd::Authorization::RulesBuilder
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#rules' do
|
12
|
+
subject { builder.rules }
|
13
|
+
|
14
|
+
let(:rule) { stub('rule') }
|
15
|
+
|
16
|
+
let(:action) { :foo }
|
17
|
+
|
18
|
+
let(:block) { lambda{|user, params| } }
|
19
|
+
|
20
|
+
before do
|
21
|
+
Rddd::Authorization::Rule.expects(:new).returns(rule)
|
22
|
+
|
23
|
+
builder.can(:foo, &block)
|
24
|
+
end
|
25
|
+
|
26
|
+
its(:first) { should be rule }
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rddd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -31,6 +31,9 @@ files:
|
|
31
31
|
- lib/rddd.rb
|
32
32
|
- lib/rddd/aggregate_root.rb
|
33
33
|
- lib/rddd/aggregate_root_finders.rb
|
34
|
+
- lib/rddd/authorization/authorize.rb
|
35
|
+
- lib/rddd/authorization/rule.rb
|
36
|
+
- lib/rddd/authorization/rules_builder.rb
|
34
37
|
- lib/rddd/configuration.rb
|
35
38
|
- lib/rddd/entity.rb
|
36
39
|
- lib/rddd/repository.rb
|
@@ -42,6 +45,10 @@ files:
|
|
42
45
|
- rddd.gemspec
|
43
46
|
- spec/integration_spec.rb
|
44
47
|
- spec/lib/aggregate_root_spec.rb
|
48
|
+
- spec/lib/authorization/authorize_spec.rb
|
49
|
+
- spec/lib/authorization/integration_spec.rb
|
50
|
+
- spec/lib/authorization/rule_spec.rb
|
51
|
+
- spec/lib/authorization/rules_builder_spec.rb
|
45
52
|
- spec/lib/entity_spec.rb
|
46
53
|
- spec/lib/repository_factory_spec.rb
|
47
54
|
- spec/lib/repository_spec.rb
|
@@ -78,6 +85,10 @@ summary: Intention of rddd is to provide basic skeleton for DDD ruby application
|
|
78
85
|
test_files:
|
79
86
|
- spec/integration_spec.rb
|
80
87
|
- spec/lib/aggregate_root_spec.rb
|
88
|
+
- spec/lib/authorization/authorize_spec.rb
|
89
|
+
- spec/lib/authorization/integration_spec.rb
|
90
|
+
- spec/lib/authorization/rule_spec.rb
|
91
|
+
- spec/lib/authorization/rules_builder_spec.rb
|
81
92
|
- spec/lib/entity_spec.rb
|
82
93
|
- spec/lib/repository_factory_spec.rb
|
83
94
|
- spec/lib/repository_spec.rb
|