def test_set_get_session(): from sqlalchemy_oso.session import set_get_session from oso import Oso def get_session(): engine = create_engine("sqlite://") Base.metadata.create_all(engine) Session = sessionmaker(bind=engine) session = Session() load_fixture_data(session) return session oso = Oso() set_get_session(oso, get_session) register_models(oso, Base) test_str = """get_repo(name: String) if session = OsoSession.get() and repo = session.query(Repository).filter_by(name: name).first() and repo.name = name; """ oso.load_str(test_str) results = oso.query_rule("get_repo", "Abbey Road") assert next(results) results = oso.query_rule("get_repo", "Abbey Road") assert next(results)
def authorize_model_filter(oso: Oso, actor, action, session: Session, model): """Return SQLAlchemy expression that applies the policy to ``model``. Executing this query will return only authorized objects. If the request is not authorized, a query that always contains no result will be returned. :param oso: The oso class to use for evaluating the policy. :param actor: The actor to authorize. :param action: The action to authorize. :param session: The SQLAlchemy session. :param model: The model to authorize, must be a SQLAlchemy model. """ try: mapped_class = inspect(model, raiseerr=True).class_ except AttributeError: raise TypeError(f"Expected a model; received: {model}") partial_resource = Partial("resource", TypeConstraint(polar_model_name(mapped_class))) results = oso.query_rule("allow", actor, action, partial_resource) combined_filter = None has_result = False for result in results: has_result = True resource_partial = result["bindings"]["resource"] filter = partial_to_filter(resource_partial, session, model, get_model=oso.get_class) if combined_filter is None: combined_filter = filter else: combined_filter = combined_filter | filter if not has_result: return sql.false() return combined_filter
# Test that a built in string method can be called. oso.load_str("""?= x = "hello world!" and x.endswith("world!");""") # Test that a custom error type is thrown. exception_thrown = False try: oso.load_str("missingSemicolon()") except UnrecognizedEOF as e: exception_thrown = True assert ( str(e) == "hit the end of the file unexpectedly. Did you forget a semi-colon at line 1, column 19" ) assert exception_thrown assert list(oso.query_rule("specializers", D("hello"), B.C("hello"))) assert list(oso.query_rule("floatLists")) assert list(oso.query_rule("intDicts")) assert list(oso.query_rule("comparisons")) assert list(oso.query_rule("testForall")) assert list(oso.query_rule("testRest")) assert list(oso.query_rule("testMatches", A("hello"))) assert list(oso.query_rule("testMethodCalls", A("hello"), B.C("hello"))) assert list(oso.query_rule("testOr")) assert list(oso.query_rule("testHttpAndPathMapper")) assert list(oso.query_rule("testUnifyClass", A)) # Test that cut doesn't return anything. assert not list(oso.query_rule("testCut")) # Test that a constant can be called.
def authorize_model(oso: Oso, actor, action, session: Session, model): """Return SQLAlchemy expression that applies the policy to ``model``. Executing this query will return only authorized objects. If the request is not authorized, a query that always contains no result will be returned. :param oso: The oso class to use for evaluating the policy. :param actor: The actor to authorize. :param action: The action to authorize. :param session: The SQLAlchemy session. :param model: The model to authorize, must be a SQLAlchemy model or alias. """ def get_field_type(model, field): try: field = getattr(model, field) except AttributeError: raise PolarRuntimeError(f"Cannot get property {field} on {model}.") try: return field.entity.class_ except AttributeError as e: raise PolarRuntimeError( f"Cannot determine type of {field} on {model}.") from e oso.host.get_field = get_field_type try: mapped_class = inspect(model, raiseerr=True).class_ except AttributeError: raise TypeError(f"Expected a model; received: {model}") resource = Variable("resource") constraint = TypeConstraint(resource, polar_model_name(mapped_class)) results = oso.query_rule( "allow", actor, action, resource, bindings={resource: constraint}, accept_expression=True, ) combined_filter = None has_result = False for result in results: has_result = True resource_partial = result["bindings"]["resource"] filter = partial_to_filter(resource_partial, session, model, get_model=oso.get_class) if combined_filter is None: combined_filter = filter else: combined_filter = combined_filter | filter if not has_result: return sql.false() return combined_filter
# Test that a built in string method can be called. oso.load_str("""?= x = "hello world!" and x.endswith("world!");""") # Test that a custom error type is thrown. exception_thrown = False try: oso.load_str("missingSemicolon()") except UnrecognizedEOF as e: exception_thrown = True assert ( str(e) == "hit the end of the file unexpectedly. Did you forget a semi-colon at line 1, column 19" ) assert exception_thrown assert list(oso.query_rule("specializers", D("hello"), B.C("hello"))) assert list(oso.query_rule("floatLists")) assert list(oso.query_rule("intDicts")) assert list(oso.query_rule("comparisons")) assert list(oso.query_rule("testForall")) assert list(oso.query_rule("testRest")) assert list(oso.query_rule("testMatches", A("hello"))) assert list(oso.query_rule("testMethodCalls", A("hello"), B.C("hello"))) assert list(oso.query_rule("testOr")) assert list(oso.query_rule("testUnifyClass", A)) # Test that cut doesn't return anything. assert not list(oso.query_rule("testCut")) # Test that a constant can be called. oso.register_constant(math, "MyMath")