I've added some features to the opl parsing and re...
# talk-keto
w
I've added some features to the opl parsing and rewrite logic for keto. Some of the notable feature implementations I've added: • 1319: traversals across unions and type intersections support in opl ◦ this allows
||,&&, and !
use within a traversal without having to do something like
this.related.blah.traverse(b => b.related.foo.includes(ctx.subject)) || this.related.blah.traverse(b => b.permits.foobar(ctx))
◦ instead this can be done:
this.related.blah.traverse(b => b.related.foo.includes(ctx.subject) || b.permits.foobar(ctx))
◦ this feature also includes the ability to declare a relation to be a type intersection (with the typechecks appropriately updated) so that in the traversal, so long as one of the type intersection types have the relation, the typecheck will succeed. In addition, the rewrite logic has been greatly enhanced to support traversing across these associated namespaces as appropriate. • 1204: opl (and rewrite and typecheck) support for
this == ctx.subject
or
this.equals(ctx.subject)
◦ (Incidentally,
== ctx.subject and .equals(ctx.subject)
are supported within nested traversals) • 1131: opl (and rewrite and typecheck) support for arbitrary depth nested traversals I also cleaned up some of the test cases and added new cases for (most) of the new features. I'm still working on this actively but I have test data and validation scripts and opl rule scripts for each new feature if you're interested. I'll open a draft PR *eventually*™ but I wanted to give folks a chance to look at this before I did so. https://github.com/cmmoran/keto/tree/feat/kitchen-sink is my fork / working branch with all of the features currently combined. To point out some more functionality that is enabled by this fork there is a file in
contrib/namespace-type-lib
called
test.ts
. This file contains OPL logic that is invalid (ternary
p instanceof User ? ... : ...
) syntax. This fork enables the core of this logic to be valid (minus the ternary syntax - though I thought about how to implement this and think type intersection is much more useful since supporting ternary syntax would be only good for binary type unions or intersections) the only changes that would need to be made to the OPL file are:
Copy code
// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0

import {Context, Namespace, SubjectSet} from "@ory/keto-namespace-types"

// This test is not really a valid config, but rather a check of the types.
class User implements Namespace {
  related: {
    friends: User[]
  }
}

class Group implements Namespace {
  related: {
    members: (User & Group)[]
  }

  permits = {
    isMember: (ctx: Context): boolean =>
      this.related.members.traverse((m) =>
        m.equals(ctx.subject) ||
        m.permits.isMember(ctx),
      ),
  }
}

class File implements Namespace {
  related: {
    viewers: (User & SubjectSet<Group, "members">)[]
  }

  permits = {
    view: (ctx: Context): boolean =>
      this.related.viewers.traverse((p) =>
        p.related.friends.includes(ctx.subject) ||
        p.permits.isMember(ctx)
      ) || this.related.viewers.includes(ctx.subject),
  }
}
and this would be valid (and typechecked) rule configuration. Here is the sample data to test this out for yourself: (Add these tuples to your keto instance)
Copy code
User:dave#friends@alice
Group:admins#members@alice
Group:users#members@dave
Group:admins#members@semi-admins
Group:semi-admins#members@carol
File:readme.txt#viewers@Group:users#members
File:readme.txt#viewers@Group:admins#
Run these checks:
Copy code
check Allowed File:readme.txt#view@alice
check Denied File:readme.txt#view@bob
check Allowed File:readme.txt#view@dave
check Allowed File:readme.txt#view@carol
check Allowed File:readme.txt#view@Group:admins
Also, notice that the OPL file can be verified as valid syntactically. (and the corresponding namespaces are parsed properly and in a way that the rewrite engine can parse and evaluate the rules as written in the OPL)