Skip to content

Commit e6afec4

Browse files
authored
fix(core): fix subject-condition-sets Create/Update with protojson marshaling (#245)
Resolves #244 Utilizes protojson and json.RawMessage for arrays of protos to properly marshal/unmarshal protos as json. The prior implementation seemingly ignored fields at times and this is the approach taken by the platform and recommended for proto marshaling.
1 parent ca6ce5a commit e6afec4

File tree

1 file changed

+58
-53
lines changed

1 file changed

+58
-53
lines changed

cmd/policy-subjectConditionSets.go

Lines changed: 58 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,55 @@ package cmd
33
import (
44
"encoding/json"
55
"fmt"
6-
"io/ioutil"
6+
"io"
77
"os"
88

99
"github.com/evertras/bubble-table/table"
1010
"github.com/opentdf/otdfctl/pkg/cli"
1111
"github.com/opentdf/otdfctl/pkg/man"
1212
"github.com/opentdf/platform/protocol/go/policy"
1313
"github.com/spf13/cobra"
14+
"google.golang.org/protobuf/encoding/protojson"
1415
)
1516

17+
// Helper to unmarshal SubjectSets from JSON (stored as JSONB in the database column)
18+
func unmarshalSubjectSetsProto(conditionJSON []byte) ([]*policy.SubjectSet, error) {
19+
var (
20+
raw []json.RawMessage
21+
ss []*policy.SubjectSet
22+
)
23+
if err := json.Unmarshal(conditionJSON, &raw); err != nil {
24+
return nil, err
25+
}
26+
27+
for _, r := range raw {
28+
s := policy.SubjectSet{}
29+
if err := protojson.Unmarshal(r, &s); err != nil {
30+
return nil, err
31+
}
32+
ss = append(ss, &s)
33+
}
34+
35+
return ss, nil
36+
}
37+
38+
// Helper to marshal SubjectSets into JSON (stored as JSONB in the database column)
39+
func marshalSubjectSetsProto(subjectSet []*policy.SubjectSet) ([]byte, error) {
40+
var raw []json.RawMessage
41+
for _, ss := range subjectSet {
42+
b, err := protojson.Marshal(ss)
43+
if err != nil {
44+
return nil, err
45+
}
46+
raw = append(raw, b)
47+
}
48+
return json.Marshal(raw)
49+
}
50+
1651
func policy_createSubjectConditionSet(cmd *cobra.Command, args []string) {
1752
h := NewHandler(cmd)
1853
defer h.Close()
19-
var (
20-
ss []*policy.SubjectSet
21-
ssBytes []byte
22-
)
54+
var ssBytes []byte
2355

2456
flagHelper := cli.NewFlagHelper(cmd)
2557
ssFlagJSON := flagHelper.GetOptionalString("subject-sets")
@@ -41,7 +73,7 @@ func policy_createSubjectConditionSet(cmd *cobra.Command, args []string) {
4173
}
4274
defer jsonFile.Close()
4375

44-
bytes, err := ioutil.ReadAll(jsonFile)
76+
bytes, err := io.ReadAll(jsonFile)
4577
if err != nil {
4678
cli.ExitWithError(fmt.Sprintf("Failed to read bytes from file at path: %s", ssFileJSON), err)
4779
}
@@ -50,7 +82,8 @@ func policy_createSubjectConditionSet(cmd *cobra.Command, args []string) {
5082
ssBytes = []byte(ssFlagJSON)
5183
}
5284

53-
if err := json.Unmarshal(ssBytes, &ss); err != nil {
85+
ss, err := unmarshalSubjectSetsProto(ssBytes)
86+
if err != nil {
5487
cli.ExitWithError("Error unmarshalling subject sets", err)
5588
}
5689

@@ -59,8 +92,8 @@ func policy_createSubjectConditionSet(cmd *cobra.Command, args []string) {
5992
cli.ExitWithError("Error creating subject condition set", err)
6093
}
6194

62-
var subjectSetsJSON []byte
63-
if subjectSetsJSON, err = json.Marshal(scs.SubjectSets); err != nil {
95+
subjectSetsJSON, err := marshalSubjectSetsProto(scs.SubjectSets)
96+
if err != nil {
6497
cli.ExitWithError("Error marshalling subject condition set", err)
6598
}
6699

@@ -88,8 +121,8 @@ func policy_getSubjectConditionSet(cmd *cobra.Command, args []string) {
88121
if err != nil {
89122
cli.ExitWithError(fmt.Sprintf("Subject Condition Set with id %s not found", id), err)
90123
}
91-
var subjectSetsJSON []byte
92-
if subjectSetsJSON, err = json.Marshal(scs.SubjectSets); err != nil {
124+
subjectSetsJSON, err := marshalSubjectSetsProto(scs.SubjectSets)
125+
if err != nil {
93126
cli.ExitWithError("Error marshalling subject condition set", err)
94127
}
95128

@@ -123,8 +156,8 @@ func policy_listSubjectConditionSets(cmd *cobra.Command, args []string) {
123156
)
124157
rows := []table.Row{}
125158
for _, scs := range scsList {
126-
var subjectSetsJSON []byte
127-
if subjectSetsJSON, err = json.Marshal(scs.SubjectSets); err != nil {
159+
subjectSetsJSON, err := marshalSubjectSetsProto(scs.SubjectSets)
160+
if err != nil {
128161
cli.ExitWithError("Error marshalling subject condition set", err)
129162
}
130163
metadata := cli.ConstructMetadata(scs.Metadata)
@@ -149,14 +182,18 @@ func policy_updateSubjectConditionSet(cmd *cobra.Command, args []string) {
149182
metadataLabels := flagHelper.GetStringSlice("label", metadataLabels, cli.FlagHelperStringSliceOptions{Min: 0})
150183
ssFlagJSON := flagHelper.GetOptionalString("subject-sets")
151184

152-
var ss []*policy.SubjectSet
185+
var (
186+
ss []*policy.SubjectSet
187+
err error
188+
)
153189
if ssFlagJSON != "" {
154-
if err := json.Unmarshal([]byte(ssFlagJSON), &ss); err != nil {
190+
ss, err = unmarshalSubjectSetsProto([]byte(ssFlagJSON))
191+
if err != nil {
155192
cli.ExitWithError("Error unmarshalling subject sets", err)
156193
}
157194
}
158195

159-
_, err := h.UpdateSubjectConditionSet(id, ss, getMetadataMutable(metadataLabels), getMetadataUpdateBehavior())
196+
_, err = h.UpdateSubjectConditionSet(id, ss, getMetadataMutable(metadataLabels), getMetadataUpdateBehavior())
160197
if err != nil {
161198
cli.ExitWithError("Error updating subject condition set", err)
162199
}
@@ -166,8 +203,8 @@ func policy_updateSubjectConditionSet(cmd *cobra.Command, args []string) {
166203
cli.ExitWithError("Error getting subject condition set", err)
167204
}
168205

169-
var subjectSetsJSON []byte
170-
if subjectSetsJSON, err = json.Marshal(scs.SubjectSets); err != nil {
206+
subjectSetsJSON, err := marshalSubjectSetsProto(scs.SubjectSets)
207+
if err != nil {
171208
cli.ExitWithError("Error marshalling subject condition set", err)
172209
}
173210

@@ -202,8 +239,8 @@ func policy_deleteSubjectConditionSet(cmd *cobra.Command, args []string) {
202239
cli.ExitWithError(fmt.Sprintf("Subject Condition Set with id %s not found", id), err)
203240
}
204241

205-
var subjectSetsJSON []byte
206-
if subjectSetsJSON, err = json.Marshal(scs.SubjectSets); err != nil {
242+
subjectSetsJSON, err := marshalSubjectSetsProto(scs.SubjectSets)
243+
if err != nil {
207244
cli.ExitWithError("Error marshalling subject condition set", err)
208245
}
209246

@@ -290,37 +327,5 @@ func init() {
290327
),
291328
)
292329
policy_subjectConditionSetsCmd = &doc.Command
293-
policyCmd.AddCommand(&doc.Command)
294-
}
295-
296-
func getSubjectConditionSetOperatorFromChoice(choice string) (policy.SubjectMappingOperatorEnum, error) {
297-
switch choice {
298-
case "IN":
299-
return policy.SubjectMappingOperatorEnum_SUBJECT_MAPPING_OPERATOR_ENUM_IN, nil
300-
case "NOT_IN":
301-
return policy.SubjectMappingOperatorEnum_SUBJECT_MAPPING_OPERATOR_ENUM_NOT_IN, nil
302-
default:
303-
return policy.SubjectMappingOperatorEnum_SUBJECT_MAPPING_OPERATOR_ENUM_UNSPECIFIED, fmt.Errorf("Unknown operator must be specified ['IN', 'NOT_IN']: %s", choice)
304-
}
305-
}
306-
307-
func getSubjectConditionSetBooleanTypeFromChoice(choice string) (policy.ConditionBooleanTypeEnum, error) {
308-
switch choice {
309-
case "AND":
310-
return policy.ConditionBooleanTypeEnum_CONDITION_BOOLEAN_TYPE_ENUM_AND, nil
311-
case "OR":
312-
return policy.ConditionBooleanTypeEnum_CONDITION_BOOLEAN_TYPE_ENUM_OR, nil
313-
default:
314-
return policy.ConditionBooleanTypeEnum_CONDITION_BOOLEAN_TYPE_ENUM_UNSPECIFIED, fmt.Errorf("Unknown boolean type must be specified ['AND', 'OR']: %s", choice)
315-
}
316-
}
317-
318-
func getMarshaledSubjectSets(subjectSets string) ([]*policy.SubjectSet, error) {
319-
var ss []*policy.SubjectSet
320-
321-
if err := json.Unmarshal([]byte(subjectSets), &ss); err != nil {
322-
return nil, err
323-
}
324-
325-
return ss, nil
330+
policyCmd.AddCommand(policy_subjectConditionSetsCmd)
326331
}

0 commit comments

Comments
 (0)