Class: Placet::Engine
- Inherits:
-
Object
- Object
- Placet::Engine
- Defined in:
- lib/placet/engine.rb
Overview
コア評価エンジン(PDP)。純粋関数として動作し、適合性テストの対象となる。 入力は principal 文字列の配列のみで、derive の由来(via)などランタイム層の 拡張は関知しない
Instance Method Summary collapse
- #decide(principals, action) ⇒ Object
-
#initialize(definition, registry: nil) ⇒ Engine
constructor
A new instance of Engine.
-
#scope_plan(static_principals, action, relations:) ⇒ Object
一覧フィルタリングの計画を返す。 static_principals: 静的 principal(rel: を含まない導出結果) relations: 対象モデルに定義された relation 名のリスト.
-
#validate_action!(action, error_class: Error) ⇒ Object
action 検証の一元的な入口。決定要求・scope 合成の action は具体的 (ワイルドカード不可)かつレジストリ宣言済み(使用時)でなければならない。 typo は静かな全拒否 / 空 scope になるため即エラーにする。 宣言時 fail-fast には error_class に DefinitionError を渡して使う.
Constructor Details
#initialize(definition, registry: nil) ⇒ Engine
Returns a new instance of Engine.
25 26 27 28 29 30 31 |
# File 'lib/placet/engine.rb', line 25 def initialize(definition, registry: nil) @definition = definition @registry = registry @grant_cache = {} @match_cache = {} @valid_actions = Set.new end |
Instance Method Details
#decide(principals, action) ⇒ Object
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/placet/engine.rb', line 33 def decide(principals, action) validate_action!(action) matches = matches_for(action) matched = [] principals.each do |principal| @definition..fetch(principal, []).each do |policy_name| matches.fetch(policy_name, []).each do |index, effect| matched << Determinant.new(principal: principal, policy: policy_name, statement: index, effect: effect) end end end denies, allows = matched.partition { |m| m.effect == "deny" } return Decision.new(decision: :deny, basis: :explicit_deny, determinants: denies) if denies.any? return Decision.new(decision: :permit, basis: :explicit_allow, determinants: allows) if allows.any? Decision.new(decision: :deny, basis: :implicit_deny, determinants: []) end |
#scope_plan(static_principals, action, relations:) ⇒ Object
一覧フィルタリングの計画を返す。 static_principals: 静的 principal(rel: を含まない導出結果) relations: 対象モデルに定義された relation 名のリスト
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/placet/engine.rb', line 57 def scope_plan(static_principals, action, relations:) validate_action!(action) allow_ps, deny_ps = grants(action) static = static_principals.to_a if static.any? { |p| deny_ps.include?(p) } return ScopePlan.new(kind: "empty", include_relations: [], exclude_relations: []) end exclude = relations.select { |name| deny_ps.include?("rel:#{name}") } if static.any? { |p| allow_ps.include?(p) } return ScopePlan.new(kind: "all", include_relations: [], exclude_relations: exclude) end include_ = relations.select { |name| allow_ps.include?("rel:#{name}") } if include_.empty? ScopePlan.new(kind: "empty", include_relations: [], exclude_relations: []) else ScopePlan.new(kind: "union", include_relations: include_, exclude_relations: exclude) end end |
#validate_action!(action, error_class: Error) ⇒ Object
action 検証の一元的な入口。決定要求・scope 合成の action は具体的 (ワイルドカード不可)かつレジストリ宣言済み(使用時)でなければならない。 typo は静かな全拒否 / 空 scope になるため即エラーにする。 宣言時 fail-fast には error_class に DefinitionError を渡して使う
84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/placet/engine.rb', line 84 def validate_action!(action, error_class: Error) return if @valid_actions.include?(action) unless action.is_a?(String) && action =~ CONCRETE_ACTION_RE raise error_class, "action は具体的でなければならない: #{action.inspect}" end unless @registry.nil? || @registry.known_action?(action) raise error_class, "未知の action: #{action}(レジストリに未宣言)" end @valid_actions << action end |