Skip to content

Commit 64636b6

Browse files
authored
topaz issue 607 (#197)
update Authorizer built-ins documentation
1 parent 8fb0385 commit 64636b6

File tree

1 file changed

+254
-35
lines changed

1 file changed

+254
-35
lines changed

docs/directory/built-ins.mdx

Lines changed: 254 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,15 @@ description: Built-in Functions that can be used in your policy
66

77
# Built-in Functions
88

9-
Topaz provides a set of built-in functions that can be used in your policy. These functions make it easier to leverage information found the Topaz directory.
9+
Topaz provides a set of built-in functions that can be used in your policy. These functions make it easier to leverage information from the Topaz directory.
1010

11-
### `ds.identity`
12-
```js
13-
ds.identity({
14-
"id": "<value>"
15-
})
16-
```
17-
Looks up a user identity by one of the ids (e.g. email address or PID), and returns the `identifier` of the user object associated to the identity instance.
1811

19-
For example: `ds.identity({ "id": "[email protected]" })` will return `dfdadc39-7335-404d-af66-c77cf13a15f8`.
2012

2113
### `ds.object`
14+
15+
> `ds.object` is an OPA built-in function, wrapping the gRPC directory reader [GetObject](https://buf.build/aserto-dev/directory/docs/v0.33.5:aserto.directory.reader.v3#aserto.directory.reader.v3.Reader.GetObject) function,
16+
taking in a [GetObjectRequest](https://buf.build/aserto-dev/directory/docs/v0.33.5:aserto.directory.reader.v3#aserto.directory.reader.v3.GetObjectRequest) as input, returning a [GetObjectResponse](https://buf.build/aserto-dev/directory/docs/v0.33.5:aserto.directory.reader.v3#aserto.directory.reader.v3.GetObjectResponse).
17+
2218
```js
2319
ds.object({
2420
"object_type": "<object type>",
@@ -35,6 +31,8 @@ If `with_relation` is included and set to `true`, the response includes all the
3531

3632
### `ds.relation`
3733

34+
> `ds.relation` is an OPA built-in function, wrapping the gRPC directory reader [GetRelation](https://buf.build/aserto-dev/directory/docs/v0.33.5:aserto.directory.reader.v3#aserto.directory.reader.v3.Reader.GetRelation) function, taking in a [GetRelationRequest](https://buf.build/aserto-dev/directory/docs/v0.33.5:aserto.directory.reader.v3#aserto.directory.reader.v3.GetRelationRequest) as input, returning a [GetRelationResponse](https://buf.build/aserto-dev/directory/docs/v0.33.5:aserto.directory.reader.v3#aserto.directory.reader.v3.GetRelationResponse).
35+
3836
```js
3937
ds.relation({
4038
"object_type": "<object type>",
@@ -49,59 +47,53 @@ ds.relation({
4947
Returns the relation instance that connects the subject with the object through the relation identified by `<object type>` and `<relation name>`.
5048
If `with_objects` is included and set to `true`, the response includes all the subject and object instances.
5149

52-
### `ds.check`
50+
### `ds.relations`
51+
52+
> `ds.relations` is an OPA built-in function, wrapping the gRPC directory reader [GetRelations](https://buf.build/aserto-dev/directory/docs/v0.33.5:aserto.directory.reader.v3#aserto.directory.reader.v3.Reader.GetRelations) function, taking in a [GetRelationsRequest](https://buf.build/aserto-dev/directory/docs/v0.33.5:aserto.directory.reader.v3#aserto.directory.reader.v3.GetRelationsRequest) as input, returning a [GetRelationsResponse](https://buf.build/aserto-dev/directory/docs/v0.33.5:aserto.directory.reader.v3#aserto.directory.reader.v3.GetRelationsResponse).
5353
5454
```js
55-
ds.check({
55+
ds.relations({
5656
"object_type": "<object type>",
5757
"object_id": "<object identifier>",
58-
"relation": "<relation or permission name>",
58+
"relation": "<relation name>",
5959
"subject_type": "<subject type>",
60-
"subject_id": "<subject identifier>"
60+
"subject_id": "<subject identifier>",
61+
"subject_relation": "subject relation name>",
62+
"with_objects": <boolean>,
63+
"with_empty_subject_relation": <boolean>
6164
})
6265
```
6366

64-
An object is identified by the combination of its `<object type>` and `<object identifier>`. The same is true for a subject.
65-
66-
A relation type is uniquely identified by the object type name and the relation name. A relation instance of that type will relate an object instance to a subject instance.
67-
68-
`ds.check` returns `true` if the object instance has a relation or permission of the type specified to the subject instance.
69-
67+
### `ds.check`
7068

71-
### `ds.check_relation`
69+
> `ds.check` is an OPA built-in function, wrapping the gRPC directory reader [Check](https://buf.build/aserto-dev/directory/docs/v0.33.5:aserto.directory.reader.v3#aserto.directory.reader.v3.Reader.Check) function, taking in a [CheckRequest](https://buf.build/aserto-dev/directory/docs/v0.33.5:aserto.directory.reader.v3#aserto.directory.reader.v3.CheckRequest) as input, returning a [CheckResponse](https://buf.build/aserto-dev/directory/docs/v0.33.5:aserto.directory.reader.v3#aserto.directory.reader.v3.CheckResponse).
7270
7371
```js
74-
ds.check_relation({
72+
ds.check({
7573
"object_type": "<object type>",
7674
"object_id": "<object identifier>",
77-
"relation": "<relation name>",
75+
"relation": "<relation or permission name>",
7876
"subject_type": "<subject type>",
7977
"subject_id": "<subject identifier>"
8078
})
8179
```
80+
8281
An object is identified by the combination of its `<object type>` and `<object identifier>`. The same is true for a subject.
8382

8483
A relation type is uniquely identified by the object type name and the relation name. A relation instance of that type will relate an object instance to a subject instance.
8584

86-
`ds.check_relation` returns `true` if the object instance has a relation of the type specified to the subject instance.
85+
`ds.check` returns `true` if the object instance has a relation or permission of the type specified to the subject instance.
8786

88-
### `ds.check_permission`
8987

90-
```js
91-
ds.check_permission({
92-
"object_type": "<object type>",
93-
"object_id": "<object identifier>",
94-
"permission": "<permission name>",
95-
"subject_type": "<subject type>",
96-
"subject_id": "<subject identifier>"
97-
})
98-
```
99-
An object is identified by the combination of its `<object type>` and `<object identifier>`. The same is true for a subject.
88+
### `ds.checks`
89+
90+
> `ds.checks` is an OPA built-in function, wrapping the gRPC directory reader [Checks](https://buf.build/aserto-dev/directory/docs/v0.33.5:aserto.directory.reader.v3#aserto.directory.reader.v3.Reader.Checks) function, taking in a [ChecksRequest](https://buf.build/aserto-dev/directory/docs/v0.33.5:aserto.directory.reader.v3#aserto.directory.reader.v3.ChecksRequest) as input, returning a [ChecksResponse](https://buf.build/aserto-dev/directory/docs/v0.33.5:aserto.directory.reader.v3#aserto.directory.reader.v3.ChecksResponse).
10091
101-
`ds.check_permission` returns`true` if the subject has the permission `<permission name>` referenced through one or more relations to the object.
10292

10393
### `ds.graph`
10494

95+
> `ds.graph` is an OPA built-in function, wrapping the gRPC directory reader [GetGraph](https://buf.build/aserto-dev/directory/docs/v0.33.5:aserto.directory.reader.v3#aserto.directory.reader.v3.Reader.GetGraph) function, taking in a [GetGraphRequest](https://buf.build/aserto-dev/directory/docs/v0.33.5:aserto.directory.reader.v3#aserto.directory.reader.v3.GetGraphRequest) as input, returning a [GetGraphResponse](https://buf.build/aserto-dev/directory/docs/v0.33.5:aserto.directory.reader.v3#aserto.directory.reader.v3.GetGraphResponse).
96+
10597
```js
10698
ds.graph({
10799
"object_type": "<object type>",
@@ -122,3 +114,230 @@ If `object_id` is provided, the results include all subjects of the specified `s
122114
If `subject_id` is provided, the results include all objects of the specified type with which the subject has the given relation.
123115

124116
If `explain` is set to `true` the output also includes all the graph paths that connect the given object or subject with the returned results.
117+
118+
119+
### `ds.identity` (OBSOLETE)
120+
121+
```js
122+
ds.identity({
123+
"id": "<value>"
124+
})
125+
```
126+
127+
`ds.identity` can be used to look up `object_id` of the `user` `object_type` associated to the `user` object via the 'identifier' relationship between the 'identity' and `user` object instance.
128+
129+
The canonical usage pattern using the Citadel data set:
130+
131+
```js
132+
i = ds.identity({"id":"CiRmZDA2MTRkMy1jMzlhLTQ3ODEtYjdiZC04Yjk2ZjVhNTEwMGQSBWxvY2Fs"})
133+
```
134+
135+
returns:
136+
137+
```js
138+
139+
```
140+
141+
> 'ds.identity' is obsoleted as it has hardcoded dependencies on the existence of the `identity` and `user` object types as well as the `identifier` relationship to associate them. This implementation is a leftover from the early days before the directory exposed a manifest.
142+
143+
### `ds.user` (OBSOLETE)
144+
145+
```js
146+
ds.user({
147+
"id": "<value>"
148+
})
149+
```
150+
151+
`ds.user` can be used to retrieve the `user` object type instance, associated with a given `identity` value.
152+
153+
> `ds.identity` is obsoleted as it has hardcoded dependencies on the existence of the 'user' object type. This implementation is a leftover from the early days before the directory exposed a manifest.
154+
155+
The canonical usage pattern using the Citadel data set:
156+
157+
```js
158+
u = ds.user({"id": "[email protected]"})
159+
```
160+
161+
returns:
162+
163+
```js
164+
"u": {
165+
"created_at": "2025-09-09T14:38:32.702237888Z",
166+
"display_name": "Rick Sanchez",
167+
"etag": "14425732754714629540",
168+
169+
"properties": {
170+
"email": "[email protected]",
171+
"picture": "https://www.topaz.sh/assets/templates/v33/citadel/img/Rick%20Sanchez.jpg",
172+
"roles": [
173+
"admin",
174+
"evil_genius"
175+
],
176+
"status": "USER_STATUS_ACTIVE"
177+
},
178+
"type": "user",
179+
"updated_at": "2025-09-09T14:38:32.702237888Z"
180+
}
181+
```
182+
183+
The canonical usage pattern of `ds.identity` and `ds.user`
184+
185+
```js
186+
i1 = ds.identity({"id":"CiRmZDA2MTRkMy1jMzlhLTQ3ODEtYjdiZC04Yjk2ZjVhNTEwMGQSBWxvY2Fs"})
187+
u1 = ds.user({"id": i1})
188+
```
189+
190+
can be replaced using:
191+
```js
192+
i2 = ds.object({"object_type":"identity", "object_id": "CiRmZDA2MTRkMy1jMzlhLTQ3ODEtYjdiZC04Yjk2ZjVhNTEwMGQSBWxvY2Fs", "with_relations": true})
193+
u2 = ds.object({"object_type":"user", "object_id": i2.relations[0].object_id})
194+
```
195+
196+
assuming the existence of existing constraints imposed by `ds.identity` and `ds.user`
197+
198+
More likely one wants to simplify this using just relationships:
199+
```js
200+
i3 = ds.relation({
201+
"subject_type": "identity",
202+
"subject_id": "CiRmZDA2MTRkMy1jMzlhLTQ3ODEtYjdiZC04Yjk2ZjVhNTEwMGQSBWxvY2Fs",
203+
"relation": "identifier",
204+
"object_type": "user",
205+
"with_objects": false
206+
})
207+
208+
u3 = ds.object({
209+
"object_type": i3.result.object_type,
210+
"object_id": i3.result.object_id
211+
})
212+
```
213+
214+
This approach does not assume types or directionality of the relationship.
215+
216+
### `ds.check_relation` (OBSOLETE)
217+
218+
> `ds.check_relation` is **OBSOLETE** use `ds.check` instead
219+
220+
Convert:
221+
222+
```js
223+
x = ds.check_relation({
224+
"object_id": "",
225+
"object_type": "",
226+
"relation": "",
227+
"subject_id": "",
228+
"subject_type": "",
229+
"trace": false
230+
})
231+
```
232+
233+
into:
234+
235+
```js
236+
x = ds.check({
237+
"object_id": "",
238+
"object_type": "",
239+
"relation": "",
240+
"subject_id": "",
241+
"subject_type": "",
242+
"trace": false
243+
})
244+
```
245+
246+
Summary: rename `ds.check_relation` into `ds.check`.
247+
248+
### `ds.check_permission` (OBSOLETE)
249+
250+
> `ds.check_permission` is **OBSOLETE** use `ds.check` instead
251+
252+
Convert:
253+
254+
```js
255+
x = ds.check_permission({
256+
"object_id": "",
257+
"object_type": "",
258+
"permission": "",
259+
"subject_id": "",
260+
"subject_type": "",
261+
"trace": false
262+
})
263+
```
264+
265+
into:
266+
267+
```js
268+
x = ds.check({
269+
"object_id": "",
270+
"object_type": "",
271+
"relation": "",
272+
"subject_id": "",
273+
"subject_type": "",
274+
"trace": false
275+
})
276+
```
277+
278+
Summary: rename `ds.check_permission` into `ds.check` and rename the `permission` field into `relation`.
279+
280+
## Built-in Request Shape Discovery
281+
282+
One can discover the built-in argument (request) shape, by passing in an `empty` JSON object `{}` as the argument.
283+
284+
For example, to discover the input arguments of the `ds.checks` built-in:
285+
286+
```js
287+
r = ds.checks({})
288+
```
289+
290+
returns
291+
292+
```js
293+
"r": {
294+
"ds.checks": {
295+
"checks": [
296+
{
297+
"object_id": "",
298+
"object_type": "",
299+
"relation": "",
300+
"subject_id": "",
301+
"subject_type": "",
302+
"trace": false
303+
}
304+
],
305+
"default": {
306+
"object_id": "",
307+
"object_type": "",
308+
"relation": "",
309+
"subject_id": "",
310+
"subject_type": "",
311+
"trace": false
312+
}
313+
}
314+
}
315+
```
316+
317+
> NOTE: the request fields are returned in alphabetical order, not in ordinal order!
318+
319+
This allows one to copy-paste the input shape as a template:
320+
321+
```js
322+
x = ds.checks({
323+
"default": {
324+
"object_id": "",
325+
"object_type": "",
326+
"relation": "",
327+
"subject_id": "",
328+
"subject_type": "",
329+
"trace": false
330+
},
331+
"checks": [
332+
{
333+
"object_id": "",
334+
"object_type": "",
335+
"relation": "",
336+
"subject_id": "",
337+
"subject_type": "",
338+
"trace": false
339+
}
340+
],
341+
}
342+
)
343+
```

0 commit comments

Comments
 (0)