Skip to content

Commit

Permalink
chore: add modular models blog and explainer doc (#697)
Browse files Browse the repository at this point in the history
Co-authored-by: Raghd Hamzeh <[email protected]>
Co-authored-by: Steve Hobbs <[email protected]>
Co-authored-by: Andrés Aguiar <[email protected]>
Co-authored-by: Raghd Hamzeh <[email protected]>
  • Loading branch information
5 people authored Mar 29, 2024
1 parent fe3cf02 commit 5bf5c73
Show file tree
Hide file tree
Showing 7 changed files with 264 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .github/workflows/markdown.links.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@
},
{
"pattern": "https://calendar.google.com"
},
{
"pattern": "https://openfga.dev/docs/modeling/modular-models"
}
],
"httpHeaders": [
Expand Down
4 changes: 4 additions & 0 deletions blog/authors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@ aaguiar:
title: Product Manager
url: https://github.com/aaguiarz
image_url: /img/blog/authors/andres.jpg
eharris:
name: Ewan Harris
url: https://github.com/ewanharris
image_url: /img/blog/authors/ewan.jpg
42 changes: 42 additions & 0 deletions blog/modular-models-announcement.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
title: Modular Models
description: Modular Models
slug: modular-models-announcement
date: 2024-04-21
authors: eharris
tags: [openfga,features]
image: https://openfga.dev/img/og-rich-embed.png
hide_table_of_contents: false
---
# Release Candidate for Modular Models

Modular models aims to improve the model authoring experience when multiple teams are maintaining a model, such as:

- A model can grow large and difficult to understand
- As more teams begin to contribute to a model, the ownership boundaries may not be clear and code review processes might not scale

With modular models, a single model can be separated across multiple files allow grouping of types and conditions into modules. This means that a model can be organized more easily in terms of team or organizational structure. Used in conjunction with features such as [GitHub](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners), [GitLab](https://docs.gitlab.com/ee/user/project/codeowners/) or [Gitea's](https://docs.gitea.com/usage/code-owners) code owners. code owners, it should become easier to ensure the owners of an portion of your model are correctly assigned to review it.

## How to use it?

Modular models is currently shipped as an experimental feature while we gather feedback, in order for you to try it out.

* Update to the [v0.3.0 release](https://github.com/openfga/cli/releases/tag/v0.3.0) of the CLI
* With the CLI you will be able to write your modular model and test it against a store file you have, but you will not be able to write your model to any OpenFGA server that does not enable this feature.
* Update to [v0.2.20](https://github.com/openfga/vscode-ext/releases/tag/v0.2.20) of the VS Code Extension
* Download [v1.5.1](https://github.com/openfga/openfga/releases/tag/v1.5.1) of OpenFGA
* As this is currently experimental, you will need to start OpenFGA with `openfga run --experimental enable-modular-models`.
* Check out the modular models sample store in the [sample-stores repo](https://github.com/openfga/sample-stores/tree/main/stores/modular)
* Review the [documentation for this feature](https://openfga.dev/docs/modeling/modular-models)

## What's next?

We intend to move this feature out of RC within the next few weeks, so as we gather feedback we'll deal with any issues that arise and look to improve upon any areas of the developer experience as needed.

Looking beyond the near term, modular models allows us to implement [additional API authorization options for OpenFGA](https://github.com/openfga/roadmap/issues/30).

## Reach out!

We want to learn how you use this feature and how we can improve it!

Please reach out through our [community channels](https://openfga.dev/community) with any questions or feedback.
205 changes: 205 additions & 0 deletions docs/content/modeling/modular-models.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
---
sidebar_position: 6
slug: /modeling/modular-models
description: Modular Models
---

import {
AuthzModelSnippetViewer,
CardBox,
CheckRequestViewer,
DocumentationNotice,
Playground,
ProductConcept,
ProductName,
ProductNameFormat,
RelatedSection,
RelationshipTuplesViewer,
SyntaxFormat,
WriteRequestViewer,
SupportedLanguage,
} from '@components/Docs';

# Modular Models

<DocumentationNotice />

Modular models allows splitting your authorization module across multiple files and modules, improving upon some of the challenges that may be faced when operating an authorization model within a company, such as:

- A model can grow large and difficult to understand
- As more teams begin to contribute to a model, the ownership boundaries may not be clear and code review processes might not scale

With modular models, a single model can be split across multiple files in a project. It can be organized in a way that makes sense for the project or teams collaborating on it, and it enables ownership for reviews to be expressed using a feature such as [GitHub's](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners), [GitLab's](https://docs.gitlab.com/ee/user/project/codeowners/) or [Gitea's](https://docs.gitea.com/usage/code-owners) code owners.

## Key Concepts

### `fga.mod`

The `fga.mod` is the project file for modular models. This file specifies the schema version for the final combined model and lists the individual files that make up the modular model.

| Property | Description |
| -------- | -------- |
| `schema` | The schema version to be used for the combined model |
| `contents` | The individual files that make up the modular model |

### Modules

Modules are declared using the `module` keyword in the DSL, and a module can be written across multiple files. A single file cannot have more than one module.

Currently, modules are stored as metadata but are not used by <ProductName format={ProductNameFormat.ShortForm}/>. Module metadata will be used in upcoming features, such as applying authorization to writing and reading/querying tuples.

### Type Extensions

As teams implement features, they might find that core types they are dependent upon might not contain all the realtions they need. However, it might not make sense for these relations to be owned by the owner of that type if they aren't needed across the system.

To solve this, individual types can be extended within other modules to implement the relations needed.

In order to allow this, there are certain requirements for type extension:

- The extended type must exist
- A single type can only be extended once per file
- The relations added must not already exist, or be part of another type extension

## Example

In this example we'll look at how an authorization model for a SaaS compny with a issue tracking and wiki software could implement modular models.

### Core

It's likely there will be a core set of types owned by a team that manages the overall identity for the company, this would provide the basics usch as users, organizations and groups that can be used by each respective product area.

```dsl.openfga
module core
type user
type organization
relations
define member: [user]
define admin: [user]
type group
relations
define member: [user]
```

### Issue tracking

In the issue tracking software we'd likely separate out the project and issue related types into separate files, we'll also extend the `organization` type here so that we can add a relation specific to the issue tracking feature, which is the ability to authorize who can create a project.

```dsl.openfga
module issue-tracker
extend type organization
relations
define can_create_project: admin
type project
relations
define organization: [organization]
define viewer: member from organization
```

```dsl.openfga
module issue-tracker
type ticket
relations
define project: [project]
define owner: [user]
```

### Wiki

Our wiki model we'll handle in one file for now until it grows some more. Again, we'll also extend the `organization` type here so that we can add a relation to track who can create a space.

```dsl.openfga
module wiki
extend type organization
relations
define can_create_space: admin
type space
relations
define organization: [organization]
define can_view_pages: member from organization
type page
relations
define space: [space]
define owner: [user]
```

### `fga.mod`

In order to deploy this model we'll need to create our `fga.mod` manifest file, in here we'll set our schema version and list the individual module files that make up our model.

```yaml
schema: '1.2'
contents:
- core.fga
- issue-tracker/projects.fga
- issue-tracker//tickets.fga
- wiki.fga
```
### Putting it all together
Now that we have our individual parts of the modular model, we're able to write this model to <ProductName format={ProductNameFormat.ShortForm}/> and then run tests against it.
In order to write our model we need to use the CLI and run:
```shell
fga model write --store-id=$FGA_STORE_ID --file fga.mod
```

We can then write tuples and query this model as you would expect with a singular file authorization model.

<WriteRequestViewer
relationshipTuples={[
{
user: 'user:anne',
relation: 'admin',
object: 'organization:acme',
},
{
user: 'organization:acme',
relation: 'organization',
object: 'space:acme',
},
{
user: 'organization:acme',
relation: 'organization',
object: 'project:acme',
},
]}
skipSetup={true}
allowedLanguages={[
SupportedLanguage.JS_SDK,
SupportedLanguage.GO_SDK,
SupportedLanguage.DOTNET_SDK,
SupportedLanguage.PYTHON_SDK,
SupportedLanguage.JAVA_SDK,
SupportedLanguage.CLI,
SupportedLanguage.CURL,
]}
/>

<CheckRequestViewer user={'user:anne'} relation={'can_create_space'} object={'organization:acme'} allowed={true} />

### Viewing the model

When viewing the combined model DSL via the CLI with `fga model get --store-id=$FGA_STORE_ID`, the DSL will be annotated with comments defining the source module and file for types, relations and conditions.

For example, if we look specifically at the `organization` type we can see that the type is defined in the `core.fga` file as part of the `core` module, and then the `can_create_project` relation is defined in `issue-tracker/projects.fga` as part of the `issuer-tracker` module and the `can_create_space` relation is defined in the `wiki.fga` file as part of the `wiki` module.

```dsl.openfga
type organization # module: core, file: core.fga
relations
define admin: [user]
define member: [user] or admin
define can_create_project: admin # extended by: module: issue-tracker, file: issue-tracker/projects.fga
define can_create_space: admin # extended by: module: wiki, file: wiki.fga
```
5 changes: 5 additions & 0 deletions docs/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,11 @@ const sidebars = {
label: "Testing Models",
id: 'content/modeling/testing-models',
},
{
type: 'doc',
label: "Modular Models",
id: 'content/modeling/modular-models',
},
{
type: 'category',
collapsed: true,
Expand Down
3 changes: 2 additions & 1 deletion src/theme/prism-include-languages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ const { PrismExtensions } = tools;

const languageDefinition = {
...PrismExtensions.languageDefinition,
[OpenFgaDslThemeTokenType.KEYWORD]: /\b(type|relations|define|and|or|but not|from|as|model|schema|condition)\b/,
[OpenFgaDslThemeTokenType.KEYWORD]:
/\b(type|relations|define|and|or|but not|from|as|model|schema|condition|module|extend)\b/,
condition: {
pattern: /(\bcondition\s+)\w+/i,
lookbehind: true,
Expand Down
3 changes: 3 additions & 0 deletions static/img/blog/authors/ewan.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 5bf5c73

Please sign in to comment.