isomorfeus-policy 1.0.0.zeta10 → 1.0.0.zeta11

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
  SHA256:
3
- metadata.gz: dde2839e7e6082294bd1ec7a15d223f4e6e4f028ebfcb389770c7d3577d3ca02
4
- data.tar.gz: 22478dbe44ffdf8e4adc64d98eac458ac219d3abe2006db154d81edde18fa8a3
3
+ metadata.gz: 7bedcdf8ad204326ee51b54af14b3d58db6f79b6b41d924dcb983f11591e6a16
4
+ data.tar.gz: b21ce828d2c87062e1ddb532e597a37bbb89f9e2f2ad773db76c0c977ba5d2ae
5
5
  SHA512:
6
- metadata.gz: 671d97f51ceb6fc06f0c3bc9ba1f772edcc0579c1fcc0bb17aeda7b738f8677aa8d113a710332117166615ae0aaa12663c84deb7436e2d9b79ed18d04edba7aa
7
- data.tar.gz: 730493a585556eb655a10caa77e0c609d0a12725b32674e69c07c11fa1b397e8467ba1dcceb804716b3084af3e7f07aebbf45a3a5f2c4f75f09fbc17e40bddbf
6
+ metadata.gz: db1ddf450cfd0c6d2473566f6034f27cc0d9040c0e523f1de8a92f4404303cc9da0132d71fd51397a880da86c1dea07f9a381822b1e960c1d0bba3a60808bc06
7
+ data.tar.gz: 1dccbbb984918beeaac23e607b8c28766f1f8105273c24e2cb0d187d38bcc5b445ec40cc53d10a95c97c111086bbd44fa54674a857a4ea9f7b405540b8e04b6a
data/README.md CHANGED
@@ -14,11 +14,26 @@ Everything that is not explicitly allowed somewhere is denied.
14
14
 
15
15
  Place the policy file in your projects `isomorfeus/policies`.
16
16
 
17
- Example Policy:
17
+ Any class that would like to authorize for accessing a resource needs to include the `LucidAuthorization::Mixin`
18
+ or inherit from `LucidAuthorization::Base`. Example:
19
+
18
20
  ```ruby
19
- class MySimplePolicy < LucidPolicy::Base
21
+ class MyUser
22
+ include LucdiAuthorization::Mixin
23
+ end
24
+ ```
25
+ Any instance of that class then has the following methods available:
26
+ - `authorized?(target_class, method_name, props)` - returning true or false
27
+ - `authorized!(target_class, method_name, props)` - raising a exception if access is denied, otherwise returning true
28
+
29
+ These methods, when called, look for a Policy class. The Policy classs must be named after the user class plus the word 'Policy'.
30
+ Example:
20
31
 
21
- policy_for UserOrRoleClass
32
+ For a class `MyUser` the policy class must be `MyUserPolicy`.
33
+
34
+ Example Policy:
35
+ ```ruby
36
+ class MyUserPolicy < LucidPolicy::Base
22
37
 
23
38
  allow BlaBlaGraph, :load
24
39
 
@@ -30,26 +45,26 @@ Example Policy:
30
45
  # allow all
31
46
  # deny all
32
47
 
33
- with_condition do |user_or_role_instance, target_class, target_method, *props|
34
- role.class == AdminRole
48
+ with_condition do |user_instance, target_class, target_method, *props|
49
+ user_instance.class == AdminRole
35
50
  end
36
51
 
37
- refine BlaGraph, :load, :count do |user_or_role_instance, target_class, target_method, *props|
38
- allow if user_or_role_instance.verified?
52
+ refine BlaGraph, :load, :count do |user_instance, target_class, target_method, *props|
53
+ allow if user_instance.verified?
39
54
  deny
40
55
  end
41
56
  end
42
57
  ```
43
58
  and then any of:
44
59
  ```ruby
45
- user_or_role_instance.authorized?(target_class)
46
- user_or_role_instance.authorized?(target_class, target_method)
47
- user_or_role_instance.authorized?(target_class, target_method, *props)
60
+ user.authorized?(target_class)
61
+ user.authorized?(target_class, target_method)
62
+ user.authorized?(target_class, target_method, *props)
48
63
  ```
49
64
  or:
50
65
  ```ruby
51
- user_or_role_instance.authorized!(target_class)
52
- user_or_role_instance.authorized!(target_class, target_method)
53
- user_or_role_instance.authorized!(target_class, target_method, *props)
66
+ user.authorized!(target_class)
67
+ user.authorized!(target_class, target_method)
68
+ user.authorized!(target_class, target_method, *props)
54
69
  ```
55
70
  which will raise a LucidPolicy::Exception unless authorized
@@ -4,13 +4,20 @@ module Isomorfeus
4
4
  @cached_array_classes ||= {}
5
5
  end
6
6
 
7
- def cached_policy_class(class_name)
8
- return "::#{class_name}".constantize if Isomorfeus.development?
9
- return cached_policy_classes[class_name] if cached_policy_classes.key?(class_name)
10
- cached_policy_classes[class_name] = "::#{class_name}".constantize
11
- end
7
+ if RUBY_ENGINE == 'opal'
8
+ def cached_policy_class(class_name)
9
+ return "::#{class_name}".constantize if Isomorfeus.development?
10
+ return cached_policy_classes[class_name] if cached_policy_classes.key?(class_name)
11
+ cached_policy_classes[class_name] = "::#{class_name}".constantize
12
+ end
13
+ else
14
+ def cached_policy_class(class_name)
15
+ return nil unless valid_policy_class_name?(class_name)
16
+ return "::#{class_name}".constantize if Isomorfeus.development?
17
+ return cached_policy_classes[class_name] if cached_policy_classes.key?(class_name)
18
+ cached_policy_classes[class_name] = "::#{class_name}".constantize
19
+ end
12
20
 
13
- if RUBY_ENGINE != 'opal'
14
21
  def valid_policy_class_names
15
22
  @valid_policy_class_names ||= Set.new
16
23
  end
@@ -1,5 +1,5 @@
1
1
  module Isomorfeus
2
2
  module Policy
3
- VERSION = '1.0.0.zeta10'
3
+ VERSION = '1.0.0.zeta11'
4
4
  end
5
5
  end
@@ -1,17 +1,20 @@
1
1
  require 'isomorfeus-react'
2
2
  require 'isomorfeus/policy/config'
3
- require 'lucid_policy/exception'
4
- require 'isomorfeus/policy/helper'
5
- require 'lucid_policy/mixin'
6
- require 'lucid_policy/base'
7
- require 'anonymous'
8
- require 'isomorfeus/policy/anonymous_policy'
9
3
 
10
4
  if RUBY_ENGINE == 'opal'
5
+ Isomorfeus.zeitwerk.push_dir('isomorfeus_policy')
6
+ require_tree 'isomorfeus_policy', :autoload
11
7
  Isomorfeus.zeitwerk.push_dir('policies')
12
8
  else
13
- Opal.append_path(__dir__.untaint) unless Opal.paths.include?(__dir__.untaint)
9
+ require 'isomorfeus_policy/lucid_policy/exception'
10
+ require 'isomorfeus_policy/lucid_policy/helper'
11
+ require 'isomorfeus_policy/lucid_policy/mixin'
12
+ require 'isomorfeus_policy/lucid_policy/base'
13
+ require 'isomorfeus_policy/lucid_authorization/mixin'
14
+ require 'isomorfeus_policy/lucid_authorization/base'
15
+ require 'isomorfeus_policy/anonymous'
14
16
 
17
+ Opal.append_path(__dir__.untaint) unless Opal.paths.include?(__dir__.untaint)
15
18
  path = File.expand_path(File.join('isomorfeus', 'policies'))
16
19
  Isomorfeus.zeitwerk.push_dir(path)
17
20
  end
@@ -0,0 +1,7 @@
1
+ class Anonymous
2
+ include LucidAuthorization::Mixin
3
+
4
+ def key
5
+ 'anonymous'
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module LucidAuthorization
2
+ class Base
3
+ include LucidAuthorization::Mixin
4
+ end
5
+ end
@@ -0,0 +1,23 @@
1
+ module LucidAuthorization
2
+ module Mixin
3
+ def authorized?(target_class, target_method = nil, *props)
4
+ begin
5
+ class_name = self.class.name
6
+ class_name = class_name.split('>::').last if class_name.start_with?('#<')
7
+ policy_class = Isomorfeus.cached_policy_class("#{class_name}Policy")
8
+ rescue ::NameError
9
+ policy_class = nil
10
+ end
11
+ return false unless policy_class
12
+ policy_class.new(self).authorized?(target_class, target_method, *props)
13
+ end
14
+
15
+ def authorized!(target_class, target_method = nil, *props)
16
+ class_name = self.class.name
17
+ class_name = class_name.split('>::').last if class_name.start_with?('#<')
18
+ policy_class = Isomorfeus.cached_policy_class("#{class_name}Policy")
19
+ raise LucidPolicy::Exception, "#{self}: policy class #{class_name}Policy not found!" unless policy_class
20
+ policy_class.new(self).authorized!(target_class, target_method, *props)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ module LucidPolicy
2
+ class Base
3
+ include LucidPolicy::Mixin
4
+
5
+ if RUBY_ENGINE != 'opal'
6
+ def self.inherited(base)
7
+ Isomorfeus.add_valid_policy_class(base)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module LucidPolicy
2
+ class Helper < BasicObject
3
+ attr_reader :result
4
+
5
+ def initialize
6
+ @result= nil
7
+ end
8
+
9
+ def allow
10
+ @result = :allow if @result.nil?
11
+ nil
12
+ end
13
+
14
+ def deny
15
+ @result = :deny if @result.nil?
16
+ nil
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,128 @@
1
+ module LucidPolicy
2
+ module Mixin
3
+ def self.included(base)
4
+ base.instance_exec do
5
+ if RUBY_ENGINE != 'opal'
6
+ Isomorfeus.add_valid_policy_class(base) unless base == LucidPolicy::Base
7
+ end
8
+
9
+ def authorization_rules
10
+ @authorization_rules ||= { classes: {}, conditions: [], others: :deny }
11
+ end
12
+
13
+ def all
14
+ :others
15
+ end
16
+
17
+ def allow(*classes_and_methods)
18
+ _raise_allow_deny_first if @refine_used
19
+ @allow_deny_used = true
20
+ _allow_or_deny(:allow, *classes_and_methods)
21
+ end
22
+
23
+ def deny(*classes_and_methods)
24
+ _raise_allow_deny_first if @refine_used
25
+ @allow_deny_used = true
26
+ _allow_or_deny(:deny, *classes_and_methods)
27
+ end
28
+
29
+ def others
30
+ :others
31
+ end
32
+
33
+ def refine(*classes_and_methods, &block)
34
+ _raise_allow_deny_first unless @allow_deny_used
35
+ @refine_used = true
36
+ _allow_or_deny(nil, *classes_and_methods, &block)
37
+ end
38
+
39
+ def with_condition(&block)
40
+ authorization_rules[:conditions] << block
41
+ end
42
+
43
+ private
44
+
45
+ def _raise_allow_deny_first
46
+ raise LucidPolicy::Exception, "#{self}: 'allow' or 'deny' must appear before 'refine'"
47
+ end
48
+
49
+ def _allow_or_deny(allow_or_deny, *classes_and_methods, &block)
50
+ rules = authorization_rules
51
+ allow_or_deny_or_block = block_given? ? block : allow_or_deny.to_sym
52
+
53
+ target_classes = []
54
+ target_methods = []
55
+
56
+ if classes_and_methods.first == :others
57
+ rules[:others] = allow_or_deny_or_block
58
+ return
59
+ end
60
+
61
+ classes_and_methods.each do |class_or_method|
62
+ if (class_or_method.class == String || class_or_method.class == Symbol) && class_or_method.to_s[0].downcase == class_or_method.to_s[0]
63
+ target_methods << class_or_method.to_sym
64
+ else
65
+ target_classes << class_or_method
66
+ end
67
+ end
68
+
69
+ target_classes.each do |target_class|
70
+ rules[:classes][target_class] = {} unless rules[:classes].key?(target_class)
71
+ if allow_or_deny && target_methods.empty?
72
+ rules[:classes][target_class][:default] = allow_or_deny_or_block
73
+ else
74
+ rules[:classes][target_class][:default] = :deny unless rules[:classes][target_class].key?(:default)
75
+ rules[:classes][target_class][:methods] = {} unless rules[:classes][target_class].key?(:methods)
76
+ target_methods.each do |target_method|
77
+ rules[:classes][target_class][:methods][target_method] = allow_or_deny_or_block
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ def initialize(object)
85
+ @object = object
86
+ end
87
+
88
+ def authorized?(target_class, target_method = nil, *props)
89
+ raise LucidPolicy::Exception, "#{self}: At least the class must be given!" unless target_class
90
+ result = :deny
91
+
92
+ rules = self.class.authorization_rules
93
+
94
+ condition_result = true
95
+ rules[:conditions].each do |condition|
96
+ condition_result = condition.call(@object, target_class, target_method, *props, &condition)
97
+ break unless condition_result == true
98
+ end
99
+
100
+ if condition_result == true
101
+ result = if rules[:classes].key?(target_class)
102
+ if target_method && rules[:classes][target_class].key?(:methods) &&
103
+ rules[:classes][target_class][:methods].key?(target_method)
104
+ rules[:classes][target_class][:methods][target_method]
105
+ else
106
+ rules[:classes][target_class][:default]
107
+ end
108
+ else
109
+ rules[:others]
110
+ end
111
+
112
+ if result.class == Proc
113
+ policy_helper = LucidPolicy::Helper.new
114
+ policy_helper.instance_exec(@object, target_class, target_method, *props, &result)
115
+ result = policy_helper.result
116
+ end
117
+ end
118
+
119
+ result == :allow ? true : false
120
+ end
121
+
122
+ def authorized!(target_class, target_method = nil, *props)
123
+ return true if authorized?(target_class, target_method, *props)
124
+ raise LucidPolicy::Exception, "#{@object}: not authorized to call #{target_class}.#{target_method}(#{props})!"
125
+ end
126
+ end
127
+ end
128
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: isomorfeus-policy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.zeta10
4
+ version: 1.0.0.zeta11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Biedermann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-19 00:00:00.000000000 Z
11
+ date: 2019-12-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: opal
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 16.12.4
33
+ version: 16.12.6
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 16.12.4
40
+ version: 16.12.6
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: isomorfeus-redux
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -58,28 +58,28 @@ dependencies:
58
58
  requirements:
59
59
  - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: 1.0.0.zeta10
61
+ version: 1.0.0.zeta11
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - '='
67
67
  - !ruby/object:Gem::Version
68
- version: 1.0.0.zeta10
68
+ version: 1.0.0.zeta11
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: opal-webpack-loader
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: 0.9.9
75
+ version: 0.9.10
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: 0.9.9
82
+ version: 0.9.10
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rake
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -116,15 +116,16 @@ extra_rdoc_files: []
116
116
  files:
117
117
  - LICENSE
118
118
  - README.md
119
- - lib/anonymous.rb
120
119
  - lib/isomorfeus-policy.rb
121
- - lib/isomorfeus/policy/anonymous_policy.rb
122
120
  - lib/isomorfeus/policy/config.rb
123
- - lib/isomorfeus/policy/helper.rb
124
121
  - lib/isomorfeus/policy/version.rb
125
- - lib/lucid_policy/base.rb
126
- - lib/lucid_policy/exception.rb
127
- - lib/lucid_policy/mixin.rb
122
+ - lib/isomorfeus_policy/anonymous.rb
123
+ - lib/isomorfeus_policy/lucid_authorization/base.rb
124
+ - lib/isomorfeus_policy/lucid_authorization/mixin.rb
125
+ - lib/isomorfeus_policy/lucid_policy/base.rb
126
+ - lib/isomorfeus_policy/lucid_policy/exception.rb
127
+ - lib/isomorfeus_policy/lucid_policy/helper.rb
128
+ - lib/isomorfeus_policy/lucid_policy/mixin.rb
128
129
  homepage: http://isomorfeus.com
129
130
  licenses:
130
131
  - MIT
data/lib/anonymous.rb DELETED
@@ -1,6 +0,0 @@
1
- class Anonymous
2
- # policy methods get added by Isomorfeus::Transport::AnonymousPolicy
3
- def id
4
- 'anonymous'
5
- end
6
- end
@@ -1,8 +0,0 @@
1
- module Isomorfeus
2
- module Policy
3
- class AnonymousPolicy < LucidPolicy::Base
4
- policy_for Anonymous
5
- deny all
6
- end
7
- end
8
- end
@@ -1,21 +0,0 @@
1
- module Isomorfeus
2
- module Policy
3
- class Helper < BasicObject
4
- attr_reader :result
5
-
6
- def initialize
7
- @result= nil
8
- end
9
-
10
- def allow
11
- @result = :allow if @result.nil?
12
- nil
13
- end
14
-
15
- def deny
16
- @result = :deny if @result.nil?
17
- nil
18
- end
19
- end
20
- end
21
- end
@@ -1,5 +0,0 @@
1
- module LucidPolicy
2
- class Base
3
- include LucidPolicy::Mixin
4
- end
5
- end
@@ -1,135 +0,0 @@
1
- module LucidPolicy
2
- module Mixin
3
- def self.included(base)
4
- base.instance_exec do
5
- def policy_for(a_class)
6
- raise LucidPolicy::Exception, "policy_for #{a_class} can only be used once within #{self}!" if @the_class
7
- @the_class = a_class
8
- unless a_class.methods.include?(:authorization_rules)
9
- a_class.define_singleton_method(:authorization_rules) do
10
- @authorization_rules ||= {}
11
- end
12
- end
13
- unless a_class.method_defined?(:authorized?)
14
- a_class.define_method(:authorized?) do |*class_method_props|
15
- target_class = class_method_props[0]
16
- raise "At least the class must be given!" unless target_class
17
- target_method = class_method_props[1]
18
- props = class_method_props[2..-1]
19
-
20
- result = :deny
21
- self.class.authorization_rules.each_value do |rules|
22
- condition_result = true
23
- rules[:conditions].each do |condition|
24
- condition_result = condition.call(self, target_class, target_method, *props, &condition)
25
- break unless condition_result == true
26
- end
27
-
28
- if condition_result == true
29
- result = if rules[:classes].key?(target_class)
30
- if target_method && rules[:classes][target_class].key?(:methods) &&
31
- rules[:classes][target_class][:methods].key?(target_method)
32
- rules[:classes][target_class][:methods][target_method]
33
- else
34
- rules[:classes][target_class][:default]
35
- end
36
- else
37
- rules[:others]
38
- end
39
-
40
- if result.class == Proc
41
- policy_helper = Isomorfeus::Policy::Helper.new
42
- policy_helper.instance_exec(self, target_class, target_method, *props, &result)
43
- result = policy_helper.result
44
- end
45
- end
46
- break if result == :allow
47
- end
48
- result == :allow ? true : false
49
- end
50
- end
51
- unless a_class.method_defined?(:authorized!)
52
- a_class.define_method(:authorized!) do |*class_method_props|
53
- return true if authorized?(*class_method_props)
54
- raise LucidPolicy::Exception, "#{self} not authorized to call #{class_method_props}"
55
- end
56
- end
57
- @the_class.authorization_rules[self.to_s] = { classes: {}, conditions: [], others: :deny }
58
- end
59
-
60
- def all
61
- :others
62
- end
63
-
64
- def allow(*classes_and_methods)
65
- _raise_allow_deny_first if @refine_used
66
- _allow_or_deny(:allow, *classes_and_methods)
67
- end
68
-
69
- def deny(*classes_and_methods)
70
- _raise_allow_deny_first if @refine_used
71
- _allow_or_deny(:deny, *classes_and_methods)
72
- end
73
-
74
- def others
75
- :others
76
- end
77
-
78
- def refine(*classes_and_methods, &block)
79
- @refine_used = true
80
- _allow_or_deny(nil, *classes_and_methods, &block)
81
- end
82
-
83
- def with_condition(&block)
84
- _raise_policy_first unless @the_class
85
- @the_class.authorization_rules[self.to_s][:conditions] << block
86
- end
87
-
88
- private
89
-
90
- def _raise_policy_first
91
- raise LucidPolicy::Exception, "'allow' or 'deny' must appear before 'refine'"
92
- end
93
-
94
- def _raise_policy_first
95
- raise LucidPolicy::Exception, "policy_for Class must be specified first"
96
- end
97
-
98
- def _allow_or_deny(allow_or_deny, *classes_and_methods, &block)
99
- _raise_policy_first unless @the_class
100
- rule_hash = @the_class.authorization_rules[self.to_s]
101
- allow_or_deny_or_block = block_given? ? block : allow_or_deny.to_sym
102
-
103
- target_classes = []
104
- target_methods = []
105
-
106
- if classes_and_methods.first == :others
107
- rule_hash[:others] = allow_or_deny_or_block
108
- return
109
- end
110
-
111
- classes_and_methods.each do |class_or_method|
112
- if (class_or_method.class == String || class_or_method.class == Symbol) && class_or_method.to_s[0].downcase == class_or_method.to_s[0]
113
- target_methods << class_or_method.to_sym
114
- else
115
- target_classes << class_or_method
116
- end
117
- end
118
-
119
- target_classes.each do |target_class|
120
- rule_hash[:classes][target_class] = {} unless rule_hash[:classes].key?(target_class)
121
- if allow_or_deny && target_methods.empty?
122
- rule_hash[:classes][target_class][:default] = allow_or_deny_or_block
123
- else
124
- rule_hash[:classes][target_class][:default] = :deny unless rule_hash[:classes][target_class].key?(:default)
125
- rule_hash[:classes][target_class][:methods] = {} unless rule_hash[:classes][target_class].key?(:methods)
126
- target_methods.each do |target_method|
127
- rule_hash[:classes][target_class][:methods][target_method] = allow_or_deny_or_block
128
- end
129
- end
130
- end
131
- end
132
- end
133
- end
134
- end
135
- end