From dcb7594717304f80667c111eabf047917bd7bdc3 Mon Sep 17 00:00:00 2001 From: Tolga Ozen Date: Thu, 19 Sep 2024 10:18:35 +0300 Subject: [PATCH 1/2] refactor: modify DSL rules to support new structure --- assets/example-shapes/disney-plus.yaml | 2 +- docs/getting-started/modeling.mdx | 6 +-- docs/use-cases/abac.mdx | 65 ++++++++++++++------------ 3 files changed, 39 insertions(+), 34 deletions(-) diff --git a/assets/example-shapes/disney-plus.yaml b/assets/example-shapes/disney-plus.yaml index 957dac099..6f3ce6307 100644 --- a/assets/example-shapes/disney-plus.yaml +++ b/assets/example-shapes/disney-plus.yaml @@ -45,7 +45,7 @@ schema: |- context.data.age >= age_rating } - rule check_region(region string, allowed_region string[]) { + rule check_region(allowed_region string[]) { context.data.region in allowed_region } diff --git a/docs/getting-started/modeling.mdx b/docs/getting-started/modeling.mdx index 60214d78c..63b65bf3e 100644 --- a/docs/getting-started/modeling.mdx +++ b/docs/getting-started/modeling.mdx @@ -345,11 +345,11 @@ entity organization { attribute ip_range string[] - permission view = check_ip_range(request.ip, ip_range) or admin + permission view = check_ip_range(ip_range) or admin } -rule check_ip_range(ip string, ip_range string[]) { - ip in ip_range +rule check_ip_range(ip_range string[]) { + context.data.ip in ip_range } ``` diff --git a/docs/use-cases/abac.mdx b/docs/use-cases/abac.mdx index 111392c9e..b77cd17c0 100644 --- a/docs/use-cases/abac.mdx +++ b/docs/use-cases/abac.mdx @@ -87,11 +87,11 @@ entity organization { attribute ip_range string[] - permission view = check_ip_range(request.ip, ip_range) or admin + permission view = check_ip_range(ip_range) or admin } rule check_ip_range(ip string, ip_range string[]) { - ip in ip_range + context.data.ip in ip_range } ``` @@ -134,11 +134,11 @@ entity organization { attribute location string[] - permission view = check_location(request.current_location, location) or admin + permission view = check_location(location) or admin } -rule check_location(current_location string, location string[]) { - current_location in location +rule check_location(location string[]) { + context.data.current_location in location } ``` @@ -158,11 +158,13 @@ Integer can be used as attribute data type in several scenarios where numerical ```perm entity content { - permission view = check_age(request.age) + attribute min_age integer + + permission view = check_age(min_age) } -rule check_age(age integer) { - age >= 18 +rule check_age(min_age integer) { + context.data.age >= min_age } ``` If you don’t create the related attribute data, Permify accounts integer as `0` @@ -183,11 +185,11 @@ entity account { relation owner @user attribute balance double - permission withdraw = check_balance(request.amount, balance) and owner + permission withdraw = check_balance(balance) and owner } -rule check_balance(amount double, balance double) { - (balance >= amount) && (amount <= 5000) +rule check_balance(balance double) { + (balance >= context.data.amount) && (context.data.amount <= 5000) } ``` If you don’t create the related attribute data, Permify accounts double as `0.0` @@ -248,7 +250,9 @@ entity organization { relation member @user - permission view = is_weekday(request.day_of_week) and member + attribute valid_weekdays string[] + + permission view = is_weekday(valid_weekdays) and member } entity repository { @@ -258,8 +262,8 @@ entity repository { permission view = organization.view } -rule is_weekday(day_of_week string) { - day_of_week != 'saturday' && day_of_week != 'sunday' +rule is_weekday(valid_weekdays string[]) { + context.data.day_of_week in valid_weekdays } ``` @@ -270,12 +274,12 @@ The permissions in this model state that to 'view' the repository, the user must - organization:1#member@user:1 **Check Evolution Sub Queries Organization View** -→ organization:1$is_weekday(context.day_of_week) → true +→ organization:1$is_weekday(valid_weekdays) → true → organization:1#member@user:1 → true **Request keys before hash** -- `check*{snapshot}*{schema*version}*{context}\_organization:1$is_weekday(context.day_of_week)` → true +- `check*{snapshot}*{schema*version}*{context}\_organization:1$is_weekday(valid_weekdays)` → true - `check*{snapshot}*{schema*version}*{context}\_post:1#member@user:1` → true ### Example of Banking System @@ -292,11 +296,11 @@ entity account { relation owner @user attribute balance double - permission withdraw = check_balance(request.amount, balance) and owner + permission withdraw = check_balance(balance) and owner } -rule check_balance(amount double, balance double) { - (balance >= amount) && (amount <= 5000) +rule check_balance(balance double) { + (balance >= context.data.amount) && (context.data.amount <= 5000) } ``` @@ -314,12 +318,12 @@ Both of these conditions need to be true for the **`withdraw`** permission to be - account:1$balance|double:4000 **Check Evolution Sub Queries For Account Withdraw** -→ account:1$check_balance(context.amount,balance) → true +→ account:1$check_balance(balance) → true → account:1#owner@user:1 → true **Request keys before hash** -- `check*{snapshot}*{schema*version}*{context}\_account:1$check_balance(context.amount,balance)` → true +- `check*{snapshot}*{schema*version}*{context}\_account:1$check_balance(balance)` → true - `check*{snapshot}*{schema*version}*{context}\_account:1#owner@user:1` → true ### Hierarchical Usage @@ -395,11 +399,11 @@ entity organization { attribute ip_range string[] - permission view = check_ip_range(request.ip_address, ip_range) or admin + permission view = check_ip_range(ip_range) or admin } -rule check_ip_range(ip_address string, ip_range string[]) { - ip in ip_range +rule check_ip_range(ip_range string[]) { + context.data.ip in ip_range } ``` @@ -411,7 +415,7 @@ For instance, "context": { "data": { "ip_address": "187.182.51.206", - "day_of_week": "monday" + "day_of_week": "monday" }, } ``` @@ -529,10 +533,10 @@ This YAML snippet specifies a validation context with no tuples or attributes, a **Example in model** ```yaml -permission delete = is_weekday(request.day_of_week) +permission delete = is_weekday(valid_weekdays) ``` -In the model, a **`delete`** permission rule is set. It calls the function **`is_weekday`** with the value of **`day_of_week`** from the context. If **`is_weekday("saturday")`** is true, the delete permission is granted. +In the model, a **`delete`** permission rule is set. It calls the function **`is_weekday`** with the value of **`valid_weekdays`** from the related entity. If **`is_weekday(["monday", "tuesday", "wednesday", "thursday", "friday"])`** is true, the delete permission is granted. **Create Validation File** @@ -554,18 +558,19 @@ schema: >- relation organization @organization attribute is_public boolean + attribute valid_weekdays string[] permission view = is_public permission edit = organization.view - permission delete = is_weekday(request.day_of_week) + permission delete = is_weekday(valid_weekdays) } rule check_credit(credit integer) { credit > 5000 } - rule is_weekday(day_of_week string) { - day_of_week != 'saturday' && day_of_week != 'sunday' + rule is_weekday(valid_weekdays string[]) { + context.data.day_of_week in valid_weekdays } relationships: From aabf008037cbc9f107f8487a6007db097355331a Mon Sep 17 00:00:00 2001 From: Tolga Ozen Date: Thu, 19 Sep 2024 10:56:04 +0300 Subject: [PATCH 2/2] fix: update context parameter in EntityFilter's method call --- internal/engines/entityFilter.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/engines/entityFilter.go b/internal/engines/entityFilter.go index 036289405..20a586dfc 100644 --- a/internal/engines/entityFilter.go +++ b/internal/engines/entityFilter.go @@ -66,6 +66,10 @@ func (engine *EntityFilter) EntityFilter( }, ) // Retrieve the linked entrances between the entity reference and subject. + if entrances == nil { + return nil + } + // Create a new context for executing goroutines and a cancel function. cctx, cancel := context.WithCancel(ctx) defer cancel() @@ -83,7 +87,7 @@ func (engine *EntityFilter) EntityFilter( return err } case schema.ComputedUserSetLinkedEntrance: // If the linked entrance is a computed user set entrance. - err = engine.lt(ctx, request, &base.EntityAndRelation{ // Call the run method with a new entity and relation. + err = engine.lt(cont, request, &base.EntityAndRelation{ // Call the run method with a new entity and relation. Entity: &base.Entity{ Type: entrance.TargetEntrance.GetType(), Id: request.GetSubject().GetId(),