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, logger: Logger.new($stdout)) ⇒ CoreEnforcer

Returns a new instance of CoreEnforcer.



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

def initialize(model = nil, adapter = nil, logger: Logger.new($stdout))
  if model.is_a? String
    if adapter.is_a? String
      init_with_file(model, adapter, logger: logger)
    else
      init_with_adapter(model, adapter, logger: logger)
    end
  elsif adapter.is_a? String
    raise 'Invalid parameters for enforcer.'
  else
    init_with_model_and_adapter(model, adapter, logger: logger)
  end
end

Instance Attribute Details

#adapterObject

Returns the value of attribute adapter.



33
34
35
# File 'lib/casbin-ruby/core_enforcer.rb', line 33

def adapter
  @adapter
end

Returns the value of attribute auto_build_role_links.



33
34
35
# File 'lib/casbin-ruby/core_enforcer.rb', line 33

def auto_build_role_links
  @auto_build_role_links
end

#auto_saveObject

Returns the value of attribute auto_save.



33
34
35
# File 'lib/casbin-ruby/core_enforcer.rb', line 33

def auto_save
  @auto_save
end

#effectorObject

Returns the value of attribute effector.



33
34
35
# File 'lib/casbin-ruby/core_enforcer.rb', line 33

def effector
  @effector
end

#enabledObject Also known as: enabled?

Returns the value of attribute enabled.



33
34
35
# File 'lib/casbin-ruby/core_enforcer.rb', line 33

def enabled
  @enabled
end

#modelObject

Returns the value of attribute model.



34
35
36
# File 'lib/casbin-ruby/core_enforcer.rb', line 34

def model
  @model
end

#rm_mapObject

Returns the value of attribute rm_map.



33
34
35
# File 'lib/casbin-ruby/core_enforcer.rb', line 33

def rm_map
  @rm_map
end

#watcherObject

Returns the value of attribute watcher.



33
34
35
# File 'lib/casbin-ruby/core_enforcer.rb', line 33

def watcher
  @watcher
end

Class Method Details

.new_model(path = '', text = '', logger: Logger.new($stdout)) ⇒ Object

creates a model.



69
70
71
72
73
74
75
76
77
78
# File 'lib/casbin-ruby/core_enforcer.rb', line 69

def self.new_model(path = '', text = '', logger: Logger.new($stdout))
  m = Model::Model.new logger: logger
  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



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

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



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

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

manually rebuild the role inheritance relations.



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

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

#clear_policyObject

clears all policy.



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

def clear_policy
  model.clear_policy
end

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



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

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.



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

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.



163
164
165
# File 'lib/casbin-ruby/core_enforcer.rb', line 163

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).



195
196
197
# File 'lib/casbin-ruby/core_enforcer.rb', line 195

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)


202
203
204
205
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
# File 'lib/casbin-ruby/core_enforcer.rb', line 202

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)


147
148
149
# File 'lib/casbin-ruby/core_enforcer.rb', line 147

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

#init_with_adapter(model_path, adapter = nil, logger: Logger.new($stdout)) ⇒ Object

initializes an enforcer with a database adapter.



43
44
45
46
47
48
# File 'lib/casbin-ruby/core_enforcer.rb', line 43

def init_with_adapter(model_path, adapter = nil, logger: Logger.new($stdout))
  m = new_model(model_path)
  init_with_model_and_adapter(m, adapter, logger: logger)

  self.model_path = model_path
end

#init_with_file(model_path, policy_path, logger: Logger.new($stdout)) ⇒ Object

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



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

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

#init_with_model_and_adapter(m, adapter = nil, logger: Logger.new($stdout)) ⇒ Object

initializes an enforcer with a model and a database adapter.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/casbin-ruby/core_enforcer.rb', line 51

def init_with_model_and_adapter(m, adapter = nil, logger: Logger.new($stdout))
  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(logger: logger)

  # 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)


126
127
128
129
130
131
132
133
134
135
# File 'lib/casbin-ruby/core_enforcer.rb', line 126

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)


138
139
140
141
142
143
144
# File 'lib/casbin-ruby/core_enforcer.rb', line 138

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.



87
88
89
90
91
92
# File 'lib/casbin-ruby/core_enforcer.rb', line 87

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.



116
117
118
119
120
121
122
123
# File 'lib/casbin-ruby/core_enforcer.rb', line 116

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



80
81
82
# File 'lib/casbin-ruby/core_enforcer.rb', line 80

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

#role_managerObject

gets the current role manager.



101
102
103
# File 'lib/casbin-ruby/core_enforcer.rb', line 101

def role_manager
  rm_map['g']
end

#role_manager=(rm) ⇒ Object

sets the current role manager.



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

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

#save_policyObject



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

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

  adapter.save_policy(model)

  watcher&.update
end