careful-honey-27437
05/05/2025, 5:11 AMbrief-egg-61061
05/05/2025, 5:11 AMbrief-egg-61061
05/05/2025, 5:12 AM/opl/syntax/check
endpoint allows you to validate your OPL code before deploying it: POST /opl/syntax/check
This endpoint expects the OPL file in the body of the request and will return any syntax errors found [Ory Keto API Reference](https://www.ory.sh/docs/keto/reference/rest-api). ### Common Issues There are some known issues with OPL that you might encounter: 1. Traverse Function Issues: There's a documented issue where the traverse.(...)
function doesn't work as expected in some cases. This can result in permission checks returning false
when they should return true
[Github Issue #1330](https://github.com/ory/keto/issues/1330). 2. Inconsistencies with this.permits(ctx)
: When using this.permits(ctx)
to reference other permission functions that call transitive relations, you might get inconsistent results. In some cases, directly calling the transitive relation in each permission function works better than referencing another permission function [Github Issue #1626](https://github.com/ory/keto/issues/1626). 3. Relation Tuple Deletion: There's an inconsistency in the API where you cannot DELETE relation tuples that you defined with a namespace. Instead, you need to use the PATCH API endpoint to remove them [Github Issue #1330](https://github.com/ory/keto/issues/1330). ### Debugging in Docker If you're running Ory in Docker and need to debug, Ory Kratos provides debugging support: 1. For Docker Compose setups, you can use the Dockerfile-debug
file and the docker-compose.template.dbg
template [Debugging Ory Kratos in Docker](https://www.ory.sh/docs/kratos/debug/debug-docker-delve-ory-kratos). 2. For standalone Docker containers, you can use the Dockerfile-debug
file directly [Standalone Docker Container Debugging](https://www.ory.sh/docs/kratos/debug/debug-docker-delve-ory-kratos#as-a-standalone-docker-container). ### Logging You can adjust the log level to get more detailed information by setting the LOG_LEVEL
environment variable. Supported levels include: - debug - info - warn - error - fatal - panic [Ory Hydra FAQ](https://www.ory.sh/docs/hydra/faq#can-i-set-the-log-level-to-warn-error-debug-) If you have a more specific question about debugging OPL, please provide more details so I can give you a more targeted answer.careful-honey-27437
05/05/2025, 5:12 AMallowed: false
.careful-honey-27437
05/05/2025, 5:13 AMallowed: false
. But if User:123
has the relation of edtors
to Article:abc
then the check for the read
permit (relation) should return `allowed: true`: import { Namespace, Context } from “@ory/keto-namespace-types”
class User implements Namespace { }
class Organization implements Namespace {
related: {
owners: User[]
admins: User[]
}
permits = {
create: (ctx: Context): boolean =>
this.related.owners.includes(ctx.subject) ||
this.related.admins.includes(ctx.subject),
create_organization_admin: (ctx: Context): boolean =>
this.related.owners.includes(ctx.subject),
create_publication_admin: (ctx: Context): boolean =>
this.related.owners.includes(ctx.subject) ||
this.related.admins.includes(ctx.subject),
read: (ctx: Context): boolean =>
this.related.owners.includes(ctx.subject) ||
this.related.admins.includes(ctx.subject),
update: (ctx: Context): boolean =>
this.related.owners.includes(ctx.subject) ||
this.related.admins.includes(ctx.subject),
delete: (ctx: Context): boolean =>
this.related.owners.includes(ctx.subject) ||
this.related.admins.includes(ctx.subject),
}
}
class Publication implements Namespace {
related: {
organizations: Organization[]
admins: User[]
editors: User[]
}
permits = {
create: (ctx: Context): boolean =>
this.related.admins.includes(ctx.subject) ||
this.related.editors.includes(ctx.subject) ||
this.related.organizations.traverse((org) => org.permits.create(ctx)),
create_publication_admin: (ctx: Context): boolean =>
this.related.organizations.traverse((org) => org.permits.create_publication_admin(ctx)),
create_publication_editor: (ctx: Context): boolean =>
this.related.admins.includes(ctx.subject) ||
this.related.organizations.traverse((org) => org.permits.create(ctx)),
read: (ctx: Context): boolean =>
this.related.admins.includes(ctx.subject) ||
this.related.editors.includes(ctx.subject) ||
this.related.organizations.traverse((org) => org.permits.read(ctx)),
update: (ctx: Context): boolean =>
this.related.admins.includes(ctx.subject) ||
this.related.editors.includes(ctx.subject) ||
this.related.organizations.traverse((org) => org.permits.update(ctx)),
delete: (ctx: Context): boolean =>
this.related.admins.includes(ctx.subject) ||
this.related.editors.includes(ctx.subject) ||
this.related.organizations.traverse((org) => org.permits.delete(ctx)),
}
}
class Article implements Namespace {
related: {
publications: Publication[]
editors: User[]
collaborators: User[]
}
permits = {
create: (ctx: Context): boolean =>
this.related.editors.includes(ctx.subject) ||
this.related.collaborators.includes(ctx.subject) ||
this.related.publications.traverse((pub) => pub.permits.create(ctx)),
create_article_editor: (ctx: Context): boolean =>
this.related.publications.traverse((pub) => pub.permits.create(ctx)),
create_article_collaborator: (ctx: Context): boolean =>
this.related.editors.includes(ctx.subject) ||
this.related.publications.traverse((pub) => pub.permits.create(ctx)),
read: (ctx: Context): boolean =>
this.related.editors.includes(ctx.subject) ||
this.related.collaborators.includes(ctx.subject) ||
this.related.publications.traverse((pub) => pub.permits.read(ctx)),
read_author_id: (ctx: Context): boolean =>
this.related.editors.includes(ctx.subject) ||
this.related.publications.traverse((pub) => pub.permits.read(ctx)),
update: (ctx: Context): boolean =>
this.related.editors.includes(ctx.subject) ||
this.related.collaborators.includes(ctx.subject) ||
this.related.publications.traverse((pub) => pub.permits.update(ctx)),
delete: (ctx: Context): boolean =>
this.related.editors.includes(ctx.subject) ||
this.related.collaborators.includes(ctx.subject) ||
this.related.publications.traverse((pub) => pub.permits.delete(ctx)),
}
}brief-egg-61061
05/05/2025, 5:13 AMbrief-egg-61061
05/05/2025, 5:14 AMallowed: false
when you expect it to return true
. This appears to be related to a known issue with the traverse
function in OPL. ## Analysis of Your Issue Based on your configuration, if User:123
has the relation of editors
to Article:abc
, then checking the read
permit should indeed return allowed: true
. This is because your Article
namespace has the following permission definition: typescript read: (ctx: Context): boolean => this.related.editors.includes(ctx.subject) || this.related.collaborators.includes(ctx.subject) || this.related.publications.traverse((pub) => pub.permits.read(ctx)),
The first condition this.related.editors.includes(ctx.subject)
should evaluate to true
if User:123
is in the editors
relation of Article:abc
. ## Known Issues with OPL There are a couple of known issues with OPL that might be affecting your configuration: 1. Traverse Function Issues: There's a documented issue where the traverse.(...)
function doesn't work as expected in some cases. This can result in permission checks returning false
when they should return true
[Github Issue #1330](https://github.com/ory/keto/issues/1330). 2. Inconsistencies with this.permits(ctx)
: When using this.permits(ctx)
to reference other permission functions that call transitive relations, you might get inconsistent results [Github Issue #1626](https://github.com/ory/keto/issues/1626). ## Possible Solutions 1. Check Your Relation Tuples: Make sure that the relation tuple Article:abc#editors@User:123
actually exists in your database. You can verify this using the Ory Keto CLI or API. 2. Simplify Your Permission Model: Try simplifying your permission model to isolate the issue. For example, you could temporarily remove the traverse
calls to see if the basic includes
checks work correctly. 3. Direct Transitive Calls: Based on the issue #1626, you might want to try replacing any this.permits.X(ctx)
calls with direct transitive calls to see if that resolves the issue. 4. Check Namespace Definitions: Ensure that your namespace definitions match exactly what's in your database. Namespaces are case-sensitive. 5. API Endpoint: Make sure you're using the correct API endpoint for permission checks. The endpoint should be: GET /relation-tuples/check?namespace=Article&object=abc&relation=read&subject_id=123
If you're still experiencing issues after trying these solutions, you might want to report this as a bug to the Ory team, as it could be related to the known issues with the traverse
function or other aspects of OPL. For more information on creating and debugging permission models, you can refer to the [Ory Permissions documentation on creating permission models](https://www.ory.sh/docs/keto/modeling/create-permission-model).