<@U04UQ68083H> I have the following model ```//@t...
# ory-copilot
c
@chilly-king-10285 I have the following model
Copy code
//@ts-ignore
import { Namespace, SubjectSet, Context } from "@ory/keto-namespace-types";

export class User implements Namespace {}
export class Group implements Namespace {
  related: {
    members: (User | Group)[];
  };
}

export class Service implements Namespace {
  related: {
    viewers: (User | SubjectSet<Group, "members">)[];
    editors: (User | SubjectSet<Group, "members">)[];
  };

  permits = {
    read: (ctx: Context): boolean =>
      this.related.viewers.includes(ctx.subject) || this.permits.create(ctx),
    create: (ctx: Context): boolean =>
      this.related.editors.includes(ctx.subject),
    update: (ctx: Context): boolean =>
      this.related.editors.includes(ctx.subject),
    delete: (ctx: Context): boolean =>
      this.related.editors.includes(ctx.subject),
  };
}

export class Pharmacy implements Namespace {
  related: {
    parents: Service[];
    viewers: (User | SubjectSet<Group, "members">)[];
    admins: (User | SubjectSet<Group, "members">)[];
    purchase_admins: (User | SubjectSet<Group, "members">)[];
    audit_admins: (User | SubjectSet<Group, "members">)[];
    auditors: (User | SubjectSet<Group, "members">)[];
  };

  permits = {
    view_purchase: (ctx: Context): boolean =>
      this.related.viewers.includes(ctx.subject) ||
      this.related.purchase_admins.includes(ctx.subject) ||
      this.related.audit_admins.includes(ctx.subject) ||
      this.related.auditors.includes(ctx.subject) ||
      this.related.parents.traverse((parent) =>
        parent.related.viewers.includes(ctx.subject)
      ) ||
      this.related.parents.traverse((parent) => parent.permits.read(ctx)),
    create_purchase: (ctx: Context) =>
      this.related.admins.includes(ctx.subject) ||
      this.related.purchase_admins.includes(ctx.subject) ||
      this.related.parents.traverse((parent) =>
        parent.related.editors.includes(ctx.subject)
      ) ||
      this.related.parents.traverse((parent) => parent.permits.update(ctx)),
    create_audit: (ctx: Context): boolean =>
      this.related.audit_admins.includes(ctx.subject) ||
      this.related.admins.includes(ctx.subject) ||
      this.related.parents.traverse((parent) =>
        parent.related.editors.includes(ctx.subject)
      ) ||
      this.related.parents.traverse((parent) => parent.permits.update(ctx)),
    view_audit: (ctx: Context): boolean =>
      this.related.viewers.includes(ctx.subject) ||
      this.related.audit_admins.includes(ctx.subject) ||
      this.related.auditors.includes(ctx.subject) ||
      this.related.parents.traverse((parent) =>
        parent.related.viewers.includes(ctx.subject)
      ) ||
      this.related.parents.traverse((parent) => parent.permits.update(ctx)),
    edit_audit: (ctx: Context) =>
      this.related.audit_admins.includes(ctx.subject) ||
      this.related.auditors.includes(ctx.subject) ||
      this.related.parents.traverse((parent) =>
        parent.related.editors.includes(ctx.subject)
      ) ||
      this.related.parents.traverse((parent) => parent.permits.edit(ctx)),
  };
}
c
A message from kapa.ai
The model you've provided is a good example of how to use Ory's permission model to manage access control in your application. It defines several entities (User, Group, Service, Pharmacy) and their relationships, as well as the permissions associated with these entities. Here's a brief overview of your model: -
User
and
Group
are simple entities with no permissions defined.
Group
has a relationship with its members, which can be either
User
or
Group
. -
Service
has relationships with its viewers and editors, and defines permissions for reading, creating, updating, and deleting. -
Pharmacy
is a more complex entity with relationships to its parent
Service
, viewers, admins, purchase admins, audit admins, and auditors. It defines permissions for viewing purchases, creating purchases, creating audits, viewing audits, and editing audits. The permissions are defined as TypeScript functions that return a boolean value based on the relationships in Ory Permissions. These functions allow you to define the access control policies for your application. For example, the
view_purchase
permission in the
Pharmacy
class checks if the subject is a viewer, a purchase admin, an audit admin, an auditor, or if the subject can view the parent
Service
. Remember that in Ory Permissions, relationships and permissions are two key concepts that allow you to manage access control and permissions in your application. Relationships are facts about entities stored in Ory Permissions, while permissions are defined in the Ory Permission Language, which is a subset of TypeScript ([source](https://www.ory.sh/docs/keto/guides/simple-access-check-guide#understand-ory-permissions)). Also, note that all relations are defined as array types
T[]
because there are naturally only many-to-many relations in Keto ([source](https://www.ory.sh/docs/keto/reference/ory-permission-language#relation-declaration)). If you have any specific questions about your model or how to use it with Ory, feel free to ask!