brave-memory-91176
06/21/2024, 6:54 AMpermits property. Can you give an example in TypeScript (using the SDK) of defining a relationship between a User and a Document ? Additionally, can you given an example in TypeScript (using the SDK) of performing a permission check for the given models and relationships?chilly-king-10285
06/21/2024, 6:54 AMchilly-king-10285
06/21/2024, 6:54 AMUser and a Document in TypeScript using the Ory Permission Language (OPL). This is done by declaring the relationships inside the corresponding class in the OPL. Here's an example: typescript import { Namespace, Context } from "@ory/keto-namespace-types" class User implements Namespace {} class Document implements Namespace { related: { owners: User[] editors: User[] viewers: User[] parents: Folder[] } } In this example, a Document can have owners, editors, viewers, and parents (which are Folders). Each of these relationships is a many-to-many relationship with User or Folder objects. Next, let's define permissions in the permits property of the Document class. These permissions are expressed as TypeScript functions that take a context containing the subject and answer permission checks based on the relationships the object has to the subject. Here's an example: typescript class Document implements Namespace { related: { owners: User[] editors: User[] viewers: User[] parents: Folder[] } permits = { view: (ctx: Context): boolean => this.related.viewers.includes(ctx.subject) || this.related.editors.includes(ctx.subject) || this.related.owners.includes(ctx.subject) || this.related.parents.traverse((parent) => parent.permits.view(ctx)), } } In this example, a User can view a Document if they are a viewer, editor, or owner of the Document, or if they can view the parent Folder. Please note that these examples are based on the Ory Permission Language (OPL), which is a developer-friendly configuration language defined as a subset of TypeScript. It's designed to be quick to learn and has a familiar source in contrary to other, proprietary languages used to represent permissions[^1^][^2^]. [^1^]: https://www.ory.sh/docs/keto/modeling/create-permission-model#define-relationships-in-the-opl [^2^]: https://www.ory.sh/docs/keto/modeling/create-permission-model#define-permissions-in-the-oplbrave-memory-91176
06/21/2024, 6:57 AMchilly-king-10285
06/21/2024, 6:57 AMchilly-king-10285
06/21/2024, 6:57 AMrelationship and permissions modules. Here's an example of how to create a relationship and check a permission: typescript // Create a relationship await ory .relationship .createRelationship({createRelationshipBody: {/* ... */}}) // Check a permission const isAllowed = await ory .permission .checkPermission({namespace: "n", /* ... */}) .then(({data}) => data.allowed) In the createRelationship function, you would replace {/* ... */} with the details of the relationship you want to create. Similarly, in the checkPermission function, you would replace {namespace: "n", /* ... */} with the details of the permission you want to check[^1^]. Please note that these examples are based on the Ory SDK V1 upgrade guide[^1^]. [^1^]: https://www.ory.sh/docs/guides/upgrade/sdk-v1#permissions--access-controlbrave-memory-91176
06/21/2024, 6:58 AMchilly-king-10285
06/21/2024, 6:58 AMchilly-king-10285
06/21/2024, 6:59 AMtypescript // Create a relationship await ory .relationship .createRelationship({createRelationshipBody: {namespace: 'users', object: 'user1', relation: 'owns', subject: 'file1'}}) // Check a permission const isAllowed = await ory .permission .checkPermission({namespace: 'users', object: 'user1', relation: 'owns', subject: 'file1'}) .then(({data}) => data.allowed) In this example, we're creating a relationship where user1 owns file1, and then checking if user1 has the owns permission for file1. Please note that this is a hypothetical example and may not work as-is. You should refer to the Ory Keto SDK documentation for the exact syntax and parameters for these functions in TypeScript.brave-memory-91176
06/21/2024, 7:01 AMowns come from? Based on the initial permission rules that you provided, there is a view permission defined in the permits property.
How is that supposed to be used?chilly-king-10285
06/21/2024, 7:01 AMchilly-king-10285
06/21/2024, 7:01 AMowns relation in the example was just a hypothetical example to illustrate the structure of the function call. In the context of the permission model defined in the knowledge sources, the relations are view, edit, delete, and `share`[^1^][^2^]. The permits property in the Document class defines these permissions as functions. These functions take a context containing the subject (the user performing the action) and return a boolean value indicating whether the action is permitted based on the relationships the object (the document) has to the subject[^2^]. Here's an example of how the view permission is defined: typescript permits = { view: (ctx: Context): boolean => this.related.viewers.includes(ctx.subject) || this.related.editors.includes(ctx.subject) || this.related.owners.includes(ctx.subject) || this.related.parents.traverse((parent) => parent.permits.view(ctx)), } In this example, a user can view a document if they are a viewer, editor, or owner of the document, or if they can view the parent folder[^2^]. When checking permissions using the SDK, you would use the checkPermission function with the appropriate namespace, object, relation, and subject. The relation would be one of the permissions defined in the permits property, such as view, edit, delete, or share. [^1^]: https://www.ory.sh/docs/keto/modeling/create-permission-model#list-permissions-to-check-for-each-object [^2^]: https://www.ory.sh/docs/keto/modeling/create-permission-model#define-permissions-in-the-oplbrave-memory-91176
06/21/2024, 7:07 AMrelation property being one of the related properties of the permission rules.
However, there is no mention of using the view and edit permissions (defined as permits ) when creating the relationships.
The documentation also mentions “With the relationships created, try running queries that illustrate use cases”. How does this translate into checking for permissions using the TypeScript SDK?chilly-king-10285
06/21/2024, 7:07 AMchilly-king-10285
06/21/2024, 7:07 AMbrave-memory-91176
06/21/2024, 10:15 AMchilly-king-10285
06/21/2024, 10:15 AMchilly-king-10285
06/21/2024, 10:16 AMbrave-memory-91176
06/21/2024, 10:23 AMchilly-king-10285
06/21/2024, 10:23 AMchilly-king-10285
06/21/2024, 10:24 AMEmployee, Company, and SSOConfiguration. typescript import { Namespace, Context } from "@ory/keto-namespace-types" class Employee implements Namespace {} class Company implements Namespace { related: { employees: Employee[] owners: Employee[] ssoConfigManagers: Employee[] ssoConfiguration: SSOConfiguration[] } } class SSOConfiguration implements Namespace { related: { company: Company[] } } In this example, a Company can have employees, owners, and ssoConfigManagers (which are all Employee objects), and an ssoConfiguration (which is an SSOConfiguration object). Next, let's define the permissions in the permits property of the Company class: typescript class Company implements Namespace { related: { employees: Employee[] owners: Employee[] ssoConfigManagers: Employee[] ssoConfiguration: SSOConfiguration[] } permits = { manageSSO: (ctx: Context): boolean => this.related.ssoConfigManagers.includes(ctx.subject), assignRoles: (ctx: Context): boolean => this.related.owners.includes(ctx.subject), } } In this example, an Employee can manageSSO if they are an ssoConfigManager of the Company, and can assignRoles if they are an owner of the Company. Please note that this is a hypothetical example and may not work as-is. You should refer to the Ory Keto documentation for the exact syntax and parameters for these functions in TypeScript[^1^][^2^]. As for the diagram, I'm an AI text-based assistant and I'm unable to draw diagrams. However, you can visualize the relationships as follows: - Company has relationships to multiple Employee entities (as employees, owners, and ssoConfigManagers), and to an SSOConfiguration entity. - Employee entities are related to a Company entity. - SSOConfiguration is related to a Company entity. [^1^]: https://www.ory.sh/docs/keto/modeling/create-permission-model#define-relationships-in-the-opl [^2^]: https://www.ory.sh/docs/keto/modeling/create-permission-model#define-permissions-in-the-oplbrave-memory-91176
06/21/2024, 11:30 AMchilly-king-10285
06/21/2024, 11:30 AMchilly-king-10285
06/21/2024, 11:31 AMEmployee, Owner, and SSOConfigManager. typescript import {{ Namespace, Context }} from "@ory/keto-namespace-types" class Employee implements Namespace {{}} class Owner extends Employee {{}} class SSOConfigManager extends Employee {{}} In this example, Owner and SSOConfigManager are roles that inherit from the Employee role. Next, let's define the permissions in the permits property of the Company class: typescript class Company implements Namespace {{ related: {{ employees: Employee[] owners: Owner[] ssoConfigManagers: SSOConfigManager[] ssoConfiguration: SSOConfiguration[] }} permits = {{ manageSSO: (ctx: Context): boolean => this.related.ssoConfigManagers.includes(ctx.subject), assignRoles: (ctx: Context): boolean => this.related.owners.includes(ctx.subject), }} }} In this example, an Employee can manageSSO if they have the SSOConfigManager role in the Company, and can assignRoles if they have the Owner role in the Company. Please note that this is a hypothetical example and may not work as-is. You should refer to the Ory Keto documentation for the exact syntax and parameters for these functions in TypeScript[^1^][^2^]. [^1^]: https://www.ory.sh/docs/keto/modeling/create-permission-model#define-relationships-in-the-opl [^2^]: https://www.ory.sh/docs/keto/modeling/create-permission-model#define-permissions-in-the-oplbrave-memory-91176
06/21/2024, 11:32 AMchilly-king-10285
06/21/2024, 11:32 AMchilly-king-10285
06/21/2024, 11:33 AMeditor of a document: typescript await ory .relationship .createRelationship({createRelationshipBody: {namespace: 'documents', object: 'doc1', relation: 'editors', subject: 'user1'}}) And here's how you might create a relationship where another user is an owner of the same document: typescript await ory .relationship .createRelationship({createRelationshipBody: {namespace: 'documents', object: 'doc1', relation: 'owners', subject: 'user2'}}) In these examples, user1 is an editor of doc1, and user2 is an owner of doc1. Please note that these are hypothetical examples and may not work as-is. You should refer to the Ory Keto SDK documentation for the exact syntax and parameters for these functions in TypeScript[^1^]. [^1^]: https://www.ory.sh/docs/guides/upgrade/sdk-v1#permissions--access-controlbrave-memory-91176
06/21/2024, 11:34 AMchilly-king-10285
06/21/2024, 11:34 AMchilly-king-10285
06/21/2024, 11:34 AMEmployee, Company, and SSOConfigManager roles. Here's a hypothetical example of how you might do that using the TypeScript SDK: typescript // Create an Employee relationship for a Company await ory .relationship .createRelationship({createRelationshipBody: {namespace: 'companies', object: 'company1', relation: 'employees', subject: 'employee1'}}) // Create an Owner relationship for a Company await ory .relationship .createRelationship({createRelationshipBody: {namespace: 'companies', object: 'company1', relation: 'owners', subject: 'employee2'}}) // Create an SSOConfigManager relationship for a Company await ory .relationship .createRelationship({createRelationshipBody: {namespace: 'companies', object: 'company1', relation: 'ssoConfigManagers', subject: 'employee3'}}) In these examples, employee1 is an employee of company1, employee2 is an owner of company1, and employee3 is an ssoConfigManager of company1. Please note that these are hypothetical examples and may not work as-is. You should refer to the Ory Keto SDK documentation for the exact syntax and parameters for these functions in TypeScript[^1^]. [^1^]: https://www.ory.sh/docs/guides/upgrade/sdk-v1#permissions--access-controlbrave-memory-91176
06/21/2024, 11:37 AMOwner and SSOConfigManager . How does this translate when defining relationships for users?chilly-king-10285
06/21/2024, 11:37 AMchilly-king-10285
06/21/2024, 11:37 AMOwner and SSOConfigManager are considered as subjects, similar to Employee. When defining relationships, you would specify these roles as the subject. Here's a hypothetical example of how you might create a relationship where a user has the Owner role for a company: typescript await ory .relationship .createRelationship({{createRelationshipBody: {{namespace: 'companies', object: 'company1', relation: 'owners', subject: 'owner1'}}) And here's how you might create a relationship where another user has the SSOConfigManager role for the same company: typescript await ory .relationship .createRelationship({{createRelationshipBody: {{namespace: 'companies', object: 'company1', relation: 'ssoConfigManagers', subject: 'ssoConfigManager1'}}) In these examples, owner1 is an Owner of company1, and ssoConfigManager1 is an SSOConfigManager of company1. Please note that these are hypothetical examples and may not work as-is. You should refer to the Ory Keto SDK documentation for the exact syntax and parameters for these functions in TypeScript[^1^]. [^1^]: https://www.ory.sh/docs/guides/upgrade/sdk-v1#permissions--access-controlbrave-memory-91176
06/21/2024, 11:38 AMchilly-king-10285
06/21/2024, 11:38 AMchilly-king-10285
06/21/2024, 11:39 AMEmployee, Company, and SSOConfiguration. typescript import { Namespace, Context } from "@ory/keto-namespace-types" class Employee implements Namespace {} class Company implements Namespace { related: { employees: Employee[] owners: Employee[] ssoConfigManagers: Employee[] ssoConfiguration: SSOConfiguration[] } } class SSOConfiguration implements Namespace { related: { company: Company[] } } In this example, a Company can have employees, owners, and ssoConfigManagers (which are all Employee objects), and an ssoConfiguration (which is an SSOConfiguration object). Next, let's define the permissions in the permits property of the Company class: typescript class Company implements Namespace { related: { employees: Employee[] owners: Employee[] ssoConfigManagers: Employee[] ssoConfiguration: SSOConfiguration[] } permits = { manageSSO: (ctx: Context): boolean => this.related.ssoConfigManagers.includes(ctx.subject), assignRoles: (ctx: Context): boolean => this.related.owners.includes(ctx.subject), } } In this example, an Employee can manageSSO if they are an ssoConfigManager of the Company, and can assignRoles if they are an owner of the Company. Please note that this is a hypothetical example and may not work as-is. You should refer to the Ory Keto documentation for the exact syntax and parameters for these functions in TypeScript[^1^][^2^]. [^1^]: https://www.ory.sh/docs/keto/modeling/create-permission-model#define-relationships-in-the-opl [^2^]: https://www.ory.sh/docs/keto/modeling/create-permission-model#define-permissions-in-the-oplbrave-memory-91176
06/21/2024, 11:40 AMchilly-king-10285
06/21/2024, 11:40 AMchilly-king-10285
06/21/2024, 11:41 AMEmployee, Company, and SSOConfiguration models, ABAC can be used to control access based on specific attributes of these entities. For example, an Employee can be granted the ability to manage the SSOConfiguration of a Company if they have the ssoConfigManager attribute. Similarly, an Employee can be granted the ability to assign roles to other employees if they have the owner attribute. Here's how the permissions are defined in the permits property of the Company class: typescript class Company implements Namespace {{ related: {{ employees: Employee[] owners: Employee[] ssoConfigManagers: Employee[] ssoConfiguration: SSOConfiguration[] }} permits = {{ manageSSO: (ctx: Context): boolean => this.related.ssoConfigManagers.includes(ctx.subject), assignRoles: (ctx: Context): boolean => this.related.owners.includes(ctx.subject), }} }} In this example, the manageSSO and assignRoles permissions are granted based on the ssoConfigManager and owner attributes of the Employee, respectively[^1^]. The advantage of ABAC is that it allows for a high degree of customization and flexibility. It can handle complex access control scenarios that can't be easily managed with simpler models like Role-Based Access Control (RBAC). However, it can also be more complex to implement and manage due to the need to define and evaluate multiple attributes. [^1^]: https://www.ory.sh/docs/keto/modeling/create-permission-model#define-permissions-in-the-oplbrave-memory-91176
06/21/2024, 11:43 AMchilly-king-10285
06/21/2024, 11:43 AMchilly-king-10285
06/21/2024, 11:44 AMEmployee, Company, and SSOConfiguration models, RBAC can be used to control access based on the roles that an Employee has in a Company. For example, an Employee can be assigned the Owner or SSOConfigManager role for a Company. Here's how the roles are defined: typescript import {{ Namespace, Context }} from "@ory/keto-namespace-types" class Employee implements Namespace {{}} class Owner extends Employee {{}} class SSOConfigManager extends Employee {{}} In this example, Owner and SSOConfigManager are roles that inherit from the Employee role. And here's how you might create a relationship where a user has the Owner role for a company: typescript await ory .relationship .createRelationship({{createRelationshipBody: {{namespace: 'companies', object: 'company1', relation: 'owners', subject: 'owner1'}}) And here's how you might create a relationship where another user has the SSOConfigManager role for the same company: typescript await ory .relationship .createRelationship({{createRelationshipBody: {{namespace: 'companies', object: 'company1', relation: 'ssoConfigManagers', subject: 'ssoConfigManager1'}}) In these examples, owner1 is an Owner of company1, and ssoConfigManager1 is an SSOConfigManager of `company1`[^1^]. The advantage of RBAC is that it's simple and intuitive to understand. It's easy to manage access control by assigning users to roles and defining what each role can do. However, it may not be flexible enough to handle complex access control scenarios that require more granular permissions based on specific attributes of the user or resource, which is where Attribute-Based Access Control (ABAC) can be more suitable. [^1^]: https://www.ory.sh/docs/guides/upgrade/sdk-v1#permissions--access-control