From c4d84f6209deea8b5993409a66208b5dd35f5807 Mon Sep 17 00:00:00 2001 From: hperl <34397+hperl@users.noreply.github.com> Date: Mon, 10 Oct 2022 13:15:29 +0200 Subject: [PATCH] feat: allow permits referencing permits You can now use `this.permits.(ctx)` to reference another permission in a permission declaration. Example: comment: (ctx: Context) => this.permits.read(ctx) --- ...=snapshots-advanced_typescript_syntax.json | 11 ++++++ internal/schema/parser.go | 34 ++++++++++++++----- internal/schema/parser_test.go | 3 +- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/internal/schema/.snapshots/TestParser-suite=snapshots-advanced_typescript_syntax.json b/internal/schema/.snapshots/TestParser-suite=snapshots-advanced_typescript_syntax.json index 6f76fe664..83413403a 100644 --- a/internal/schema/.snapshots/TestParser-suite=snapshots-advanced_typescript_syntax.json +++ b/internal/schema/.snapshots/TestParser-suite=snapshots-advanced_typescript_syntax.json @@ -60,6 +60,17 @@ ] } }, + { + "name": "comment", + "rewrite": { + "operator": "or", + "children": [ + { + "relation": "read" + } + ] + } + }, { "name": "update", "rewrite": { diff --git a/internal/schema/parser.go b/internal/schema/parser.go index c12239a12..59b383a50 100644 --- a/internal/schema/parser.go +++ b/internal/schema/parser.go @@ -395,18 +395,36 @@ func setOperation(typ itemType) ast.Operator { } func (p *parser) parsePermissionExpression() (child ast.Child) { - var name item + var name, verb item - if !p.match("this", ".", "related", ".", &name, ".") { + if !p.match("this", ".", &verb, ".", &name) { return } - switch item := p.next(); item.Val { - case "traverse": - child = p.parseTupleToSubjectSet(name) - case "includes": - child = p.parseComputedSubjectSet(name) + + switch verb.Val { + case "related": + if !p.match(".") { + return + } + switch item := p.next(); item.Val { + case "traverse": + child = p.parseTupleToSubjectSet(name) + case "includes": + child = p.parseComputedSubjectSet(name) + default: + p.addFatal(item, "expected 'traverse' or 'includes', got %q", item.Val) + } + + case "permits": + if !p.match("(", "ctx", ")") { + return + } + p.addCheck(checkCurrentNamespaceHasRelation(&p.namespace, name)) + return &ast.ComputedSubjectSet{Relation: name.Val} + default: - p.addFatal(item, "expected 'traverse' or 'includes', got %q", item.Val) + p.addFatal(verb, "expected 'related' or 'permits', got %q", verb.Val) + } return diff --git a/internal/schema/parser_test.go b/internal/schema/parser_test.go index cb576afa7..f08d74685 100644 --- a/internal/schema/parser_test.go +++ b/internal/schema/parser_test.go @@ -95,8 +95,7 @@ class Resource implements Namespace { this.related.medicalAnnotators.traverse((role) => role.related.member.includes(ctx.subject)) || this.related.supervisors.traverse((role) => role.related.member.includes(ctx.subject)), - // TODO: support referencing permits. - // comment: (ctx: Context) => this.permits.read(ctx), + comment: (ctx: Context) => this.permits.read(ctx), update: (ctx: Context) => this.related.admins.traverse((role) => role.related.member.includes(ctx.subject)) || this.related.annotators.traverse((role) => role.related.member.includes(ctx.subject)) ||