From 7627ee2aca16d6be0ae7edc366895b61baefc5c2 Mon Sep 17 00:00:00 2001 From: Ronen Hilewicz Date: Tue, 3 Dec 2024 12:10:55 -0500 Subject: [PATCH] Builtins emit default values in JSON results (#507) The `ds.checks` builtin returns an array of `CheckResponse` messages. Each element has a boolean `check` field indicating the outcome of one check. However, because `false` is the default value for `bool` the marshaled JSON object doesn't include the `check` field at all when it is false. Dealing with missing fields is difficult in Rego (I couldn't figure it out). The code below takes a resource context of the form: ```json { "object_type": "", "checks": [ {"object_id": "", "relation": ""} ] } ``` It computes an array of results of the form: ```json [ {"object_id": "", "relation": "", "allowed": true/false} ] ``` If default values are omitted from the returned results, the array will only include checks that evaluated to true. ```rego raw := ds.checks({ "default": { "object_type": input.resource.object_type, "subject_type": "user", "subject_id": input.user.id }, "checks": checks }) results := x { x := [ {"object_id": check.object_id, "relation": check.relation, "allowed": result.check } | check := checks[i] result = raw[i] ] } ``` This commit adds `EmitDefaultValues: true` to the `protojson.MarshalOptions` used by the builtins to marshal rpc responses to JSON. --- builtins/edge/ds/helper.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/builtins/edge/ds/helper.go b/builtins/edge/ds/helper.go index ecffd538..882652ba 100644 --- a/builtins/edge/ds/helper.go +++ b/builtins/edge/ds/helper.go @@ -37,12 +37,13 @@ func helpMsg(fnName string, msg proto.Message) (*ast.Term, error) { // ProtoToBuf, marshal proto message to buffer. func ProtoToBuf(w io.Writer, msg proto.Message) error { b, err := protojson.MarshalOptions{ - Multiline: false, - Indent: "", - AllowPartial: false, - UseProtoNames: true, - UseEnumNumbers: false, - EmitUnpopulated: false, + Multiline: false, + Indent: "", + AllowPartial: false, + UseProtoNames: true, + UseEnumNumbers: false, + EmitUnpopulated: false, + EmitDefaultValues: true, }.Marshal(msg) if err != nil { return err