ruby-rego 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.reek.yml +80 -0
- data/.vscode/extensions.json +19 -0
- data/.vscode/launch.json +35 -0
- data/.vscode/settings.json +25 -0
- data/.vscode/tasks.json +117 -0
- data/.yardopts +12 -0
- data/ARCHITECTURE.md +39 -0
- data/CHANGELOG.md +25 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +183 -0
- data/RELEASING.md +37 -0
- data/Rakefile +38 -0
- data/SECURITY.md +26 -0
- data/Steepfile +10 -0
- data/TODO.md +35 -0
- data/benchmark/builtin_calls.rb +29 -0
- data/benchmark/complex_policy.rb +19 -0
- data/benchmark/comprehensions.rb +19 -0
- data/benchmark/simple_rules.rb +20 -0
- data/examples/README.md +27 -0
- data/examples/sample_config.yaml +2 -0
- data/examples/simple_policy.rego +7 -0
- data/examples/validation_policy.rego +11 -0
- data/exe/rego-validate +6 -0
- data/lib/ruby/rego/ast/base.rb +95 -0
- data/lib/ruby/rego/ast/binary_op.rb +64 -0
- data/lib/ruby/rego/ast/call.rb +27 -0
- data/lib/ruby/rego/ast/composite.rb +48 -0
- data/lib/ruby/rego/ast/comprehension.rb +63 -0
- data/lib/ruby/rego/ast/every.rb +37 -0
- data/lib/ruby/rego/ast/import.rb +32 -0
- data/lib/ruby/rego/ast/literal.rb +70 -0
- data/lib/ruby/rego/ast/module.rb +32 -0
- data/lib/ruby/rego/ast/package.rb +22 -0
- data/lib/ruby/rego/ast/query.rb +63 -0
- data/lib/ruby/rego/ast/reference.rb +58 -0
- data/lib/ruby/rego/ast/rule.rb +114 -0
- data/lib/ruby/rego/ast/unary_op.rb +42 -0
- data/lib/ruby/rego/ast/variable.rb +22 -0
- data/lib/ruby/rego/ast.rb +17 -0
- data/lib/ruby/rego/builtins/aggregates.rb +124 -0
- data/lib/ruby/rego/builtins/base.rb +95 -0
- data/lib/ruby/rego/builtins/collections/array_ops.rb +103 -0
- data/lib/ruby/rego/builtins/collections/object_ops.rb +120 -0
- data/lib/ruby/rego/builtins/collections/set_ops.rb +51 -0
- data/lib/ruby/rego/builtins/collections.rb +137 -0
- data/lib/ruby/rego/builtins/comparisons/casts.rb +139 -0
- data/lib/ruby/rego/builtins/comparisons.rb +84 -0
- data/lib/ruby/rego/builtins/numeric_helpers.rb +56 -0
- data/lib/ruby/rego/builtins/registry.rb +199 -0
- data/lib/ruby/rego/builtins/registry_helpers.rb +27 -0
- data/lib/ruby/rego/builtins/strings/case_ops.rb +22 -0
- data/lib/ruby/rego/builtins/strings/concat.rb +19 -0
- data/lib/ruby/rego/builtins/strings/formatting.rb +35 -0
- data/lib/ruby/rego/builtins/strings/helpers.rb +62 -0
- data/lib/ruby/rego/builtins/strings/number_helpers.rb +48 -0
- data/lib/ruby/rego/builtins/strings/search.rb +63 -0
- data/lib/ruby/rego/builtins/strings/split.rb +19 -0
- data/lib/ruby/rego/builtins/strings/substring.rb +22 -0
- data/lib/ruby/rego/builtins/strings/trim.rb +42 -0
- data/lib/ruby/rego/builtins/strings/trim_helpers.rb +62 -0
- data/lib/ruby/rego/builtins/strings.rb +58 -0
- data/lib/ruby/rego/builtins/types.rb +89 -0
- data/lib/ruby/rego/call_name.rb +55 -0
- data/lib/ruby/rego/cli.rb +1122 -0
- data/lib/ruby/rego/compiled_module.rb +114 -0
- data/lib/ruby/rego/compiler.rb +1097 -0
- data/lib/ruby/rego/environment/overrides.rb +33 -0
- data/lib/ruby/rego/environment/reference_resolution.rb +86 -0
- data/lib/ruby/rego/environment.rb +230 -0
- data/lib/ruby/rego/environment_pool.rb +71 -0
- data/lib/ruby/rego/error_handling.rb +58 -0
- data/lib/ruby/rego/error_payload.rb +34 -0
- data/lib/ruby/rego/errors.rb +196 -0
- data/lib/ruby/rego/evaluator/assignment_support.rb +126 -0
- data/lib/ruby/rego/evaluator/binding_helpers.rb +60 -0
- data/lib/ruby/rego/evaluator/comprehension_evaluator.rb +182 -0
- data/lib/ruby/rego/evaluator/expression_dispatch.rb +45 -0
- data/lib/ruby/rego/evaluator/expression_evaluator.rb +492 -0
- data/lib/ruby/rego/evaluator/object_literal_evaluator.rb +52 -0
- data/lib/ruby/rego/evaluator/operator_evaluator.rb +163 -0
- data/lib/ruby/rego/evaluator/query_node_builder.rb +38 -0
- data/lib/ruby/rego/evaluator/reference_key_resolver.rb +50 -0
- data/lib/ruby/rego/evaluator/reference_resolver.rb +352 -0
- data/lib/ruby/rego/evaluator/rule_evaluator/bindings.rb +70 -0
- data/lib/ruby/rego/evaluator/rule_evaluator.rb +550 -0
- data/lib/ruby/rego/evaluator/rule_value_provider.rb +56 -0
- data/lib/ruby/rego/evaluator/variable_collector.rb +221 -0
- data/lib/ruby/rego/evaluator.rb +174 -0
- data/lib/ruby/rego/lexer/number_reader.rb +68 -0
- data/lib/ruby/rego/lexer/stream.rb +137 -0
- data/lib/ruby/rego/lexer/string_reader.rb +90 -0
- data/lib/ruby/rego/lexer/template_string_reader.rb +62 -0
- data/lib/ruby/rego/lexer.rb +206 -0
- data/lib/ruby/rego/location.rb +73 -0
- data/lib/ruby/rego/memoization.rb +67 -0
- data/lib/ruby/rego/parser/collections.rb +173 -0
- data/lib/ruby/rego/parser/expressions.rb +216 -0
- data/lib/ruby/rego/parser/precedence.rb +42 -0
- data/lib/ruby/rego/parser/query.rb +139 -0
- data/lib/ruby/rego/parser/references.rb +115 -0
- data/lib/ruby/rego/parser/rules.rb +310 -0
- data/lib/ruby/rego/parser.rb +210 -0
- data/lib/ruby/rego/policy.rb +50 -0
- data/lib/ruby/rego/result.rb +91 -0
- data/lib/ruby/rego/token.rb +206 -0
- data/lib/ruby/rego/unifier.rb +451 -0
- data/lib/ruby/rego/value.rb +379 -0
- data/lib/ruby/rego/version.rb +7 -0
- data/lib/ruby/rego/with_modifiers/with_modifier.rb +37 -0
- data/lib/ruby/rego/with_modifiers/with_modifier_applier.rb +48 -0
- data/lib/ruby/rego/with_modifiers/with_modifier_builtin_override.rb +128 -0
- data/lib/ruby/rego/with_modifiers/with_modifier_context.rb +120 -0
- data/lib/ruby/rego/with_modifiers/with_modifier_path_key_resolver.rb +42 -0
- data/lib/ruby/rego/with_modifiers/with_modifier_path_override.rb +99 -0
- data/lib/ruby/rego/with_modifiers/with_modifier_root_scope.rb +58 -0
- data/lib/ruby/rego.rb +72 -0
- data/sig/objspace.rbs +4 -0
- data/sig/psych.rbs +7 -0
- data/sig/rego_validate.rbs +382 -0
- data/sig/ruby/rego.rbs +2150 -0
- metadata +172 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../ast"
|
|
4
|
+
require_relative "../errors"
|
|
5
|
+
require_relative "../value"
|
|
6
|
+
require_relative "with_modifier_builtin_override"
|
|
7
|
+
require_relative "with_modifier_path_key_resolver"
|
|
8
|
+
require_relative "with_modifier_path_override"
|
|
9
|
+
require_relative "with_modifier_root_scope"
|
|
10
|
+
|
|
11
|
+
module Ruby
|
|
12
|
+
module Rego
|
|
13
|
+
module WithModifiers
|
|
14
|
+
# Applies a single with modifier in a given environment.
|
|
15
|
+
class WithModifierContext
|
|
16
|
+
# @param modifier [WithModifier]
|
|
17
|
+
# @param environment [Environment]
|
|
18
|
+
# @param expression_evaluator [Evaluator::ExpressionEvaluator]
|
|
19
|
+
def initialize(modifier:, environment:, expression_evaluator:)
|
|
20
|
+
@modifier = modifier
|
|
21
|
+
@environment = environment
|
|
22
|
+
@expression_evaluator = expression_evaluator
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @yieldparam environment [Environment]
|
|
26
|
+
# @return [Object]
|
|
27
|
+
def apply(&)
|
|
28
|
+
return apply_reference(&) if target.is_a?(AST::Reference)
|
|
29
|
+
return apply_variable(&) if target.is_a?(AST::Variable)
|
|
30
|
+
|
|
31
|
+
raise EvaluationError.new("Unsupported with target: #{target.class}", rule: nil, location: target.location)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
attr_reader :modifier, :environment, :expression_evaluator
|
|
37
|
+
|
|
38
|
+
def target
|
|
39
|
+
modifier.target
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def value
|
|
43
|
+
modifier.value
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def apply_reference(&)
|
|
47
|
+
scope = reference_scope
|
|
48
|
+
overridden = reference_override(scope)
|
|
49
|
+
return overridden if overridden.is_a?(UndefinedValue)
|
|
50
|
+
|
|
51
|
+
scope.with_override(overridden, &)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def reference_scope
|
|
55
|
+
base = target.base
|
|
56
|
+
location = target.location
|
|
57
|
+
unless base.is_a?(AST::Variable)
|
|
58
|
+
raise EvaluationError.new("Unsupported with target base: #{base.class}", rule: nil, location: location)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
WithModifierRootScope.new(
|
|
62
|
+
environment: environment,
|
|
63
|
+
name: base.name,
|
|
64
|
+
location: location
|
|
65
|
+
)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def reference_override(scope)
|
|
69
|
+
keys = reference_path_keys
|
|
70
|
+
return UndefinedValue.new if keys.is_a?(UndefinedValue)
|
|
71
|
+
|
|
72
|
+
replacement = resolved_value
|
|
73
|
+
WithModifierPathOverride.new(
|
|
74
|
+
base_value: scope.base_value,
|
|
75
|
+
keys: keys,
|
|
76
|
+
replacement: replacement,
|
|
77
|
+
location: target.location
|
|
78
|
+
).apply
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# :reek:TooManyStatements
|
|
82
|
+
# Returns UndefinedValue when any path key is undefined to short-circuit modifier application.
|
|
83
|
+
def reference_path_keys
|
|
84
|
+
resolver = WithModifierPathKeyResolver.new(expression_evaluator: expression_evaluator)
|
|
85
|
+
keys = target.path.map { |segment| resolver.resolve(segment) }
|
|
86
|
+
undefined_key = keys.find { |key| key.is_a?(UndefinedValue) }
|
|
87
|
+
undefined_key || keys
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def apply_variable(&)
|
|
91
|
+
name = target.name
|
|
92
|
+
if WithModifierRootScope::ROOT_NAMES.include?(name)
|
|
93
|
+
scope = WithModifierRootScope.new(
|
|
94
|
+
environment: environment,
|
|
95
|
+
name: name,
|
|
96
|
+
location: target.location
|
|
97
|
+
)
|
|
98
|
+
return scope.with_override(resolved_value, &)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
apply_builtin_override(name, &)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def apply_builtin_override(name, &)
|
|
105
|
+
WithModifierBuiltinOverride.new(
|
|
106
|
+
name: name,
|
|
107
|
+
value: value,
|
|
108
|
+
expression_evaluator: expression_evaluator,
|
|
109
|
+
location: target.location
|
|
110
|
+
).apply(environment, &)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def resolved_value
|
|
114
|
+
resolved = expression_evaluator.evaluate(value)
|
|
115
|
+
resolved.is_a?(Value) ? resolved.to_ruby : resolved
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../ast"
|
|
4
|
+
require_relative "../value"
|
|
5
|
+
|
|
6
|
+
module Ruby
|
|
7
|
+
module Rego
|
|
8
|
+
module WithModifiers
|
|
9
|
+
# Resolves reference path segments for with modifiers.
|
|
10
|
+
class WithModifierPathKeyResolver
|
|
11
|
+
# @param expression_evaluator [Evaluator::ExpressionEvaluator]
|
|
12
|
+
def initialize(expression_evaluator:)
|
|
13
|
+
@expression_evaluator = expression_evaluator
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# @param segment [Object]
|
|
17
|
+
# @return [Object]
|
|
18
|
+
# :reek:FeatureEnvy
|
|
19
|
+
# :reek:TooManyStatements
|
|
20
|
+
def resolve(segment)
|
|
21
|
+
raw = segment.is_a?(AST::RefArg) ? segment.value : segment
|
|
22
|
+
key = resolved_key(raw)
|
|
23
|
+
return key if key.is_a?(UndefinedValue)
|
|
24
|
+
|
|
25
|
+
key.is_a?(Symbol) ? key.to_s : key
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
attr_reader :expression_evaluator
|
|
31
|
+
|
|
32
|
+
# :reek:FeatureEnvy
|
|
33
|
+
def resolved_key(raw)
|
|
34
|
+
resolved = expression_evaluator.evaluate(raw)
|
|
35
|
+
return resolved if resolved.is_a?(UndefinedValue)
|
|
36
|
+
|
|
37
|
+
resolved.is_a?(Value) ? resolved.to_ruby : resolved
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../errors"
|
|
4
|
+
|
|
5
|
+
module Ruby
|
|
6
|
+
module Rego
|
|
7
|
+
module WithModifiers
|
|
8
|
+
# Applies a path-based override to a Ruby object.
|
|
9
|
+
# :reek:DataClump
|
|
10
|
+
# :reek:FeatureEnvy
|
|
11
|
+
# :reek:TooManyStatements
|
|
12
|
+
# :reek:DuplicateMethodCall
|
|
13
|
+
class WithModifierPathOverride
|
|
14
|
+
# @param base_value [Object]
|
|
15
|
+
# @param keys [Array<Object>]
|
|
16
|
+
# @param replacement [Object]
|
|
17
|
+
# @param location [Location, nil]
|
|
18
|
+
def initialize(base_value:, keys:, replacement:, location: nil)
|
|
19
|
+
@base_value = base_value
|
|
20
|
+
@keys = keys
|
|
21
|
+
@replacement = replacement
|
|
22
|
+
@location = location
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @return [Object]
|
|
26
|
+
def apply
|
|
27
|
+
apply_to(base_value, keys)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
attr_reader :base_value, :keys, :replacement, :location
|
|
33
|
+
|
|
34
|
+
def apply_to(container, path_keys)
|
|
35
|
+
return replacement if path_keys.empty?
|
|
36
|
+
|
|
37
|
+
return apply_hash(container, path_keys) if container.is_a?(Hash)
|
|
38
|
+
return apply_array(container, path_keys) if container.is_a?(Array)
|
|
39
|
+
|
|
40
|
+
apply_missing_container(path_keys)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def apply_hash(container, path_keys)
|
|
44
|
+
key = path_keys.first
|
|
45
|
+
rest = path_keys.drop(1)
|
|
46
|
+
updated = container.dup
|
|
47
|
+
normalized_key = key.is_a?(Symbol) ? key.to_s : key
|
|
48
|
+
updated[normalized_key] = apply_to(container[normalized_key], rest)
|
|
49
|
+
updated
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def apply_array(container, path_keys)
|
|
53
|
+
key = path_keys.first
|
|
54
|
+
rest = path_keys.drop(1)
|
|
55
|
+
index = array_index(key)
|
|
56
|
+
updated = container.dup
|
|
57
|
+
updated[index] = apply_to(container[index], rest)
|
|
58
|
+
updated
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def array_index(key)
|
|
62
|
+
return key if key.is_a?(Integer)
|
|
63
|
+
return Integer(key, 10) if numeric_key?(key)
|
|
64
|
+
|
|
65
|
+
error = invalid_index_error(key)
|
|
66
|
+
raise error
|
|
67
|
+
rescue ArgumentError
|
|
68
|
+
error = invalid_index_error(key)
|
|
69
|
+
raise error
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def apply_missing_container(path_keys)
|
|
73
|
+
key = path_keys.first
|
|
74
|
+
rest = path_keys.drop(1)
|
|
75
|
+
# @type var replacement_container: Array[Object] | Hash[Object, Object]
|
|
76
|
+
replacement_container = array_index_key?(key) ? [] : {}
|
|
77
|
+
apply_to(replacement_container, [key] + rest)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# :reek:UtilityFunction
|
|
81
|
+
def array_index_key?(key)
|
|
82
|
+
numeric_key?(key)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# :reek:UtilityFunction
|
|
86
|
+
def numeric_key?(key)
|
|
87
|
+
return true if key.is_a?(Integer)
|
|
88
|
+
|
|
89
|
+
key.is_a?(String) && key.match?(/\A-?\d+\z/)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def invalid_index_error(key)
|
|
93
|
+
message = "Invalid array index for with modifier: #{key.inspect}"
|
|
94
|
+
EvaluationError.new(message, rule: nil, location: location)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../errors"
|
|
4
|
+
|
|
5
|
+
module Ruby
|
|
6
|
+
module Rego
|
|
7
|
+
module WithModifiers
|
|
8
|
+
# Encapsulates input/data root access for with modifiers.
|
|
9
|
+
class WithModifierRootScope
|
|
10
|
+
ROOT_NAMES = %w[input data].freeze
|
|
11
|
+
|
|
12
|
+
# @param environment [Environment]
|
|
13
|
+
# @param name [String]
|
|
14
|
+
# @param location [Location, nil]
|
|
15
|
+
def initialize(environment:, name:, location: nil)
|
|
16
|
+
@environment = environment
|
|
17
|
+
@name = name
|
|
18
|
+
@location = location
|
|
19
|
+
validate_name
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @return [Object]
|
|
23
|
+
def base_value
|
|
24
|
+
input_scope? ? environment.input.to_ruby : environment.data.to_ruby
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @param overridden [Object]
|
|
28
|
+
# @yieldparam environment [Environment]
|
|
29
|
+
# @return [Object]
|
|
30
|
+
def with_override(overridden, &)
|
|
31
|
+
if input_scope?
|
|
32
|
+
environment.with_overrides(input: overridden, &)
|
|
33
|
+
else
|
|
34
|
+
environment.with_overrides(data: overridden, &)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
attr_reader :environment, :name, :location
|
|
41
|
+
|
|
42
|
+
def input_scope?
|
|
43
|
+
name == "input"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def validate_name
|
|
47
|
+
return if ROOT_NAMES.include?(name)
|
|
48
|
+
|
|
49
|
+
raise EvaluationError.new(
|
|
50
|
+
"With modifier expects input or data reference",
|
|
51
|
+
rule: nil,
|
|
52
|
+
location: location
|
|
53
|
+
)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
data/lib/ruby/rego.rb
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "rego/version"
|
|
4
|
+
require_relative "rego/location"
|
|
5
|
+
require_relative "rego/errors"
|
|
6
|
+
require_relative "rego/error_handling"
|
|
7
|
+
require_relative "rego/token"
|
|
8
|
+
require_relative "rego/lexer"
|
|
9
|
+
require_relative "rego/ast"
|
|
10
|
+
require_relative "rego/call_name"
|
|
11
|
+
require_relative "rego/parser"
|
|
12
|
+
require_relative "rego/value"
|
|
13
|
+
require_relative "rego/builtins/base"
|
|
14
|
+
require_relative "rego/builtins/registry"
|
|
15
|
+
require_relative "rego/builtins/types"
|
|
16
|
+
require_relative "rego/builtins/aggregates"
|
|
17
|
+
require_relative "rego/builtins/strings"
|
|
18
|
+
require_relative "rego/builtins/collections"
|
|
19
|
+
require_relative "rego/builtins/comparisons"
|
|
20
|
+
require_relative "rego/memoization"
|
|
21
|
+
require_relative "rego/environment"
|
|
22
|
+
require_relative "rego/environment_pool"
|
|
23
|
+
require_relative "rego/compiled_module"
|
|
24
|
+
require_relative "rego/compiler"
|
|
25
|
+
require_relative "rego/with_modifiers/with_modifier"
|
|
26
|
+
require_relative "rego/unifier"
|
|
27
|
+
require_relative "rego/result"
|
|
28
|
+
require_relative "rego/evaluator"
|
|
29
|
+
require_relative "rego/policy"
|
|
30
|
+
|
|
31
|
+
module Ruby
|
|
32
|
+
# Top-level namespace for the Ruby Rego gem.
|
|
33
|
+
module Rego
|
|
34
|
+
class << self
|
|
35
|
+
# Parse Rego source into an AST module.
|
|
36
|
+
#
|
|
37
|
+
# @param source [String] Rego source code
|
|
38
|
+
# @return [AST::Module] parsed AST module
|
|
39
|
+
def parse(source)
|
|
40
|
+
ErrorHandling.wrap("parsing") do
|
|
41
|
+
tokens = Lexer.new(source).tokenize
|
|
42
|
+
Parser.new(tokens).parse
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Compile Rego source into an immutable compiled module.
|
|
47
|
+
#
|
|
48
|
+
# @param source [String] Rego source code
|
|
49
|
+
# @return [CompiledModule] compiled and indexed module
|
|
50
|
+
def compile(source)
|
|
51
|
+
ErrorHandling.wrap("compilation") do
|
|
52
|
+
Compiler.new.compile(parse(source))
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Evaluate Rego source against input and data.
|
|
57
|
+
#
|
|
58
|
+
# @param source [String] Rego source code
|
|
59
|
+
# @param input [Object] input document
|
|
60
|
+
# @param data [Object] data document
|
|
61
|
+
# @param query [Object, nil] optional query path
|
|
62
|
+
# @return [Result] evaluation result
|
|
63
|
+
# :reek:LongParameterList
|
|
64
|
+
def evaluate(source, input: {}, data: {}, query: nil)
|
|
65
|
+
compiled_module = compile(source)
|
|
66
|
+
ErrorHandling.wrap("evaluation") do
|
|
67
|
+
Evaluator.new(compiled_module, input: input, data: data).evaluate(query)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
data/sig/objspace.rbs
ADDED