wooden-manchester-52124
04/01/2025, 1:50 PMbrief-egg-61061
04/01/2025, 1:50 PMbrief-egg-61061
04/01/2025, 1:51 PMory is allowed
command which resolves subject sets and subject set rewrites [ory is allowed](https://www.ory.sh/docs/cli/ory-is-allowed#ory-is-allowed).wooden-manchester-52124
04/01/2025, 5:18 PMbrief-egg-61061
04/01/2025, 5:18 PMbrief-egg-61061
04/01/2025, 5:18 PMPATCH admin/relation-tuples
endpoint in Ory Network, you need to format your request properly. Based on the knowledge sources, here's how you can do it: The PATCH endpoint allows you to add relation tuples with subject sets. Here's an example of how to add a subject set: json { "namespace": "Project", "object": "ProjectUUID", "relation": "viewers", "subject_set": { "namespace": "Email", "object": "<mailto:user@example.com|user@example.com>", "relation": "owner" } }
This example would create a relation tuple that grants viewing access to a project for anyone who is an owner of the specified email address. It's worth noting that there's an important distinction between the DELETE and PATCH endpoints when working with relation tuples that include subject sets. As mentioned in one of the issues: > There is an inconsistency in the API that is not mentioned here, because you cannot DELETE the relation tuple that you defined with the namespace anymore. You can only PATCH them to remove it with the PATCH API endpoint. The delete endpoint will give you an error that the relation tuple misses a subjectSet.relation property. The patch endpoint will not do that. [Github Issue #1330](https://github.com/ory/keto/issues/1330) So when you need to remove a relation tuple with a subject set, you should use the PATCH endpoint rather than the DELETE endpoint. Also, if you're trying to use an empty relation in your subject set, note that this was previously not supported through the UI, but you can use a wildcard ...
in place of an empty relation as mentioned in a GitHub issue [Github Issue #151](https://github.com/ory/network/issues/151). When working with relation tuples, be careful with DELETE operations. There was a reported issue where sending a DELETE request with a non-existent ID could delete all relation tuples [Github Issue #230](https://github.com/ory/network/issues/230). For more information about the structure of relation tuples and subject sets, you can refer to the Ory Keto protocol documentation. I hope this helps! Let me know if you need any clarification.wooden-manchester-52124
04/01/2025, 5:20 PMbrief-egg-61061
04/01/2025, 5:20 PMbrief-egg-61061
04/01/2025, 5:20 PMFolder keto/ viewers Group:developer#members
This is a subject set relationship where Group:developer#members
is a subject set that refers to all subjects who have the "members" relation on the "developer" object in the "Group" namespace [Get started with Ory Permissions](https://www.ory.sh/docs/guides/permissions/overview#example). Additionally, you can define permission rules using the Ory Permission Language (OPL) in the Console by going to the Permission Rules tab, which allows you to create more complex permission structures including subject set rewrites [Get started with Ory Permissions](https://www.ory.sh/docs/guides/permissions/overview#example). If you prefer working with the CLI instead of the Console, you can also create relationships with subject sets using the Ory CLI as shown in our previous conversation.wooden-manchester-52124
04/01/2025, 6:21 PMbrief-egg-61061
04/01/2025, 6:21 PMbrief-egg-61061
04/01/2025, 6:21 PMtypescript import { Namespace, Context } from "@ory/keto-namespace-types" class User implements Namespace {} class AdminGroup implements Namespace { related: { members: User[] } } class Folder implements Namespace { related: { parents: Folder[] viewers: User[] } permits = { view: (ctx: Context): boolean => // Regular permission check for explicit relationships this.related.viewers.includes(ctx.subject) || this.related.parents.traverse((parent) => parent.permits.view(ctx)) || // Global rule for AdminGroup members AdminGroup.related.members.includes(ctx.subject) } } class File implements Namespace { related: { parents: Folder[] viewers: User[] owners: User[] } permits = { view: (ctx: Context): boolean => // Regular permission check for explicit relationships this.related.viewers.includes(ctx.subject) || this.related.owners.includes(ctx.subject) || this.related.parents.traverse((parent) => parent.permits.view(ctx)) || // Global rule for AdminGroup members AdminGroup.related.members.includes(ctx.subject), edit: (ctx: Context): boolean => this.related.owners.includes(ctx.subject) || // Global rule for AdminGroup members AdminGroup.related.members.includes(ctx.subject) } }
In this OPL configuration: 1. We define an AdminGroup
namespace with a members
relation that contains User
objects. 2. For both File
and Folder
namespaces, we add a condition to each permission check that grants access if the subject is a member of the AdminGroup
. 3. This approach doesn't require explicit relationships between the AdminGroup members and each File/Folder - it's a global rule that applies to all objects. The key part is adding AdminGroup.related.members.includes(ctx.subject)
to each permission function. This checks if the subject is a member of the AdminGroup, and if so, grants the permission regardless of other relationships. You can define this in the Ory Console by going to Permissions → Relationships and switching to the Permission Rules tab [Get started with Ory Permissions](https://www.ory.sh/docs/guides/permissions/overview#example). This approach leverages the power of the Ory Permission Language to define global rules that don't require explicit relationships for each object, effectively implementing a wildcard-like access pattern for AdminGroup members. For more details on creating permission models with OPL, you can refer to the [Create a permission model](https://www.ory.sh/docs/keto/modeling/create-permission-model) documentation.wooden-manchester-52124
04/01/2025, 6:24 PMbrief-egg-61061
04/01/2025, 6:24 PMbrief-egg-61061
04/01/2025, 6:24 PMrelated
property directly on the AdminGroup
class rather than on an instance of it. In OPL, when you want to check if a user is a member of a group from another namespace's permission function, you need to use the traverse
method instead of trying to access the class directly. Here's the corrected version: typescript import { Namespace, Context, SubjectSet } from "@ory/keto-namespace-types" class User implements Namespace {} class AdminGroup implements Namespace { related: { members: User[] } } class Folder implements Namespace { related: { parents: Folder[] viewers: User[] admins: SubjectSet<AdminGroup, "members">[] } permits = { view: (ctx: Context): boolean => // Regular permission check for explicit relationships this.related.viewers.includes(ctx.subject) || this.related.parents.traverse((parent) => parent.permits.view(ctx)) || // Check if subject is in AdminGroup members this.related.admins.includes(ctx.subject) } } class File implements Namespace { related: { parents: Folder[] viewers: User[] owners: User[] admins: SubjectSet<AdminGroup, "members">[] } permits = { view: (ctx: Context): boolean => // Regular permission check for explicit relationships this.related.viewers.includes(ctx.subject) || this.related.owners.includes(ctx.subject) || this.related.parents.traverse((parent) => parent.permits.view(ctx)) || // Check if subject is in AdminGroup members this.related.admins.includes(ctx.subject), edit: (ctx: Context): boolean => this.related.owners.includes(ctx.subject) || // Check if subject is in AdminGroup members this.related.admins.includes(ctx.subject) } }
The key changes are: 1. Added a SubjectSet<AdminGroup, "members">[]
relation called admins
to both File
and Folder
classes 2. Used this.related.admins.includes(ctx.subject)
to check if the subject is a member of the AdminGroup To make this work, you'll need to create a relationship tuple for each File and Folder that should be accessible by AdminGroup members. For example: File:document1#admins@AdminGroup:admingroup1#members Folder:folder1#admins@AdminGroup:admingroup1#members
If you want a truly global rule without having to create individual relationships for each file/folder, you might need to consider a different approach in your permission model design, as OPL doesn't directly support wildcards in the way you described. The permission checks are always performed against specific objects and their relationships.