rddd 0.1.5 → 0.1.6
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/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
|