permission_policy 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d197b0a408448eb634f15c4229434f643229daca
4
- data.tar.gz: a3861829e10f0738d884080167e91f76cb802736
3
+ metadata.gz: cf58d8db5cb145457f2477e95784d7083d1ae3a9
4
+ data.tar.gz: 6186f34bf9b8171db1b061123e37d78c975c25b2
5
5
  SHA512:
6
- metadata.gz: aa90267b5878dbdad8f3140a0ac8f5e08a2db1e8aa06e8d6e742eb36d07491a4fc91989d23a7b6844e7bf9fb42f73a4019ba1e620c105fff55624bb69405ca88
7
- data.tar.gz: 12974cc8b86fabea2530d79872816bcd1bc94810d9fcbc1270f2fe193921b0b7f92ba93d6bae8938cd2b126b3befa36cc8b0468769522c062402169c774a6cd7
6
+ metadata.gz: a01d8c7b01188ab26ad30d5ee23ea8e7c7f4c25c71f88a2bd5310849d09c6a3c2da8f30b12d091cd6fd0ca62f0133c435ad019c30dc58df931314ae339f481fe
7
+ data.tar.gz: 14fdc5e33244dd581c6f48cf940b24e1bec4f1297e526246c7a81457570c1b2b5625098256d3d2c58d76b24ee8b9ad0810313485f5921beb0debaff7d8d59f9d
data/CHANGELOG.md CHANGED
@@ -1,4 +1,8 @@
1
1
 
2
+ # 0.1.0
3
+
4
+ * [REFACTORING] change the way *configuration* is handled (breaking changes)
5
+
2
6
  # 0.0.6
3
7
 
4
8
  * [ENHANCEMENT] moar convenience with `skip_verify_authorization`
data/README.md CHANGED
@@ -6,6 +6,21 @@
6
6
  * dependencies
7
7
 
8
8
 
9
+ ## Authorization is hard
10
+
11
+ There are plenty of diferent solutions to this problem.
12
+ Because the requirements can be very difficult and as the system grows the problems become even worse. Exspecially when you need to support change.
13
+ The hardest part may be thight coupling and issues with encapsulation through the whole application.
14
+ To avoid repetitive and grwoing if/else branches you want a single responsible system.
15
+
16
+ In general, the permission policy defines and controls whether a current **object** (usually the user) can perform a specific **action** on a given **subject**. This decision is commonly based on one or more
17
+ factors:
18
+
19
+ * role
20
+ * type (or a set of attributes)
21
+ * enabled features / areas of the application
22
+
23
+
9
24
  ## Installation
10
25
 
11
26
  Add this line to your application's Gemfile:
@@ -122,6 +137,13 @@ You can extend the permission policy by:
122
137
  - implement new permission strategies, which help the policy to find the 'decider'
123
138
 
124
139
 
140
+ ## possible ideas/improvements:
141
+
142
+ - support skip_verify_authorization only:/except: [:actions]
143
+ - register features and roles in the policy
144
+ - raise NoSuchFeature
145
+ - get available "permissions" for role/subject/feature
146
+
125
147
  ## Contributing
126
148
 
127
149
  1. Fork it ( https://github.com/[my-github-username]/permission_policy/fork )
@@ -4,8 +4,9 @@ module PermissionPolicy
4
4
 
5
5
  def initialize(context)
6
6
  @preconditions = []
7
+ @context = context
7
8
 
8
- PermissionPolicy.preconditions.each do |precondition|
9
+ context.authorization_preconditions.each do |precondition|
9
10
  set! precondition, context.public_send(precondition)
10
11
  @preconditions << precondition
11
12
  end
@@ -40,7 +41,9 @@ module PermissionPolicy
40
41
 
41
42
  # Finds the matching strategy which can decide if the action is allowed by lazy checking
42
43
  def strategy_for(*args)
43
- PermissionPolicy.strategies.lazy.map { |klass| Strategies.const_get(klass).new(self, *args) }.find(&:match?)
44
+ @context.authorization_strategies.lazy.map do |klass|
45
+ Strategies.const_get(klass).new(self, *args)
46
+ end.find(&:match?)
44
47
  end
45
48
 
46
49
  def set!(var, value)
@@ -1,38 +1,4 @@
1
1
  module PermissionPolicy
2
- class Configuration < OpenStruct
3
- def preconditions
4
- precondition_attributes || [:current_user]
5
- end
6
-
7
- def strategies
8
- strategy_order || [:UnknownStrategy]
9
- end
10
-
11
- def verification
12
- verify_authorization || false
13
- end
14
- end
15
-
16
- class << self
17
- attr_accessor :configuration
18
-
19
- extend Forwardable
20
- delegate [:preconditions, :strategies, :verification] => :config
21
-
22
- def configure
23
- yield(config)
24
- end
25
-
26
- def config
27
- self.configuration ||= Configuration.new
28
- end
29
-
30
- def authorize_with(*args)
31
- configure { |c| c.precondition_attributes = *args }
32
- end
33
-
34
- def verify_authorization!(setting)
35
- configure { |c| c.verify_authorization = setting }
36
- end
2
+ class Configuration
37
3
  end
38
4
  end
@@ -3,16 +3,20 @@ require 'active_support/concern'
3
3
  module PermissionPolicy
4
4
  module ControllerAdditions
5
5
  module ClassMethods
6
- def authorize_with(*args)
7
- PermissionPolicy.authorize_with(*args)
6
+ def authorize_with(*preconditions)
7
+ define_method('authorization_preconditions') { preconditions }
8
8
  end
9
9
 
10
10
  def verify_authorization!
11
- PermissionPolicy.verify_authorization!(true)
11
+ define_method('authorization_verification?') { true }
12
12
  end
13
13
 
14
14
  def skip_verify_authorization
15
- PermissionPolicy.verify_authorization!(false)
15
+ define_method('authorization_verification?') { false }
16
+ end
17
+
18
+ def authorization_strategies(*strategies)
19
+ define_method('authorization_strategies') { strategies }
16
20
  end
17
21
  end
18
22
 
@@ -23,7 +27,7 @@ module PermissionPolicy
23
27
  helper_method :allowed?
24
28
  delegate :allowed?, to: :permission_policy
25
29
  delegate :authorize!, to: :permission_policy
26
- after_action -> { verify_authorization if PermissionPolicy.verification }
30
+ after_action -> { verify_authorization if authorization_verification? }
27
31
  end
28
32
 
29
33
  def permission_policy
@@ -1,3 +1,3 @@
1
1
  module PermissionPolicy
2
- VERSION = '0.0.6'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -1,13 +1,9 @@
1
1
  module PermissionPolicy
2
2
  RSpec.describe 'Authorization' do
3
- before do
4
- PermissionPolicy.authorize_with :my_user, :my_account
5
- end
6
-
7
- subject { PermissionPolicy::Authorization.new(context) }
3
+ subject { PermissionPolicy::Authorization.new(controller_context) }
8
4
 
9
5
  context 'valid' do
10
- let(:context) { double('context', my_user: 'foo', my_account: 'bar') }
6
+ let(:controller_context) { double('context', authorization_preconditions: [:my_user, :my_account], my_user: 'foo', my_account: 'bar') }
11
7
 
12
8
  it 'sets attribute readers for each precondition' do
13
9
  expect(subject.my_user).to eq('foo')
@@ -20,7 +16,7 @@ module PermissionPolicy
20
16
  end
21
17
 
22
18
  context 'invalid' do
23
- let(:context) { double('context', my_user: nil, my_account: nil) }
19
+ let(:controller_context) { double('context', authorization_preconditions: [:my_user, :my_account], my_user: nil, my_account: nil) }
24
20
 
25
21
  it 'raises missing precondition error' do
26
22
  expect { subject }.to raise_error('missing precondition: my_user')
@@ -1,13 +1,4 @@
1
1
  module PermissionPolicy
2
2
  RSpec.describe Configuration do
3
- before { PermissionPolicy.configuration = nil }
4
-
5
- it 'has a default precondition' do
6
- expect(subject.preconditions).to eq([:current_user])
7
- end
8
-
9
- it 'has a default strategy' do
10
- expect(subject.strategies).to eq([:UnknownStrategy])
11
- end
12
3
  end
13
4
  end
@@ -6,38 +6,118 @@ class MetalTestController < ActionController::Metal
6
6
  include PermissionPolicy::ControllerAdditions::InstanceMethods
7
7
  extend PermissionPolicy::ControllerAdditions::ClassMethods
8
8
 
9
+ authorize_with :foo, :bar
10
+ verify_authorization!
11
+ authorization_strategies :TestStrategy, :UnknownStrategy
12
+
9
13
  def foo
14
+ 'foo'
10
15
  end
11
16
 
12
17
  def bar
18
+ 'bar'
19
+ end
20
+
21
+ def baz
22
+ 'baz'
23
+ end
24
+ end
25
+
26
+ class TestController < MetalTestController
27
+ def not_authorized_action
28
+ 'you will never see me'
29
+ end
30
+
31
+ def not_allowed_action
32
+ authorize! :something
33
+ 'you also wont see me, but get a different error'
34
+ end
35
+
36
+ def allowed_action
37
+ authorize! :view, subject: 'some_subject'
38
+ 'ok go ahead'
39
+ end
40
+ end
41
+
42
+ class TestStrategy < PermissionPolicy::Strategies::BaseStrategy
43
+ def match?
44
+ options[:subject] == 'some_subject'
45
+ end
46
+
47
+ def allowed?
48
+ { view: true, manage: false }[action]
49
+ end
50
+ end
51
+
52
+ class SkipTestController < MetalTestController
53
+ authorize_with :baz
54
+ skip_verify_authorization
55
+
56
+ def skipped_authorization
57
+ 'ohai'
13
58
  end
14
59
  end
15
60
 
16
61
 
17
62
  module PermissionPolicy
18
63
  RSpec.describe 'ControllerAdditions' do
19
- subject { MetalTestController.new }
20
64
 
21
- context 'authorization' do
22
- before do
23
- MetalTestController.authorize_with :foo, :bar
24
- is_expected.to receive(:foo) { 'foo' }
25
- is_expected.to receive(:bar) { 'bar' }
65
+ context 'instance_methods' do
66
+ subject { MetalTestController.new }
67
+
68
+ describe 'authorization' do
69
+ it 'is available through #permission_policy' do
70
+ expect(subject.permission_policy).to be_kind_of(PermissionPolicy::Authorization)
71
+ end
72
+
73
+ it 'is initialized with precondition foo' do
74
+ expect(subject.permission_policy.foo).to eq('foo')
75
+ end
76
+
77
+ it 'is initialized with precondition bar' do
78
+ expect(subject.permission_policy.bar).to eq('bar')
79
+ end
26
80
  end
27
81
 
28
- it 'is available throuth #permission_policy' do
29
- expect(subject.permission_policy).to be_kind_of(PermissionPolicy::Authorization)
82
+ describe 'helpers' do
83
+ it { is_expected.to respond_to :authorize! }
84
+ it { is_expected.to respond_to :allowed? }
30
85
  end
86
+ end
87
+
88
+ context 'class_methods' do
89
+ subject { TestController.new }
90
+
91
+ describe '#verify_authorization!' do
92
+ context 'no call to #authorize!' do
93
+ it 'is not verified' do
94
+ expect { subject.process_action :not_authorized_action }.to raise_error PermissionPolicy::NotVerified
95
+ end
96
+ end
97
+
98
+ context 'with #authorize! but not allowed' do
99
+ it 'is still not allowed' do
100
+ expect { subject.process_action :not_allowed_action }.to raise_error PermissionPolicy::NotAllowed
101
+ end
102
+ end
31
103
 
32
- it 'is initialized with preconditions' do
33
- expect(subject.permission_policy.foo).to eq('foo')
34
- expect(subject.permission_policy.bar).to eq('bar')
104
+ context '#authorized! and allowed' do
105
+ it 'is allowed' do
106
+ expect(subject.process_action :allowed_action).to eq('ok go ahead')
107
+ end
108
+ end
35
109
  end
36
110
  end
37
111
 
38
- context 'helpers' do
39
- it { is_expected.to respond_to :authorize! }
40
- it { is_expected.to respond_to :allowed? }
112
+ describe '#skip_verify_authorization' do
113
+ subject { SkipTestController.new }
114
+
115
+ context 'with :only option' do
116
+ it 'skips this action' do
117
+ expect(subject.process_action :skipped_authorization).to eq('ohai')
118
+ end
119
+ end
41
120
  end
121
+
42
122
  end
43
123
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: permission_policy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marco Schaden
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-01-30 00:00:00.000000000 Z
12
+ date: 2015-02-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport