zero_authorization 1.0.0 → 1.4.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: c71ff5e0e8ab8e104e78ba8c1c3c86528a552a5c
4
- data.tar.gz: 9d960e3adbe023f1bbcf1321642cbc2a5d1a54aa
3
+ metadata.gz: e1890303102d3d41dea0c99df76d07cc731bfc1c
4
+ data.tar.gz: 337d2c4103dc0a5c099c642394296b9b86ae5c70
5
5
  SHA512:
6
- metadata.gz: 6b88ea53e319c66c3d04c116563df6af81375217d4934f135668fca7839dccba1467fb9450c6177e5e52fd969f752ac8cf6fb0c79a0fc6bba82f7af4643b0aad
7
- data.tar.gz: a8d2a23fab3871be610f7296c2b3fae38a6e027d6c63caf667d4bfbfe957aa73b77371c76e5c7421aab4734f853603fd264c643262196a6b825cbe09d61ae9a3
6
+ metadata.gz: 6adf012cb827cb91b5da8e96d52e375d2c8b14b1ebaf7ec8ba77c39ca1dd66d14c0b6fd45f596b9df0ef4cb61a668b0ace078b22f0e6799e6519c5575f49af86
7
+ data.tar.gz: a1463d0d766c3597b6e7724a37926c048c069eea052bd680a35927582ffc66939f8436c39df2d65fbf30ecd53a0952ef33e1e20d7f592873cfda9dcfa3d605c5
data/README.md CHANGED
@@ -22,40 +22,37 @@ Or install it yourself as:
22
22
 
23
23
  :role_role_name_one:
24
24
  :can_do:
25
- :Account:
26
- - :create
27
- - :save
28
- - :update
25
+ :account:
26
+ - create
27
+ - save
28
+ - update
29
29
  :User:
30
- - :create
31
- - :save
32
- - :update
33
- :ModelCrudHistory: :anything
30
+ - :create
31
+ - :save
32
+ - :update
33
+ :model_crud_history: :nothing
34
34
  :Permission: :anything
35
35
  :cant_do:
36
36
  :Project:
37
37
  - :destroy
38
+ :model_crud_history: :anything
38
39
  :role_role_name_two:
39
40
  :can_do:
40
41
  :Project:
41
- - :create
42
- - :save:
43
- :if:
44
- :authorize?
45
- - :update:
46
- :if:
47
- :authorize?
48
- - :destroy:
49
- :if:
50
- :authorize?
42
+ - create
43
+ - save: is_authorized?
44
+ - :update: is_authorized?
45
+ - :destroy: is_authorized?
46
+ :user:
47
+ create: :create_authorized?
48
+ save: :update_authorized?
49
+ update: :update_authorized?
51
50
  :role_role_name_three:
52
51
  :can_do:
53
- :Plant:
54
- - :create
55
- - :save
56
- - :update
57
- - :destroy
58
- :cant_do: :anything
52
+ - :Project
53
+ - :Organization
54
+ :cant_do:
55
+ - :User
59
56
 
60
57
  2. Restrict models for activity and let rule-set(s) via zero-authorization take control of activity
61
58
 
@@ -75,6 +72,18 @@ Or install it yourself as:
75
72
 
76
73
  4. (Re-)boot application.
77
74
 
75
+ ## Rules for rule-sets execution (Precedence: from top to bottom)
76
+
77
+ 1. Rule 00: If no rule-sets are available for 'can do' and 'cant do' then is authorized true '(with warning message)'.
78
+ 2. Rule 01: If role can't do 'anything' or can do 'nothing' then is authorized false.
79
+ 3. Rule 02: If role can't do 'nothing' or can do 'anything' then is authorized true.
80
+ 4. Rule 03: If role can't do 'specified' method and given 'evaluate' method returns true then is authorized false.
81
+ 5. Rule 04: If role can't do 'specified' method and given 'evaluate' method returns false then is authorized true.
82
+ 6. Rule 05: If role can do 'specified' method and given 'evaluate' method returns true then is authorized true.
83
+ 7. Rule 06: If role can do 'specified' method and given 'evaluate' method returns false then is authorized false.
84
+ 8. Rule 07: If role can't do 'specified' method then is authorized false.
85
+ 9. Rule 08: If role can do 'specified' method then is authorized true.
86
+
78
87
  ## Contributing
79
88
 
80
89
  1. Fork it
@@ -26,13 +26,12 @@ module ZeroAuthorization
26
26
  # Authorization for authorization mode :strict
27
27
  def authorize_strictly(action)
28
28
  role = ZeroAuthorization::Role.role
29
- raise 'ZeroAuthorizationRoleNotAvailable' if role.nil?
29
+ raise ZeroAuthorization::Exceptions::RoleNotAvailable, 'Executing authorize_strictly but role not available' if role.nil?
30
30
 
31
31
  if zero_authorized_core(role, action)
32
32
  return true
33
33
  else
34
- logger.debug 'ZeroAuthorization: Not authorized to perform activity.'
35
- raise 'NotAuthorized'
34
+ raise ZeroAuthorization::Exceptions::NotAuthorized.new(role), "Not authorized to execute #{action} on #{self.class.name}."
36
35
  end
37
36
 
38
37
  false
@@ -41,7 +40,7 @@ module ZeroAuthorization
41
40
  # Authorization for authorization mode :warning
42
41
  def authorize_with_warning(action)
43
42
  role = ZeroAuthorization::Role.role
44
- raise 'ZeroAuthorizationRoleNotAvailable' if role.nil?
43
+ raise ZeroAuthorization::Exceptions::RoleNotAvailable, 'Executing authorize_with_warning but role not available' if role.nil?
45
44
 
46
45
  if zero_authorized_core(role, action)
47
46
  return true
@@ -68,48 +67,41 @@ module ZeroAuthorization
68
67
  elsif self.class.authorization_mode == :superficial
69
68
  return authorize_superficially(action)
70
69
  else
71
- raise 'InvalidAuthorizationMode'
70
+ raise ZeroAuthorization::Exceptions::InvalidAuthorizationMode
72
71
  end
73
72
  end
74
73
 
75
74
  # Core of authorization after reading/parsing rule set for current role
75
+ # Rules for rule-sets execution (Precedence: from top to bottom)
76
+ # Rule 00: If no rule-sets are available for 'can do' and 'cant do' then is authorized true '(with warning message)'.
77
+ # Rule 01: If role can't do 'anything' or can do 'nothing' then is authorized false.
78
+ # Rule 02: If role can't do 'nothing' or can do 'anything' then is authorized true.
79
+ # Rule 03: If role can't do 'specified' method and given 'evaluate' method returns true then is authorized false.
80
+ # Rule 04: If role can't do 'specified' method and given 'evaluate' method returns false then is authorized true.
81
+ # Rule 05: If role can do 'specified' method and given 'evaluate' method returns true then is authorized true.
82
+ # Rule 06: If role can do 'specified' method and given 'evaluate' method returns false then is authorized false.
83
+ # Rule 07: If role can't do 'specified' method then is authorized false.
84
+ # Rule 08: If role can do 'specified' method then is authorized true.
76
85
  def zero_authorized_core(role, action)
77
- _auth_flag = false
78
- unless role.rule_set[:can_do].nil?
79
- if role.rule_set[:can_do] == :anything
80
- _auth_flag = true
81
-
82
- elsif role.rule_set[:can_do].is_a?(Hash)
83
-
84
- if role.rule_set[:can_do][self.class.name.to_sym] == :anything
85
- _auth_flag = true
86
- else
87
- logger.debug "----------- self.class.name.to_sym: #{self.class.name.to_sym}"
88
- symbolized_actions = role.rule_set[:can_do][self.class.name.to_sym].collect { |x| x if x.is_a?(Symbol) }.compact
89
- _auth_flag = if symbolized_actions.include?(action)
90
- true
91
- else
92
- conditional_check =nil
93
- (role.rule_set[:can_do][self.class.name.to_sym]- symbolized_actions).each do |action_rule_hash|
94
- conditional_check = action_rule_hash[action] if action_rule_hash.keys.include? action
95
- end
96
- conditional_check ||= {}
97
- conditional_check= conditional_check[:if]
98
- return self.send(conditional_check) unless conditional_check.nil?
99
- false
100
- end
101
- #_auth_flag = true if (role.rule_set[:can_do][self.class.name.to_sym] || []).include?(action)
102
- end
103
- end
104
- end
105
- unless role.rule_set[:cant_do].nil?
106
- if role.rule_set[:cant_do] == :anything
107
- _auth_flag = false
108
- elsif role.rule_set[:cant_do].is_a?(Hash)
109
- _auth_flag = false if (role.rule_set[:cant_do][self.class.name.to_sym] || []).include?(action)
110
- end
86
+ can_rights = role.can_do_rights(self.class.name)
87
+ can_rights_names = can_rights.keys
88
+ cant_rights = role.cant_do_rights(self.class.name)
89
+ cant_rights_names = cant_rights.keys
90
+
91
+ if can_rights.empty? and cant_rights.empty? #Rule 00
92
+ _temp_i = "#{self.class.name} is exempted from ZeroAuthorization. To enable back, try adding rule-set(s) in role_n_privileges.yml"
93
+ puts _temp_i
94
+ Rails.logger.info _temp_i
95
+ return true
111
96
  end
112
- _auth_flag
97
+ return false if cant_rights_names.include?(:anything) or can_rights_names.include?(:nothing) #Rule 01
98
+ return true if cant_rights_names.include?(:nothing) or can_rights_names.include?(:anything) #Rule 02
99
+ return (self.send(cant_rights[action.to_sym]) ? false : true) unless cant_rights[action.to_sym].nil? # Rule 03 and Rule 04
100
+ return (self.send(can_rights[action.to_sym]) ? true : false) unless can_rights[action.to_sym].nil? # Rule 05 and Rule 06
101
+ return false if cant_rights_names.include?(action.to_sym) # Rule 07
102
+ return true if can_rights_names.include?(action.to_sym) # Rule 08
103
+
104
+ raise ZeroAuthorization::Exceptions::ExecutingUnreachableCode
113
105
  end
114
106
 
115
107
  def is_zero_authorized_4_save
@@ -132,25 +124,12 @@ module ZeroAuthorization
132
124
  module ClassMethods
133
125
  attr_accessor :authorization_mode
134
126
 
127
+ def declared_methods_to_restrict
128
+ Role.methods_marked_for(self.name).keys
129
+ end
130
+
135
131
  def list_of_methods_to_guard
136
- _model_methods_set = {}
137
- Role.roles_n_privileges_hash.each do |role_key, permission_value|
138
- unless permission_value[:can_do].nil?
139
- _model_methods_set = _model_methods_set.merge(permission_value[:can_do]) { |key, oval, nval| ([oval] << [nval]).flatten.compact.uniq } if permission_value[:can_do].is_a?(Hash)
140
- end
141
- unless permission_value[:cant_do].nil?
142
- _model_methods_set = _model_methods_set.merge(permission_value[:cant_do]) { |key, oval, nval| ([oval] << [nval]).flatten.compact.uniq } if permission_value[:cant_do].is_a?(Hash)
143
- end
144
- end
145
- if _model_methods_set[self.name.to_sym] == :anything
146
- _model_methods_set.delete(self.name.to_sym)
147
- end
148
- (_model_methods_set[self.name.to_sym] || []).clone.delete_if do |x|
149
- if x.is_a? Hash
150
- x= x.keys.first
151
- end
152
- [:create, :save, :update, :destroy, :anything].include?(x)
153
- end
132
+ declared_methods_to_restrict - [:create, :save, :update, :destroy, :anything, :nothing]
154
133
  end
155
134
 
156
135
  private
@@ -161,13 +140,18 @@ module ZeroAuthorization
161
140
  # applying restriction on methods
162
141
  def initialize_methods_restriction
163
142
  list_of_methods_to_guard.each do |method_name|
164
- if method_name.is_a? Hash
165
- method_name = method_name.keys.first
166
- end
167
- send(:alias_method, "za_#{method_name}", method_name)
168
- define_method "#{method_name}" do |*args|
169
- puts 'Restricted method call..'
170
- send("za_#{method_name}", *args) if zero_authorized_checker(method_name)
143
+ if self.instance_methods.include?(method_name)
144
+ send(:alias_method, "za_#{method_name}", method_name)
145
+ define_method "#{method_name}" do |*args|
146
+ _temp_i = "Restricted method call to #{self.class.name}#{method_name}.."
147
+ puts _temp_i
148
+ Rails.logger.debug(_temp_i)
149
+ send("za_#{method_name}", *args) if zero_authorized_checker(method_name)
150
+ end
151
+ else
152
+ _temp_i = "[WARNING] ZeroAuthorization: Method '#{method_name}' unavailable in #{self.name} for restriction application."
153
+ puts _temp_i
154
+ Rails.logger.debug(_temp_i)
171
155
  end
172
156
  end
173
157
  end
@@ -1,6 +1,35 @@
1
- module Exceptions
1
+ module ZeroAuthorization
2
+ module Exceptions
3
+ class ExecutingUnreachableCode < StandardError
4
+ def initialize(msg = 'It may be a bug. Please report to ZeroAuthorization\'s authors!')
5
+ super(msg)
6
+ end
7
+ end
2
8
 
3
- #class ActivatedAlreadyError < StandardError;
4
- #end
9
+ class RoleNotAvailable < StandardError
10
+ end
5
11
 
12
+ class NotAuthorized < StandardError
13
+ attr_reader :role
14
+
15
+ def initialize(role)
16
+ @role = role
17
+ end
18
+ end
19
+
20
+ class InvalidAuthorizationMode < StandardError
21
+ def initialize(msg = 'Invalid authorization mode in use it should be from :strict, :warning or :superficial')
22
+ super(msg)
23
+ end
24
+ end
25
+
26
+ class InvalidRolesNPrivilegesHash < StandardError
27
+ attr_reader :hash_in_use
28
+
29
+ def initialize(hash_in_use)
30
+ @hash_in_use = hash_in_use
31
+ end
32
+ end
33
+
34
+ end
6
35
  end
@@ -22,15 +22,114 @@ module ZeroAuthorization
22
22
  roles_n_privileges_hash.keys.collect { |key| key.to_s.gsub(/^role_/, '') }.include?(@@role) ? new(@@role) : nil
23
23
  end
24
24
 
25
+ def can_do_rights(for_classname)
26
+ self.class.methods_marked_for(for_classname, :can_do, rule_set)
27
+ end
28
+
29
+ def cant_do_rights(for_classname)
30
+ self.class.methods_marked_for(for_classname, :cant_do, rule_set)
31
+ end
32
+
33
+ def self.methods_marked_for(for_classname, specific_can_or_cant = nil, source_class_rule_sets = nil)
34
+ method_collection = {}
35
+ if source_class_rule_sets.nil?
36
+ validate_roles_n_privileges_hash.each do |role, class_rule_sets|
37
+ method_collection.merge!(extract_rule_hash(class_rule_sets, for_classname, specific_can_or_cant))
38
+ end
39
+ else
40
+ method_collection.merge!(extract_rule_hash(source_class_rule_sets, for_classname, specific_can_or_cant))
41
+ end
42
+ method_collection
43
+ end
44
+
45
+ def self.extract_rule_hash(class_rule_sets, for_classname, specific_can_or_cant)
46
+ method_collection = {}
47
+ basic_rule = class_rule_sets[for_classname.to_sym]
48
+ basic_rule.each do |can_or_cant, rule_hash|
49
+ (method_collection.merge!(rule_hash)) if (specific_can_or_cant.nil? ? true : (can_or_cant == specific_can_or_cant)) and rule_hash.is_a?(Hash)
50
+ end if basic_rule.is_a?(Hash)
51
+ method_collection
52
+ end
53
+
25
54
  # Cache read of config/roles_n_privileges.yml for role_privileges_hash
26
55
  def self.roles_n_privileges_hash
27
- @roles_n_privileges_hash ||= YAML::load_file(File.join(Rails.root, 'config', 'roles_n_privileges.yml'))
56
+ @roles_n_privileges_hash ||= validate_roles_n_privileges_hash
28
57
  @roles_n_privileges_hash
29
58
  end
30
59
 
31
60
  # Hard read of config/roles_n_privileges.yml for role_privileges_hash
32
61
  def self.roles_n_privileges_hash_reload
33
- @roles_n_privileges_hash = YAML::load_file(File.join(Rails.root, 'config', 'roles_n_privileges.yml'))
62
+ @roles_n_privileges_hash = validate_roles_n_privileges_hash
63
+ end
64
+
65
+ def self.validate_roles_n_privileges_hash
66
+ _result_hash = {}
67
+ YAML::load_file(File.join(Rails.root, 'config', 'roles_n_privileges.yml')).each do |role_name, role_permissions|
68
+ _result_hash[role_name.to_sym] ||= {}
69
+ _rh_with_role = _result_hash[role_name.to_sym]
70
+
71
+ role_permissions.symbolize_keys!
72
+ [:can_do, :cant_do].each do |_can|
73
+
74
+ if role_permissions[_can].is_a?(Array)
75
+
76
+ role_permissions[_can].each do |class_name|
77
+ if [Symbol, String].include?(class_name.class)
78
+ _class_name = class_name.to_s.classify.to_sym
79
+ ((_rh_with_role[_class_name] ||= {})[_can] ||={}).merge!({:anything => nil})
80
+ else
81
+ raise ZeroAuthorization::Exceptions::InvalidRolesNPrivilegesHash.new(class_name), 'It should only be a Symbol or String'
82
+ end
83
+ end
84
+
85
+ elsif role_permissions[_can].is_a?(Hash)
86
+
87
+ role_permissions[_can].each do |class_name, permission_set|
88
+ _class_name = class_name.to_s.classify.to_sym
89
+
90
+ if [Symbol, String].include?(class_name.class)
91
+ if [Symbol, String].include?(permission_set.class)
92
+ if [:anything, :nothing].include?(permission_set.to_sym)
93
+ ((_rh_with_role[_class_name] ||= {})[_can] ||={}).merge!({permission_set.to_sym => nil})
94
+ else
95
+ raise ZeroAuthorization::Exceptions::InvalidRolesNPrivilegesHash.new(permission_set.to_sym), 'It should only have :anything or :nothing'
96
+ end
97
+ elsif permission_set.is_a?(Array)
98
+ permission_set.each do |i_permission_set|
99
+ if [Symbol, String].include?(i_permission_set.class)
100
+ ((_rh_with_role[_class_name] ||= {})[_can] ||={}).merge!({i_permission_set.to_sym => nil})
101
+ elsif i_permission_set.is_a?(Hash)
102
+ i_permission_set.each do |_key, _value|
103
+ if [Symbol, String].include?(_key.class) and [Symbol, String].include?(_value.class)
104
+ ((_rh_with_role[_class_name] ||= {})[_can] ||={}).merge!({_key.to_sym => _value.to_sym})
105
+ else
106
+ raise ZeroAuthorization::Exceptions::InvalidRolesNPrivilegesHash.new({_key => _value}), 'Hash should only have key and value of type Symbol or String'
107
+ end
108
+ end
109
+ else
110
+ raise ZeroAuthorization::Exceptions::InvalidRolesNPrivilegesHash.new(i_permission_set), 'It should only be a Symbol, String or Hash'
111
+ end
112
+ end
113
+ elsif permission_set.is_a?(Hash)
114
+ permission_set.each do |i_permission_key, i_permission_value|
115
+ if [Symbol, String].include?(i_permission_key.class) and [Symbol, String].include?(i_permission_value.class)
116
+ ((_rh_with_role[_class_name] ||= {})[_can] ||={}).merge!({i_permission_key.to_sym => i_permission_value.to_sym})
117
+ else
118
+ raise ZeroAuthorization::Exceptions::InvalidRolesNPrivilegesHash.new({i_permission_key => i_permission_value}), 'Hash should only have key and value of type Symbol or String'
119
+ end
120
+ end
121
+ else
122
+ raise ZeroAuthorization::Exceptions::InvalidRolesNPrivilegesHash.new(permission_set), 'It should only be a Symbol, String, Hash or Array'
123
+ end
124
+ else
125
+ raise ZeroAuthorization::Exceptions::InvalidRolesNPrivilegesHash.new(class_name), 'It should only be a Symbol or String'
126
+ end
127
+ end
128
+
129
+ end
130
+ end
131
+ end
132
+ _result_hash
34
133
  end
35
134
 
36
135
  # Do any activity with any specific temporary role and then revert back to normal situation.
@@ -1,3 +1,3 @@
1
1
  module ZeroAuthorization
2
- VERSION = "1.0.0"
2
+ VERSION = "1.4.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zero_authorization
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rajeev Kannav Sharma
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-02-04 00:00:00.000000000 Z
12
+ date: 2014-12-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -95,9 +95,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
95
  version: '0'
96
96
  requirements: []
97
97
  rubyforge_project:
98
- rubygems_version: 2.1.11
98
+ rubygems_version: 2.4.5
99
99
  signing_key:
100
100
  specification_version: 4
101
101
  summary: 'How to setup: Specify what any specific role of current root entity(logged_user)
102
102
  can do/can''t do in roles_n_privileges.yml and (re-)boot application.'
103
103
  test_files: []
104
+ has_rdoc: