Hi guys, Can you help me building a model based on...
# talk-keto
g
Hi guys, Can you help me building a model based on a combination of RBAC and ReBAC. So to give a basic example. We have a ticketing system in which tickets are created in separate projected depending on the description and issue of the ticket. Everyone who is admin of the project can create/edit/view/delete tickets and other members can perform certain operations. I want to know how should I handle that who can create projects. Not everyone can create projects, as having ReBAC means relations between object and subject, but as object(project) is not created how can achieve the relationship so will need to implement RBAC. So how can I achieve all this ACL assigned to a role and the role to user(s) in this Keto Permission model. I'm trying to figure out on how the model will span out. If anyone has impleneted or have any ideas on how to, Please do suggest some ideas/example git repos/documentation i would have missed.
p
I’m doing something similar with a project and decided on one “well known” object for attaching create roles/permissions.
g
I have tried something. Can you tell me will this work. Or you have a better way plz do suggest
Copy code
import { Namespace, SubjectSet, Context } from "@ory/keto-namespace-types"

class User implements Namespace { }

class Role implements Namespace {
  related: {
    member: (User | Role)[]
  }
}

class Permission implements Namespace {
  related: {
    allowed: (User | Role | Permission)[]
  }

  permits = {
    create_project: (ctx: Context): boolean => this.related.allowed.includes(ctx.subject),
    create_team: (ctx: Context): boolean => this.related.allowed.includes(ctx.subject)
  }
}

class Team implements Namespace {
  related: {
    admin: User[]
    member: User[]
  }

  permits = {
    add_member: (ctx: Context): boolean => this.related.admin.includes(ctx.subject),
    remove_member: (ctx: Context): boolean => this.related.admin.includes(ctx.subject),
    update_admin: (ctx: Context): boolean => this.related.admin.includes(ctx.subject),
    edit: (ctx: Context): boolean => this.related.admin.includes(ctx.subject),
    delete: (ctx: Context): boolean => this.related.admin.includes(ctx.subject),
    view: (ctx: Context): boolean => this.related.admin.includes(ctx.subject) || this.related.member.includes(ctx.subject)
  }
}

class Project implements Namespace {
  related: {
    manager: (User | SubjectSet<Team, "admin">)[],
    admin: (User | SubjectSet<Team, "admin">)[],
    viewers: (User | SubjectSet<Team, "member"> | SubjectSet<Team, "admin">)[],
  }

  permits = {
    edit: (ctx: Context): boolean => this.permits.create_ticket(ctx),
    view: (ctx: Context): boolean => this.permits.create_ticket(ctx) || this.related.viewers.includes(ctx.subject),
    delete: (ctx: Context): boolean => this.related.manager.includes(ctx.subject),
    create_ticket: (ctx: Context): boolean => this.related.manager.includes(ctx.subject) || this.related.admin.includes(ctx.subject),
  }
}

class Ticket implements Namespace {
  related: {
    manager: (User | SubjectSet<Project, "manager">)[],
    admin: (User | SubjectSet<Project, "admin">)[],
    supervisor: User[],
    engineer: User[],
  }

  permits = {
    edit: (ctx: Context): boolean => this.related.manager.includes(ctx.subject) || this.related.admin.includes(ctx.subject),
    delete: (ctx: Context): boolean => this.permits.edit(ctx),
    view: (ctx: Context): boolean => this.permits.edit(ctx) || this.related.supervisor.includes(ctx.subject) || this.related.engineer.includes(ctx.subject),
    assign: (ctx: Context): boolean => this.permits.edit(ctx),
    execute: (ctx: Context): boolean => this.permits.view(ctx),
    approve_signoff: (ctx: Context): boolean => this.permits.edit(ctx)
  }
}
p
If you’re going to just have a single
Permission
in the platform e.g.
Permission:0
then sure that seems reasonable
g
I know this is a very lame question but can you explain what do you mean by just have a single permission?
p
Your other objects e.g.
Team
,
Project
,
Ticket
all have multiple instances. Their identifiers probably come from some other database, right?
g
right
p
So my point is that the
Permission
object doesn’t have an ID from the database. There’s just one
Permission
instance with some constant ID. Check that object when determining if a user has
create_project
or
create_team
permissions.
g
got it. yeah need to think of it
have you tried anything? I am kind of stuck with my thought process and unable to progress. You said that
decided on one "well known" object for attaching create roles/permissions.
can you help me out please?
p
In our platform we have the concept of an “organization”, which is the top-most container for everything else. (The organization comes from Auth0.) So, I have
Organization
as an Ory Keto namespace and
org_xyz
as the object, and permissions like
create_ticket
on that namespace.
If you don’t have any sort of organization separation, you can just create one object in the namespace: • Namespace:
Platform
• Object:
the-platform
You’ll need a role on it like
ticket_creators
to control who has the
create_ticket
permission.
g
We do have organisational separation and i will try both the approach bcz there are some users without org separation. Thank you for this. I’ll try this