diff --git a/docs/openapiv2/apidocs.swagger.json b/docs/openapiv2/apidocs.swagger.json index eedeb12a..a4b8304b 100644 --- a/docs/openapiv2/apidocs.swagger.json +++ b/docs/openapiv2/apidocs.swagger.json @@ -32,7 +32,7 @@ "/stores": { "get": { "summary": "List all stores", - "description": "Returns a paginated list of OpenFGA stores.", + "description": "Returns a paginated list of OpenFGA stores and a continuation token to get additional stores.\nThe continuation token will be empty if there are no more stores.\n", "operationId": "ListStores", "responses": { "200": { @@ -325,7 +325,7 @@ "/stores/{store_id}/authorization-models": { "get": { "summary": "Return all the authorization models for a particular store", - "description": "The ReadAuthorizationModels API will return all the authorization models for a certain store.\nOpenFGA's response will contain an array of all authorization models, sorted in descending order of creation.\n\n## Example\nAssume that a store's authorization model has been configured twice. To get all the authorization models that have been created in this store, call GET authorization-models. The API will return a response that looks like:\n```json\n{\n \"authorization_models\": [\n {\n \"id\": \"01G50QVV17PECNVAHX1GG4Y5NC\",\n \"type_definitions\": [...]\n },\n {\n \"id\": \"01G4ZW8F4A07AKQ8RHSVG9RW04\",\n \"type_definitions\": [...]\n },\n ]\n}\n```\nIf there are more authorization models available, the response will contain an extra field `continuation_token`:\n```json\n{\n \"authorization_models\": [\n {\n \"id\": \"01G50QVV17PECNVAHX1GG4Y5NC\",\n \"type_definitions\": [...]\n },\n {\n \"id\": \"01G4ZW8F4A07AKQ8RHSVG9RW04\",\n \"type_definitions\": [...]\n },\n ],\n \"continuation_token\": \"eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==\"\n}\n```\n", + "description": "The ReadAuthorizationModels API will return all the authorization models for a certain store.\nOpenFGA's response will contain an array of all authorization models, sorted in descending order of creation.\n\n## Example\nAssume that a store's authorization model has been configured twice. To get all the authorization models that have been created in this store, call GET authorization-models. The API will return a response that looks like:\n```json\n{\n \"authorization_models\": [\n {\n \"id\": \"01G50QVV17PECNVAHX1GG4Y5NC\",\n \"type_definitions\": [...]\n },\n {\n \"id\": \"01G4ZW8F4A07AKQ8RHSVG9RW04\",\n \"type_definitions\": [...]\n },\n ],\n \"continuation_token\": \"eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==\"\n}\n```\nIf there are no more authorization models available, the `continuation_token` field will be empty\n```json\n{\n \"authorization_models\": [\n {\n \"id\": \"01G50QVV17PECNVAHX1GG4Y5NC\",\n \"type_definitions\": [...]\n },\n {\n \"id\": \"01G4ZW8F4A07AKQ8RHSVG9RW04\",\n \"type_definitions\": [...]\n },\n ],\n \"continuation_token\": \"\"\n}\n```\n", "operationId": "ReadAuthorizationModels", "responses": { "200": { @@ -777,7 +777,7 @@ "/stores/{store_id}/read": { "post": { "summary": "Get tuples from the store that matches a query, without following userset rewrite rules", - "description": "The Read API will return the tuples for a certain store that match a query filter specified in the body of the request. It is different from the `/stores/{store_id}/expand` API in that it only returns relationship tuples that are stored in the system and satisfy the query. \nIn the body:\n1. `tuple_key` is optional. If not specified, it will return all tuples in the store.\n2. `tuple_key.object` is mandatory if `tuple_key` is specified. It can be a full object (e.g., `type:object_id`) or type only (e.g., `type:`).\n3. `tuple_key.user` is mandatory if tuple_key is specified in the case the `tuple_key.object` is a type only.\n## Examples\n### Query for all objects in a type definition\nTo query for all objects that `user:bob` has `reader` relationship in the `document` type definition, call read API with body of\n```json\n{\n \"tuple_key\": {\n \"user\": \"user:bob\",\n \"relation\": \"reader\",\n \"object\": \"document:\"\n }\n}\n```\nThe API will return tuples and an optional continuation token, something like\n```json\n{\n \"tuples\": [\n {\n \"key\": {\n \"user\": \"user:bob\",\n \"relation\": \"reader\",\n \"object\": \"document:2021-budget\"\n },\n \"timestamp\": \"2021-10-06T15:32:11.128Z\"\n }\n ]\n}\n```\nThis means that `user:bob` has a `reader` relationship with 1 document `document:2021-budget`. Note that this API, unlike the List Objects API, does not evaluate the tuples in the store.\n### Query for all stored relationship tuples that have a particular relation and object\nTo query for all users that have `reader` relationship with `document:2021-budget`, call read API with body of \n```json\n{\n \"tuple_key\": {\n \"object\": \"document:2021-budget\",\n \"relation\": \"reader\"\n }\n}\n```\nThe API will return something like \n```json\n{\n \"tuples\": [\n {\n \"key\": {\n \"user\": \"user:bob\",\n \"relation\": \"reader\",\n \"object\": \"document:2021-budget\"\n },\n \"timestamp\": \"2021-10-06T15:32:11.128Z\"\n }\n ]\n}\n```\nThis means that `document:2021-budget` has 1 `reader` (`user:bob`). Note that, even if the model said that all `writers` are also `readers`, the API will not return writers such as `user:anne` because it only returns tuples and does not evaluate them.\n### Query for all users with all relationships for a particular document\nTo query for all users that have any relationship with `document:2021-budget`, call read API with body of \n```json\n{\n \"tuple_key\": {\n \"object\": \"document:2021-budget\"\n }\n}\n```\nThe API will return something like \n```json\n{\n \"tuples\": [\n {\n \"key\": {\n \"user\": \"user:anne\",\n \"relation\": \"writer\",\n \"object\": \"document:2021-budget\"\n },\n \"timestamp\": \"2021-10-05T13:42:12.356Z\"\n },\n {\n \"key\": {\n \"user\": \"user:bob\",\n \"relation\": \"reader\",\n \"object\": \"document:2021-budget\"\n },\n \"timestamp\": \"2021-10-06T15:32:11.128Z\"\n }\n ]\n}\n```\nThis means that `document:2021-budget` has 1 `reader` (`user:bob`) and 1 `writer` (`user:anne`).\n", + "description": "The Read API will return the tuples for a certain store that match a query filter specified in the body of the request. It is different from the `/stores/{store_id}/expand` API in that it only returns relationship tuples that are stored in the system and satisfy the query. \nIn the body:\n1. `tuple_key` is optional. If not specified, it will return all tuples in the store.\n2. `tuple_key.object` is mandatory if `tuple_key` is specified. It can be a full object (e.g., `type:object_id`) or type only (e.g., `type:`).\n3. `tuple_key.user` is mandatory if tuple_key is specified in the case the `tuple_key.object` is a type only.\n## Examples\n### Query for all objects in a type definition\nTo query for all objects that `user:bob` has `reader` relationship in the `document` type definition, call read API with body of\n```json\n{\n \"tuple_key\": {\n \"user\": \"user:bob\",\n \"relation\": \"reader\",\n \"object\": \"document:\"\n }\n}\n```\nThe API will return tuples and a continuation token, something like\n```json\n{\n \"tuples\": [\n {\n \"key\": {\n \"user\": \"user:bob\",\n \"relation\": \"reader\",\n \"object\": \"document:2021-budget\"\n },\n \"timestamp\": \"2021-10-06T15:32:11.128Z\"\n }\n ],\n \"continuation_token\": \"eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==\"\n}\n```\nThis means that `user:bob` has a `reader` relationship with 1 document `document:2021-budget`. Note that this API, unlike the List Objects API, does not evaluate the tuples in the store.\nThe continuation token will be empty if there are no more tuples to query.### Query for all stored relationship tuples that have a particular relation and object\nTo query for all users that have `reader` relationship with `document:2021-budget`, call read API with body of \n```json\n{\n \"tuple_key\": {\n \"object\": \"document:2021-budget\",\n \"relation\": \"reader\"\n }\n}\n```\nThe API will return something like \n```json\n{\n \"tuples\": [\n {\n \"key\": {\n \"user\": \"user:bob\",\n \"relation\": \"reader\",\n \"object\": \"document:2021-budget\"\n },\n \"timestamp\": \"2021-10-06T15:32:11.128Z\"\n }\n ],\n \"continuation_token\": \"eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==\"\n}\n```\nThis means that `document:2021-budget` has 1 `reader` (`user:bob`). Note that, even if the model said that all `writers` are also `readers`, the API will not return writers such as `user:anne` because it only returns tuples and does not evaluate them.\n### Query for all users with all relationships for a particular document\nTo query for all users that have any relationship with `document:2021-budget`, call read API with body of \n```json\n{\n \"tuple_key\": {\n \"object\": \"document:2021-budget\"\n }\n}\n```\nThe API will return something like \n```json\n{\n \"tuples\": [\n {\n \"key\": {\n \"user\": \"user:anne\",\n \"relation\": \"writer\",\n \"object\": \"document:2021-budget\"\n },\n \"timestamp\": \"2021-10-05T13:42:12.356Z\"\n },\n {\n \"key\": {\n \"user\": \"user:bob\",\n \"relation\": \"reader\",\n \"object\": \"document:2021-budget\"\n },\n \"timestamp\": \"2021-10-06T15:32:11.128Z\"\n }\n ],\n \"continuation_token\": \"eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==\"\n}\n```\nThis means that `document:2021-budget` has 1 `reader` (`user:bob`) and 1 `writer` (`user:anne`).\n", "operationId": "Read", "responses": { "200": { @@ -1316,7 +1316,8 @@ }, "continuation_token": { "type": "string", - "example": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==" + "example": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==", + "description": "The continuation token will be empty if there are no more stores." } } }, @@ -1432,7 +1433,8 @@ }, "continuation_token": { "type": "string", - "example": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==" + "example": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==", + "description": "The continuation token will be empty if there are no more models." } } }, @@ -1447,7 +1449,8 @@ }, "continuation_token": { "type": "string", - "example": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==" + "example": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==", + "description": "The continuation token will be identical if there are no new changes." } } }, @@ -1462,7 +1465,8 @@ }, "continuation_token": { "type": "string", - "example": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==" + "example": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==", + "description": "The continuation token will be empty if there are no more tuples." } } }, diff --git a/openfga/v1/openfga_service.proto b/openfga/v1/openfga_service.proto index a691b8a5..c3ee025e 100644 --- a/openfga/v1/openfga_service.proto +++ b/openfga/v1/openfga_service.proto @@ -46,7 +46,7 @@ service OpenFGAService { " }\n" "}\n" "```\n" - "The API will return tuples and an optional continuation token, something like\n" + "The API will return tuples and a continuation token, something like\n" "```json\n" "{\n" " \"tuples\": [\n" @@ -58,11 +58,13 @@ service OpenFGAService { " },\n" " \"timestamp\": \"2021-10-06T15:32:11.128Z\"\n" " }\n" - " ]\n" + " ],\n" + " \"continuation_token\": \"eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==\"\n" "}\n" "```\n" "This means that `user:bob` has a `reader` relationship with 1 document " "`document:2021-budget`. Note that this API, unlike the List Objects API, does not evaluate the tuples in the store.\n" + "The continuation token will be empty if there are no more tuples to query." "### Query for all stored relationship tuples that have a particular relation and object\n" "To query for all users that have `reader` relationship with " "`document:2021-budget`, call read API with body of \n" @@ -86,7 +88,8 @@ service OpenFGAService { " },\n" " \"timestamp\": \"2021-10-06T15:32:11.128Z\"\n" " }\n" - " ]\n" + " ],\n" + " \"continuation_token\": \"eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==\"\n" "}\n" "```\n" "This means that `document:2021-budget` has 1 `reader` (`user:bob`). " @@ -122,7 +125,8 @@ service OpenFGAService { " },\n" " \"timestamp\": \"2021-10-06T15:32:11.128Z\"\n" " }\n" - " ]\n" + " ],\n" + " \"continuation_token\": \"eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==\"\n" "}\n" "```\n" "This means that `document:2021-budget` has 1 `reader` (`user:bob`) " @@ -326,10 +330,11 @@ service OpenFGAService { " \"id\": \"01G4ZW8F4A07AKQ8RHSVG9RW04\",\n" " \"type_definitions\": [...]\n" " },\n" - " ]\n" + " ],\n" + " \"continuation_token\": \"eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==\"\n" "}\n" "```\n" - "If there are more authorization models available, the response will contain an extra field `continuation_token`:\n" + "If there are no more authorization models available, the `continuation_token` field will be empty\n" "```json\n" "{\n" " \"authorization_models\": [\n" @@ -342,7 +347,7 @@ service OpenFGAService { " \"type_definitions\": [...]\n" " },\n" " ],\n" - " \"continuation_token\": \"eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==\"\n" + " \"continuation_token\": \"\"\n" "}\n" "```\n" "" @@ -616,7 +621,9 @@ service OpenFGAService { summary: "List all stores" tags: ["Stores"] operation_id: "ListStores" - description: "Returns a paginated list of OpenFGA stores." + description: + "Returns a paginated list of OpenFGA stores and a continuation token to get additional stores.\n" + "The continuation token will be empty if there are no more stores.\n" }; } @@ -802,7 +809,10 @@ message ReadResponse { string continuation_token = 2 [ json_name = "continuation_token", (validate.rules).string.max_bytes = 5120, - (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "\"eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==\""} + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "The continuation token will be empty if there are no more tuples.", + example: "\"eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==\"" + } ]; } @@ -977,7 +987,10 @@ message ReadAuthorizationModelsResponse { string continuation_token = 2 [ json_name = "continuation_token", (validate.rules).string.max_bytes = 5120, - (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "\"eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==\""} + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "The continuation token will be empty if there are no more models.", + example: "\"eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==\"" + } ]; } @@ -1071,7 +1084,10 @@ message ReadChangesResponse { string continuation_token = 2 [ json_name = "continuation_token", (validate.rules).string.max_bytes = 5120, - (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "\"eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==\""} + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "The continuation token will be identical if there are no new changes." + example: "\"eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==\"" + } ]; } @@ -1159,6 +1175,9 @@ message ListStoresResponse { string continuation_token = 2 [ json_name = "continuation_token", (validate.rules).string.max_bytes = 5120, - (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "\"eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==\""} + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "The continuation token will be empty if there are no more stores.", + example: "\"eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==\"" + } ]; }