toni 0.0.2 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7ac2b196171e40bf0d69e5c191c4a9435ce3855a
4
- data.tar.gz: 587bbdcb7dd9a86db28551388a8efe786b6ceaa6
3
+ metadata.gz: 14722f9cb78336b60a87caf4ab45e8b7d17c37d1
4
+ data.tar.gz: dd9abb810b120478e41d070d04efe88dc1bd3b80
5
5
  SHA512:
6
- metadata.gz: bdadf5d1db3e86f10963fda52f7b810d2f1ad87c071a0959d871f3f28a9bbac9dae2e28838eeaa7bfb3e4eb9f60ecf7fe88476cb2bff28e00de6415fd940b177
7
- data.tar.gz: aa782e08c89471234beb82c2690f29c6ed0f8a10dc9e597e2ef8cd159784bf86d59278daf56e318301d43d6b83324d4c00e5fb6331618e64e2abca87c3752902
6
+ metadata.gz: 6ba6677c52e0da7577d75865e2f4484b1b353809dfa0b96b081e32ba9faf877fbe70447d05a85e936863275287ff74b1ee0dce03da490b4d55a4f8d9a4507fb2
7
+ data.tar.gz: 267549c89b11bd2c3a9c2a9364c318fdc5e2df5294bb3cb50b6c813224e409677ba74b6c3f23f49b7c90f53bf07485dd5f3cb87087ff9aa4a13868ddad00acbb
@@ -1,5 +1,6 @@
1
1
  require "toni/version"
2
2
  require "toni/anonymous_user"
3
+ require "toni/permission_filter"
3
4
  require "toni/builder"
4
5
 
5
6
  module Toni
@@ -10,6 +11,7 @@ module Toni
10
11
  class NoMethodForMatcherError < StandardError; end
11
12
  class NotAuthorizedError < StandardError; end
12
13
  class MissingMatcherError < StandardError; end
14
+ class MissingPermissionFilterError < StandardError; end
13
15
 
14
16
  class << self
15
17
  def current_user
@@ -40,6 +42,12 @@ module Toni
40
42
  roles.select { |role_symbol, r| current_user.role_symbols.include?(role_symbol) }.values
41
43
  end
42
44
 
45
+ def current_permissions_for(activity, resource_or_name)
46
+ current_roles.map do |r|
47
+ r.permissions_for(activity, resource_or_name)
48
+ end.flatten
49
+ end
50
+
43
51
  def without_authorization(&block)
44
52
  @without_authorization = true
45
53
  result = block_given? ? yield : nil
@@ -0,0 +1,50 @@
1
+ module Toni
2
+ module InModel
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+
6
+ [:create, :update, :destroy].each do |action|
7
+ base.send(:"before_#{action}") do |object|
8
+ activity = action == :destroy ? :delete : action
9
+ Toni.permitted_to?(activity, object, bang: true)
10
+ end
11
+ end
12
+
13
+ base.send(:after_find) do |object|
14
+ Toni.permitted_to?(:read, object, bang: true)
15
+ end
16
+
17
+ # TODO: Should be active record only
18
+ base.scope :permitted_to, -> {
19
+ base.send(:filter_by_permissions)
20
+ }
21
+ end
22
+
23
+ module ClassMethods
24
+
25
+ private
26
+
27
+ def filter_by_permissions
28
+ where(*scope_for_filter_permissions)
29
+ end
30
+
31
+ def scope_for_filter_permissions
32
+ permissions = Toni.current_permissions_for(:read, authorization_context)
33
+ return ["0 = 1"] if permissions.empty?
34
+ permissions.inject([""]) do |cond, p|
35
+ conditions = p.matchers.map(&:filter_condition).compact.inject([""]) do |cond2, filter_cond|
36
+ concat_filters(cond2, filter_cond)
37
+ end
38
+ concat_filters(cond, conditions, " OR ")
39
+ end
40
+ end
41
+
42
+ def concat_filters(cond, conditions, separator=" AND ")
43
+ return cond if conditions[0] == ""
44
+ cond[0] = "#{cond[0]}#{separator unless cond[0].empty?}(#{conditions[0]})"
45
+ cond.push(*conditions[1..-1])
46
+ cond
47
+ end
48
+ end
49
+ end
50
+ end
@@ -12,12 +12,16 @@ module Toni
12
12
  end
13
13
 
14
14
  def add_matcher(method_name, matcher, is_attr = false)
15
- @matchers << PermissionMatcher.new(method_name, matcher, is_attr)
15
+ @matchers << PermissionMatcher::Base.new(method_name, matcher, is_attr)
16
16
  end
17
17
 
18
- def permitted_to?(activity, res, options={})
18
+ def permission_for?(activity, res)
19
19
  resource_name == (res.is_a?(Symbol) ? res : res.class.authorization_context) &&
20
- activities.include?(activity) && matches?(res)
20
+ activities.include?(activity)
21
+ end
22
+
23
+ def permitted_to?(activity, res, options={})
24
+ permission_for?(activity, res) && matches?(res)
21
25
  end
22
26
 
23
27
  private
@@ -0,0 +1,81 @@
1
+ module Toni
2
+ class PermissionFilter
3
+ attr_reader :permission_matcher
4
+
5
+ def self.permission_filters
6
+ @filterable_matchers ||= constants.select do |c|
7
+ const_get(c).is_a?(Class)
8
+ end
9
+ end
10
+
11
+ def initialize(permission_matcher)
12
+ @permission_matcher = permission_matcher
13
+ end
14
+
15
+ def filter_condition
16
+ raise "implement me"
17
+ end
18
+
19
+ def matcher
20
+ permission_matcher.matcher
21
+ end
22
+
23
+ def attr_name
24
+ permission_matcher.method_name
25
+ end
26
+
27
+ class Eq < PermissionFilter
28
+ def filter_condition
29
+ ["#{attr_name} = ?", matcher.expected]
30
+ end
31
+
32
+ def filter_condition_inverse
33
+ ["#{attr_name} != ?", matcher.expected]
34
+ end
35
+ end
36
+
37
+ class BeNil < PermissionFilter
38
+ def filter_condition
39
+ ["#{attr_name} IS NULL"]
40
+ end
41
+
42
+ def filter_condition_inverse
43
+ ["#{attr_name} IS NOT NULL"]
44
+ end
45
+ end
46
+
47
+ class BeTruthy < PermissionFilter
48
+ def filter_condition
49
+ ["#{attr_name} IS NOT NULL AND #{attr_name} != ''"]
50
+ end
51
+
52
+ def filter_condition_inverse
53
+ BeFalsey.new(permission_matcher).filter_condition
54
+ end
55
+ end
56
+
57
+ class BeFalsey < PermissionFilter
58
+ def filter_condition
59
+ ["#{attr_name} = '' OR #{attr_name} IS NULL"]
60
+ end
61
+
62
+ def filter_condition_inverse
63
+ BeTruthy.new(permission_matcher).filter_condition
64
+ end
65
+ end
66
+
67
+ class BeBetween < PermissionFilter
68
+ def filter_condition
69
+ ["#{attr_name} >= ? AND #{attr_name} <= ?",
70
+ matcher.instance_variable_get(:@min),
71
+ matcher.instance_variable_get(:@max)]
72
+ end
73
+
74
+ def filter_condition_inverse
75
+ ["#{attr_name} < ? OR #{attr_name} > ?",
76
+ matcher.instance_variable_get(:@min),
77
+ matcher.instance_variable_get(:@max)]
78
+ end
79
+ end
80
+ end
81
+ end
@@ -1,54 +1,4 @@
1
- module Toni
2
- class PermissionMatcher
3
-
4
- attr_reader :method_name, :matcher, :is_attr
5
-
6
- def initialize(method_name, matcher, is_attr = false)
7
- @method_name = method_name
8
- @matcher = matcher
9
- @is_attr = is_attr
10
- end
11
-
12
- def matches?(object)
13
- unless object.respond_to?(method_name)
14
- raise Toni::NoMethodForMatcherError.new("#{method_name} is not defined for #{object.inspect}")
15
- end
16
- matcher.matches?(object.send(method_name))
17
- end
18
-
19
- class NotMatcher
20
- attr_reader :matcher
21
-
22
- def initialize
23
- @matcher = nil
24
- end
25
-
26
- def method_missing(method_name, *args)
27
- builder = Toni::Builder::ExpectationBuilder.new
28
- if builder.respond_to?(method_name)
29
- @matcher = builder.send(method_name, *args)
30
- else
31
- super
32
- end
33
- end
34
-
35
- def matches?(object)
36
- raise Toni::MissingMatcherError if @matcher.nil?
37
- !@matcher.matches?(object)
38
- end
39
- end
40
-
41
- class PermittedToMatcher
42
-
43
- def initialize(activity)
44
- @activity = activity
45
- end
46
-
47
- def matches?(object)
48
- Toni.permitted_to?(@activity, object)
49
- end
50
-
51
- end
52
-
53
- end
54
- end
1
+ require 'toni/permission_matcher/has_matcher'
2
+ require 'toni/permission_matcher/base'
3
+ require 'toni/permission_matcher/not_matcher'
4
+ require 'toni/permission_matcher/permitted_to_matcher'
@@ -0,0 +1,31 @@
1
+ module Toni
2
+ module PermissionMatcher
3
+
4
+ class Base
5
+
6
+ include HasMatcher
7
+
8
+ attr_reader :method_name, :is_attr
9
+
10
+ def initialize(method_name, matcher, is_attr = false)
11
+ @method_name = method_name
12
+ @matcher = matcher
13
+ @is_attr = is_attr
14
+ end
15
+
16
+ def matches?(object)
17
+ unless object.respond_to?(method_name)
18
+ raise Toni::NoMethodForMatcherError.new("#{method_name} is not defined for #{object.inspect}")
19
+ end
20
+ matcher.matches?(object.send(method_name))
21
+ end
22
+
23
+ def filter_condition
24
+ return nil unless is_attr
25
+ super
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,41 @@
1
+ module Toni
2
+ module PermissionMatcher
3
+
4
+ module HasMatcher
5
+
6
+ def self.included(base)
7
+ base.send(:attr_reader, :matcher)
8
+ end
9
+
10
+ def matches?(object)
11
+ raise "implement me"
12
+ end
13
+
14
+ def filter_condition
15
+ return matcher.filter_condition if matcher.respond_to?(:filter_condition)
16
+
17
+ filter = permission_filter
18
+ if filter.nil?
19
+ raise Toni::MissingPermissionFilterError.new("No permission matcher for #{matcher.class.inspect}")
20
+ end
21
+
22
+ filter.filter_condition
23
+ end
24
+
25
+ private
26
+
27
+ def permission_filter
28
+ if permission_filter_class
29
+ Toni::PermissionFilter.const_get(permission_filter_class).new(self)
30
+ end
31
+ end
32
+
33
+ def permission_filter_class
34
+ @permission_filter ||= Toni::PermissionFilter.permission_filters.detect do |c|
35
+ !matcher.class.name.nil? && c.to_s.split('::').last == matcher.class.name.split('::').last
36
+ end
37
+ end
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,37 @@
1
+ module Toni
2
+ module PermissionMatcher
3
+
4
+ class NotMatcher
5
+
6
+ include HasMatcher
7
+
8
+ def initialize
9
+ @matcher = nil
10
+ end
11
+
12
+ def method_missing(method_name, *args)
13
+ builder = Toni::Builder::ExpectationBuilder.new
14
+ if builder.respond_to?(method_name)
15
+ @matcher = builder.send(method_name, *args)
16
+ else
17
+ super
18
+ end
19
+ end
20
+
21
+ def matches?(object)
22
+ raise Toni::MissingMatcherError if @matcher.nil?
23
+ !@matcher.matches?(object)
24
+ end
25
+
26
+ def filter_condition
27
+ filter = permission_filter
28
+ unless filter && filter.respond_to?(:filter_condition_inverse)
29
+ raise Toni::MissingPermissionFilterError.new("No permission matcher for #{matcher.class.inspect}")
30
+ end
31
+
32
+ filter.filter_condition_inverse
33
+ end
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,15 @@
1
+ module Toni
2
+ module PermissionMatcher
3
+ class PermittedToMatcher
4
+
5
+ def initialize(activity)
6
+ @activity = activity
7
+ end
8
+
9
+ def matches?(object)
10
+ Toni.permitted_to?(@activity, object)
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -26,6 +26,14 @@ module Toni
26
26
  end
27
27
  end
28
28
 
29
+ def permissions_for(activity, res)
30
+ unless res.is_a?(Symbol) || res.class.respond_to?(:authorization_context)
31
+ raise Toni::NoAuthorizationContextProvidedError
32
+ end
33
+ res = res.class.authorization_context unless res.is_a?(Symbol)
34
+ current_permissions.select { |p| p.permission_for?(activity, res) }
35
+ end
36
+
29
37
  private
30
38
 
31
39
  def current_permissions
@@ -1,3 +1,3 @@
1
1
  module Toni
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,135 @@
1
+ require "toni"
2
+ require "toni/in_model"
3
+ require "active_record"
4
+ require "spec_helper"
5
+
6
+ describe Toni::InModel do
7
+ let(:record_class) do
8
+ Class.new(ActiveRecord::Base) do
9
+ def self.table_name
10
+ :test
11
+ end
12
+ def self.authorization_context
13
+ :resource_name
14
+ end
15
+ end
16
+ end
17
+
18
+ let(:record) { record_class.new }
19
+
20
+ before do
21
+ record_class.destroy_all
22
+ allow(Toni).to receive(:current_roles) { [] }
23
+ end
24
+
25
+ context :before_filter do
26
+ it "adds before filter on include" do
27
+ expect(record_class).to receive(:before_destroy)
28
+ expect(record_class).to receive(:before_create)
29
+ expect(record_class).to receive(:before_update)
30
+ expect(record_class).to receive(:after_find)
31
+ record_class.send(:include, Toni::InModel)
32
+ end
33
+
34
+ it "calls permitted_to? if records gets found" do
35
+ record_class.send(:include, Toni::InModel)
36
+ Toni.without_authorization { record.save }
37
+ allow(Toni).to receive(:permitted_to?) { true }
38
+ expect(Toni).to receive(:permitted_to?).with(:read, record_class, bang: true)
39
+ record_class.find(record.id)
40
+ end
41
+
42
+ it "calls permitted_to? if records gets created" do
43
+ record_class.send(:include, Toni::InModel)
44
+ allow(Toni).to receive(:permitted_to?) { true }
45
+ expect(Toni).to receive(:permitted_to?).with(:create, record_class, bang: true)
46
+ record.save
47
+ end
48
+
49
+ it "calls permitted_to? if records gets updated" do
50
+ record_class.send(:include, Toni::InModel)
51
+ allow(Toni).to receive(:permitted_to?) { true }
52
+ record.save
53
+ record.foo = :x
54
+ expect(Toni).to receive(:permitted_to?).with(:update, record_class, bang: true)
55
+ record.save
56
+ end
57
+
58
+ it "calls permitted_to? if records gets destroyes" do
59
+ record_class.send(:include, Toni::InModel)
60
+ allow(Toni).to receive(:permitted_to?) { true }
61
+ record.save
62
+ expect(Toni).to receive(:permitted_to?).with(:delete, record_class, bang: true)
63
+ record.destroy
64
+ end
65
+
66
+ it "does not create record if permitted_to bangs" do
67
+ record_class.send(:include, Toni::InModel)
68
+ allow(Toni).to receive(:permitted_to?) { raise Toni::NotAuthorizedError }
69
+ expect { record.save }.to raise_error(Toni::NotAuthorizedError)
70
+ expect(record_class.count).to eq(0)
71
+ end
72
+
73
+ it "does not update record if permitted_to bangs" do
74
+ record_class.send(:include, Toni::InModel)
75
+ Toni.without_authorization { record.save }
76
+ allow(Toni).to receive(:permitted_to?) { raise Toni::NotAuthorizedError }
77
+ record.foo = :x
78
+ expect { record.save }.to raise_error(Toni::NotAuthorizedError)
79
+ expect(record_class.count).to eq(1)
80
+ allow(Toni).to receive(:permitted_to?) { true }
81
+ expect(record_class.first.foo).to be_nil
82
+ end
83
+
84
+ it "does not destroy record if permitted_to bangs" do
85
+ record_class.send(:include, Toni::InModel)
86
+ Toni.without_authorization { record.save }
87
+ allow(Toni).to receive(:permitted_to?) { raise Toni::NotAuthorizedError }
88
+ expect { record.destroy }.to raise_error(Toni::NotAuthorizedError)
89
+ expect(record_class.count).to eq(1)
90
+ end
91
+ end
92
+
93
+ context :scope do
94
+
95
+ let(:matcher) { RSpec::Matchers::BuiltIn::BeNil.new }
96
+ let(:matcher2) { RSpec::Matchers::BuiltIn::Eq.new("x") }
97
+ let(:matcher3) { RSpec::Matchers::BuiltIn::Eq.new("y") }
98
+ let(:permission) do
99
+ p = Toni::Permission.new(:resource_name, [:read, :create])
100
+ p.add_matcher(:foo, matcher, true)
101
+ p.add_matcher(:bar, matcher2, true)
102
+ p
103
+ end
104
+ let(:permission2) do
105
+ p = Toni::Permission.new(:resource_name, [:read])
106
+ p.add_matcher(:foo, matcher3, true)
107
+ p
108
+ end
109
+
110
+ it "creates a scope" do
111
+ expect(record_class).to receive(:scope).with(:permitted_to, anything)
112
+ record_class.send(:include, Toni::InModel)
113
+ end
114
+
115
+ it "creates a useful scope" do
116
+ record_class.send(:include, Toni::InModel)
117
+ allow(Toni).to receive(:current_permissions_for).with(:read, :resource_name) do
118
+ [permission, permission2]
119
+ end
120
+ expect(record_class.send(:scope_for_filter_permissions)).to eq(["((foo IS NULL) AND (bar = ?)) OR ((foo = ?))", "x", "y"])
121
+ end
122
+
123
+ it "scopes permitted_to" do
124
+ allow(Toni).to receive(:current_permissions_for).with(:read, :resource_name) do
125
+ [permission, permission2]
126
+ end
127
+ record_class.send(:include, Toni::InModel)
128
+ allow(Toni).to receive(:permitted_to?) { true }
129
+ r1 = record_class.create(foo: "x", bar: "y")
130
+ r2 = record_class.create(foo: nil, bar: "x")
131
+ r3 = record_class.create(foo: "y", bar: "something")
132
+ expect(record_class.permitted_to.map(&:id)).to eq([r2.id, r3.id])
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,69 @@
1
+ require "spec_helper"
2
+ require "toni"
3
+ require "ostruct"
4
+
5
+ describe Toni::PermissionFilter do
6
+
7
+ let(:expectation_builder) { Toni::Builder::ExpectationBuilder.new }
8
+ let(:matcher) { expectation_builder.eq("test") }
9
+ let(:permission_matcher) { Toni::PermissionMatcher::Base.new(:foo, matcher, true) }
10
+
11
+ let(:permission_filter) do
12
+ described_class.new(permission_matcher)
13
+ end
14
+
15
+ describe ".permission_filters" do
16
+ it "returns constants of available permission filters" do
17
+ expect(Toni::PermissionFilter.permission_filters).to match_array([
18
+ :Eq, :BeNil, :BeTruthy, :BeFalsey, :BeBetween
19
+ ])
20
+ end
21
+ end
22
+
23
+ describe Toni::PermissionFilter::Eq do
24
+ it "creates condition" do
25
+ expect(permission_filter.filter_condition).to eq(["foo = ?", "test"])
26
+ end
27
+ it "creates opposite condition" do
28
+ expect(permission_filter.filter_condition_inverse).to eq(["foo != ?", "test"])
29
+ end
30
+ end
31
+
32
+ describe Toni::PermissionFilter::BeNil do
33
+ it "creates condition" do
34
+ expect(permission_filter.filter_condition).to eq(["foo IS NULL"])
35
+ end
36
+ it "creates opposite condition" do
37
+ expect(permission_filter.filter_condition_inverse).to eq(["foo IS NOT NULL"])
38
+ end
39
+ end
40
+
41
+ describe Toni::PermissionFilter::BeTruthy do
42
+ it "creates condition" do
43
+ expect(permission_filter.filter_condition).to eq(["foo IS NOT NULL AND foo != ''"])
44
+ end
45
+ it "creates opposite condition" do
46
+ expect(permission_filter.filter_condition_inverse).to eq(["foo = '' OR foo IS NULL"])
47
+ end
48
+ end
49
+
50
+ describe Toni::PermissionFilter::BeFalsey do
51
+ it "creates condition" do
52
+ expect(permission_filter.filter_condition).to eq(["foo = '' OR foo IS NULL"])
53
+ end
54
+ it "creates opposite condition" do
55
+ expect(permission_filter.filter_condition_inverse).to eq(["foo IS NOT NULL AND foo != ''"])
56
+ end
57
+ end
58
+
59
+ describe Toni::PermissionFilter::BeBetween do
60
+ let(:matcher) { expectation_builder.be_between(5, 10) }
61
+ it "creates condition" do
62
+ expect(permission_filter.filter_condition).to eq(["foo >= ? AND foo <= ?", 5, 10])
63
+ end
64
+ it "creates opposite condition" do
65
+ expect(permission_filter.filter_condition_inverse).to eq(["foo < ? OR foo > ?", 5, 10])
66
+ end
67
+ end
68
+
69
+ end
@@ -12,11 +12,11 @@ describe Toni::PermissionMatcher do
12
12
  end
13
13
  end.new
14
14
  end
15
- let(:permission_matcher) { Toni::PermissionMatcher.new(:foo, matcher) }
15
+ let(:permission_matcher) { Toni::PermissionMatcher::Base.new(:foo, matcher) }
16
16
 
17
17
  describe :method_name do
18
18
  it "sets the method_name on initialize" do
19
- expect(Toni::PermissionMatcher.new(:method_name, nil).method_name).to eq(:method_name)
19
+ expect(Toni::PermissionMatcher::Base.new(:method_name, nil).method_name).to eq(:method_name)
20
20
  end
21
21
  end
22
22
 
@@ -32,6 +32,33 @@ describe Toni::PermissionMatcher do
32
32
  end
33
33
  end
34
34
 
35
+ describe :filter_condition do
36
+ let(:expectation_builder) { Toni::Builder::ExpectationBuilder.new }
37
+ let(:matcher2) { expectation_builder.eq("test") }
38
+ let(:permission_matcher) { Toni::PermissionMatcher::Base.new(:foo, matcher2, true) }
39
+
40
+ it "return nil if is_attr is false" do
41
+ permission_matcher = Toni::PermissionMatcher::Base.new(:foo, matcher2, false)
42
+ expect(permission_matcher.filter_condition).to eq(nil)
43
+ end
44
+
45
+ it "gets filter condition from filterable permission matcher if it exist" do
46
+ expect_any_instance_of(Toni::PermissionFilter::Eq).to receive(:filter_condition)
47
+ permission_matcher.filter_condition
48
+ end
49
+
50
+ it "raises error when permission matcher is not available" do
51
+ allow(permission_matcher).to receive(:permission_filter) { nil }
52
+ expect { permission_matcher.filter_condition }.to raise_error(Toni::MissingPermissionFilterError)
53
+ end
54
+
55
+ it "uses filter_condition method of matcher if matcher responds" do
56
+ allow(matcher2).to receive(:respond_to?) { true }
57
+ expect(matcher2).to receive(:filter_condition) { "condition" }
58
+ expect(permission_matcher.filter_condition).to eq("condition")
59
+ end
60
+ end
61
+
35
62
  describe :matches? do
36
63
  let(:object) do
37
64
  Class.new do
@@ -66,14 +93,14 @@ describe Toni::PermissionMatcher do
66
93
 
67
94
  it "returns true if matcher is rspec nil matcher and value is nil" do
68
95
  matcher = RSpec::Matchers::BuiltIn::BeNil.new
69
- permission_matcher = Toni::PermissionMatcher.new(:foo, matcher)
96
+ permission_matcher = Toni::PermissionMatcher::Base.new(:foo, matcher)
70
97
  expect(permission_matcher.matches?(object)).to eq(true)
71
98
  end
72
99
 
73
100
  it "returns false if matcher is rspec nil matcher and value is not nil" do
74
101
  allow(object).to receive(:foo) { "a string" }
75
102
  matcher = RSpec::Matchers::BuiltIn::BeNil.new
76
- permission_matcher = Toni::PermissionMatcher.new(:foo, matcher)
103
+ permission_matcher = Toni::PermissionMatcher::Base.new(:foo, matcher)
77
104
  expect(permission_matcher.matches?(object)).to eq(false)
78
105
  end
79
106
  end
@@ -103,6 +130,20 @@ describe Toni::PermissionMatcher::NotMatcher do
103
130
  end
104
131
  end
105
132
 
133
+ describe :filter_condition do
134
+ it "gets filter condition from child matcher if it responds to filter_condition_inverse" do
135
+ not_matcher.be_truthy
136
+ expect_any_instance_of(Toni::PermissionFilter::BeTruthy).to receive(:filter_condition_inverse)
137
+ not_matcher.filter_condition
138
+ end
139
+
140
+ it "raises error when child matcher does not respond to filter_condition_inverse" do
141
+ not_matcher.be_truthy
142
+ allow_any_instance_of(Toni::PermissionFilter::BeTruthy).to receive(:respond_to?) { false }
143
+ expect { not_matcher.filter_condition }.to raise_error(Toni::MissingPermissionFilterError)
144
+ end
145
+ end
146
+
106
147
  end
107
148
 
108
149
  describe Toni::PermissionMatcher::PermittedToMatcher do
@@ -21,7 +21,22 @@ describe Toni::Permission do
21
21
  describe :add_matcher do
22
22
  it "adds the matcher" do
23
23
  permission.add_matcher(:foo, nil)
24
- expect(permission.matchers.first).to be_instance_of(Toni::PermissionMatcher)
24
+ expect(permission.matchers.first).to be_instance_of(Toni::PermissionMatcher::Base)
25
+ end
26
+ end
27
+
28
+ describe :permission_for? do
29
+ let(:permission) do
30
+ Toni::Permission.new(:resource_name, [:read, :create])
31
+ end
32
+ it "should be allowed to read resource_name" do
33
+ expect(permission.permission_for?(:read, :resource_name)).to eq(true)
34
+ end
35
+ it "should be allowed to delete resource_name" do
36
+ expect(permission.permission_for?(:delete, :resource_name)).to eq(false)
37
+ end
38
+ it "should be allowed to read xxx" do
39
+ expect(permission.permission_for?(:read, :xxx)).to eq(false)
25
40
  end
26
41
  end
27
42
 
@@ -31,16 +46,9 @@ describe Toni::Permission do
31
46
  Toni::Permission.new(:resource_name, [:read, :create])
32
47
  end
33
48
 
34
- context "with resource_name" do
35
- it "should be allowed to read resource_name" do
36
- expect(permission.permitted_to?(:read, :resource_name)).to eq(true)
37
- end
38
- it "should be allowed to delete resource_name" do
39
- expect(permission.permitted_to?(:delete, :resource_name)).to eq(false)
40
- end
41
- it "should be allowed to read xxx" do
42
- expect(permission.permitted_to?(:read, :xxx)).to eq(false)
43
- end
49
+ it "calls permission_for?" do
50
+ expect(permission).to receive(:permission_for?).with(:read, :resource_name) { true }
51
+ expect(permission.permitted_to?(:read, :resource_name)).to eq(true)
44
52
  end
45
53
 
46
54
  context "with matchers" do
@@ -34,6 +34,26 @@ describe Toni::Role do
34
34
  end
35
35
  end
36
36
 
37
+ describe :permissions_for do
38
+
39
+ let(:permission) { Toni::Permission.new(:resource_name, [:read, :create]) }
40
+ let(:permission2) { Toni::Permission.new(:other_resource, [:read, :create]) }
41
+
42
+ let(:role) do
43
+ role = Toni::Role.new(:user)
44
+ role.add_permission(permission)
45
+ role.add_permission(permission2)
46
+ role
47
+ end
48
+
49
+ it "returns all permissions that are belonging to resource and activity" do
50
+ allow(permission).to receive(:permission_for?).with(:read, :resource_name) { true }
51
+ allow(permission2).to receive(:permission_for?).with(:read, :resource_name) { false }
52
+ expect(role.permissions_for(:read, :resource_name)).to eq([permission])
53
+ end
54
+
55
+ end
56
+
37
57
  describe :permitted_to? do
38
58
 
39
59
  let(:permission) do
@@ -56,6 +56,19 @@ describe Toni do
56
56
  end
57
57
  end
58
58
 
59
+ describe ".current_permissions_for" do
60
+ let(:user_role) { Toni::Role.new(:user) }
61
+ let(:seller_role) { Toni::Role.new(:seller) }
62
+ let(:permission1) { Toni::Permission.new(:books, [:read]) }
63
+ let(:permission2) { Toni::Permission.new(:books, [:read]) }
64
+ it "gets the permissions that are assigned to current roles for a specific resource" do
65
+ allow(Toni).to receive(:current_roles) { [user_role, seller_role] }
66
+ expect(user_role).to receive(:permissions_for).with(:read, :books) { [permission1] }
67
+ expect(seller_role).to receive(:permissions_for).with(:read, :books) { [permission2] }
68
+ expect(Toni.current_permissions_for(:read, :books)).to eq([permission1, permission2])
69
+ end
70
+ end
71
+
59
72
  describe ".without_authorization" do
60
73
  it "executes block without authorization and returns result of the given block" do
61
74
  with_authorization = Toni.permitted_to?(:something, :test)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toni
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jalyna
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-10 00:00:00.000000000 Z
11
+ date: 2014-08-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec-expectations
@@ -131,8 +131,14 @@ files:
131
131
  - lib/toni.rb
132
132
  - lib/toni/anonymous_user.rb
133
133
  - lib/toni/builder.rb
134
+ - lib/toni/in_model.rb
134
135
  - lib/toni/permission.rb
136
+ - lib/toni/permission_filter.rb
135
137
  - lib/toni/permission_matcher.rb
138
+ - lib/toni/permission_matcher/base.rb
139
+ - lib/toni/permission_matcher/has_matcher.rb
140
+ - lib/toni/permission_matcher/not_matcher.rb
141
+ - lib/toni/permission_matcher/permitted_to_matcher.rb
136
142
  - lib/toni/role.rb
137
143
  - lib/toni/rspec_helper.rb
138
144
  - lib/toni/sinatra.rb
@@ -140,6 +146,8 @@ files:
140
146
  - spec/spec_helper.rb
141
147
  - spec/toni/anonymous_user_spec.rb
142
148
  - spec/toni/builder_spec.rb
149
+ - spec/toni/in_model_spec.rb
150
+ - spec/toni/permission_filter_spec.rb
143
151
  - spec/toni/permission_matcher_spec.rb
144
152
  - spec/toni/permission_spec.rb
145
153
  - spec/toni/role_spec.rb
@@ -177,6 +185,8 @@ test_files:
177
185
  - spec/spec_helper.rb
178
186
  - spec/toni/anonymous_user_spec.rb
179
187
  - spec/toni/builder_spec.rb
188
+ - spec/toni/in_model_spec.rb
189
+ - spec/toni/permission_filter_spec.rb
180
190
  - spec/toni/permission_matcher_spec.rb
181
191
  - spec/toni/permission_spec.rb
182
192
  - spec/toni/role_spec.rb