<@U04UQ68083H>, What is the best way to configure ...
# ory-copilot
m
@chilly-king-10285, What is the best way to configure Ory Permissions using OPL to grant a 'sysadmin' super-user access to all resources? Let’s assume I have a Super-user team group made up of multiple users.
Copy code
class User implements Namespace {
}

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

export class Project implements Namespace {

related: {
    viewer: SubjectSet<Group, "members">[]
  }

  permits = {
    read: (ctx: Context): boolean =>
      this.related.viewer.includes(ctx.subject) ||
      this.permits.write(ctx),
  }
is there a way to grant read/viewer access automatically through OPL directly? or I do need to necessarily create tuple like these: • granting direct access to each namespace as viewer • project-viewer-super-user-team, document-viewer-super-user-team
Copy code
{
    "namespace": "Group",
    "object": "super_users",
    "relation": "members",
    "subject_set": {
      "namespace": "User",
      "object": "admin-user"
    }
  },
Copy code
{
  "namespace": "Project",
  "object": "my-project",
  "relation": "viewer",
  "subject_set": {
    "namespace": "Group",
    "object": "super_users",
    "relation": "members"
  }
}
b
A message from kapa.ai
To grant a "sysadmin" super-user group access to all resources in Ory Permissions using OPL (Ory Permission Language), you generally have two main options: ### 1. Grant Access via Relationship Tuples The standard and recommended approach is to create relationship tuples that explicitly grant the super-user group access to each resource or namespace. For example, you would add the "super_users" group as a
viewer
(or other relevant relation) to each resource:
Copy code
json {   "namespace": "Group",   "object": "super_users",   "relation": "members",   "subject_set": {     "namespace": "User",     "object": "admin-user"   } }
Copy code
json {   "namespace": "Project",   "object": "my-project",   "relation": "viewer",   "subject_set": {     "namespace": "Group",     "object": "super_users",     "relation": "members"   } }
This approach is directly supported and aligns with how Ory Permissions is designed to work: permissions are granted based on relationships between subjects (users/groups) and objects (resources) [Get started with Ory Permissions](https://www.ory.sh/docs/guides/permissions/overview#example). ### 2. Grant Access via OPL Rules The OPL itself is not designed to provide "global" or "wildcard" access to all resources for a group without some form of relationship tuple. OPL rules define how permissions are derived from relationships, but they do not provide a way to say "if subject is in super_users, always allow" for all resources, unless you encode that logic in every namespace's permission rule. For example, you could add a check in your OPL for each resource type:
Copy code
typescript permits = {   read: (ctx: Context): boolean =>     this.related.viewer.includes(ctx.subject) ||     ctx.subject.isInGroup("super_users") || // Pseudocode, not supported natively     this.permits.write(ctx), }
However, the OPL does not natively support a global
isInGroup
function or wildcard matching
. You would still need to encode the logic for each namespace, and you would need to ensure that the relationship between users and the "super_users" group exists as tuples. The OPL is evaluated per resource and per namespace, and there is no built-in global override mechanism [Ory Permission Language specification](https://www.ory.sh/docs/keto/reference/ory-permission-language#statements). ### Conclusion - You must create relationship tuples to grant the "super_users" group access to each resource or namespace. There is no OPL-only way to grant global access without these tuples. - You can make your OPL rules check for membership in the "super_users" group, but the group membership itself must be represented as tuples, and you must add this logic to each relevant permission rule. - There is no built-in OPL feature for global or wildcard access; permissions are always derived from relationships and the rules you define per namespace [Create a permission model](https://www.ory.sh/docs/keto/modeling/create-permission-model#define-permissions-in-the-opl). If you have many resources, you may want to automate the creation of these tuples for the "super_users" group across all relevant namespaces and objects. --- Summary: You need to create relationship tuples to grant super-user access. OPL rules can reference these relationships, but cannot grant global access without them. There is no OPL-only shortcut for super-user access; relationships are the source of truth for permissions in Ory Permissions.
m
@chilly-king-10285 I want to make your OPL rules check for membership in the "super_users" group, but the group membership itself must be represented as tuples, and you must add this logic to each relevant permission rule. - explain how to define global
isInGroup
function
b
A message from kapa.ai
Ory Permission Language (OPL) does not provide a built-in global
isInGroup
function or a way to define global helper functions that can be reused across all namespaces. Instead, OPL rules are written per namespace, and permission checks are based on the relationships (tuples) you define between users, groups, and resources. To check if a user is a member of the
super_users
group within your OPL rules, you must model this relationship using tuples and then reference this relationship in each relevant permission rule. Here’s how you can do it: ### 1. Model the Group Membership as a Relationship First, ensure you have a
Group
namespace with a
members
relation, and that you create tuples representing membership:
Copy code
typescript class User implements Namespace {}  class Group implements Namespace {   related: {     members: (User | Group)[]   } }
Then, create a tuple for the super user group membership (using the Ory Console or CLI):
Copy code
json {   "namespace": "Group",   "object": "super_users",   "relation": "members",   "subject_id": "user-id" }
or for multiple users, repeat for each user. ### 2. Reference the Group Membership in Permission Rules In each namespace where you want to grant super-user access, you can add a check to see if the subject is a member of the
super_users
group. This is done by including a
SubjectSet
reference in your permission rule. For example:
Copy code
typescript import { Namespace, SubjectSet, Context } from "@ory/permission-namespace-types"  class Project implements Namespace {   related: {     viewer: (User | SubjectSet<Group, "members">)[]   }    permits = {     read: (ctx: Context): boolean =>       this.related.viewer.includes(ctx.subject) ||       // Grant access if user is in super_users group       this.related.viewer.includes(SubjectSet<Group, "members">("super_users")) ||       this.permits.write(ctx),   } }
However, OPL does not support defining a global function like
isInGroup
that you can call from anywhere. Instead, you must explicitly check for the group membership in each permission rule where you want this logic to apply. The check is typically done by including a
SubjectSet
for the group in the relevant relation (e.g.,
viewer
), and then ensuring your tuples reflect the group membership [Ory Permission Language specification](https://www.ory.sh/docs/keto/reference/ory-permission-language#statements) [Create a permission model](https://www.ory.sh/docs/keto/modeling/create-permission-model#define-permissions-in-the-opl). ### Summary - There is no global
isInGroup
function
in OPL. - You must model group membership as tuples and reference the group in each permission rule where you want to grant access. - The logic must be repeated in each relevant namespace’s permission rule. If you need to apply this logic across many namespaces, you will need to repeat the check in each one, as OPL does not support global helper functions or imports.
m
@chilly-king-10285 show me an example of "The logic must be repeated in each relevant namespace’s permission rule."
b
A message from kapa.ai
Certainly! Here’s how you would repeat the logic for checking if a user is a member of the
super_users
group in each relevant namespace’s permission rule, based on the OPL (Ory Permission Language) examples from the knowledge sources. Suppose you have two namespaces:
Project
and
Document
. In both, you want to grant read access to anyone who is a member of the
super_users
group, in addition to the usual access rules. You would write the permission rules like this:
Copy code
typescript import { Namespace, SubjectSet, Context } from "@ory/permission-namespace-types"  class User implements Namespace {}  class Group implements Namespace {   related: {     members: (User | Group)[]   } }  class Project implements Namespace {   related: {     viewers: (User | SubjectSet<Group, "members">)[]   }    permits = {     read: (ctx: Context): boolean =>       this.related.viewers.includes(ctx.subject) ||       // Grant access if user is in super_users group       SubjectSet<Group, "members">("super_users").includes(ctx.subject)   } }  class Document implements Namespace {   related: {     viewers: (User | SubjectSet<Group, "members">)[]   }    permits = {     read: (ctx: Context): boolean =>       this.related.viewers.includes(ctx.subject) ||       // Grant access if user is in super_users group       SubjectSet<Group, "members">("super_users").includes(ctx.subject)   } }
Key point: You must add the check for
super_users
membership in the
read
permission of both
Project
and
Document
namespaces. This is what is meant by "the logic must be repeated in each relevant namespace’s permission rule" [Ory Permission Language specification](https://www.ory.sh/docs/keto/reference/ory-permission-language#examples). > Note: The actual syntax for checking group membership in OPL is to include the group as a
SubjectSet
in the relevant relation and ensure the tuples exist. The above is illustrative; you may need to adjust the syntax to match your OPL environment and how you model relationships. If you have more namespaces (e.g.,
Folder
,
File
, etc.), you would repeat this logic in each one’s permission rules as needed.
m
@chilly-king-10285 show me the minimum tuple to be configured with the '/admin/relation-tuples' endpoint to handle the above relationship
b
A message from kapa.ai
To handle the relationship where a user is a member of the
super_users
group (so you can reference this group in your OPL permission rules), you need to create a tuple that expresses this membership. Using the
/admin/relation-tuples
endpoint, the minimum tuple required would look like this:
Copy code
json {   "namespace": "Group",   "object": "super_users",   "relation": "members",   "subject_id": "user-id" }
- `namespace`: The namespace for groups, here
"Group"
. - `object`: The specific group, here
"super_users"
. - `relation`: The relation, here
"members"
. - `subject_id`: The user you want to make a super user, e.g.,
"user-id"
. This tuple states: User with ID
user-id
is a member of the
super_users
group
. You can create this tuple using the
/admin/relation-tuples
endpoint with a
PUT
request and the above JSON as the body [Ory API Reference - createRelationship](https://www.ory.sh/docs/reference/api#createrelationship). If you want to add more users, repeat this tuple for each user with their respective
subject_id
. > This is the minimum configuration needed to represent the relationship in Ory Permissions. The actual permission logic in OPL will then reference this group membership as described previously.
m
@chilly-king-10285 how to grant viewer permission through OPL now to super_users ?
b
A message from kapa.ai
To grant
viewer
permission to the
super_users
group through OPL, you need to: 1. Model the group membership as a relationship tuple (as shown previously). 2. Reference the
super_users
group in your OPL permission rule
by including it as a
SubjectSet
in the relevant relation. Here’s how you can do it, based on the OPL examples from the knowledge sources: Suppose you have a
Project
namespace and want to grant
viewer
permission to all members of the
super_users
group. You would define your OPL like this:
Copy code
typescript import { Namespace, SubjectSet, Context } from "@ory/permission-namespace-types"  class User implements Namespace {}  class Group implements Namespace {   related: {     members: (User | Group)[]   } }  class Project implements Namespace {   related: {     viewers: (User | SubjectSet<Group, "members">)[]   }    permits = {     view: (ctx: Context): boolean =>       this.related.viewers.includes(ctx.subject)   } }
How does this grant access to
super_users
?
- You add a relationship tuple that makes the
super_users
group a
viewer
of the project:
Copy code
json     {       "namespace": "Project",       "object": "my-project",       "relation": "viewers",       "subject_set": {         "namespace": "Group",         "object": "super_users",         "relation": "members"       }     }
- Now, any user who is a member of the
super_users
group (as defined by the membership tuple) will have
viewer
permission on the project, because the OPL rule checks if the subject is included in the
viewers
relation, which now includes the
super_users
group as a
SubjectSet
 [Get started with Ory Permissions](https://www.ory.sh/docs/guides/permissions/overview#example) [Ory Permission Language specification](https://www.ory.sh/docs/keto/reference/ory-permission-language#examples). Summary: You grant
viewer
permission to
super_users
by adding the group as a
SubjectSet
to the
viewers
relation in your OPL and creating the corresponding relationship tuple. The OPL rule then automatically grants access to all members of the
super_users
group.
m
@chilly-king-10285 can I do this for only a parent project and let all the child projects inherit this privilege?
b
A message from kapa.ai
Yes, you can grant the
super_users
group viewer permission on a parent project and have all child projects inherit this privilege, if your OPL permission model is set up to support hierarchical (transitive) permissions. In Ory Permission Language (OPL), you can define permission rules that check not only the direct
viewers
of a project, but also traverse parent relationships to inherit permissions. Here’s how you would typically model this:
Copy code
typescript import { Namespace, SubjectSet, Context } from "@ory/permission-namespace-types"  class User implements Namespace {}  class Group implements Namespace {   related: {     members: (User | Group)[]   } }  class Project implements Namespace {   related: {     viewers: (User | SubjectSet<Group, "members">)[]     parents: Project[]   }    permits = {     view: (ctx: Context): boolean =>       this.related.viewers.includes(ctx.subject) ||       this.related.parents.traverse((parent) => parent.permits.view(ctx))   } }
With this model: - If you add the
super_users
group as a
viewer
to the parent project (using a tuple), all child projects will inherit this permission through the
parents.traverse(...)
rule. - Any user who is a member of the
super_users
group will have viewer access to the parent project and all its descendants, as long as the parent-child relationships are correctly set up in your tuples. This approach is explicitly described in the Ory documentation for hierarchical permission models, where permissions can be inherited through parent relationships [Define permissions in the OPL](https://www.ory.sh/docs/keto/modeling/create-permission-model#define-permissions-in-the-opl). Summary: You only need to grant the
super_users
group viewer permission on the parent project. If your OPL rules use parent traversal as shown above, all child projects will automatically inherit this privilege.
m
@chilly-king-10285 how to define parent relationshiop for a new project and parent/superuser ? can you show me all the cfg tuple?
b
A message from kapa.ai
To define a parent relationship for a new project and grant the
super_users
group viewer access (so that this access is inherited by child projects), you need to create the following relationship tuples: ### 1. Parent Relationship Tuple This tuple establishes the parent-child relationship between two projects (e.g.,
child-project
is a child of
parent-project
):
Copy code
json {   "namespace": "Project",   "object": "child-project",   "relation": "parents",   "subject_id": "parent-project" }
- `namespace`: The namespace, here
"Project"
. - `object`: The child project, e.g.,
"child-project"
. - `relation`: The relation, here
"parents"
. - `subject_id`: The parent project, e.g.,
"parent-project"
. ### 2. Superuser Group Membership Tuple This tuple makes a user a member of the
super_users
group:
Copy code
json {   "namespace": "Group",   "object": "super_users",   "relation": "members",   "subject_id": "admin-user" }
- `namespace`:
"Group"
- `object`:
"super_users"
- `relation`:
"members"
- `subject_id`: The user ID, e.g.,
"admin-user"
### 3. Grant Viewer Permission to Superuser Group on Parent Project This tuple grants the
super_users
group viewer access to the parent project:
Copy code
json {   "namespace": "Project",   "object": "parent-project",   "relation": "viewers",   "subject_set": {     "namespace": "Group",     "object": "super_users",     "relation": "members"   } }
- `namespace`:
"Project"
- `object`:
"parent-project"
- `relation`:
"viewers"
- `subject_set`: Points to the
super_users
group membership --- With these tuples: - The
super_users
group is a viewer of the parent project. - Any user who is a member of
super_users
will have viewer access to the parent project. - If your OPL permission model uses parent traversal (as shown in previous answers), all child projects will inherit this viewer privilege from the parent project [Get started with Ory Permissions](https://www.ory.sh/docs/guides/permissions/overview#example) [Create a permission model](https://www.ory.sh/docs/keto/modeling/create-permission-model#define-relationships-in-the-opl). If you need to create these tuples via the
/admin/relation-tuples
endpoint, you can send them as a batch using the
patchRelationships
API with the
insert
action [Keto API Reference - patchRelationships](https://www.ory.sh/docs/keto/reference/rest-api).