oso-oso 0.2.5

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9e511f86c5a330c1bb071824398085362def8ba7
4
+ data.tar.gz: da3baaad23fb6e28c8ef0558bbf1deb659c03700
5
+ SHA512:
6
+ metadata.gz: 9d55c689e8ffc0e3f7b533f54d3e622f77bd7f563182fc7b9dfc047a7a9b1554ed02711fbb8326f55fed76529dde2040d6f829bd4439a63773c9bb58ffb8c8a3
7
+ data.tar.gz: 60b1c8f83803656373a108a64159636292bc91c1840292e7c01ea0c74961533d076ceaa6576010ecdf9dc062bc60c6b112e9900b726db227a322aa52c41f40e0
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ vendor
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,17 @@
1
+ ---
2
+ include:
3
+ - "lib/**/*.rb"
4
+ exclude:
5
+ - spec/**/*
6
+ - test/**/*
7
+ - vendor/**/*
8
+ - ".bundle/**/*"
9
+ require: []
10
+ domains: []
11
+ reporters:
12
+ - rubocop
13
+ - require_not_found
14
+ - typecheck
15
+ require_paths: []
16
+ plugins: []
17
+ max_files: 5000
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
@@ -0,0 +1,95 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ oso-oso (0.2.5)
5
+ ffi (~> 1.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ ast (2.4.1)
11
+ backport (1.1.2)
12
+ benchmark (0.1.0)
13
+ byebug (11.1.3)
14
+ coderay (1.1.3)
15
+ diff-lcs (1.3)
16
+ e2mmap (0.1.0)
17
+ ffi (1.13.1)
18
+ jaro_winkler (1.5.4)
19
+ maruku (0.7.3)
20
+ method_source (1.0.0)
21
+ mini_portile2 (2.4.0)
22
+ nokogiri (1.10.9)
23
+ mini_portile2 (~> 2.4.0)
24
+ parallel (1.19.1)
25
+ parser (2.7.1.3)
26
+ ast (~> 2.4.0)
27
+ pry (0.13.1)
28
+ coderay (~> 1.1)
29
+ method_source (~> 1.0)
30
+ pry-byebug (3.9.0)
31
+ byebug (~> 11.0)
32
+ pry (~> 0.13.0)
33
+ rainbow (3.0.0)
34
+ rake (12.3.3)
35
+ regexp_parser (1.7.1)
36
+ reverse_markdown (2.0.0)
37
+ nokogiri
38
+ rexml (3.2.4)
39
+ rspec (3.9.0)
40
+ rspec-core (~> 3.9.0)
41
+ rspec-expectations (~> 3.9.0)
42
+ rspec-mocks (~> 3.9.0)
43
+ rspec-core (3.9.2)
44
+ rspec-support (~> 3.9.3)
45
+ rspec-expectations (3.9.2)
46
+ diff-lcs (>= 1.2.0, < 2.0)
47
+ rspec-support (~> 3.9.0)
48
+ rspec-mocks (3.9.1)
49
+ diff-lcs (>= 1.2.0, < 2.0)
50
+ rspec-support (~> 3.9.0)
51
+ rspec-support (3.9.3)
52
+ rubocop (0.85.1)
53
+ parallel (~> 1.10)
54
+ parser (>= 2.7.0.1)
55
+ rainbow (>= 2.2.2, < 4.0)
56
+ regexp_parser (>= 1.7)
57
+ rexml
58
+ rubocop-ast (>= 0.0.3)
59
+ ruby-progressbar (~> 1.7)
60
+ unicode-display_width (>= 1.4.0, < 2.0)
61
+ rubocop-ast (0.0.3)
62
+ parser (>= 2.7.0.1)
63
+ ruby-progressbar (1.10.1)
64
+ solargraph (0.39.8)
65
+ backport (~> 1.1)
66
+ benchmark
67
+ bundler (>= 1.17.2)
68
+ e2mmap
69
+ jaro_winkler (~> 1.5)
70
+ maruku (~> 0.7, >= 0.7.3)
71
+ nokogiri (~> 1.9, >= 1.9.1)
72
+ parser (~> 2.3)
73
+ reverse_markdown (>= 1.0.5, < 3)
74
+ rubocop (~> 0.52)
75
+ thor (~> 1.0)
76
+ tilt (~> 2.0)
77
+ yard (~> 0.9, >= 0.9.24)
78
+ thor (1.0.1)
79
+ tilt (2.0.10)
80
+ unicode-display_width (1.7.0)
81
+ yard (0.9.25)
82
+
83
+ PLATFORMS
84
+ ruby
85
+
86
+ DEPENDENCIES
87
+ oso-oso!
88
+ pry-byebug (~> 3.9.0)
89
+ rake (~> 12.0)
90
+ rspec (~> 3.0)
91
+ solargraph (~> 0.39.8)
92
+ yard (~> 0.9.25)
93
+
94
+ BUNDLED WITH
95
+ 2.1.4
@@ -0,0 +1,10 @@
1
+ .PHONY: install rust test
2
+
3
+ rust:
4
+ $(MAKE) -C ../.. rust-build
5
+
6
+ install: rust
7
+ bundle install
8
+
9
+ test: install
10
+ bundle exec rake spec
@@ -0,0 +1,30 @@
1
+ # Oso::Oso
2
+
3
+ ## Installation
4
+
5
+ Add this line to your application's Gemfile:
6
+
7
+ ```ruby
8
+ gem 'oso-oso'
9
+ ```
10
+
11
+ And then execute:
12
+
13
+ $ bundle install
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install oso-oso
18
+
19
+ ## Development
20
+
21
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run
22
+ `rake spec` to run the tests. You can also run `bin/console` for an interactive
23
+ prompt that will allow you to experiment.
24
+
25
+ To install this gem onto your local machine, run `bundle exec rake install`. To
26
+ release a new version, update the version number in `version.rb`, and then run
27
+ `bundle exec rake release`, which will create a git tag for the version, push
28
+ git commits and tags, and push the `.gem` file to
29
+ [rubygems.org](https://rubygems.org).
30
+
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
9
+
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'oso'
6
+
7
+ polar = Oso::Polar.new.tap do |p| # rubocop:disable Lint/UselessAssignment
8
+ p.load_str('f(1); f(2); g(1); g(2); h(2); k(x) := f(x), h(x), g(x);')
9
+ puts 'f(x)', p.send(:query_str, 'f(x)').to_a
10
+ puts 'k(x)', p.send(:query_str, 'k(x)').to_a
11
+
12
+ p.load_str('foo(1, 2); foo(3, 4); foo(5, 6);')
13
+ expected = [{ 'x' => 1, 'y' => 2 }, { 'x' => 3, 'y' => 4 }, { 'x' => 5, 'y' => 6 }]
14
+ raise 'AssertionError' if p.send(:query_str, 'foo(x, y)').to_a != expected
15
+
16
+ class TestClass # rubocop:disable Style/Documentation
17
+ def my_method
18
+ 1
19
+ end
20
+ end
21
+
22
+ p.register_class(TestClass)
23
+
24
+ p.load_str('external(x, 3) := x = new TestClass{}.my_method;')
25
+ results = p.send(:query_str, 'external(1, x)')
26
+ p results.next
27
+
28
+ # p.load_str('testDebug() := debug(), foo(x, y), k(y);')
29
+ # p.send(:query_str, 'testDebug()').next
30
+ end
31
+
32
+ require 'pry'
33
+ Pry.start
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
Binary file
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'oso/http'
4
+ require 'oso/oso'
5
+ require 'oso/path_mapper'
6
+ require 'oso/polar'
7
+ require 'oso/version'
8
+
9
+ # Top-level namespace for oso authorization library.
10
+ module Oso
11
+ def self.new
12
+ ::Oso::Oso.new
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Oso
4
+ # An HTTP resource.
5
+ class Http
6
+ def initialize(hostname: nil, path: nil, query: nil)
7
+ @hostname = hostname
8
+ @path = path
9
+ @query = query
10
+ end
11
+
12
+ private
13
+
14
+ attr_reader :hostname, :path, :query
15
+ end
16
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Oso
4
+ # Oso authorization API.
5
+ class Oso
6
+ def initialize
7
+ @polar = ::Oso::Polar.new
8
+ register_class(Http, name: 'Http')
9
+ register_class(PathMapper, name: 'PathMapper')
10
+ end
11
+
12
+ def load_file(file)
13
+ polar.load_file(file)
14
+ end
15
+
16
+ def load_str(str)
17
+ polar.load_str(str)
18
+ end
19
+
20
+ def register_class(cls, name: nil) # rubocop:disable Naming/MethodParameterName
21
+ if block_given?
22
+ polar.register_class(cls, name: name, from_polar: Proc.new)
23
+ else
24
+ polar.register_class(cls, name: name)
25
+ end
26
+ end
27
+
28
+ def allow(actor:, action:, resource:)
29
+ polar.query_pred('allow', args: [actor, action, resource]).next
30
+ true
31
+ rescue StopIteration
32
+ false
33
+ end
34
+
35
+ def query_predicate(name, *args)
36
+ polar.query_pred(name, args: args)
37
+ end
38
+
39
+ def load_queued_files
40
+ polar.load_queued_files
41
+ end
42
+
43
+ private
44
+
45
+ attr_reader :polar
46
+ end
47
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Oso
4
+ # Map from a template string with capture groups of the form
5
+ # `{name}` to a dictionary of the form `{name: captured_value}`
6
+ class PathMapper
7
+ def initialize(template:)
8
+ capture_group = /({([^}]+)})/
9
+
10
+ template = template.dup
11
+ template.scan(capture_group).each do |outer, inner|
12
+ template = if inner == '*'
13
+ template.gsub! outer, '.*'
14
+ else
15
+ template.gsub! outer, "(?<#{inner}>[^/]+)"
16
+ end
17
+ end
18
+ @pattern = /\A#{template}\Z/
19
+ end
20
+
21
+ def map(string)
22
+ string.match(pattern)&.named_captures || {}
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :pattern
28
+ end
29
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'oso/polar/errors'
4
+ require 'oso/polar/ffi'
5
+ require 'oso/polar/polar'
6
+ require 'oso/polar/predicate'
7
+ require 'oso/polar/query'
8
+ require 'oso/polar/query_event'
9
+ require 'oso/polar/variable'
10
+
11
+ module Oso
12
+ # Top-level namespace for Polar language library.
13
+ module Polar
14
+ def self.new
15
+ ::Oso::Polar::Polar.new
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Oso
4
+ module Polar
5
+ # Base error type for Oso::Polar.
6
+ class Error < ::RuntimeError
7
+ attr_reader :stack_trace
8
+
9
+ # @param message [String]
10
+ # @param details [Hash]
11
+ def initialize(message = nil, details: nil)
12
+ @details = details
13
+ if details and details.key?("stack_trace")
14
+ @stack_trace = details['stack_trace']
15
+ else
16
+ @stack_trace = nil
17
+ end
18
+ super(message)
19
+ end
20
+ end
21
+
22
+ # Expected to find an FFI error to convert into a Ruby exception but found none.
23
+ class FFIErrorNotFound < Error; end
24
+
25
+ # Generic runtime exception.
26
+ class PolarRuntimeError < Error; end
27
+
28
+ # Errors from across the FFI boundary.
29
+
30
+ class SerializationError < PolarRuntimeError; end
31
+ class UnsupportedError < PolarRuntimeError; end
32
+ class PolarTypeError < PolarRuntimeError; end
33
+ class StackOverflowError < PolarRuntimeError; end
34
+
35
+ # Errors originating from this side of the FFI boundary.
36
+
37
+ class UnregisteredClassError < PolarRuntimeError; end
38
+ class MissingConstructorError < PolarRuntimeError; end
39
+ class UnregisteredInstanceError < PolarRuntimeError; end
40
+ class DuplicateInstanceRegistrationError < PolarRuntimeError; end
41
+ class InvalidCallError < PolarRuntimeError; end
42
+ class InvalidConstructorError < PolarRuntimeError; end
43
+ class InlineQueryFailedError < PolarRuntimeError; end
44
+ class NullByteInPolarFileError < PolarRuntimeError; end
45
+ class UnexpectedPolarTypeError < PolarRuntimeError; end
46
+ class PolarFileExtensionError < PolarRuntimeError # rubocop:disable Style/Documentation
47
+ def initialize
48
+ super('Polar files must have .pol or .polar extension.')
49
+ end
50
+ end
51
+ class PolarFileNotFoundError < PolarRuntimeError # rubocop:disable Style/Documentation
52
+ # @param file [String]
53
+ def initialize(file)
54
+ super("Could not find file: #{file}")
55
+ end
56
+ end
57
+ class DuplicateClassAliasError < PolarRuntimeError # rubocop:disable Style/Documentation
58
+ # @param as [String]
59
+ # @param old [Class]
60
+ # @param new [Class]
61
+ def initialize(name:, old:, new:) # rubocop:disable Naming/MethodParameterName
62
+ super("Attempted to alias #{new} as '#{name}', but #{old} already has that alias.")
63
+ end
64
+ end
65
+
66
+ # Generic operational exception.
67
+ class OperationalError < Error; end
68
+ class UnknownError < OperationalError; end
69
+
70
+ # Catch-all for a parsing error that doesn't match any of the more specific types.
71
+ class ParseError < Error
72
+ class ExtraToken < ParseError; end
73
+ class IntegerOverflow < ParseError; end
74
+ class InvalidTokenCharacter < ParseError; end
75
+ class InvalidToken < ParseError; end
76
+ class UnrecognizedEOF < ParseError; end
77
+ class UnrecognizedToken < ParseError; end
78
+ end
79
+
80
+ # Generic Polar API exception.
81
+ class ApiError < Error; end
82
+ class ParameterError < ApiError; end
83
+ end
84
+ end