oso-oso 0.23.0 → 0.24.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 +4 -4
- data/Gemfile.lock +7 -6
- data/Makefile +1 -1
- data/ext/oso-oso/lib/libpolar.dylib +0 -0
- data/ext/oso-oso/lib/libpolar.so +0 -0
- data/ext/oso-oso/lib/polar.dll +0 -0
- data/lib/oso/oso.rb +22 -23
- data/lib/oso/polar/data/adapter/active_record_adapter.rb +56 -0
- data/lib/oso/polar/data/adapter.rb +22 -0
- data/lib/oso/polar/data/filter.rb +59 -0
- data/lib/oso/polar/data.rb +4 -0
- data/lib/oso/polar/errors.rb +0 -1
- data/lib/oso/polar/expression.rb +1 -1
- data/lib/oso/polar/ffi/error.rb +4 -22
- data/lib/oso/polar/ffi/polar.rb +60 -35
- data/lib/oso/polar/ffi/query.rb +48 -22
- data/lib/oso/polar/ffi/{source.rb → rust_string.rb} +9 -3
- data/lib/oso/polar/ffi.rb +28 -20
- data/lib/oso/polar/host.rb +19 -8
- data/lib/oso/polar/polar.rb +82 -15
- data/lib/oso/polar/query.rb +29 -11
- data/lib/oso/polar.rb +1 -0
- data/lib/oso/version.rb +1 -1
- metadata +7 -5
- data/lib/oso/polar/ffi/message.rb +0 -40
- data/lib/oso/polar/ffi/query_event.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 719c88b2531d9c6d1e638928e6be3abba68b67d0
|
4
|
+
data.tar.gz: 327124db69d3aa57ff06a1089c24124d60175c26
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4af7eba0a1bcac195ae51719991191ea78d4c0437bf7aacad7f09fce54d848559178485e098b5a9b150353c3feececd415533e7f311592e38cd6df8d263772c1
|
7
|
+
data.tar.gz: 57bca613ce91ddf645d7cafb89641286c1c41f1aec70cb4c9378b3157b8cd4291315e08083f19add35dad38325e423539831ffdcce2bc610bd685d328d2703e1
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
oso-oso (0.
|
4
|
+
oso-oso (0.24.0)
|
5
5
|
ffi (~> 1.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -21,14 +21,14 @@ GEM
|
|
21
21
|
arel (9.0.0)
|
22
22
|
ast (2.4.2)
|
23
23
|
backport (1.2.0)
|
24
|
-
benchmark (0.
|
24
|
+
benchmark (0.2.0)
|
25
25
|
byebug (11.1.3)
|
26
26
|
coderay (1.1.3)
|
27
27
|
concurrent-ruby (1.1.9)
|
28
28
|
diff-lcs (1.4.4)
|
29
29
|
e2mmap (0.1.0)
|
30
30
|
ffi (1.15.4)
|
31
|
-
i18n (1.8.
|
31
|
+
i18n (1.8.11)
|
32
32
|
concurrent-ruby (~> 1.0)
|
33
33
|
jaro_winkler (1.5.4)
|
34
34
|
maruku (0.7.3)
|
@@ -49,7 +49,7 @@ GEM
|
|
49
49
|
rainbow (3.0.0)
|
50
50
|
rake (12.3.3)
|
51
51
|
regexp_parser (2.1.1)
|
52
|
-
reverse_markdown (2.
|
52
|
+
reverse_markdown (2.1.1)
|
53
53
|
nokogiri
|
54
54
|
rexml (3.2.5)
|
55
55
|
rspec (3.10.0)
|
@@ -64,7 +64,7 @@ GEM
|
|
64
64
|
rspec-mocks (3.10.2)
|
65
65
|
diff-lcs (>= 1.2.0, < 2.0)
|
66
66
|
rspec-support (~> 3.10.0)
|
67
|
-
rspec-support (3.10.
|
67
|
+
rspec-support (3.10.3)
|
68
68
|
rubocop (0.89.1)
|
69
69
|
parallel (~> 1.10)
|
70
70
|
parser (>= 2.7.1.1)
|
@@ -97,12 +97,13 @@ GEM
|
|
97
97
|
tilt (2.0.10)
|
98
98
|
tzinfo (1.2.9)
|
99
99
|
thread_safe (~> 0.1)
|
100
|
-
unicode-display_width (1.
|
100
|
+
unicode-display_width (1.8.0)
|
101
101
|
yard (0.9.26)
|
102
102
|
|
103
103
|
PLATFORMS
|
104
104
|
ruby
|
105
105
|
x86_64-darwin-20
|
106
|
+
x86_64-linux
|
106
107
|
|
107
108
|
DEPENDENCIES
|
108
109
|
activerecord
|
data/Makefile
CHANGED
Binary file
|
data/ext/oso-oso/lib/libpolar.so
CHANGED
Binary file
|
data/ext/oso-oso/lib/polar.dll
CHANGED
Binary file
|
data/lib/oso/oso.rb
CHANGED
@@ -181,27 +181,17 @@ module Oso
|
|
181
181
|
# @param resource_cls The resource being accessed.
|
182
182
|
#
|
183
183
|
# @return A query for resources accessible to the actor.
|
184
|
-
def authorized_query(actor, action, resource_cls)
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
actor,
|
190
|
-
action,
|
191
|
-
resource,
|
192
|
-
bindings: { 'resource' => type_constraint(resource, resource_cls) },
|
193
|
-
accept_expression: true
|
194
|
-
)
|
195
|
-
|
196
|
-
results = results.each_with_object([]) do |result, out|
|
197
|
-
result.each do |key, val|
|
198
|
-
out.push({ 'bindings' => { key => host.to_polar(val) } })
|
184
|
+
def authorized_query(actor, action, resource_cls)
|
185
|
+
if host.use_new_data_filtering?
|
186
|
+
|
187
|
+
unless host.types[resource_cls].build_query == ::Oso::Polar::Host::DEFAULT_BUILD_QUERY
|
188
|
+
warn 'Warning: redundant data filtering configuration detected'
|
199
189
|
end
|
200
|
-
end
|
201
190
|
|
202
|
-
|
203
|
-
|
204
|
-
|
191
|
+
new_authorized_query(actor, action, resource_cls)
|
192
|
+
else
|
193
|
+
old_authorized_query(actor, action, resource_cls)
|
194
|
+
end
|
205
195
|
end
|
206
196
|
|
207
197
|
# Determine the resources of type +resource_cls+ that +actor+
|
@@ -213,10 +203,15 @@ module Oso
|
|
213
203
|
#
|
214
204
|
# @return A list of resources accessible to the actor.
|
215
205
|
def authorized_resources(actor, action, resource_cls)
|
216
|
-
q = authorized_query
|
217
|
-
|
218
|
-
|
219
|
-
|
206
|
+
q = authorized_query(actor, action, resource_cls)
|
207
|
+
|
208
|
+
if host.use_new_data_filtering?
|
209
|
+
host.adapter.execute_query q
|
210
|
+
elsif q.nil?
|
211
|
+
[]
|
212
|
+
else
|
213
|
+
host.types[resource_cls].exec_query[q]
|
214
|
+
end
|
220
215
|
end
|
221
216
|
|
222
217
|
# Register default values for data filtering query functions.
|
@@ -228,5 +223,9 @@ module Oso
|
|
228
223
|
host.exec_query = exec_query if exec_query
|
229
224
|
host.combine_query = combine_query if combine_query
|
230
225
|
end
|
226
|
+
|
227
|
+
def data_filtering_adapter=(adapter)
|
228
|
+
host.adapter = adapter
|
229
|
+
end
|
231
230
|
end
|
232
231
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Oso
|
4
|
+
module Polar
|
5
|
+
module Data
|
6
|
+
class Adapter
|
7
|
+
# Example data filtering adapter for ActiveRecord
|
8
|
+
class ActiveRecordAdapter < Adapter
|
9
|
+
def build_query(filter) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
10
|
+
types = filter.types
|
11
|
+
query = filter.relations.reduce(filter.model.all) do |q, rel|
|
12
|
+
rec = types[rel.left].fields[rel.name]
|
13
|
+
q.joins(
|
14
|
+
"INNER JOIN #{rel.right.table_name} ON " \
|
15
|
+
"#{rel.left.table_name}.#{rec.my_field} = " \
|
16
|
+
"#{rel.right.table_name}.#{rec.other_field}"
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
filter.conditions.map do |conjs|
|
21
|
+
conjs.reduce(query) do |q, conj|
|
22
|
+
q.where(*sqlize(conj))
|
23
|
+
end
|
24
|
+
end.reduce(:or).distinct
|
25
|
+
end
|
26
|
+
|
27
|
+
def execute_query(query)
|
28
|
+
query.to_a
|
29
|
+
end
|
30
|
+
|
31
|
+
OPS = {
|
32
|
+
'Eq' => '=', 'In' => 'IN', 'Nin' => 'NOT IN', 'Neq' => '!='
|
33
|
+
}.freeze
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def sqlize(cond)
|
38
|
+
args = []
|
39
|
+
lhs = add_side cond.left, args
|
40
|
+
rhs = add_side cond.right, args
|
41
|
+
args.unshift "#{lhs} #{OPS[cond.cmp]} #{rhs}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_side(side, args)
|
45
|
+
if side.is_a? ::Oso::Polar::Data::Filter::Projection
|
46
|
+
"#{side.source.table_name}.#{side.field || side.source.primary_key}"
|
47
|
+
else
|
48
|
+
args.push side
|
49
|
+
'?'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Oso
|
4
|
+
module Polar
|
5
|
+
module Data
|
6
|
+
# Abstract data adapter
|
7
|
+
#
|
8
|
+
# An Adapter has to implement two methods.
|
9
|
+
class Adapter
|
10
|
+
# Make a query object from a filter
|
11
|
+
def build_query(_filter)
|
12
|
+
raise "build_query not implemented for #{self}"
|
13
|
+
end
|
14
|
+
|
15
|
+
# Make a list of objects from a query
|
16
|
+
def execute_query(_query)
|
17
|
+
raise "execute_query not implemented for #{self}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Oso
|
4
|
+
module Polar
|
5
|
+
# Data filtering interface for Ruby
|
6
|
+
module Data
|
7
|
+
# Abstract data filter used by the Adapter API.
|
8
|
+
class Filter
|
9
|
+
attr_reader :model, :relations, :conditions, :types
|
10
|
+
|
11
|
+
def initialize(model:, relations:, conditions:, types:)
|
12
|
+
@model = model
|
13
|
+
@relations = relations
|
14
|
+
@conditions = conditions
|
15
|
+
@types = types
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.parse(polar, blob)
|
19
|
+
types = polar.host.types
|
20
|
+
model = types[blob['root']].klass.get
|
21
|
+
relations = blob['relations'].map do |rel|
|
22
|
+
Relation.parse(polar, *rel)
|
23
|
+
end
|
24
|
+
conditions = blob['conditions'].map do |disj|
|
25
|
+
disj.map { |conj| Condition.parse(polar, *conj) }
|
26
|
+
end
|
27
|
+
new(model: model, relations: relations, conditions: conditions, types: types)
|
28
|
+
end
|
29
|
+
|
30
|
+
Projection = Struct.new(:source, :field)
|
31
|
+
|
32
|
+
Relation = Struct.new(:left, :name, :right) do
|
33
|
+
def self.parse(polar, left, name, right)
|
34
|
+
Relation.new(polar.name_to_class(left), name, polar.name_to_class(right))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
Condition = Struct.new(:left, :cmp, :right) do
|
39
|
+
def self.parse(polar, left, cmp, right)
|
40
|
+
Condition.new(parse_side(polar, left), cmp, parse_side(polar, right))
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.parse_side(polar, side)
|
44
|
+
key = side.keys.first
|
45
|
+
val = side[key]
|
46
|
+
case key
|
47
|
+
when 'Field'
|
48
|
+
Projection.new(polar.name_to_class(val[0]), val[1])
|
49
|
+
when 'Immediate'
|
50
|
+
polar.host.to_ruby('value' => [[val.keys.first, val.values.first]])
|
51
|
+
else
|
52
|
+
raise key
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/oso/polar/errors.rb
CHANGED
@@ -26,7 +26,6 @@ module Oso
|
|
26
26
|
class UnsupportedError < PolarRuntimeError; end
|
27
27
|
class PolarTypeError < PolarRuntimeError; end
|
28
28
|
class StackOverflowError < PolarRuntimeError; end
|
29
|
-
class FileLoadingError < PolarRuntimeError; end
|
30
29
|
|
31
30
|
# Errors originating from this side of the FFI boundary.
|
32
31
|
|
data/lib/oso/polar/expression.rb
CHANGED
data/lib/oso/polar/ffi/error.rb
CHANGED
@@ -6,29 +6,13 @@ module Oso
|
|
6
6
|
module Polar
|
7
7
|
module FFI
|
8
8
|
# Wrapper class for Error FFI pointer + operations.
|
9
|
-
class Error
|
10
|
-
def to_s
|
11
|
-
@to_s ||= read_string.force_encoding('UTF-8')
|
12
|
-
end
|
13
|
-
|
14
|
-
Rust = Module.new do
|
15
|
-
extend ::FFI::Library
|
16
|
-
ffi_lib FFI::LIB_PATH
|
17
|
-
|
18
|
-
attach_function :get, :polar_get_error, [], Error
|
19
|
-
attach_function :free, :string_free, [Error], :int32
|
20
|
-
end
|
21
|
-
private_constant :Rust
|
22
|
-
|
9
|
+
class Error
|
23
10
|
# Check for an FFI error and convert it into a Ruby exception.
|
24
11
|
#
|
25
12
|
# @return [::Oso::Polar::Error] if there's an FFI error.
|
26
13
|
# @return [::Oso::Polar::FFIErrorNotFound] if there isn't one.
|
27
|
-
def self.get(enrich_message) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
28
|
-
error =
|
29
|
-
return ::Oso::Polar::FFIErrorNotFound if error.null?
|
30
|
-
|
31
|
-
error = JSON.parse(error.to_s)
|
14
|
+
def self.get(error_str, enrich_message) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
15
|
+
error = JSON.parse(error_str.to_s)
|
32
16
|
msg = error['formatted']
|
33
17
|
kind, body = error['kind'].first
|
34
18
|
|
@@ -90,7 +74,7 @@ module Oso
|
|
90
74
|
# @param msg [String]
|
91
75
|
# @param details [Hash<String, Object>]
|
92
76
|
# @return [::Oso::Polar::PolarRuntimeError] the object converted into the expected format.
|
93
|
-
private_class_method def self.runtime_error(kind, msg:, details:)
|
77
|
+
private_class_method def self.runtime_error(kind, msg:, details:)
|
94
78
|
case kind
|
95
79
|
when 'Unsupported'
|
96
80
|
::Oso::Polar::UnsupportedError.new(msg, details: details)
|
@@ -98,8 +82,6 @@ module Oso
|
|
98
82
|
::Oso::Polar::PolarTypeError.new(msg, details: details)
|
99
83
|
when 'StackOverflow'
|
100
84
|
::Oso::Polar::StackOverflowError.new(msg, details: details)
|
101
|
-
when 'FileLoading'
|
102
|
-
::Oso::Polar::FileLoadingError.new(msg, details: details)
|
103
85
|
else
|
104
86
|
::Oso::Polar::PolarRuntimeError.new(msg, details: details)
|
105
87
|
end
|
data/lib/oso/polar/ffi/polar.rb
CHANGED
@@ -6,7 +6,7 @@ module Oso
|
|
6
6
|
module Polar
|
7
7
|
module FFI
|
8
8
|
# Wrapper class for Polar FFI pointer + operations.
|
9
|
-
class Polar < ::FFI::AutoPointer
|
9
|
+
class Polar < ::FFI::AutoPointer # rubocop:disable Metrics/ClassLength
|
10
10
|
attr_accessor :enrich_message
|
11
11
|
|
12
12
|
Rust = Module.new do
|
@@ -14,21 +14,28 @@ module Oso
|
|
14
14
|
ffi_lib FFI::LIB_PATH
|
15
15
|
|
16
16
|
attach_function :new, :polar_new, [], FFI::Polar
|
17
|
-
attach_function :load, :polar_load, [FFI::Polar, :string],
|
18
|
-
attach_function :clear_rules, :polar_clear_rules, [FFI::Polar],
|
17
|
+
attach_function :load, :polar_load, [FFI::Polar, :string], CResultVoid
|
18
|
+
attach_function :clear_rules, :polar_clear_rules, [FFI::Polar], CResultVoid
|
19
19
|
attach_function :next_inline_query, :polar_next_inline_query, [FFI::Polar, :uint32], FFI::Query
|
20
20
|
attach_function :new_id, :polar_get_external_id, [FFI::Polar], :uint64
|
21
|
-
attach_function :new_query_from_str, :polar_new_query, [FFI::Polar, :string, :uint32],
|
22
|
-
attach_function :new_query_from_term, :polar_new_query_from_term, [FFI::Polar, :string, :uint32],
|
23
|
-
attach_function :register_constant, :polar_register_constant, [FFI::Polar, :string, :string],
|
24
|
-
attach_function :register_mro, :polar_register_mro, [FFI::Polar, :string, :string],
|
25
|
-
attach_function :next_message, :polar_next_polar_message, [FFI::Polar],
|
21
|
+
attach_function :new_query_from_str, :polar_new_query, [FFI::Polar, :string, :uint32], CResultQuery
|
22
|
+
attach_function :new_query_from_term, :polar_new_query_from_term, [FFI::Polar, :string, :uint32], CResultQuery
|
23
|
+
attach_function :register_constant, :polar_register_constant, [FFI::Polar, :string, :string], CResultVoid
|
24
|
+
attach_function :register_mro, :polar_register_mro, [FFI::Polar, :string, :string], CResultVoid
|
25
|
+
attach_function :next_message, :polar_next_polar_message, [FFI::Polar], CResultString
|
26
26
|
attach_function :free, :polar_free, [FFI::Polar], :int32
|
27
|
+
attach_function :result_free, :result_free, [:pointer], :int32
|
27
28
|
attach_function(
|
28
29
|
:build_filter_plan,
|
29
30
|
:polar_build_filter_plan,
|
30
31
|
[FFI::Polar, :string, :string, :string, :string],
|
31
|
-
|
32
|
+
CResultString
|
33
|
+
)
|
34
|
+
attach_function(
|
35
|
+
:build_data_filter,
|
36
|
+
:polar_build_data_filter,
|
37
|
+
[FFI::Polar, :string, :string, :string, :string],
|
38
|
+
CResultString
|
32
39
|
)
|
33
40
|
end
|
34
41
|
private_constant :Rust
|
@@ -36,10 +43,7 @@ module Oso
|
|
36
43
|
# @return [FFI::Polar]
|
37
44
|
# @raise [FFI::Error] if the FFI call returns an error.
|
38
45
|
def self.create
|
39
|
-
|
40
|
-
handle_error if polar.null?
|
41
|
-
|
42
|
-
polar
|
46
|
+
Rust.new
|
43
47
|
end
|
44
48
|
|
45
49
|
def build_filter_plan(types, partials, variable, class_tag)
|
@@ -47,9 +51,19 @@ module Oso
|
|
47
51
|
partials = JSON.dump(partials)
|
48
52
|
plan = Rust.build_filter_plan(self, types, partials, variable, class_tag)
|
49
53
|
process_messages
|
50
|
-
|
54
|
+
plan = check_result plan
|
55
|
+
# TODO(gw) more error checking?
|
56
|
+
JSON.parse plan.to_s
|
57
|
+
end
|
58
|
+
|
59
|
+
def build_data_filter(types, partials, variable, class_tag)
|
60
|
+
types = JSON.dump(types)
|
61
|
+
partials = JSON.dump(partials)
|
62
|
+
plan = Rust.build_data_filter(self, types, partials, variable, class_tag)
|
63
|
+
process_messages
|
64
|
+
plan = check_result plan
|
51
65
|
# TODO(gw) more error checking?
|
52
|
-
JSON.parse plan
|
66
|
+
JSON.parse plan.to_s
|
53
67
|
end
|
54
68
|
|
55
69
|
# @param sources [Array<Source>]
|
@@ -57,14 +71,14 @@ module Oso
|
|
57
71
|
def load(sources)
|
58
72
|
loaded = Rust.load(self, JSON.dump(sources))
|
59
73
|
process_messages
|
60
|
-
|
74
|
+
check_result loaded
|
61
75
|
end
|
62
76
|
|
63
77
|
# @raise [FFI::Error] if the FFI call returns an error.
|
64
78
|
def clear_rules
|
65
79
|
cleared = Rust.clear_rules(self)
|
66
80
|
process_messages
|
67
|
-
|
81
|
+
check_result cleared
|
68
82
|
end
|
69
83
|
|
70
84
|
# @return [FFI::Query] if there are remaining inline queries.
|
@@ -79,12 +93,7 @@ module Oso
|
|
79
93
|
# @return [Integer]
|
80
94
|
# @raise [FFI::Error] if the FFI call returns an error.
|
81
95
|
def new_id
|
82
|
-
|
83
|
-
# TODO(gj): I don't think this error check is correct. If getting a new ID fails on the
|
84
|
-
# Rust side, it'll probably surface as a panic (e.g., the KB lock is poisoned).
|
85
|
-
handle_error if id.zero?
|
86
|
-
|
87
|
-
id
|
96
|
+
Rust.new_id(self)
|
88
97
|
end
|
89
98
|
|
90
99
|
# @param str [String] Query string.
|
@@ -93,9 +102,7 @@ module Oso
|
|
93
102
|
def new_query_from_str(str)
|
94
103
|
query = Rust.new_query_from_str(self, str, 0)
|
95
104
|
process_messages
|
96
|
-
|
97
|
-
|
98
|
-
query
|
105
|
+
check_result query
|
99
106
|
end
|
100
107
|
|
101
108
|
# @param term [Hash<String, Object>]
|
@@ -104,9 +111,7 @@ module Oso
|
|
104
111
|
def new_query_from_term(term)
|
105
112
|
query = Rust.new_query_from_term(self, JSON.dump(term), 0)
|
106
113
|
process_messages
|
107
|
-
|
108
|
-
|
109
|
-
query
|
114
|
+
check_result query
|
110
115
|
end
|
111
116
|
|
112
117
|
# @param name [String]
|
@@ -114,7 +119,7 @@ module Oso
|
|
114
119
|
# @raise [FFI::Error] if the FFI call returns an error.
|
115
120
|
def register_constant(value, name:)
|
116
121
|
registered = Rust.register_constant(self, name, JSON.dump(value))
|
117
|
-
|
122
|
+
check_result registered
|
118
123
|
end
|
119
124
|
|
120
125
|
# @param name [String]
|
@@ -122,11 +127,24 @@ module Oso
|
|
122
127
|
# @raise [FFI::Error] if the FFI call returns an error.
|
123
128
|
def register_mro(name, mro)
|
124
129
|
registered = Rust.register_mro(self, name, JSON.dump(mro))
|
125
|
-
|
130
|
+
check_result registered
|
126
131
|
end
|
127
132
|
|
128
133
|
def next_message
|
129
|
-
Rust.next_message(self)
|
134
|
+
check_result Rust.next_message(self)
|
135
|
+
end
|
136
|
+
|
137
|
+
def process_message(message, enrich_message)
|
138
|
+
message = JSON.parse(message.to_s)
|
139
|
+
kind = message['kind']
|
140
|
+
msg = enrich_message.call(message['msg'])
|
141
|
+
|
142
|
+
case kind
|
143
|
+
when 'Print'
|
144
|
+
puts(msg)
|
145
|
+
when 'Warning'
|
146
|
+
warn(format('[warning] %<msg>s', msg: msg))
|
147
|
+
end
|
130
148
|
end
|
131
149
|
|
132
150
|
def process_messages
|
@@ -134,12 +152,19 @@ module Oso
|
|
134
152
|
message = next_message
|
135
153
|
break if message.null?
|
136
154
|
|
137
|
-
message
|
155
|
+
process_message(message, enrich_message)
|
138
156
|
end
|
139
157
|
end
|
140
158
|
|
141
|
-
def
|
142
|
-
|
159
|
+
def check_result(res)
|
160
|
+
result = res[:result]
|
161
|
+
error = res[:error]
|
162
|
+
Rust.result_free(res)
|
163
|
+
|
164
|
+
raise 'internal error: both result and error pointers are not null' if !error.null? && !result.zero?
|
165
|
+
raise FFI::Error.get(error, enrich_message) unless error.null?
|
166
|
+
|
167
|
+
result
|
143
168
|
end
|
144
169
|
end
|
145
170
|
end
|
data/lib/oso/polar/ffi/query.rb
CHANGED
@@ -13,15 +13,16 @@ module Oso
|
|
13
13
|
extend ::FFI::Library
|
14
14
|
ffi_lib FFI::LIB_PATH
|
15
15
|
|
16
|
-
attach_function :debug_command, :polar_debug_command, [FFI::Query, :string],
|
17
|
-
attach_function :call_result, :polar_call_result, [FFI::Query, :uint64, :string],
|
18
|
-
attach_function :question_result, :polar_question_result, [FFI::Query, :uint64, :int32],
|
19
|
-
attach_function :application_error, :polar_application_error, [FFI::Query, :string],
|
20
|
-
attach_function :next_event, :polar_next_query_event, [FFI::Query],
|
21
|
-
attach_function :next_message, :polar_next_query_message, [FFI::Query],
|
22
|
-
attach_function :source, :polar_query_source_info, [FFI::Query],
|
16
|
+
attach_function :debug_command, :polar_debug_command, [FFI::Query, :string], CResultVoid
|
17
|
+
attach_function :call_result, :polar_call_result, [FFI::Query, :uint64, :string], CResultVoid
|
18
|
+
attach_function :question_result, :polar_question_result, [FFI::Query, :uint64, :int32], CResultVoid
|
19
|
+
attach_function :application_error, :polar_application_error, [FFI::Query, :string], CResultVoid
|
20
|
+
attach_function :next_event, :polar_next_query_event, [FFI::Query], CResultString
|
21
|
+
attach_function :next_message, :polar_next_query_message, [FFI::Query], CResultString
|
22
|
+
attach_function :source, :polar_query_source_info, [FFI::Query], CResultString
|
23
23
|
attach_function :free, :query_free, [FFI::Query], :int32
|
24
|
-
attach_function :
|
24
|
+
attach_function :result_free, :result_free, [:pointer], :int32
|
25
|
+
attach_function :bind, :polar_bind, [FFI::Query, :string, :string], CResultVoid
|
25
26
|
end
|
26
27
|
private_constant :Rust
|
27
28
|
|
@@ -30,15 +31,15 @@ module Oso
|
|
30
31
|
def debug_command(cmd)
|
31
32
|
res = Rust.debug_command(self, cmd)
|
32
33
|
process_messages
|
33
|
-
|
34
|
+
check_result res
|
34
35
|
end
|
35
36
|
|
36
|
-
# @param
|
37
|
+
# @param value [Object]
|
37
38
|
# @param call_id [Integer]
|
38
39
|
# @raise [FFI::Error] if the FFI call returns an error.
|
39
|
-
def call_result(
|
40
|
-
res = Rust.call_result(self, call_id,
|
41
|
-
|
40
|
+
def call_result(value, call_id:)
|
41
|
+
res = Rust.call_result(self, call_id, JSON.dump(value))
|
42
|
+
check_result res
|
42
43
|
end
|
43
44
|
|
44
45
|
# @param result [Boolean]
|
@@ -47,14 +48,14 @@ module Oso
|
|
47
48
|
def question_result(result, call_id:)
|
48
49
|
result = result ? 1 : 0
|
49
50
|
res = Rust.question_result(self, call_id, result)
|
50
|
-
|
51
|
+
check_result res
|
51
52
|
end
|
52
53
|
|
53
54
|
# @param message [String]
|
54
55
|
# @raise [FFI::Error] if the FFI call returns an error.
|
55
56
|
def application_error(message)
|
56
57
|
res = Rust.application_error(self, message)
|
57
|
-
|
58
|
+
check_result res
|
58
59
|
end
|
59
60
|
|
60
61
|
# @return [::Oso::Polar::QueryEvent]
|
@@ -62,18 +63,32 @@ module Oso
|
|
62
63
|
def next_event
|
63
64
|
event = Rust.next_event(self)
|
64
65
|
process_messages
|
65
|
-
|
66
|
+
event = check_result event
|
66
67
|
|
67
68
|
::Oso::Polar::QueryEvent.new(JSON.parse(event.to_s))
|
68
69
|
end
|
69
70
|
|
70
71
|
def bind(name, value)
|
71
72
|
res = Rust.bind(self, name, JSON.dump(value))
|
72
|
-
|
73
|
+
check_result res
|
73
74
|
end
|
74
75
|
|
75
76
|
def next_message
|
76
|
-
Rust.next_message(self)
|
77
|
+
check_result Rust.next_message(self)
|
78
|
+
end
|
79
|
+
|
80
|
+
def process_message(message, enrich_message)
|
81
|
+
message = JSON.parse(message.to_s)
|
82
|
+
kind = message['kind']
|
83
|
+
msg = message['msg']
|
84
|
+
msg = enrich_message.call(msg)
|
85
|
+
|
86
|
+
case kind
|
87
|
+
when 'Print'
|
88
|
+
puts(msg)
|
89
|
+
when 'Warning'
|
90
|
+
warn(format('[warning] %<msg>s', msg: msg))
|
91
|
+
end
|
77
92
|
end
|
78
93
|
|
79
94
|
def process_messages
|
@@ -81,7 +96,7 @@ module Oso
|
|
81
96
|
message = next_message
|
82
97
|
break if message.null?
|
83
98
|
|
84
|
-
message
|
99
|
+
process_message(message, enrich_message)
|
85
100
|
end
|
86
101
|
end
|
87
102
|
|
@@ -89,13 +104,24 @@ module Oso
|
|
89
104
|
# @raise [FFI::Error] if the FFI call returns an error.
|
90
105
|
def source
|
91
106
|
res = Rust.source(self)
|
92
|
-
|
107
|
+
res = check_result res
|
93
108
|
|
94
109
|
res.to_s
|
95
110
|
end
|
96
111
|
|
97
|
-
|
98
|
-
|
112
|
+
# Unwrap the result by (a) extracting the pointers for
|
113
|
+
# result and error, (b) freeing the result pointers, and then
|
114
|
+
# (c) either returning the result pointer, or constructing and
|
115
|
+
# raising the error.
|
116
|
+
def check_result(res)
|
117
|
+
result = res[:result]
|
118
|
+
error = res[:error]
|
119
|
+
Rust.result_free(res)
|
120
|
+
|
121
|
+
raise 'internal error: both result and error pointers are not null' if !error.null? && !result.zero?
|
122
|
+
raise FFI::Error.get(error, enrich_message) unless error.null?
|
123
|
+
|
124
|
+
result
|
99
125
|
end
|
100
126
|
end
|
101
127
|
end
|
@@ -1,10 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'json'
|
4
|
+
|
3
5
|
module Oso
|
4
6
|
module Polar
|
5
7
|
module FFI
|
6
|
-
# Wrapper class for
|
7
|
-
|
8
|
+
# Wrapper class for Rust strings.
|
9
|
+
#
|
10
|
+
# Since we force all strings to go through this
|
11
|
+
# the `AutoPointer` class will handle
|
12
|
+
# actually freeing the string when deleting it
|
13
|
+
class RustString < ::FFI::AutoPointer
|
8
14
|
# @return [String]
|
9
15
|
def to_s
|
10
16
|
@to_s ||= read_string.force_encoding('UTF-8')
|
@@ -14,7 +20,7 @@ module Oso
|
|
14
20
|
extend ::FFI::Library
|
15
21
|
ffi_lib FFI::LIB_PATH
|
16
22
|
|
17
|
-
attach_function :free, :string_free, [
|
23
|
+
attach_function :free, :string_free, [RustString], :int32
|
18
24
|
end
|
19
25
|
|
20
26
|
private_constant :Rust
|
data/lib/oso/polar/ffi.rb
CHANGED
@@ -4,6 +4,7 @@ require 'ffi'
|
|
4
4
|
|
5
5
|
module Oso
|
6
6
|
module Polar
|
7
|
+
# FFI classes shared between all ffi/*.rb modules
|
7
8
|
module FFI
|
8
9
|
LIB = "#{::FFI::Platform::LIBPREFIX}polar.#{::FFI::Platform::LIBSUFFIX}"
|
9
10
|
RELEASE_PATH = File.expand_path(File.join(__dir__, "../../../ext/oso-oso/lib/#{LIB}"))
|
@@ -18,41 +19,50 @@ module Oso
|
|
18
19
|
|
19
20
|
# Wrapper class for Polar FFI pointer + operations.
|
20
21
|
class Polar < ::FFI::AutoPointer
|
22
|
+
def zero?
|
23
|
+
null?
|
24
|
+
end
|
25
|
+
|
21
26
|
def self.release(ptr)
|
22
27
|
Rust.free(ptr) unless ptr.null?
|
23
28
|
end
|
24
29
|
end
|
25
30
|
# Wrapper class for Query FFI pointer + operations.
|
26
31
|
class Query < ::FFI::AutoPointer
|
27
|
-
def
|
28
|
-
|
32
|
+
def zero?
|
33
|
+
null?
|
29
34
|
end
|
30
|
-
|
31
|
-
# Wrapper class for QueryEvent FFI pointer + operations.
|
32
|
-
class QueryEvent < ::FFI::AutoPointer
|
35
|
+
|
33
36
|
def self.release(ptr)
|
34
37
|
Rust.free(ptr) unless ptr.null?
|
35
38
|
end
|
36
39
|
end
|
37
|
-
|
38
|
-
class
|
39
|
-
|
40
|
-
|
40
|
+
|
41
|
+
# Wrapper class for Rust strings FFI pointer + operations.
|
42
|
+
class RustString < ::FFI::AutoPointer
|
43
|
+
def zero?
|
44
|
+
null?
|
41
45
|
end
|
42
|
-
|
43
|
-
# Wrapper class for Message FFI pointer + operations.
|
44
|
-
class Message < ::FFI::AutoPointer
|
46
|
+
|
45
47
|
def self.release(ptr)
|
46
48
|
Rust.free(ptr) unless ptr.null?
|
47
49
|
end
|
48
50
|
end
|
49
51
|
|
50
|
-
#
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
52
|
+
# Helper method to generate a Result type for different
|
53
|
+
# inner types
|
54
|
+
def self.result(result_klass)
|
55
|
+
Class.new(::FFI::Struct) do
|
56
|
+
layout :result, result_klass, :error, RustString
|
57
|
+
end.by_ref
|
55
58
|
end
|
59
|
+
|
60
|
+
# Defines the result type version of
|
61
|
+
# each of these structs
|
62
|
+
# result(T) => { result: T, error: string }
|
63
|
+
CResultVoid = result(:int)
|
64
|
+
CResultString = result(RustString)
|
65
|
+
CResultQuery = result(Query)
|
56
66
|
end
|
57
67
|
private_constant :FFI
|
58
68
|
end
|
@@ -60,7 +70,5 @@ end
|
|
60
70
|
|
61
71
|
require 'oso/polar/ffi/polar'
|
62
72
|
require 'oso/polar/ffi/query'
|
63
|
-
require 'oso/polar/ffi/query_event'
|
64
73
|
require 'oso/polar/ffi/error'
|
65
|
-
require 'oso/polar/ffi/
|
66
|
-
require 'oso/polar/ffi/source'
|
74
|
+
require 'oso/polar/ffi/rust_string'
|
data/lib/oso/polar/host.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'data'
|
4
|
+
|
3
5
|
module Oso
|
4
6
|
module Polar
|
5
7
|
# Ruby code reloaders (i.e. the one used by rails) swap out the value of
|
@@ -67,7 +69,7 @@ module Oso
|
|
67
69
|
public
|
68
70
|
|
69
71
|
attr_writer :accept_expression
|
70
|
-
attr_accessor :build_query, :combine_query, :exec_query
|
72
|
+
attr_accessor :build_query, :combine_query, :exec_query, :adapter
|
71
73
|
|
72
74
|
DEFAULT_COMBINE_QUERY = proc { raise 'implement combine_query to use data filtering' }
|
73
75
|
DEFAULT_BUILD_QUERY = proc { raise 'implement build_query to use data filtering' }
|
@@ -95,9 +97,10 @@ module Oso
|
|
95
97
|
# @return [Class]
|
96
98
|
# @raise [UnregisteredClassError] if the class has not been registered.
|
97
99
|
def get_class(name)
|
98
|
-
|
100
|
+
typ = types[name]
|
101
|
+
raise UnregisteredClassError, name if typ.nil?
|
99
102
|
|
100
|
-
|
103
|
+
typ.klass.get
|
101
104
|
end
|
102
105
|
|
103
106
|
# Store a Ruby class in the {#types} cache.
|
@@ -337,21 +340,25 @@ module Oso
|
|
337
340
|
value
|
338
341
|
when 'Number'
|
339
342
|
num = value.values.first
|
340
|
-
|
343
|
+
case value.keys.first
|
344
|
+
when 'Float'
|
341
345
|
case num
|
342
346
|
when 'Infinity'
|
343
|
-
|
347
|
+
Float::INFINITY
|
344
348
|
when '-Infinity'
|
345
|
-
|
349
|
+
-Float::INFINITY
|
346
350
|
when 'NaN'
|
347
|
-
|
351
|
+
Float::NAN
|
348
352
|
else
|
349
353
|
unless value['Float'].is_a? Float # rubocop:disable Metrics/BlockNesting
|
350
354
|
raise PolarRuntimeError, "Expected a floating point number, got \"#{value['Float']}\""
|
351
355
|
end
|
356
|
+
|
357
|
+
num
|
352
358
|
end
|
359
|
+
else
|
360
|
+
num
|
353
361
|
end
|
354
|
-
num
|
355
362
|
when 'List'
|
356
363
|
value.map { |el| to_ruby(el) }
|
357
364
|
when 'Dictionary'
|
@@ -389,6 +396,10 @@ module Oso
|
|
389
396
|
get_instance(Regexp.last_match[1].to_i).to_s
|
390
397
|
end
|
391
398
|
end
|
399
|
+
|
400
|
+
def use_new_data_filtering?
|
401
|
+
!adapter.nil?
|
402
|
+
end
|
392
403
|
end
|
393
404
|
end
|
394
405
|
end
|
data/lib/oso/polar/polar.rb
CHANGED
@@ -84,20 +84,8 @@ module Oso
|
|
84
84
|
@ffi_polar
|
85
85
|
end
|
86
86
|
|
87
|
-
|
88
|
-
|
89
|
-
def get_class_name(klass) # rubocop:disable Metrics/AbcSize
|
90
|
-
if host.types.key? klass
|
91
|
-
host.types[klass].name
|
92
|
-
elsif host.types.key? klass.name
|
93
|
-
host.types[klass.name].name
|
94
|
-
else
|
95
|
-
rec = host.types.values.find { |v| v.klass.get == klass }
|
96
|
-
raise "Unknown class `#{klass}`" if rec.nil?
|
97
|
-
|
98
|
-
host.types[klass] = rec
|
99
|
-
rec.name
|
100
|
-
end
|
87
|
+
def name_to_class(class_name)
|
88
|
+
host.types[class_name].klass.get
|
101
89
|
end
|
102
90
|
|
103
91
|
# Clear all rules and rule sources from the current Polar instance
|
@@ -259,10 +247,89 @@ module Oso
|
|
259
247
|
|
260
248
|
private
|
261
249
|
|
250
|
+
# new/old data filtering core API shared logic
|
251
|
+
def partial_query(actor, action, resource_cls) # rubocop:disable Metrics/MethodLength
|
252
|
+
var_name = 'resource'
|
253
|
+
resource = Variable.new var_name
|
254
|
+
|
255
|
+
partials = query_rule(
|
256
|
+
'allow',
|
257
|
+
actor,
|
258
|
+
action,
|
259
|
+
resource,
|
260
|
+
bindings: { var_name => type_constraint(resource, resource_cls) },
|
261
|
+
accept_expression: true
|
262
|
+
)
|
263
|
+
|
264
|
+
partials.each_with_object([]) do |result, out|
|
265
|
+
result.each do |key, val|
|
266
|
+
out.push prefilter_isas(key, val)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
def new_authorized_query(actor, action, resource_class)
|
272
|
+
partials = partial_query(actor, action, resource_class)
|
273
|
+
types = host.serialize_types
|
274
|
+
class_name = class_to_name resource_class
|
275
|
+
plan = ffi.build_data_filter(types, partials, 'resource', class_name)
|
276
|
+
filter = ::Oso::Polar::Data::Filter.parse(self, plan)
|
277
|
+
host.adapter.build_query filter
|
278
|
+
end
|
279
|
+
|
280
|
+
def old_authorized_query(actor, action, resource_cls)
|
281
|
+
results = partial_query(actor, action, resource_cls)
|
282
|
+
::Oso::Polar::DataFiltering::FilterPlan
|
283
|
+
.parse(self, results, class_to_name(resource_cls))
|
284
|
+
.build_query
|
285
|
+
end
|
286
|
+
|
287
|
+
# handle Isa constraints in a partial query
|
288
|
+
def prefilter_isas(key, val) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
289
|
+
# this will usually be the case! sometimes not, if it's an instance.
|
290
|
+
if val.is_a?(Expression) && val.operator == 'And'
|
291
|
+
# get the isas
|
292
|
+
isas, othas = val.args.partition do |expr|
|
293
|
+
expr.operator == 'Isa' &&
|
294
|
+
expr.args[1].is_a?(Pattern) &&
|
295
|
+
expr.args[1].fields.empty?
|
296
|
+
end
|
297
|
+
|
298
|
+
# drop all the isas we can verify now, keep everything else
|
299
|
+
othas += isas.reject do |isa|
|
300
|
+
isa.args[0].is_a? name_to_class isa.args[1].tag
|
301
|
+
end
|
302
|
+
|
303
|
+
# TODO(gw) check the rest of them instead of just adding them?
|
304
|
+
val.args = othas
|
305
|
+
end
|
306
|
+
val = host.to_polar val
|
307
|
+
{ 'bindings' => { key => val } }
|
308
|
+
end
|
309
|
+
|
310
|
+
# get the (maybe user-supplied) name of a class.
|
311
|
+
# kind of a hack because of class autoreloading.
|
312
|
+
def class_to_name(klass) # rubocop:disable Metrics/AbcSize
|
313
|
+
if (rec = host.types[klass]) || (rec = host.types[klass.name])
|
314
|
+
rec.name
|
315
|
+
elsif (rec = host.types.values.find { |v| v.klass.get == klass })
|
316
|
+
host.types[klass] = rec
|
317
|
+
rec.name
|
318
|
+
else
|
319
|
+
raise NameError, "Unknown class `#{klass}`"
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
def try_class_to_name(klass)
|
324
|
+
class_to_name klass
|
325
|
+
rescue NameError
|
326
|
+
nil
|
327
|
+
end
|
328
|
+
|
262
329
|
def type_constraint(var, cls)
|
263
330
|
Expression.new(
|
264
331
|
'And',
|
265
|
-
[Expression.new('Isa', [var, Pattern.new(
|
332
|
+
[Expression.new('Isa', [var, Pattern.new(class_to_name(cls), {})])]
|
266
333
|
)
|
267
334
|
end
|
268
335
|
|
data/lib/oso/polar/query.rb
CHANGED
@@ -94,8 +94,7 @@ module Oso
|
|
94
94
|
else
|
95
95
|
instance.__send__(attribute, *args, **kwargs)
|
96
96
|
end
|
97
|
-
|
98
|
-
call_result(result, call_id: call_id)
|
97
|
+
call_result(host.to_polar(result), call_id: call_id)
|
99
98
|
rescue ArgumentError, NoMethodError => e
|
100
99
|
application_error(e.message)
|
101
100
|
call_result(nil, call_id: call_id)
|
@@ -143,7 +142,7 @@ module Oso
|
|
143
142
|
calls[call_id] = value.lazy
|
144
143
|
end
|
145
144
|
|
146
|
-
result =
|
145
|
+
result = next_call_result(call_id)
|
147
146
|
call_result(result, call_id: call_id)
|
148
147
|
rescue StopIteration
|
149
148
|
call_result(nil, call_id: call_id)
|
@@ -245,12 +244,32 @@ module Oso
|
|
245
244
|
|
246
245
|
def handle_relationship(call_id, instance, rel) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
247
246
|
typ = host.types[rel.other_type]
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
247
|
+
|
248
|
+
if host.use_new_data_filtering?
|
249
|
+
cls = typ.klass.get
|
250
|
+
|
251
|
+
condition = ::Oso::Polar::Data::Filter::Condition.new(
|
252
|
+
::Oso::Polar::Data::Filter::Projection.new(cls, rel.other_field),
|
253
|
+
'Eq',
|
254
|
+
instance.send(rel.my_field)
|
255
|
+
)
|
256
|
+
|
257
|
+
filter = ::Oso::Polar::Data::Filter.new(
|
258
|
+
model: cls,
|
259
|
+
relations: [],
|
260
|
+
conditions: [[condition]],
|
261
|
+
types: host.types
|
262
|
+
)
|
263
|
+
|
264
|
+
res = host.adapter.execute_query host.adapter.build_query(filter)
|
265
|
+
else
|
266
|
+
constraint = ::Oso::Polar::DataFiltering::Filter.new(
|
267
|
+
kind: 'Eq',
|
268
|
+
field: rel.other_field,
|
269
|
+
value: instance.send(rel.my_field)
|
270
|
+
)
|
271
|
+
res = typ.exec_query[typ.build_query[[constraint]]]
|
272
|
+
end
|
254
273
|
|
255
274
|
if rel.kind == 'one'
|
256
275
|
raise "multiple parents: #{res}" unless res.length == 1
|
@@ -258,8 +277,7 @@ module Oso
|
|
258
277
|
res = res[0]
|
259
278
|
end
|
260
279
|
|
261
|
-
|
262
|
-
call_result(res, call_id: call_id)
|
280
|
+
call_result(host.to_polar(res), call_id: call_id)
|
263
281
|
end
|
264
282
|
end
|
265
283
|
end
|
data/lib/oso/polar.rb
CHANGED
data/lib/oso/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oso-oso
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.24.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oso Security, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -162,16 +162,18 @@ files:
|
|
162
162
|
- lib/oso/errors.rb
|
163
163
|
- lib/oso/oso.rb
|
164
164
|
- lib/oso/polar.rb
|
165
|
+
- lib/oso/polar/data.rb
|
166
|
+
- lib/oso/polar/data/adapter.rb
|
167
|
+
- lib/oso/polar/data/adapter/active_record_adapter.rb
|
168
|
+
- lib/oso/polar/data/filter.rb
|
165
169
|
- lib/oso/polar/data_filtering.rb
|
166
170
|
- lib/oso/polar/errors.rb
|
167
171
|
- lib/oso/polar/expression.rb
|
168
172
|
- lib/oso/polar/ffi.rb
|
169
173
|
- lib/oso/polar/ffi/error.rb
|
170
|
-
- lib/oso/polar/ffi/message.rb
|
171
174
|
- lib/oso/polar/ffi/polar.rb
|
172
175
|
- lib/oso/polar/ffi/query.rb
|
173
|
-
- lib/oso/polar/ffi/
|
174
|
-
- lib/oso/polar/ffi/source.rb
|
176
|
+
- lib/oso/polar/ffi/rust_string.rb
|
175
177
|
- lib/oso/polar/host.rb
|
176
178
|
- lib/oso/polar/pattern.rb
|
177
179
|
- lib/oso/polar/polar.rb
|
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'json'
|
4
|
-
|
5
|
-
module Oso
|
6
|
-
module Polar
|
7
|
-
module FFI
|
8
|
-
# Wrapper class for Message FFI pointer + operations.
|
9
|
-
class Message < ::FFI::AutoPointer
|
10
|
-
# @return [String]
|
11
|
-
def to_s
|
12
|
-
@to_s ||= read_string.force_encoding('UTF-8')
|
13
|
-
end
|
14
|
-
|
15
|
-
Rust = Module.new do
|
16
|
-
extend ::FFI::Library
|
17
|
-
ffi_lib FFI::LIB_PATH
|
18
|
-
|
19
|
-
attach_function :free, :string_free, [Message], :int32
|
20
|
-
end
|
21
|
-
|
22
|
-
def process(enrich_message)
|
23
|
-
message = JSON.parse(to_s)
|
24
|
-
kind = message['kind']
|
25
|
-
msg = message['msg']
|
26
|
-
msg = enrich_message.call(msg)
|
27
|
-
|
28
|
-
case kind
|
29
|
-
when 'Print'
|
30
|
-
puts(msg)
|
31
|
-
when 'Warning'
|
32
|
-
warn(format('[warning] %<msg>s', msg: msg))
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
private_constant :Rust
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Oso
|
4
|
-
module Polar
|
5
|
-
module FFI
|
6
|
-
# Wrapper class for QueryEvent FFI pointer + operations.
|
7
|
-
class QueryEvent < ::FFI::AutoPointer
|
8
|
-
# @return [String]
|
9
|
-
def to_s
|
10
|
-
@to_s ||= read_string.force_encoding('UTF-8')
|
11
|
-
end
|
12
|
-
|
13
|
-
Rust = Module.new do
|
14
|
-
extend ::FFI::Library
|
15
|
-
ffi_lib FFI::LIB_PATH
|
16
|
-
|
17
|
-
attach_function :free, :string_free, [FFI::QueryEvent], :int32
|
18
|
-
end
|
19
|
-
private_constant :Rust
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|