Skip to content

Commit cea8e59

Browse files
committed
OpenFGA API Protobuf for Idempotent Writes
1 parent c0b62b2 commit cea8e59

File tree

5 files changed

+2901
-2624
lines changed

5 files changed

+2901
-2624
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ may be overly strict. In those cases you can bypass it with `commit --no-verify`
2121

2222
1. Generate the sources as above
2323
2. In the `proto` directory execute the following commands:
24-
```
24+
```shell
2525
go mod init go.buf.build/openfga/go/openfga/api
2626
go mod tidy
2727
```
2828
3. In OpenFGA, add the following line to your `go.mod`:
29-
```
29+
```shell
3030
replace github.com/openfga/api/proto => /path/to/proto
3131
```
3232

docs/openapiv2/apidocs.swagger.json

Lines changed: 31 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

openfga/v1/openfga_service.proto

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,9 @@ service OpenFGAService {
154154
"type definitions allow OpenFGA to determine whether a "
155155
"relationship exists between an object and an user.\n"
156156
"In the body, `writes` adds new tuples and `deletes` removes existing tuples. When deleting a tuple, any `condition` specified with it is ignored.\n"
157-
"The API is not idempotent: if, later on, you try to add the same tuple key (even if the `condition` is different), or if you try to delete a non-existing tuple, it will throw an error.\n"
157+
"The API is not idempotent by default: if, later on, you try to add the same tuple key (even if the `condition` is different), or if you try to delete a non-existing tuple, it will throw an error.\n"
158+
"In order to allow writes in case an identical tuple already exists in the database, you may modify the behavior using `\"on_duplicate\": \"ON_DUPLICATE_IGNORE\"`\n"
159+
"In order to allow deletes in case a tuple was already deleted from the database, you may modify the behavior using `\"on_missing\": \"ON_MISSING_IGNORE\"`\n"
158160
"The API will not allow you to write tuples such as `document:2021-budget#viewer@document:2021-budget#viewer`, because they are implicit.\n"
159161
"An `authorization_model_id` may be specified in the body. If it is, it will be used to assert that each written tuple (not deleted) "
160162
"is valid for the model specified. If it is not specified, the latest authorization model ID will be used.\n"
@@ -170,7 +172,8 @@ service OpenFGAService {
170172
" \"user\": \"user:anne\",\n"
171173
" \"relation\": \"writer\",\n"
172174
" \"object\": \"document:2021-budget\"\n"
173-
" }\n"
175+
" },\n"
176+
" \"on_duplicate\": \"ON_DUPLICATE_ERROR\"\n"
174177
" ]\n"
175178
" },\n"
176179
" \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\"\n"
@@ -187,7 +190,8 @@ service OpenFGAService {
187190
" \"user\": \"user:bob\",\n"
188191
" \"relation\": \"reader\",\n"
189192
" \"object\": \"document:2021-budget\"\n"
190-
" }\n"
193+
" },\n"
194+
" \"on_missing\": \"ON_MISSING_ERROR\"\n"
191195
" ]\n"
192196
" }\n"
193197
"}\n"
@@ -1241,13 +1245,33 @@ message ReadResponse {
12411245
];
12421246
}
12431247

1248+
enum OnDuplicate {
1249+
ON_DUPLICATE_UNSPECIFIED = 0; // If set to 'ON_DUPLICATE_UNSPECIFIED' OR not set, the API will behave as if it was set to 'ON_DUPLICATE_ERROR'.
1250+
ON_DUPLICATE_ERROR = 1; // If set to 'ON_DUPLICATE_ERROR', the API will return an error if a tuple already exists.
1251+
ON_DUPLICATE_IGNORE = 2; // If set to 'ON_DUPLICATE_IGNORE', the API will not return an error if a tuple already exists and all the attributes (including condition and context ) are matching.
1252+
}
1253+
12441254
message WriteRequestWrites {
12451255
repeated TupleKey tuple_keys = 1 [
12461256
json_name = "tuple_keys",
12471257
(google.api.field_behavior) = REQUIRED,
12481258
(validate.rules).repeated.min_items = 1,
12491259
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {min_items: 1}
12501260
];
1261+
OnDuplicate on_duplicate = 2 [
1262+
json_name = "on_duplicate",
1263+
(validate.rules).enum.defined_only = true,
1264+
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
1265+
example: "\"ON_DUPLICATE_ERROR\""
1266+
description: "If set to 'ON_DUPLICATE_ERROR', the API will return an error if a tuple already exists. If set to 'ON_DUPLICATE_IGNORE', the API will not return an error if a tuple already exists and all the attributes are matching."
1267+
}
1268+
];
1269+
}
1270+
1271+
enum OnMissing {
1272+
ON_MISSING_UNSPECIFIED = 0; // If set to 'ON_DUPLICATE_UNSPECIFIED' OR not set, the API will behave as if it was set to 'ON_MISSING_ERROR'.
1273+
ON_MISSING_ERROR = 1; // If set to 'ON_MISSING_ERROR', the API will return an error if a tuple does not exist.
1274+
ON_MISSING_IGNORE = 2; // If set to 'ON_MISSING_IGNORE', the API will not return an error if a tuple does not exist.
12511275
}
12521276

12531277
message WriteRequestDeletes {
@@ -1257,6 +1281,14 @@ message WriteRequestDeletes {
12571281
(validate.rules).repeated.min_items = 1,
12581282
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {min_items: 1}
12591283
];
1284+
OnMissing on_missing = 2 [
1285+
json_name = "on_missing",
1286+
(validate.rules).enum.defined_only = true,
1287+
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
1288+
example: "\"ON_MISSING_ERROR\""
1289+
description: "If set to 'ON_MISSING_ERROR', the API will return an error if a tuple does not exist. If set to 'ON_MISSING_IGNORE', the API will not return an error if a tuple does not exist."
1290+
}
1291+
];
12601292
}
12611293

12621294
message WriteRequest {

0 commit comments

Comments
 (0)