Exemplo n.º 1
0
def test_partial_subfield_isa():
    from test_app.models import Post, User

    alice = User(name="alice")
    alice.save()
    not_alice = User(name="not alice")
    not_alice.save()

    Post(created_by=alice).save(),
    Post(created_by=not_alice).save(),
    Post(created_by=alice).save(),

    Oso.load_str("""
            allow(_, _, post: test_app::Post) if check(post.created_by);
            check(user: test_app::User) if user.name = "alice";
            check(post: test_app::Post) if post.is_private = false;
        """)

    authorize_filter = authorize_model(None, Post, actor="foo", action="bar")
    assert (
        str(authorize_filter) == "(OR:" +
        " (AND: (NOT (AND: ('pk__in', []))), (NOT (AND: ('pk__in', []))), ('created_by__name', 'alice')),"
        + " ('pk__in', []))")
    authorized_posts = Post.objects.filter(authorize_filter)
    assert (
        str(authorized_posts.query) ==
        'SELECT "test_app_post"."id", "test_app_post"."is_private", "test_app_post"."name",'
        +
        ' "test_app_post"."timestamp", "test_app_post"."option", "test_app_post"."created_by_id"'
        + ' FROM "test_app_post" LEFT OUTER JOIN "test_app_user"' +
        ' ON ("test_app_post"."created_by_id" = "test_app_user"."id") WHERE "test_app_user"."name" = alice'
    )
    assert authorized_posts.count() == 2
Exemplo n.º 2
0
def test_partial_isa_with_path():
    from test_app.models import Post, User

    alice = User(name="alice")
    alice.save()
    not_alice = User(name="not alice")
    not_alice.save()

    Post(created_by=alice).save(),
    Post(created_by=not_alice).save(),
    Post(created_by=alice).save(),

    Oso.load_str("""
            allow(_, _, post: test_app::Post) if check(post.created_by);
            check(user: test_app::User) if user.name = "alice";
            check(post: test_app::Post) if post.is_private = false;
        """)

    authorize_filter = authorize_model(None, Post, actor="foo", action="bar")
    assert (str(authorize_filter) ==
            f"(AND: {str(TRUE_FILTER)}, ('created_by__name', 'alice'))")
    authorized_posts = Post.objects.filter(authorize_filter)
    expected = """
        SELECT "test_app_post"."id", "test_app_post"."is_private", "test_app_post"."name",
               "test_app_post"."timestamp", "test_app_post"."option", "test_app_post"."created_by_id"
        FROM "test_app_post"
        INNER JOIN "test_app_user" ON ("test_app_post"."created_by_id" = "test_app_user"."id")
        WHERE "test_app_user"."name" = alice
    """
    assert str(authorized_posts.query) == " ".join(expected.split())
    assert authorized_posts.count() == 2
Exemplo n.º 3
0
def test_partial(rf, settings, partial_policy):
    from test_app.models import Post

    Post(name="test", is_private=False, timestamp=1).save()
    Post(name="test_past", is_private=False, timestamp=-1).save()
    Post(name="test_public", is_private=False, timestamp=1).save()
    Post(name="test_private", is_private=True, timestamp=1).save()
    Post(name="test_private_2", is_private=True, timestamp=1).save()

    request = rf.get("/")
    request.user = "******"

    authorize_filter = authorize_model(request, action="get", model="test_app::Post")
    q = Post.objects.filter(authorize_filter)
    assert q.count() == 2

    request = rf.get("/")
    request.user = "******"

    authorize_filter = authorize_model(request, action="get", model=Post)
    q = Post.objects.filter(authorize_filter)
    assert q.count() == 5

    q = Post.objects.authorize(request, action="get")
    assert q.count() == 5
Exemplo n.º 4
0
def test_partial_errors(rf):
    from test_app.models import Post

    Post(name="test", is_private=False, timestamp=1).save()
    Post(name="test_past", is_private=False, timestamp=-1).save()
    Post(name="test_public", is_private=False, timestamp=1).save()
    Post(name="test_private", is_private=True, timestamp=1).save()
    Post(name="test_private_2", is_private=True, timestamp=1).save()

    request = rf.get("/")
    request.user = "******"

    # No rules for this.
    q = Post.objects.authorize(request, action="get")
    assert q.count() == 0
Exemplo n.º 5
0
def test_negated_matches_with_partial(rf):
    from test_app.models import Post

    Post(name="test", is_private=False, timestamp=1).save()
    Oso.load_str("""
        allow(1, _, post) if not post matches test_app::Post;
        allow(2, _, post) if not post matches test_app::User;
        allow(3, _, post) if not post.created_by matches test_app::User;
        allow(4, _, post) if not post.created_by matches test_app::Post;
        """)
    request = rf.get("/")

    request.user = 1
    authorize_filter = authorize_model(request, Post)
    assert str(authorize_filter) == (
        f"(AND: {str(TRUE_FILTER)}, (NOT (AND: {str(TRUE_FILTER)})))")
    authorized_posts = Post.objects.filter(authorize_filter)
    # For some reason, this only seems to be raised when stringifying.
    with pytest.raises(EmptyResultSet):
        str(authorized_posts.query)
    assert authorized_posts.count() == 0

    request.user = 2
    authorize_filter = authorize_model(request, Post)
    assert str(authorize_filter) == str(TRUE_FILTER)
    authorized_posts = Post.objects.filter(authorize_filter)
    expected = """
        SELECT "test_app_post"."id", "test_app_post"."is_private", "test_app_post"."name",
               "test_app_post"."timestamp", "test_app_post"."option", "test_app_post"."created_by_id"
        FROM "test_app_post"
    """
    assert str(authorized_posts.query) == " ".join(expected.split())
    assert authorized_posts.count() == 1

    request.user = 3
    authorize_filter = authorize_model(request, Post)
    assert str(authorize_filter) == (
        f"(AND: {str(TRUE_FILTER)}, (NOT (AND: {str(TRUE_FILTER)})))")
    authorized_posts = Post.objects.filter(authorize_filter)
    # For some reason, this only seems to be raised when stringifying.
    with pytest.raises(EmptyResultSet):
        str(authorized_posts.query)
    assert authorized_posts.count() == 0

    request.user = 4
    authorize_filter = authorize_model(request, Post)
    assert str(authorize_filter) == str(TRUE_FILTER)
    authorized_posts = Post.objects.filter(authorize_filter)
    expected = """
        SELECT "test_app_post"."id", "test_app_post"."is_private", "test_app_post"."name",
               "test_app_post"."timestamp", "test_app_post"."option", "test_app_post"."created_by_id"
        FROM "test_app_post"
    """
    assert str(authorized_posts.query) == " ".join(expected.split())
    assert authorized_posts.count() == 1
Exemplo n.º 6
0
def test_partial_errors(rf, settings):
    from test_app.models import Post

    Post(name="test", is_private=False, timestamp=1).save()
    Post(name="test_past", is_private=False, timestamp=-1).save()
    Post(name="test_public", is_private=False, timestamp=1).save()
    Post(name="test_private", is_private=True, timestamp=1).save()
    Post(name="test_private_2", is_private=True, timestamp=1).save()

    request = rf.get("/")
    request.user = "******"

    Oso.load_str('allow(_, "fail", post: test_app::Post) if post matches {x: 1};')

    with pytest.raises(UnsupportedError):
        q = Post.objects.authorize(request, action="fail")

    # No rules for this.
    q = Post.objects.authorize(request, action="get")
    assert q.count() == 0
Exemplo n.º 7
0
def test_partial_with_allow_all(rf):
    from test_app.models import Post

    Post(name="test", is_private=False, timestamp=1).save()
    Oso.load_str("allow(_, _, _);")
    request = rf.get("/")
    request.user = "******"

    authorize_filter = authorize_model(request, Post)
    assert str(authorize_filter) == str(TRUE_FILTER)
    authorized_posts = Post.objects.filter(authorize_filter)
    expected = """
        SELECT "test_app_post"."id", "test_app_post"."is_private", "test_app_post"."name",
               "test_app_post"."timestamp", "test_app_post"."option", "test_app_post"."created_by_id"
        FROM "test_app_post"
    """
    assert str(authorized_posts.query) == " ".join(expected.split())
    assert authorized_posts.count() == 1
Exemplo n.º 8
0
def test_partial(rf, partial_policy):
    from test_app.models import Post

    posts = [
        Post(name="test", is_private=False, timestamp=1).save(),
        Post(name="test_past", is_private=False, timestamp=-1).save(),
        Post(name="test_public", is_private=False, timestamp=1).save(),
        Post(name="test_private", is_private=True, timestamp=1).save(),
        Post(name="test_private_2", is_private=True, timestamp=1).save(),
        Post(name="test_option", is_private=False, timestamp=1,
             option=True).save(),
    ]

    request = rf.get("/")
    request.user = "******"

    authorize_filter = authorize_model(request, action="get", model=Post)
    assert (
        str(authorize_filter) ==
        f"(AND: {str(TRUE_FILTER)}, ('is_private', False), ('timestamp__gt', 0), ('option', None))"
    )

    q = Post.objects.filter(authorize_filter)
    bool_cond = negated_condition('"test_app_post"."is_private"')
    expected = f"""
        SELECT "test_app_post"."id", "test_app_post"."is_private", "test_app_post"."name",
               "test_app_post"."timestamp", "test_app_post"."option", "test_app_post"."created_by_id"
        FROM "test_app_post"
        WHERE ({bool_cond}
               AND "test_app_post"."timestamp" > 0
               AND "test_app_post"."option" IS NULL)
    """
    assert str(q.query) == " ".join(expected.split())
    assert q.count() == 2

    request = rf.get("/")
    request.user = "******"

    authorize_filter = authorize_model(request, action="get", model=Post)
    assert str(authorize_filter) == str(TRUE_FILTER)

    q = Post.objects.filter(authorize_filter)
    expected = """
        SELECT "test_app_post"."id", "test_app_post"."is_private", "test_app_post"."name",
               "test_app_post"."timestamp", "test_app_post"."option", "test_app_post"."created_by_id"
        FROM "test_app_post"
    """
    assert str(q.query) == " ".join(expected.split())
    assert q.count() == len(posts)

    q = Post.objects.authorize(request, action="get")
    assert q.count() == len(posts)
Exemplo n.º 9
0
def test_null_with_partial(rf):
    from test_app.models import Post

    Post(name="test", is_private=False, timestamp=1).save()
    Oso.load_str("allow(_, _, post: test_app::Post) if post.option = nil;")
    request = rf.get("/")
    request.user = "******"

    authorize_filter = authorize_model(request, Post)
    assert (str(authorize_filter) ==
            "(AND: (NOT (AND: ('pk__in', []))), ('option', None))")
    authorized_posts = Post.objects.filter(authorize_filter)
    assert str(authorized_posts.query) == (
        'SELECT "test_app_post"."id", "test_app_post"."is_private", "test_app_post"."name", '
        +
        '"test_app_post"."timestamp", "test_app_post"."option", "test_app_post"."created_by_id"'
        + ' FROM "test_app_post"' + ' WHERE "test_app_post"."option" IS NULL')
    assert authorized_posts.count() == 1
Exemplo n.º 10
0
def test_null_with_partial(rf):
    from test_app.models import Post

    Post(name="test", is_private=False, timestamp=1).save()
    Oso.load_str("allow(_, _, post: test_app::Post) if post.option = nil;")
    request = rf.get("/")
    request.user = "******"

    authorize_filter = authorize_model(request, Post)
    assert str(authorize_filter) == "(AND: ('option', None))"
    authorized_posts = Post.objects.filter(authorize_filter)
    expected = """
        SELECT "test_app_post"."id", "test_app_post"."is_private", "test_app_post"."name",
               "test_app_post"."timestamp", "test_app_post"."option", "test_app_post"."created_by_id"
        FROM "test_app_post"
        WHERE "test_app_post"."option" IS NULL
    """
    assert str(authorized_posts.query) == " ".join(expected.split())
    assert authorized_posts.count() == 1
Exemplo n.º 11
0
def test_partial(rf, partial_policy):
    from test_app.models import Post

    posts = [
        Post(name="test", is_private=False, timestamp=1).save(),
        Post(name="test_past", is_private=False, timestamp=-1).save(),
        Post(name="test_public", is_private=False, timestamp=1).save(),
        Post(name="test_private", is_private=True, timestamp=1).save(),
        Post(name="test_private_2", is_private=True, timestamp=1).save(),
        Post(name="test_option", is_private=False, timestamp=1,
             option=True).save(),
    ]

    request = rf.get("/")
    request.user = "******"

    authorize_filter = authorize_model(request, action="get", model=Post)
    assert (
        str(authorize_filter) ==
        "(AND: (NOT (AND: ('pk__in', []))), ('is_private', False), ('timestamp__gt', 0), ('option', None))"
    )

    q = Post.objects.filter(authorize_filter)
    assert (
        str(q.query) ==
        'SELECT "test_app_post"."id", "test_app_post"."is_private", "test_app_post"."name",'
        +
        ' "test_app_post"."timestamp", "test_app_post"."option", "test_app_post"."created_by_id"'
        + ' FROM "test_app_post"' +
        ' WHERE (NOT "test_app_post"."is_private" AND "test_app_post"."timestamp" > 0 AND "test_app_post"."option" IS NULL)'
    )
    assert q.count() == 2

    request = rf.get("/")
    request.user = "******"

    authorize_filter = authorize_model(request, action="get", model=Post)
    assert str(authorize_filter) == "(NOT (AND: ('pk__in', [])))"

    q = Post.objects.filter(authorize_filter)
    assert (
        str(q.query) ==
        'SELECT "test_app_post"."id", "test_app_post"."is_private", "test_app_post"."name",'
        +
        ' "test_app_post"."timestamp", "test_app_post"."option", "test_app_post"."created_by_id"'
        + ' FROM "test_app_post"')
    assert q.count() == len(posts)

    q = Post.objects.authorize(request, action="get")
    assert q.count() == len(posts)
Exemplo n.º 12
0
def test_partial(rf, settings, partial_policy):
    from test_app.models import Post

    posts = [
        Post(name="test", is_private=False, timestamp=1).save(),
        Post(name="test_past", is_private=False, timestamp=-1).save(),
        Post(name="test_public", is_private=False, timestamp=1).save(),
        Post(name="test_private", is_private=True, timestamp=1).save(),
        Post(name="test_private_2", is_private=True, timestamp=1).save(),
        Post(name="test_option", is_private=False, timestamp=1,
             option=True).save(),
    ]

    request = rf.get("/")
    request.user = "******"

    authorize_filter = authorize_model(request,
                                       action="get",
                                       model="test_app::Post")
    assert (
        str(authorize_filter) ==
        "(AND: ('is_private', False), ('timestamp__gt', 0), ('option', None))")

    q = Post.objects.filter(authorize_filter)
    assert q.count() == 2

    request = rf.get("/")
    request.user = "******"

    authorize_filter = authorize_model(request, action="get", model=Post)
    assert str(authorize_filter) == "(AND: )"

    q = Post.objects.filter(authorize_filter)
    assert q.count() == len(posts)

    q = Post.objects.authorize(request, action="get")
    assert q.count() == len(posts)