Class: Casbin::CoreEnforcer

Inherits:
Object
  • Object
show all
Defined in:
lib/casbin-ruby/core_enforcer.rb

Overview

CoreEnforcer defines the core functionality of an enforcer. get_attr/set_attr methods is ported from Python as attr/attr=

Direct Known Subclasses

InternalEnforcer

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model = nil, adapter = nil, watcher = nil) ⇒ CoreEnforcer

Returns a new instance of CoreEnforcer.



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/casbin-ruby/core_enforcer.rb', line 19

def initialize(model = nil, adapter = nil, watcher = nil)
  model ||= Config.model
  adapter ||= Config.adapter
  @watcher = watcher || Config.watcher

  if model.is_a? String
    if adapter.is_a? String
      init_with_file(model, adapter)
    else
      init_with_adapter(model, adapter)
    end
  elsif adapter.is_a? String
    raise 'Invalid parameters for enforcer.'
  else
    init_with_model_and_adapter(model, adapter)
  end
end

Instance Attribute Details

#adapterObject

Returns the value of attribute adapter.



38
39
40
# File 'lib/casbin-ruby/core_enforcer.rb', line 38

def adapter
  @adapter
end

Returns the value of attribute auto_build_role_links.



37
38
39
# File 'lib/casbin-ruby/core_enforcer.rb', line 37

def auto_build_role_links
  @auto_build_role_links
end

#auto_saveObject

Returns the value of attribute auto_save.



37
38
39
# File 'lib/casbin-ruby/core_enforcer.rb', line 37

def auto_save
  @auto_save
end

#effectorObject

Returns the value of attribute effector.



37
38
39
# File 'lib/casbin-ruby/core_enforcer.rb', line 37

def effector
  @effector
end

#enabledObject Also known as: enabled?

Returns the value of attribute enabled.



37
38
39
# File 'lib/casbin-ruby/core_enforcer.rb', line 37

def enabled
  @enabled
end

#modelObject

Returns the value of attribute model.



38
39
40
# File 'lib/casbin-ruby/core_enforcer.rb', line 38

def model
  @model
end

#rm_mapObject

Returns the value of attribute rm_map.



37
38
39
# File 'lib/casbin-ruby/core_enforcer.rb', line 37

def rm_map
  @rm_map
end

#watcherObject (readonly)

Returns the value of attribute watcher.



38
39
40
# File 'lib/casbin-ruby/core_enforcer.rb', line 38

def watcher
  @watcher
end

Class Method Details

.new_model(path = '', text = '') ⇒ Object

creates a model.



73
74
75
76
77
78
79
80
81
82
# File 'lib/casbin-ruby/core_enforcer.rb', line 73

def self.new_model(path = '', text = '')
  m = Model::Model.new
  if path.length.positive?
    m.load_model(path)
  else
    m.load_model_from_text(text)
  end

  m
end

Instance Method Details

#add_named_domain_matching_func(ptype, fn) ⇒ Object

add_named_domain_matching_func add MatchingFunc by ptype to RoleManager



193
194
195
# File 'lib/casbin-ruby/core_enforcer.rb', line 193

def add_named_domain_matching_func(ptype, fn)
  rm_map[ptype]&.add_domain_matching_func(fn)
end

#add_named_matching_func(ptype, fn) ⇒ Object

add_named_matching_func add MatchingFunc by ptype RoleManager



188
189
190
# File 'lib/casbin-ruby/core_enforcer.rb', line 188

def add_named_matching_func(ptype, fn)
  rm_map[ptype]&.add_matching_func(fn)
end

manually rebuild the role inheritance relations.



182
183
184
185
# File 'lib/casbin-ruby/core_enforcer.rb', line 182

def build_role_links
  rm_map.each_value(&:clear)
  model.build_role_links(rm_map)
end

#clear_policyObject

clears all policy.



115
116
117
# File 'lib/casbin-ruby/core_enforcer.rb', line 115

def clear_policy
  model.clear_policy
end

controls whether to rebuild the role inheritance relations when a role is added or deleted.



177
178
179
# File 'lib/casbin-ruby/core_enforcer.rb', line 177

def enable_auto_build_role_links(auto_build_role_links)
  self.auto_build_role_links = auto_build_role_links
end

#enable_auto_save(auto_save) ⇒ Object

controls whether to save a policy rule automatically to the adapter when it is added or removed.



172
173
174
# File 'lib/casbin-ruby/core_enforcer.rb', line 172

def enable_auto_save(auto_save)
  self.auto_save = auto_save
end

#enable_enforce(enabled = true) ⇒ Object

changes the enforcing state of Casbin, when Casbin is disabled, all access will be allowed by the Enforce() function.



167
168
169
# File 'lib/casbin-ruby/core_enforcer.rb', line 167

def enable_enforce(enabled = true)
  self.enabled = enabled
end

#enforce(*rvals) ⇒ Object

decides whether a “subject” can access a “object” with the operation “action”, input parameters are usually: (sub, obj, act).



199
200
201
# File 'lib/casbin-ruby/core_enforcer.rb', line 199

def enforce(*rvals)
  enforce_ex(*rvals)[0]
end

#enforce_ex(*rvals) ⇒ Object

decides whether a “subject” can access a “object” with the operation “action”, input parameters are usually: (sub, obj, act). return judge result with reason

Raises:

  • (StandardError)


206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
# File 'lib/casbin-ruby/core_enforcer.rb', line 206

def enforce_ex(*rvals)
  return [false, []] unless enabled?

  raise 'model is undefined' unless model.model&.key?('m')
  raise 'model is undefined' unless model.model['m']&.key?('m')

  r_tokens = model.model['r']['r'].tokens
  p_tokens = model.model['p']['p'].tokens
  raise StandardError, 'invalid request size' unless r_tokens.size == rvals.size

  exp_string = model.model['m']['m'].value
  has_eval = Util.has_eval(exp_string)
  expression = exp_string
  policy_effects = Set.new
  r_parameters = load_params(r_tokens, rvals)
  policy_len = model.model['p']['p'].policy.size
  explain_index = -1
  if policy_len.positive?
    model.model['p']['p'].policy.each_with_index do |pvals, i|
      raise StandardError, 'invalid policy size' unless p_tokens.size == pvals.size

      p_parameters = load_params(p_tokens, pvals)
      parameters = r_parameters.merge(p_parameters)

      if has_eval
        rule_names = Util.get_eval_value(exp_string)
        rules = rule_names.map { |rule_name| Util.escape_assertion(p_parameters[rule_name]) }
        expression = Util.replace_eval(exp_string, rules)
      end

      result = evaluate(expression, functions, parameters)
      case result
      when TrueClass, FalseClass
        unless result
          policy_effects.add(Effect::Effector::INDETERMINATE)
          next
        end
      when Numeric
        if result.zero?
          policy_effects.add(Effect::Effector::INDETERMINATE)
          next
        end
      else
        raise 'matcher result should be true, false or a number'
      end

      if parameters.keys.include?('p_eft')
        case parameters['p_eft']
        when 'allow'
          policy_effects.add(Effect::Effector::ALLOW)
        when 'deny'
          policy_effects.add(Effect::Effector::DENY)
        else
          policy_effects.add(Effect::Effector::INDETERMINATE)
        end
      else
        policy_effects.add(Effect::Effector::ALLOW)
      end

      if effector.intermediate_effect(policy_effects) != Effect::Effector::INDETERMINATE
        explain_index = i
        break
      end
    end

  else
    raise 'please make sure rule exists in policy when using eval() in matcher' if has_eval

    parameters = r_parameters.clone
    model.model['p']['p'].tokens.each { |token| parameters[token] = '' }
    result = evaluate(expression, functions, parameters)
    if result
      policy_effects.add(Effect::Effector::ALLOW)
    else
      policy_effects.add(Effect::Effector::INDETERMINATE)
    end
  end

  final_effect = effector.final_effect(policy_effects)
  result = Effect::DefaultEffector.effect_to_bool(final_effect)

  # Log request.
  log_request(rvals, result)

  explain_rule = []
  explain_rule = model.model['p']['p'].policy[explain_index] if explain_index != -1 && explain_index < policy_len
  [result, explain_rule]
end

#filtered?Boolean

returns true if the loaded policy has been filtered.

Returns:

  • (Boolean)


151
152
153
# File 'lib/casbin-ruby/core_enforcer.rb', line 151

def filtered?
  adapter.respond_to?(:filtered?) && adapter.filtered?
end

#init_with_adapter(model_path, adapter = nil) ⇒ Object

initializes an enforcer with a database adapter.



47
48
49
50
51
52
# File 'lib/casbin-ruby/core_enforcer.rb', line 47

def init_with_adapter(model_path, adapter = nil)
  m = new_model(model_path)
  init_with_model_and_adapter(m, adapter)

  self.model_path = model_path
end

#init_with_file(model_path, policy_path) ⇒ Object

initializes an enforcer with a model file and a policy file.



41
42
43
44
# File 'lib/casbin-ruby/core_enforcer.rb', line 41

def init_with_file(model_path, policy_path)
  a = Persist::Adapters::FileAdapter.new(policy_path)
  init_with_adapter(model_path, a)
end

#init_with_model_and_adapter(m, adapter = nil) ⇒ Object

initializes an enforcer with a model and a database adapter.



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/casbin-ruby/core_enforcer.rb', line 55

def init_with_model_and_adapter(m, adapter = nil)
  if !m.is_a?(Model::Model) || (!adapter.nil? && !adapter.is_a?(Persist::Adapter))
    raise StandardError, 'Invalid parameters for enforcer.'
  end

  self.adapter = adapter

  self.model = m
  model.print_model
  self.fm = Model::FunctionMap.load_function_map

  init

  # Do not initialize the full policy when using a filtered adapter
  load_policy if adapter && !filtered?
end

#load_filtered_policy(filter) ⇒ Object

reloads a filtered policy from file/database.

Raises:

  • (ArgumentError)


130
131
132
133
134
135
136
137
138
139
# File 'lib/casbin-ruby/core_enforcer.rb', line 130

def load_filtered_policy(filter)
  model.clear_policy

  raise ArgumentError, 'filtered policies are not supported by this adapter' unless adapter.respond_to?(:filtered?)

  adapter.load_filtered_policy(model, filter)
  init_rm_map
  model.print_policy
  build_role_links if auto_build_role_links
end

#load_increment_filtered_policy(filter) ⇒ Object

appends a filtered policy from file/database.

Raises:

  • (ArgumentError)


142
143
144
145
146
147
148
# File 'lib/casbin-ruby/core_enforcer.rb', line 142

def load_increment_filtered_policy(filter)
  raise ArgumentError, 'filtered policies are not supported by this adapter' unless adapter.respond_to?(:filtered?)

  adapter.load_filtered_policy(model, filter)
  model.print_policy
  build_role_links if auto_build_role_links
end

#load_modelObject

reloads the model from the model CONF file. Because the policy is attached to a model, so the policy is invalidated and needs to be reloaded by calling load_policy.



91
92
93
94
95
96
# File 'lib/casbin-ruby/core_enforcer.rb', line 91

def load_model
  self.model = new_model
  model.load_model model_path
  model.print_model
  self.fm = Model::FunctionMap.load_function_map
end

#load_policyObject

reloads the policy from file/database.



120
121
122
123
124
125
126
127
# File 'lib/casbin-ruby/core_enforcer.rb', line 120

def load_policy
  model.clear_policy
  adapter.load_policy model

  init_rm_map
  model.print_policy
  build_role_links if auto_build_role_links
end

#new_model(*args) ⇒ Object



84
85
86
# File 'lib/casbin-ruby/core_enforcer.rb', line 84

def new_model(*args)
  self.class.new_model(*args)
end

#role_managerObject

gets the current role manager.



105
106
107
# File 'lib/casbin-ruby/core_enforcer.rb', line 105

def role_manager
  rm_map['g']
end

#role_manager=(rm) ⇒ Object

sets the current role manager.



110
111
112
# File 'lib/casbin-ruby/core_enforcer.rb', line 110

def role_manager=(rm)
  rm_map['g'] = rm
end

#save_policyObject



155
156
157
158
159
160
161
# File 'lib/casbin-ruby/core_enforcer.rb', line 155

def save_policy
  raise 'cannot save a filtered policy' if filtered?

  adapter.save_policy(model)

  watcher&.update
end