Skip to content

Commit

Permalink
feat(parser): allow quoted property access (#1273)
Browse files Browse the repository at this point in the history
  • Loading branch information
zepatrik committed Mar 8, 2023
1 parent de864ef commit 75ae307
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"Resource": [
{
"name": "scope.relation",
"types": [
{
"namespace": "Resource"
}
]
},
{
"name": "scope.action_0",
"rewrite": {
"operator": "or",
"children": [
{
"relation": "scope.relation",
"computed_subject_set_relation": "scope.action_1"
}
]
}
},
{
"name": "scope.action_1",
"rewrite": {
"operator": "or",
"children": [
{
"relation": "scope.relation",
"computed_subject_set_relation": "scope.relation"
}
]
}
},
{
"name": "scope.action_2",
"rewrite": {
"operator": "or",
"children": [
{
"relation": "scope.action_0"
}
]
}
}
]
}
22 changes: 18 additions & 4 deletions internal/schema/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ func (p *parser) match(tokens ...interface{}) (matched bool) {
if !token(p) {
return false
}
default:
panic(fmt.Sprintf("unexpected token type %T", token))
}
}
return true
Expand Down Expand Up @@ -414,10 +416,17 @@ func setOperation(typ itemType) ast.Operator {
panic("not reached")
}

func (p *parser) matchPropertyAccess(propertyName any) bool {
return p.matchIf(is(itemBracketLeft), "[", propertyName, "]") || p.match(".", propertyName)
}

func (p *parser) parsePermissionExpression() (child ast.Child) {
var name, verb item

if !p.match("this", ".", &verb, ".", &name) {
if !p.match("this", ".", &verb) {
return
}
if !p.matchPropertyAccess(&name) {
return
}

Expand All @@ -444,7 +453,6 @@ func (p *parser) parsePermissionExpression() (child ast.Child) {

default:
p.addFatal(verb, "expected 'related' or 'permits', got %q", verb.Val)

}

return
Expand All @@ -469,15 +477,21 @@ func (p *parser) parseTupleToSubjectSet(relation item) (rewrite ast.Child) {

switch verb.Val {
case "related":
if !p.matchPropertyAccess(&subjectSetRel) {
return nil
}
p.match(
".", &subjectSetRel, ".", "includes", "(", "ctx", ".", "subject",
".", "includes", "(", "ctx", ".", "subject",
optional(","), ")", optional(","), ")",
)
p.addCheck(checkAllRelationsTypesHaveRelation(
&p.namespace, relation, subjectSetRel,
))
case "permits":
p.match(".", &subjectSetRel, "(", "ctx", ")", ")")
if !p.matchPropertyAccess(&subjectSetRel) {
return nil
}
p.match("(", "ctx", ")", ")")
p.addCheck(checkAllRelationsTypesHaveRelation(
&p.namespace, relation, subjectSetRel,
))
Expand Down
12 changes: 11 additions & 1 deletion internal/schema/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,17 @@ class Resource implements Namespace {
this.related.supervisors.traverse((role) => role.related.member.includes(ctx.subject)),
};
}
`},
`}, {"quoted property names", `
class Resource implements Namespace {
related: {
"scope.relation": Resource[]
}
permits = {
"scope.action_0": (ctx: Context) => this.related["scope.relation"].traverse((r) => r.permits["scope.action_1"](ctx)),
"scope.action_1": (ctx: Context) => this.related["scope.relation"].traverse((r) => r.related["scope.relation"].includes(ctx.subject)),
"scope.action_2": (ctx: Context) => this.permits["scope.action_0"](ctx),
}
}`},
}

func TestParser(t *testing.T) {
Expand Down

0 comments on commit 75ae307

Please sign in to comment.