@@ -12,228 +12,6 @@ import (
12
12
"github.com/coder/coder/coderd/rbac/regosql/sqltypes"
13
13
)
14
14
15
- //func TestSomething(t *testing.T) {
16
- // ConvertRegoAst(ConvertConfig{
17
- // ConvertVariable: func(rego ast.Ref) (sqltypes.Node, error) {
18
- // return nil, fmt.Errorf("not implemented")
19
- // },
20
- // }, ®o.PartialQueries{})
21
- //}
22
-
23
- //func TestPartialQueriesWithVariables(t *testing.T) {
24
- // cfg := regosql.CompileConfig{
25
- // VariableTypes: NewTree().
26
- // AddElement(strings.Split("input.post.deleted", "."), Boolean{}, StaticName("deleted")).
27
- // AddElement(strings.Split("input.post.author", "."), String{}, StaticName("author")).
28
- // AddElement(strings.Split("input.post.can", "."), String{}, StaticName("can")).
29
- // AddElement(strings.Split("input.post.authors", "."), Map{ValueType: String{}},
30
- // RegexColumnNameReplace(`input\.post\.authors\.(.*)`, "authors->$1")).
31
- // AddElement(strings.Split("input.post.posts", "."), Array{elemType: String{}}, StaticName("posts")).
32
- // AddElement(strings.Split("input.post.can_list", "."), Array{elemType: String{}}, StaticName("can_list")).
33
- // AddElement(strings.Split("input.post.list", "."), Array{elemType: String{}}, StaticName("list")).
34
- // AddElement(strings.Split("input.post.moderators", "."), Array{elemType: String{}}, StaticName("moderators")),
35
- // }
36
- // //opts := ast.ParserOptions{AllFutureKeywords: true}
37
- // testCases := []struct {
38
- // Name string
39
- // Input map[string]interface{}
40
- // Unknowns []string
41
- // Rego string
42
- // ExpectedSQL string
43
- // ExpectError bool
44
- // }{
45
- // {
46
- // Name: "AlwaysFalse",
47
- // Rego: `
48
- // package example
49
- // allow = true {
50
- // input.method = "GET"
51
- // input.path = ["posts"]
52
- // }`,
53
- // Input: map[string]interface{}{
54
- // "method": "GET",
55
- // "path": []string{"users"},
56
- // "user": "bob",
57
- // },
58
- // ExpectedSQL: "false",
59
- // Unknowns: []string{"none"},
60
- // },
61
- // {
62
- // Name: "AlwaysTrue",
63
- // Rego: `
64
- // package example
65
- // allow = true {
66
- // input.method = "GET"
67
- // input.path = ["posts"]
68
- // }`,
69
- // Input: map[string]interface{}{
70
- // "method": "GET",
71
- // "path": []string{"posts"},
72
- // "user": "bob",
73
- // },
74
- // ExpectedSQL: "true",
75
- // Unknowns: []string{"none"},
76
- // },
77
- // {
78
- // Name: "SingleObject",
79
- // // "bob" = input.post.author
80
- // Rego: `
81
- // package example
82
- // allow {
83
- // input.post.author = input.user
84
- // }
85
- // `,
86
- // Input: map[string]interface{}{
87
- // "user": "bob",
88
- // },
89
- // ExpectedSQL: "'bob' = author",
90
- // Unknowns: []string{"input.post.author"},
91
- // },
92
- // {
93
- // Name: "RefBoolean",
94
- // // input.post.deleted
95
- // Rego: `
96
- // package example
97
- // allow {
98
- // input.post.deleted
99
- // }
100
- // `,
101
- // Input: map[string]interface{}{},
102
- // ExpectedSQL: "deleted",
103
- // Unknowns: []string{"input.post.deleted"},
104
- // },
105
- // {
106
- // Name: "RefWithNumber",
107
- // // Query 0: "bob" = input.post.authors.name; "bob" = input.post.list[0]
108
- // Rego: `
109
- // package example
110
- // allow {
111
- // input.post.authors["name"] = input.user
112
- // input.post.list[0] = input.user
113
- // }
114
- // `,
115
- // Input: map[string]interface{}{
116
- // "user": "bob",
117
- // },
118
- // ExpectedSQL: "authors->>name = 'bob AND list[0] = 'bob",
119
- // Unknowns: []string{"input.post.authors", "input.post.list"},
120
- // },
121
- // {
122
- // Name: "Array",
123
- // // Query 0: "bob" = input.post.author
124
- // // Query 1: "bob" = input.post.moderators[_]
125
- // Rego: `
126
- // package example
127
- // allow {
128
- // can_edit
129
- // }
130
- //
131
- // can_edit {
132
- // input.post.author = input.user
133
- // }
134
- // can_edit {
135
- // input.post.moderators[_] = input.user
136
- // }
137
- //
138
- // `,
139
- // Input: map[string]interface{}{
140
- // "user": "bob",
141
- // },
142
- // ExpectedSQL: "'bob' = author OR 'bob' = ANY(moderators)",
143
- // Unknowns: []string{"input.post.author", "input.post.moderators"},
144
- // },
145
- // {
146
- // Name: "ArrayIntersection",
147
- // // Query 0: internal.member_2(input.can_list[_], ["edit", "*"])
148
- // // Query 1: internal.member_2(input.can, ["edit", "*"])
149
- // Rego: `
150
- // package example
151
- // import future.keywords.in
152
- // allow {
153
- // input.can in ["edit", "*"]
154
- // }
155
- //
156
- // allow {
157
- // input.can_list[_] in ["edit", "*"]
158
- // }
159
- // `,
160
- // Input: map[string]interface{}{},
161
- // // TODO: Convert vars to columns
162
- // ExpectedSQL: "input.can_list && ARRAY['edit', '*'] OR input.can = ANY(ARRAY ['edit', '*'])",
163
- // Unknowns: []string{"input.can_list", "input.can"},
164
- // },
165
- // {
166
- // Name: "EveryTerm",
167
- // // "bob" = input.posts[_].author; input.posts[_]
168
- // Rego: `
169
- // package example
170
- // allow = true {
171
- // input.method = "GET"
172
- // input.path = ["posts"]
173
- // allowed[x]
174
- // }
175
- //
176
- // allowed[x] {
177
- // x := input.posts[_]
178
- // x.author == input.user
179
- // }
180
- // `,
181
- // Input: map[string]interface{}{
182
- // "method": "GET",
183
- // "path": []string{"posts"},
184
- // "user": "bob",
185
- // },
186
- // ExpectedSQL: "true",
187
- // Unknowns: []string{"input.posts"},
188
- // },
189
- //
190
- // // Failures
191
- // {
192
- // Name: "RefString",
193
- // Rego: `
194
- // package example
195
- // allow {
196
- // input.post.author
197
- // }
198
- // `,
199
- // Input: map[string]interface{}{},
200
- // Unknowns: []string{"input.post.author"},
201
- // ExpectError: true,
202
- // },
203
- // }
204
- //
205
- // for _, tc := range testCases {
206
- // tc := tc
207
- // t.Run(tc.Name, func(t *testing.T) {
208
- // t.Parallel()
209
- // ctx := context.Background()
210
- //
211
- // part, err := rego.New(
212
- // rego.Query("data.example.allow == true"),
213
- // rego.Module("policy.rego", tc.Rego),
214
- // rego.Input(tc.Input),
215
- // rego.Unknowns(tc.Unknowns),
216
- // ).Partial(ctx)
217
- // require.NoError(t, err)
218
- //
219
- // for i, q := range part.Queries {
220
- // t.Logf("Query %d: %s", i, q.String())
221
- // }
222
- // for i, s := range part.Support {
223
- // t.Logf("Support %d: %s", i, s.String())
224
- // }
225
- //
226
- // sql, err := CompileSQL(cfg, part)
227
- // if tc.ExpectError {
228
- // require.Error(t, err)
229
- // } else {
230
- // require.NoError(t, err, "compile")
231
- // require.Equal(t, tc.ExpectedSQL, sql, "sql match")
232
- // }
233
- // })
234
- // }
235
- //}
236
-
237
15
// TestRegoQueriesNoVariables handles cases without variables. These should be
238
16
// very simple and straight forward.
239
17
func TestRegoQueries (t * testing.T ) {
@@ -359,6 +137,65 @@ func TestRegoQueries(t *testing.T) {
359
137
ExpectedSQL : "((false) OR (false))" ,
360
138
VariableConverter : regosql .NoACLConverter (),
361
139
},
140
+ {
141
+ Name : "TwoExpressions" ,
142
+ Queries : []string {
143
+ `true; true` ,
144
+ },
145
+ // Special case where the bool is wrapped
146
+ ExpectedSQL : "(true AND true)" ,
147
+ VariableConverter : regosql .DefaultVariableConverter (),
148
+ },
149
+
150
+ // Actual vectors from production
151
+ {
152
+ Name : "FromOwner" ,
153
+ Queries : []string {
154
+ `` ,
155
+ `"05f58202-4bfc-43ce-9ba4-5ff6e0174a71" = input.object.org_owner` ,
156
+ `"read" in input.object.acl_user_list["d5389ccc-57a4-4b13-8c3f-31747bcdc9f1"]` ,
157
+ },
158
+ // Special case where the bool is wrapped
159
+ ExpectedSQL : "true" ,
160
+ VariableConverter : regosql .NoACLConverter (),
161
+ },
162
+ {
163
+ Name : "OrgAdmin" ,
164
+ Queries : []string {
165
+ `input.object.org_owner != "";
166
+ input.object.org_owner in {"05f58202-4bfc-43ce-9ba4-5ff6e0174a71"};
167
+ input.object.owner != "";
168
+ "d5389ccc-57a4-4b13-8c3f-31747bcdc9f1" = input.object.owner` ,
169
+ },
170
+ // Special case where the bool is wrapped
171
+ ExpectedSQL : "((organization_id :: text != '') AND " +
172
+ "(organization_id :: text = ANY(ARRAY ['05f58202-4bfc-43ce-9ba4-5ff6e0174a71'])) AND " +
173
+ "(owner_id :: text != '') AND " +
174
+ "('d5389ccc-57a4-4b13-8c3f-31747bcdc9f1' = owner_id :: text))" ,
175
+ VariableConverter : regosql .DefaultVariableConverter (),
176
+ },
177
+ {
178
+ Name : "UserACLAllow" ,
179
+ Queries : []string {
180
+ `"read" in input.object.acl_user_list["d5389ccc-57a4-4b13-8c3f-31747bcdc9f1"]` ,
181
+ `"*" in input.object.acl_user_list["d5389ccc-57a4-4b13-8c3f-31747bcdc9f1"]` ,
182
+ },
183
+ // Special case where the bool is wrapped
184
+ ExpectedSQL : "((user_acl->'d5389ccc-57a4-4b13-8c3f-31747bcdc9f1' ? 'read') OR " +
185
+ "(user_acl->'d5389ccc-57a4-4b13-8c3f-31747bcdc9f1' ? '*'))" ,
186
+ VariableConverter : regosql .DefaultVariableConverter (),
187
+ },
188
+ {
189
+ Name : "NoACLConfig" ,
190
+ Queries : []string {
191
+ `input.object.org_owner != "";
192
+ input.object.org_owner in {"05f58202-4bfc-43ce-9ba4-5ff6e0174a71"};
193
+ "read" in input.object.acl_group_list[input.object.org_owner]` ,
194
+ },
195
+ // Special case where the bool is wrapped
196
+ ExpectedSQL : "((organization_id :: text != '') AND (organization_id :: text = ANY(ARRAY ['05f58202-4bfc-43ce-9ba4-5ff6e0174a71'])) AND (false))" ,
197
+ VariableConverter : regosql .NoACLConverter (),
198
+ },
362
199
}
363
200
364
201
for _ , tc := range testCases {
0 commit comments