0.4.0

Release date: 2020-08-11

Breaking changes

Warning

This release contains breaking changes. Be sure to follow migration steps before upgrading.

Changed file loading behavior

We removed the lazy-loading of policy files from the various oso libraries. This means that all classes and constants need to be registered _before_ calling Oso.load_file. If a class is not registered, but used in a specializer, it will load but return a warning:

>>> from oso import Oso
>>> oso = Oso()
>>> oso.load_file("test.polar")
Unknown specializer Foo
001: foo(_: Foo);

Additionally, in order to remove ambiguity when the same policy file is loaded multiple times, oso will now error if the same policy is loaded multiple times:

>>> oso.load_file("test.polar")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "polar.py", line 86, in load_file
    f"File {fname} has already been loaded."
polar.exceptions.PolarFileAlreadyLoadedError: File test.polar has already been loaded.

New features

Windows Support

The three oso libraries (Python, Ruby and Java) all now work on Windows.

musl builds for Python

musl-based Python wheels (for Alpine Linux and other musl-based distributions) are built and downloadable from the releases page on GitHub.

Assignment Operator

  • The operator := may now be used to assign values to unbound variables. Unlike the unify operator (=), the assignment operator will NOT evaluate equality.

  • Attempting to assign to a non-variable will result in a parse error.

  • Attempting to assign to a bound variable will result in a runtime error.

Built-in Types

You may now write rules that specialize on any of the built-in types Boolean, Integer, Float, List, Dictionary, and String. These types are mapped to host-language classes such as java.lang.Boolean in Java or bool in Python.

Positional Arguments to Constructors

The new operator previously required an instance literal whose fields are passed to the class’s constructor as keyword arguments:

new Person{first: "First", last: "Last"}

This syntax is still supported in application languages that support keyword arguments (e.g., Python and Ruby), but some languages (e.g., Java) do not support keywords. So a new syntax was added to pass positional initialization arguments:

new Person("First", "Last")

Positional constructor arguments may be used in any application language.

Java Class Registration

The Java registerClass method now requires only a class:

registerClass(Person.class)

If you want to always use a specific constructor from within a policy, you may now specify a Constructor to use:

registerClass(Person.class, Person.class.getConstructor(String.class, String.class))

This takes the place of the function previously required to map keyword arguments to positional ones.

If you omit the constructor (recommended), the default behavior at instantiation time is to search the list returned by Class.getConstructors for a constructor that is applicable to the supplied (positional) constructor arguments; see Java Authorization Library for details.

Flask Integration (flask-oso)

The new flask-oso package makes it easy to use oso with Flask, the popular Python web framework. It includes a flask-specific authorization method with sensible defaults, middleware that ensure all requests are properly authorized, and route decorators to more succinctly use oso.

from flask_oso import authorize

@authorize(resource="get_user")
@app.route("/user")
def get_user():
    return "current user"

Other bugs & improvements

  • Fixed float parsing

  • Improved integer/float comparisons

  • Fixed checking membership in an empty list. x in [] is now always false

  • Fixed bug causing memory issues when running across multiple threads