diff --git a/blog/authors.yml b/blog/authors.yml index 6d8c3bf4f..b22519fcd 100644 --- a/blog/authors.yml +++ b/blog/authors.yml @@ -15,3 +15,4 @@ hello-caleb: name: Caleb Hunter title: Community Engagement url: https://github.com/hello-caleb + image_url: /img/blog/authors/caleb.jpg \ No newline at end of file diff --git a/blog/fine-grained-news-2024-10.md b/blog/fine-grained-news-2024-10.md new file mode 100644 index 000000000..cc080f815 --- /dev/null +++ b/blog/fine-grained-news-2024-10.md @@ -0,0 +1,65 @@ +--- +title: Fine Grained News - October 2024 +description: Fine Grained News +slug: fine-grained-news-2024-10 +date: 2024-10-30 +authors: hello-caleb +tags: [newsletter] +image: https://openfga.dev/img/og-rich-embed.png +hide_table_of_contents: false +--- +# Fine Grained News - October 2024 + +Welcome to the October edition of Fine Grained News! As we approach the end of the year, we're excited to bring you the latest updates, improvements, and community contributions shaping the future of OpenFGA. + +As always, if you’re finding the OpenFGA project to be a valuable resource, we would greatly appreciate if you would [star our repo](https://github.com/openfga/openfga) on GitHub to show your support!⭐ + +## Just Shipped + +* **OpenFGA v1.7.0:** In our latest release, we’ve introduced Access Control. This experimental feature allows you to control access to your OpenFGA server, and of course, we built it using OpenFGA! We’ve updated our Docs to show you [how to enable this feature](https://openfga.dev/docs/getting-started/setup-openfga/access-control); please share your feedback in the [GitHub Discussions](https://github.com/orgs/openfga/discussions/382)! + +* This month, we’ve also added documentation of our [OpenFGA release process](https://github.com/openfga/openfga/pull/1923). + +* We’ve [improved performance for checks involving nested tuple-to-userset relations](https://github.com/openfga/openfga/pull/2025). This is commonly used when implementing nested groups. Users can enable this with the experimental flag `enable-check-optimizations`. + +* Following last month’s launch of OpenFGA SDK support for telemetry data using OpenTelemetry, we’ve also [updated our Docs](https://openfga.dev/docs/getting-started/configure-telemetry) to guide users through configuration to collect tracing data and metrics. + +## In Progress + +**Batch Check API Endpoint:** We’re close to releasing a [new feature](https://github.com/orgs/openfga/projects/1/views/1?pane=issue&itemId=28481432&issue=openfga%7Croadmap%7C35) to enable sending multiple check operations in a single network request. + +Check out our roadmap to see what’s in the works. Feature requests and ideas can be shared in [GitHub Discussions](https://github.com/orgs/openfga/discussions). + +## Community Highlights + +* **OpenFGA at Open Source Strategy Forum 2024:** [Kiah Imani](https://www.linkedin.com/in/kiah-tolliver/) presented “Role-Based Access Is So Yesterday: Revolutionizing Authorization with OpenFGA” at the OSSF 2024 earlier this month. The presentation is now [available in Youtube](https://www.youtube.com/watch?v=uHKeE4DAHpE) +![Kiah Imani](../static/img/blog/fgn-2024-10-kiah-imani.jpeg) + +* **OpenFGA at KubeCon:** [Andres Aguiar](https://www.linkedin.com/in/aaguiar/) will participate in KubeCon/CloudNativeCon in November! OpenFGA will have a Kiosk in the Project Pavilion. He'll present a [lightning talk on OpenFGA](https://kccncna2024.sched.com/event/1iWA6/openfga-the-cloud-native-way-to-implement-fine-grained-authorization-project-lightning-talk) and participate in [The Policy Engines Showdown](https://kccncna2024.sched.com/event/1i7qp/the-policy-engines-showdown-gabriel-l-manor-permitio-andres-aguiar-okta-omri-gazitt-aserto-anders-eknert-styra-sarah-cecchetti-aws?iframe=no). + ![Andres Aguiar](../static/img/blog/fgn-2024-10-andres-aguiar.jpg) + +* **OpenFGA in Italy:** [Andrea Chiarelli](https://www.linkedin.com/in/andreachiarelli) will present [Authorize in the Cloud with OpenFGA](https://www.cloudday.it/e/sessione/3533/Autorizzare-nel-cloud-con-OpenFGA) at [Cloud Day 2024](https://www.cloudday.it/e/3486/Cloud-Day-2024) in Milan on November 20, 2024. + ![Andrea Chiarelli](../static/img/blog/fgn-2024-10-andrea-chiarelli.jpeg) + +* **New Demp Flask App Added:** To complement our OpenFGA examples and guides, we have published an [example app demonstrating the integration of OpenFGA](https://github.com/openfga/flask-demo). This app utilizes several FGA features to provide a multi-user system for folder and text file sharing. Thanks to @[ryanpq](https://github.com/openfga/flask-demo/commits?author=ryanpq) for your contribution! + ![Ryan Quinn](../static/img/blog/fgn-2024-10-ryanpq.jpg) + +* **Monthly Community Meeting:** Join us for our monthly [Community Meetings](https://github.com/openfga/community/blob/main/community-meetings.md#:~:text=OpenFGA%20Community%20Meetings), held on the second Thursday of every month at [11 AM Eastern Time (US)](https://www.worldtimebuddy.com/?qm=1&lid=12,100,5,6,8&h=5&sln=11-12&hf=1). Our next meeting is on Thursday, November 14, 2024. Our community meetings are a great way to stay updated with the latest developments, ask questions, and engage with the OpenFGA community. If you can’t join the meetings live, our [latest month's video](https://youtu.be/LITUfwqpNIo?si=ze7dhGG46rhatWBN) will always be posted on our [YouTube channel](https://www.youtube.com/@OpenFGA)! + + As always, we welcome community members to demo their use cases. If you want to demo your implementation of OpenFGA, please contact any of the OpenFGA team on our community channels linked below. + +## New Adopters + +* This month, we welcome [Gillion](https://www.gilion.com/) and [Flex](https://flex.team/) as OpenFGA adopters! If you or your company have implemented OpenFGA, we would love to hear about it! Please add your name as an adopter by updating the [ADOPTERS.md](https://github.com/openfga/community/blob/main/ADOPTERS.md#companiesprojects-using-openfga-in-production) file and sending us a PR. + +* If you or your company provides implementation services for OpenFGA, we invite you to share your information with the community in our [Implementation Services](https://github.com/openfga/community/blob/main/ADOPTERS.md#companies-offering-openfga-implementation-services) section of the ADOPTERS.md file by sending us a PR! However, please note that the OpenFGA project has not evaluated or endorsed the individuals and companies listed, and inclusion does not imply endorsement. + +## Announcements + +* **Hacktoberfest Highlights:** This Hacktoberfest, we welcomed 13 new contributors making their first commit to OpenFGA! Thanks to the incredible community participation, we saw a 28% increase in pull requests compared to September and a remarkable 260% increase in PRs on the SDK Generator. A huge thanks to this community for your continued participation and contributions! + +* **OpenFGA Community Meeting Updates:** We are adding chapters to our [YouTube channel](https://www.youtube.com/@OpenFGA) videos to simplify content navigation. We’ve begun with the most recent videos and will add chapters as time goes on. We have also begun releasing [demos](https://www.youtube.com/playlist?list=PLUR5l-oTFZqXYaB3W_OEEsUhI4l8iLYNe) as individual videos for easier content consumption. You can catch this month’s demos on [Modular Authorization](https://www.youtube.com/watch?v=ws9BjricJu4) and [Client-Side Caching](https://www.youtube.com/watch?v=sst9PyvPHSk), with Materialize Integration coming soon! + +## See you Next Month + +Fine Grained News is published every month. If you have any feedback, want to share your OpenFGA story, or have a noteworthy update, please let us know on any of our [community channels](https://openfga.dev/community) or at [community@openfga.dev](mailto:community@openfga.dev). \ No newline at end of file diff --git a/docs/content/concepts.mdx b/docs/content/concepts.mdx index d790a49c2..85212a42d 100644 --- a/docs/content/concepts.mdx +++ b/docs/content/concepts.mdx @@ -624,7 +624,7 @@ For example, the following returns all the users of type `user` that have the `v }} /> -For more information, see the the [ListUsers API Reference](/api/service#Relationship%20Queries/ListUsers). +For more information, see the [ListUsers API Reference](/api/service#Relationship%20Queries/ListUsers).
diff --git a/docs/content/getting-started/immutable-models.mdx b/docs/content/getting-started/immutable-models.mdx index 1e294e279..dbf9bc6ec 100644 --- a/docs/content/getting-started/immutable-models.mdx +++ b/docs/content/getting-started/immutable-models.mdx @@ -17,23 +17,36 @@ import { Authorization Models in are immutable, they are created once and then can no longer be deleted or modified. Each time you write an authorization model, a new version is created. -### Viewing all the authorization models +## Viewing all the authorization models You can list all the authorization models for a store using the [ReadAuthorizationModels](/api/service#/Authorization%20Models/ReadAuthorizationModels) API. This endpoint returns the results sorted in reverse chronological order, as in the first model in the list is the latest model. By default, only the last 50 models are returned, but you can paginate across by passing in the appropriate `continuation_token`. -### How to target a particular model +## How to target a particular model Some endpoints relating to tuples ([Check](/api/service#/Relationship%20Queries/Check), [ListObjects](/api/service#/Relationship%20Queries/ListObjects), [ListUsers](/api/service#/Relationship%20Queries/ListUsers), [Expand](/api/service#/Relationship%20Queries/Expand), [Write](/api/service#/Relationship%20Tuples/Write)) accept an `authorization_model_id`, which we strongly recommend passing, especially in production. In practice, you would pin the authorization model ID alongside the store ID in your configuration management system. Your services would read this value and use it in their requests to FGA. This helps you ensure that your services are using the same consistent ID across all your applications, and that rollouts can be seamless. -### Benefits of passing in an authorization model ID +## Benefits of passing in an authorization model ID Targeting a specific model ID would ensure that you don't accidentally break your authorization checks in production because a mistake was made when updating the authorization model. It would also slightly improve the latency on your check requests. If that field is passed, evaluation and validation will happen for that particular authorization model ID. If this field is not passed, will use the last created Authorization Model for that store. -### Potential use-cases +## Potential use-cases + +### Complex model migrations + +Certain model changes require adapting your application code and migrating tuples before rolling it out. For example, if you rename a relation, you need to change the application and copy the existing tuples to use the new relation name. This scenario requires the following steps: + +- Update the authorization model with the renamed relation. A new model ID will be generated but it won't be used in production yet. +- Update the application to use the new relation name. +- Copy existing tuples to use the new relation name. +- Deploy the new application targeting the new model ID. + +You can learn more about model migrations [here](../modeling/migrating/overview.mdx). + +### Progresivelly rollout changes Being able to target multiple versions of the authorization model enables you to progressively roll out model changes, which is something you should consider doing if the changes are significant. You could: @@ -41,7 +54,6 @@ Being able to target multiple versions of the authorization model enables you to - When you are confident with your model, you could implement gradual rollouts that would allow you to monitor and check if any users are having access issues before you go ahead and increase the rollout to 100% of your user base. - :::info Getting an Authorization Model's Creation Date The Authorization Model ID is a [ULID](https://github.com/ulid/spec) which includes the date created. You can extract the creation date using a library for your particular language. diff --git a/docs/content/getting-started/perform-check.mdx b/docs/content/getting-started/perform-check.mdx index c91298182..0a5912451 100644 --- a/docs/content/getting-started/perform-check.mdx +++ b/docs/content/getting-started/perform-check.mdx @@ -9,6 +9,7 @@ import { SupportedLanguage, languageLabelMap, CheckRequestViewer, + BatchCheckRequestViewer, DocumentationNotice, ProductConcept, ProductName, @@ -140,13 +141,13 @@ To obtain the [access token](https://auth0.com/docs/get-started/authentication-a -### 02. Calling check API +### 02. Calling Check API -To check whether user `user:anne` has relationship `reader` with object `document:Z` +To check whether user `user:anne` has relationship `can_view` with object `document:Z` + +The result will include an `allowed` field for each authorization check that will return `true` if the relationship exists and `false` if the relationship does not exist. + ## Related Sections \ No newline at end of file diff --git a/docs/content/getting-started/perform-list-users.mdx b/docs/content/getting-started/perform-list-users.mdx index 4da4acd3d..330714183 100644 --- a/docs/content/getting-started/perform-list-users.mdx +++ b/docs/content/getting-started/perform-list-users.mdx @@ -213,7 +213,7 @@ With the tuples: | ------------------------ | -------- | ------------------------ | | group:engineering#member | viewer | document:1 | | group:product#member | viewer | document:1 | -| user:will | member | group:engineering#member | +| user:will | member | group:engineering | Then calling the List Users API for `document:1` with relation `viewer` of type `group#member` will yield the below response. Note that the `user:will` is not returned, despite being a member of `group:engineering#member` because the `user_filters` does not target the `user` type. diff --git a/docs/content/getting-started/production-best-practices.mdx b/docs/content/getting-started/production-best-practices.mdx index c98b92c39..14b7df5fe 100644 --- a/docs/content/getting-started/production-best-practices.mdx +++ b/docs/content/getting-started/production-best-practices.mdx @@ -29,7 +29,7 @@ The following list outlines best practices for running OpenFGA in a production e We recommend: -1. Turn on caching via the flag `--check-query-cache-enabled`. This will reduce latency of requests, but it will increase the staleness of OpenFGA's responses. (The TTL is configurable). +1. Turn on in-memory caching in Check API via flags. This will reduce latency of requests, but it will increase the staleness of OpenFGA's responses. Please see [Cache Expiration](../interacting/consistency.mdx#cache-expiration) for details on the flags. 2. Prefer having a small pool of servers with high capacity (memory and CPU cores) instead of a big pool of servers, to increase cache hit ratios and simplify pool management. 3. Turn on metrics collection via the flags `--metrics-enabled` and `--datastore-metrics-enabled`. This will allow you to debug issues. 4. Turn on tracing via the flag `--trace-enabled`, but set sampling ratio to a low value, for example `--trace-sample-ratio=0.3`. This will allow you to debug issues without overwhelming the tracing server. However, keep in mind that enabling tracing comes with a slight performance cost. diff --git a/docs/content/interacting/consistency.mdx b/docs/content/interacting/consistency.mdx index 9c6a40d61..f041707b9 100644 --- a/docs/content/interacting/consistency.mdx +++ b/docs/content/interacting/consistency.mdx @@ -24,9 +24,9 @@ When querying using Read or | Name | Description | |-----------------------------|---------------------------------------------------------------------------------------------------------------| | MINIMIZE_LATENCY (default) | will serve queries from the cache when possible | -| HIGHER_CONSISTENCY | will skip the cache and query the the database directly | +| HIGHER_CONSISTENCY | will skip the cache and query the database directly | -If you write a tuple and you immediately make a check on a relation affected by that tuple using `MINIMIZE_LATENCY`, the tuple change might not be taken in consideration if serves the result from the cache. +If you write a tuple and you immediately make a Check on a relation affected by that tuple using `MINIMIZE_LATENCY`, the tuple change might not be taken in consideration if serves the result from the cache. ## When to use higher consistency @@ -51,19 +51,22 @@ if (date_modified + cache_time_to_live_period > Date.now()) { ## Cache expiration - cache is disabled by default. When not enabled, all queries will have strong consistency regardless of the consistency mode specified. + caching is disabled by default. When caching is disabled, all queries will have strong consistency regardless of the consistency mode specified. When caching is enabled, the cache will be used for queries with `MINIMIZE_LATENCY` consistency mode. You can use the following parameters to configure 's cache: -| Name | Description | -|-------------------------|---------------------------------------------------------------------------------| -| check-query-cache | Enables caching (default = false) | -| check-query-cache-limit | Configures the number of items that will be kept in the cache (default = 10000) | -| check-query-cache-ttl | Specifies the time that items will be kept in the cache (default = 10s) | +| Name | Description | +|----------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| check-cache-limit | Configures the number of items that will be kept in the in-memory cache used to resolve Check queries (default = 1000) | +| check-query-cache-enabled | Enables in-memory caching of Check subproblems (default = false). For example, if you have a relation `define viewer: owner or editor`, and the query is `Check(user:anne, viewer, doc:1)`, we'll evaluate the `owner` relation and the `editor` relation and cache both results: `(user:anne, viewer, doc:1) -> allowed=true` and `(user:anne, owner, doc:1) -> allowed=true`. | +| check-query-cache-ttl | Specifies the time that items will be kept in the cache of Check subproblems (default = 10s) | +| check-iterator-cache-enabled | Enables in-memory caching of database iterators. Each iterator is the result of a database query, for example, usersets related to a specific object, or objects related to a specific user, up to a certain number of tuples per iterator (default = false) | +| check-iterator-cache-max-results | Configures the number of tuples that will be stored for each database iterator (default = 10000) | +| check-iterator-cache-ttl | Specifies the time that items will be kept in the cache of database iterators (default = 10s) | Learn how to [configure ](../getting-started/setup-openfga/configure-openfga.mdx). -Currently, the cache is used by Check and partially in ListObjects. It will be implemented it for other query endpoints in the future. +Currently, the cache is used by Check and partially in ListObjects. It will be implemented for other query endpoints in the future. ## Future work diff --git a/docs/content/interacting/relationship-queries.mdx b/docs/content/interacting/relationship-queries.mdx index 79fb775c0..3582f51b8 100644 --- a/docs/content/interacting/relationship-queries.mdx +++ b/docs/content/interacting/relationship-queries.mdx @@ -8,6 +8,7 @@ description: An overview of how to use the Check, Read, Expand, and ListObject A import { AuthzModelSnippetViewer, CheckRequestViewer, + BatchCheckRequestViewer, DocumentationNotice, ExpandRequestViewer, ListObjectsRequestViewer, @@ -135,6 +136,56 @@ Check is designed to answer the question "Does user:X have relationship Y with o - "What are the objects that userX has relationship Y with?" - "Why does user:X have relationship Y with object:Z?" +## Batch Check + +### What is it for? + +The [Batch Check API](/api/service#Relationship%20Queries/BatchCheck) is an API endpoint that allows you to check multiple user-object-relationship combinations in a single request. + +### When to use? + +Batching authorization checks together in a single request significantly reduces overall network latency. + +Two scenarios are common to use Batch Check: +1. When determining if the user has access to a list of objects (such as [Option 1 in Search with Permissions](./search-with-permissions.mdx#option-1-search-then-check)), filter and sort on your database, then call `/batch-check`. Repeat to perform pagination. +2. When determining fields on a web page the user has access to, call `/batch-check` for every relation necessary to show/hide each field. + +For example, you can call Batch Check to determine whether `bob` has `can_view_name`, `can_view_dob`, and `can_view_ssn` relationships with `patient_record:1`. + + + +The API will return `true` depending on the level of access assigned to that user and the implied relationships inherited in the authorization model. + + +### Caveats and when not to use it + +If you are making less than 10 checks, it may be faster to call the [Check API](/api/service#Relationship%20Queries/Check) in parallel instead of Batch Check. + ## Read ### What Is It For? diff --git a/docs/content/interacting/search-with-permissions.mdx b/docs/content/interacting/search-with-permissions.mdx index 8f70aa1c1..85b91ee8b 100644 --- a/docs/content/interacting/search-with-permissions.mdx +++ b/docs/content/interacting/search-with-permissions.mdx @@ -31,12 +31,12 @@ To return the set of results that match the user's search query, you will need t There are three possible ways to do this: -### Option 1: search, then check +### Option 1: Search, then check -Pre-filter, then call Check endpoint. +Pre-filter, then call Batch Check endpoint. 1. Filter and sort on your database. -1. Call [`/check`](./relationship-queries.mdx#check) in parallel on each object returned from your database. +1. Call [`/batch-check`](./relationship-queries.mdx#batch-check) to check access for multiple objects in a single request. 1. Filter out objects the user does not have access to. 1. Return the filtered result to the user. @@ -99,6 +99,12 @@ The recommended option for this case is to use **[Local Index from Changes Endpo Use case: Searching in Google Drive, where the list of documents and folders that a user has access to can be very high, but it still is a small percentage of the entire set of documents in Google Drive. +You can consider the following strategies to transform this scenario to a **type B** one: + +- Duplicate logic from the authorization model when querying your database. For example, in a multi-tenant scenario, you can filter all resources based on the tenant the user is logged-in to. Duplicating logic from the authorization model is not ideal, but it can be a reasonable trade-off. + +- Retrieve a higher-level resource ID list with lower cardinality for efficient filtering. For example, in a document management application, first obtain the list of accessible folders for the user. You can then filter documents by these folders in your database query. This approach increases the likelihood that the user can access the documents in those folders, optimizing the query’s effectiveness. + **E.** The _number of objects of a certain type the user could have access to_ is _high_, and the _percentage of the total objects that the user can have access to_ is also _high_. In this case a **[Local Index from Changes Endpoint, Search then Check](#option-2-build-a-local-index-from-changes-endpoint-search-then-check)** would be useful. If you do not want to maintain a local index, and if the user can access a high percentage of the total, meaning that the user is more likely than not to have access to the results returned by the search query, then **[Search then Check](#option-1-search-then-check)** would work just as well. diff --git a/docs/content/modeling/migrating/overview.mdx b/docs/content/modeling/migrating/overview.mdx index 10c156199..0b0c41749 100644 --- a/docs/content/modeling/migrating/overview.mdx +++ b/docs/content/modeling/migrating/overview.mdx @@ -1,11 +1,11 @@ --- id: overview -title: 'Migrating' +title: 'Model Migrations' slug: /modeling/migrating sidebar_position: 0 --- -import { DocumentationNotice, IntroCard, CardGrid } from '@components/Docs'; +import { DocumentationNotice, ProductName, ProductNameFormat, IntroCard, CardGrid } from '@components/Docs'; @@ -19,14 +19,37 @@ This section has guides that focus on migrating models and relations. ]} /> -# Content +You can think of model migrations for in the same way as you think about relational database migrations. You can perform migrations with or without downtime for both, and for some changes, doing them without downtime is harder. + +| | Relational Databases | +|-----------------------------------------------------|-----------------------| +| Add a type | Add a table | +| Remove a type | Remove a table | +| Rename a type | Rename a table | +| Add a relation | Add a nullable column | +| Rename a relation | Rename a column | +| Delete a relation | Delete a column | + +When thinking about migrations, keep in mind that: + +- [Models are immutable](../../getting-started/immutable-models.mdx). +- The tuples that are not valid according to the specified model, are ignored when evaluating queries. + +## To add a type or relation + + 1. Add the type or relation to the authorization model, and write the model to the store. This will generate a new model ID. + 2. If you have tuples to write for the new types/relations, write them. + 3. Update the application code to start using those new types/relations. + 4. Configure the application to start using the new model ID. + +## To delete a type or relation + + 1. Delete the type or relation to the authorization model, and write the model to the store. This will generate a new model ID. + 2. Update the application code to stops using the deleted types/relations. + 3. Configure the application to start using the new model ID. + 4. Delete the tuples for the deleted type/relations. While not required, doing so can improve performance. Invalid tuples will be ignored during query evaluation, but their presence may slow down the process if they need to be retrieved. + +## To rename a type or relation + + - [This document](./migrating-relations.mdx) describes an end-to-end example for that use case. - diff --git a/docs/content/modeling/testing-models.mdx b/docs/content/modeling/testing-models.mdx index bd07996e8..dcedaf41f 100644 --- a/docs/content/modeling/testing-models.mdx +++ b/docs/content/modeling/testing-models.mdx @@ -147,10 +147,6 @@ The example above checks that `user:anne` has access to the `organization:acme` ## Write List Users tests -:::caution Warning -ListUsers is currently in an experimental release. Read [the announcement](https://openfga.dev/blog/list-users-announcement) for more information. -::: - List users tests verify the results of the [list-users API](../getting-started/perform-list-users.mdx) to validate the users who or do not have access to an object Each list users verification has the following structure: @@ -179,28 +175,17 @@ The following is an example of using the `list_users` option in ) -✓ ListObjects(user=user:anne,relation=admin,type=organization, context=) -✓ ListObjects(user=user:peter,relation=member,type=organization, context=&map[current_time:2024-02-01T00:10:00Z]) -ⅹ ListObjects(user=user:peter,relation=admin,type=organization, context=&map[current_time:2024-02-01T00:10:00Z]): expected=[organization:acm], got=[organization:acme], error= +(FAILING) : ListUsers(1/2 passing) +ⅹ ListUsers(object={Type:organization Id:acme},relation=member,user_filter={Type:user Relation:}, context:&map[current_time:2024-02-02T00:10:00Z]): expected={Users:[user:ann]}, got={Users:[user:anne]} +--- +# Test Summary # +Tests 1/2 passing +Checks 4/4 passing +ListObjects 4/4 passing ``` ## Running tests using GitHub Actions diff --git a/docs/content/modeling/user-groups.mdx b/docs/content/modeling/user-groups.mdx index 8f2872bc8..4dcac2df4 100644 --- a/docs/content/modeling/user-groups.mdx +++ b/docs/content/modeling/user-groups.mdx @@ -27,7 +27,7 @@ To add users to groups and grant groups access to an ` { + "tuple_key": { + "user":"${check.user}", + "relation":"${check.relation}", + "object":"${check.object}", + }, + "correlation_id": "${check.correlation_id}"${ + check.contextualTuples + ? `,"contextual_tuples":{"tuple_keys":[${check.contextualTuples + .map((tuple) => `{"user":"${tuple.user}","relation":"${tuple.relation}","object":"${tuple.object}"}`) + .join(',')}]}` + : '' + }${check.context ? `,"context":${JSON.stringify(check.context)}}` : ''} + }, + `, + ) + .join('')} + +# Response: +{ + "results": { + ${checks + .map( + (check) => `{ "${check.correlation_id}": { "allowed": ${check.allowed} }}, # ${check.relation} + `, + ) + .join('')} + } +}`; + } + + default: + assertNever(lang); + } + /* eslint-enable no-tabs */ +} + +export function BatchCheckRequestViewer(opts: BatchCheckRequestViewerOpts): JSX.Element { + const defaultLangs = [SupportedLanguage.CURL]; + const allowedLanguages = getFilteredAllowedLangs(opts.allowedLanguages, defaultLangs); + return defaultOperationsViewer(allowedLanguages, opts, batchCheckRequestViewer); +} diff --git a/src/components/Docs/SnippetViewer/index.ts b/src/components/Docs/SnippetViewer/index.ts index 79626669c..4f50acffa 100644 --- a/src/components/Docs/SnippetViewer/index.ts +++ b/src/components/Docs/SnippetViewer/index.ts @@ -1,4 +1,5 @@ export * from './CheckRequestViewer'; +export * from './BatchCheckRequestViewer'; export * from './DefaultTabbedViewer'; export * from './ExpandRequestViewer'; export * from './ListObjectsRequestViewer'; diff --git a/static/img/blog/fgn-2024-10-andrea-chiarelli.jpeg b/static/img/blog/fgn-2024-10-andrea-chiarelli.jpeg new file mode 100644 index 000000000..6493b12ab --- /dev/null +++ b/static/img/blog/fgn-2024-10-andrea-chiarelli.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ca1caa269277ba28c67d87ca28f9b853b36d11b6237d434ae03eba63e7e4546 +size 11035 diff --git a/static/img/blog/fgn-2024-10-andres-aguiar.jpg b/static/img/blog/fgn-2024-10-andres-aguiar.jpg new file mode 100644 index 000000000..2bc2a615e --- /dev/null +++ b/static/img/blog/fgn-2024-10-andres-aguiar.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2810387eec34215668e55b73a474335e40d8ee4a1d8a931b13208b36e54131b7 +size 11479 diff --git a/static/img/blog/fgn-2024-10-kiah-imani.jpeg b/static/img/blog/fgn-2024-10-kiah-imani.jpeg new file mode 100644 index 000000000..d5070a0af --- /dev/null +++ b/static/img/blog/fgn-2024-10-kiah-imani.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:47b91f040741353e09d54150d2a7f6c1c943db20087dd6454a773d2201a04e0c +size 10926 diff --git a/static/img/blog/fgn-2024-10-ryanpq.jpg b/static/img/blog/fgn-2024-10-ryanpq.jpg new file mode 100644 index 000000000..30847a0b4 --- /dev/null +++ b/static/img/blog/fgn-2024-10-ryanpq.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ba70a5700c876a6e2258ac82db806a084d098dec17ad584b8f106b03940520e +size 4960