Hello everyone, I'm looking to implement permissio...
# talk-keto
m
Hello everyone, I'm looking to implement permissions in a domain / tenant context. For reference, Casbin offer this here: https://casbin.org/docs/en/rbac-with-domains I've made an example for this to try and describe what I'm looking to do:
Copy code
Features:last-7-days-report#accessedBy@(Tiers:standard#subscribers)
Features:last-30-days-report#accessedBy@(Tiers:premium#subscribers)
Features:custom-days-report#accessedBy@(Addons:service-1#subscribers)
Tiers:premium#children@(Tiers:standard#subscribers)
Tiers:standard#subscribers@(Clients:Foo#members)
Tiers:premium#subscribers@(Clients:Bar#members)
Addons:service-1#subscribers@(Clients:Bar#members)
Clients:Foo#members@Users:x
Clients:Bar#members@Users:x
Copy code
import { Namespace, SubjectSet, Context } from '@ory/keto-namespace-types'

class Users implements Namespace {

}

class Clients implements Namespace {
  related: {
    members: Users[]
  }
  
  permits = {
    isMember: (ctx: Context): boolean => this.related.members.includes(ctx.subject),
  }
}

class Addons implements Namespace {
  related: {
    subscribers: Clients[]
  }

  permits = {
    access: (ctx: Context): boolean =>
        this.related.subscribers.includes(ctx.subject) && this.related.subscribers.traverse((p) => p.permits.isMember(ctx)),
  }
}

class Tiers implements Namespace {
  related: {
    subscribers: Clients[]
    children: SubjectSet<Tiers, "subscribers">[]
  }

  permits = {
    access: (ctx: Context): boolean => 
        this.related.subscribers.traverse((p) => p.permits.isMember(ctx)) || this.related.children.includes(ctx.subject),
  }
}

class Features implements Namespace {
  related: {
    accessedBy: (Addons | Tiers)[]
  }

  permits = {
      use: (ctx: Context): boolean =>
        this.related.accessedBy.traverse((p) => p.permits.access(ctx)),
  }
}
User x is a member of both Clients, and so has access to all the features, but I'm trying to scope it so they only have access to Feature
last-30-days-report
when they're accessing it through client
Bar
What I've thought is that the
/relation-tuples/check
would maybe be recursive? So you could check something like the following (which would return false, but currently returns true because the check call doesn't use the nested subject_set)
Copy code
{
  "namespace": "Features",
  "object": "last-30-days-report",
  "relation": "accessedBy",
  "subject_set": {
    "namespace": "Clients",
    "object": "Bar",
    "relation": "members",
    "subject_set": {
      "namespace": "User",
      "object": "literally-nobody"
    }
  }
}
Any thoughts on how this sounds, or alternatively, are there ways I can use the current implementation to achieve what I'm trying to do?