From efad09731a945b6be4eba0df93f0eba69cafbdf8 Mon Sep 17 00:00:00 2001 From: Andrew <109249228+pavokta@users.noreply.github.com> Date: Thu, 22 Feb 2024 15:10:09 -0800 Subject: [PATCH 1/7] Update getting-started.mdx This is a first-half edit of a very, very long document. I know that this is a lot to look over, so feel free to schedule me for a Zoom call so we can talk edits over before you merge. --- docs/content/modeling/getting-started.mdx | 122 +++++++++------------- 1 file changed, 49 insertions(+), 73 deletions(-) diff --git a/docs/content/modeling/getting-started.mdx b/docs/content/modeling/getting-started.mdx index e88d844ad..6133793a2 100644 --- a/docs/content/modeling/getting-started.mdx +++ b/docs/content/modeling/getting-started.mdx @@ -31,50 +31,39 @@ import FGAIcon from '@site/static/img/getting-started-fga-logo.svg'; -Creating a authorization model might feel odd at first. Most of us tend to think about authorization models in terms of roles and permissions. After all, most software works like that. Your existing systems are likely built on a model using roles and permissions. - -This guide outlines a process for defining your with . +This guide outlines how to define a with . ## Introduction To Modeling -To define a ReBAC model in we recommend: - -- If you have an existing system: forget about how your system works today and start thinking about how you want it to work in the future. -- Thinking about authorization starting from the resources, or objects as calls them. - -If that sounds hard, don't worry! We'll guide you through it. - - is built to quickly and reliably make is built to quickly and reliably perform -. This means providing an answer to a question: "Can user U perform action A on object O?" +, which answers ReBAC's basic question: "Can user U perform action A on object O?" ReBAC systems determine access from a to an . Authorization decisions are then yes or no answers to the question: "Does user U have relation R with object O?". - "Can user U perform an action A on object O?" + "Can user U perform an action A on object O?" - "Does user U have relation R with object O?" + "Does user U have relation R with object O?" -In the previous example, a relation R should be defined that implies permission to action A. For example: +In the previous example, relation R is defined so permission to perform action A is implied. For example: - "Can user Jane perform action view on object project sandcastle?" + "Can user Jane perform action view on object project sandcastle?" - "Can user Jane have relation view with object project sandcastle?" + "Can user Jane have relation view with object project sandcastle?" -We'll provide more detailed examples throughout this article. - -When you are modeling, you need to answer a more general question: +While modeling, the general question to answer is:
-If you can answer that question for all types of objects in your system, then you can codify that into an authorization model. - -Let's get started! +Answering that question for all object types in your system codifies your authorization model. --- ## A Process For Defining Authorization Models -Defining an authorization model requires codifying an answer to the question "why could user U perform an action A on an object O?" for all use cases or actions in your system. This is an iterative process. For the purpose of this guide, we'll go through one iteration of this process using a simplified Google Drive like system as an example. - -Steps for defining your authorization model: +Below is one iteration of the codification process, using a simplified Google Drive-like system as an example. The following steps define your authorization model: 1. [Pick the most important feature](#01-pick-the-most-important-feature) 2. [List the object types](#02-list-the-object-types) @@ -108,26 +93,24 @@ Steps for defining your authorization model: ![Pick the most important feature](./assets/getting-started-diagram-02.svg) -A feature, in the context of this document, is an action or related set of actions your users can perform in your system. We'll introduce an example feature later in this section. - -Start with the most important feature. It doesn't have to be the most complex one, but it should be the most important one. You're probably more familiar with the authorization requirements for this feature than other less important use cases. +In this context, a **feature** is an action or related set of actions your users can perform in your system. Start your model with the most important feature and ensure you're familiar with its authorization requirements. :::caution Important - Requirement clarity is fundamental when defining an authorization model. -- The scope of the feature is not important at this point. You can always iterate later. +- You can always iterate; the scope of the feature is not important. ::: #### Write It In Plain Language -Once you've picked a feature, describe its authorization related scope using simple language. Avoid using the word "roles", as this ties you to an RBAC way of thinking. +Describe your feature's authorization related scope in simple language; avoid using the word "roles" to train yourself away from RBAC-style thinking. :::info -Roles don't "disappear" in ReBAC systems like . Your users might [have roles on a given object, rather than the entire system](./roles-and-permissions.mdx). But starting from the term "role" might lead you down the wrong path. Instead it is better to discover roles while you are modeling. +Roles don't "disappear" in ReBAC systems like and your users might [have roles on a given object instead of the entire system](./roles-and-permissions.mdx). Discover roles while you are modeling instead of determining in advance which roles will be defined. ::: -Your feature description should include the , and participating in the system. Sentences should look like this: +Your feature description includes the , and participating in the system. Sentences look like this:
of objects in your system. You might be able to identify the objects in your system from your existing domain/database model. +Make a list of the of objects in your system. You can likely identify the objects in your system from your existing domain/database model. Find all the objects in the previous step using this template: @@ -205,7 +188,7 @@ Find all the objects in the previous step using this template: />
-These are all the object types from the previous step (in order of appearance) based on that template: +Returned are all the object types from the previous step (in order of appearance) based on that template: , alignment: 'left', label: 'Document' }} /> @@ -213,7 +196,7 @@ These are all the object types from the previous step (in order of appearance) b , alignment: 'left', label: 'Organization' }} /> -Let's highlight all object types in blue: +Highlight all object types in blue:
@@ -262,13 +245,13 @@ Let's highlight all object types in blue
-However, the list of object types is not finished. To complete the list of object types you must also add all the second nouns that appear in conditions as part of expressions of this format: **"\{first noun\} of a/the \{second noun\}"**. +To complete the list of object types, add all the second nouns that appear in conditions as part of expressions of this format: **"\{first noun\} of a/the \{second noun\}"**.
-Let's highlight those expressions in green: +Highlight those expressions in green:
@@ -317,8 +300,7 @@ Let's highlight those expressions in gree
-The only second noun we didn't have in our object type list is "Drive", so we'll add it to the list. -We will also need to add "User" to the list as it establishes the type of user who can establish relations. +The object type list is missing `Drive`, so we'll add it to the list. In addition, `User` must be added to establish the type of user who can create relations. @@ -328,7 +310,7 @@ We will also need to add "User" to the list as it establishes the type of user w , alignment: 'left', label: 'Drive' }} /> -Now that we have a list of object types we can start defining them using the : +Now we define them using the : -:::info Caution -You're now in the process of building a version you can use. The model above is not yet a valid authorization model accepted by . -::: - :::info Important -In a few cases other users can be part of determining whether an action can be performed on an action or not. Social media is an example of this "a user can comment on a picture if they are a friend of the user that published it". +Though you're in the process of building a version you can use, the model above is not yet a valid authorization model accepted by . + +In a few cases, other users can determine whether one action can be performed on another action. For example, on social media, sometimes a user can comment on a picture if they are a friend of the user that published it. -In those cases [**User** should also be an object type](./building-blocks/object-to-object-relationships.mdx). Following the last recommendation, we would discover the User type because it is a second noun in an expression: "friend of the user". +In those cases [**User** must be an object type](./building-blocks/object-to-object-relationships.mdx), and you would discover the User type because it is a second noun in an expression `friend of the user`. ::: ### 03. List Relations For Those Types ![List relations for those types](./assets/getting-started-diagram-04.svg) -Each of the previously defined types has a set of relations. are an important component in your model. After all, is a system. - -To identify relations for a type we in the write-up we can perform an exercise similar to the one we did in [list the type of objects in your system](#02-list-the-object-types). +Each previously defined type has a set of relations. A process similar to that above to [list the type of objects in your system](#02-list-the-object-types) defines your system's relations. Relations for a type \{type\} will be all of these: -- any noun that is the \{noun\} of a "\{noun\} of a/an/the \{type\}" expression. **These are typically the Foreign Keys in a database.** We'll highlight these in green. -- any verb or action that is the \{action\} of a "can \{action\} (in) a/an \{type\}" expression. **These are typically the permissions for a type.** We'll highlight these in yellow. +- any noun that is the \{noun\} of a "\{noun\} of a/an/the \{type\}" expression. These are typically the Foreign Keys in a database, highlighted below in green. +- any verb or action that is the \{action\} of a "can \{action\} (in) a/an \{type\}" expression. These are typically the permissions for a type, highlighted below in yellow.
@@ -476,10 +454,10 @@ The resulting list is: :::info -In , relations can only have alphanumeric characters, underscores and hyphens. We recommend using underscore (\_) to separate words and removing prepositions. E.g.: "can create a document" can become "can_create_document" or "create_document" if you are into brevity. +In , relations may only use alphanumeric characters, underscores and hyphens. We recommend using underscore (\_) to separate words and removing prepositions, so `can create a document` becomes `can_create_document` or `create_document`. ::: -Using the we can enumerate the relations for each type: +Enumerate relations for each type with the: ```dsl.openfga model @@ -514,14 +492,14 @@ type drive ``` :::info Caution -You're now in the process of building a version you can use. The model above is not yet a valid authorization model accepted by . +Though you're in the process of building a version you can use, the model above is not yet a valid authorization model accepted by . ::: ### 04. Define Relations ![Define relations](./assets/getting-started-diagram-05.svg) -We will use the to create a for each of the relations we identified. At this stage we will encode the answers to the question we asked at the beginning of the document:. +Use the to create a for each of the relations we identified, then encode the answers to the question we asked at the beginning of the document:.
-We are going to go over each type and each of its relations and create a definition for it. +Go over each type and each relation, then create a definitions for them.
@@ -541,17 +519,17 @@ We are going to go over each type and each of its relations and create a definit
-We recommend starting from objects that represent groups/containers of users. For features in most systems these are easy to define and help reason about the other types. Examples of type names for these are "team", "group", "organization", etc. +Start from objects that represent groups/containers of users, like `team`, `group`, or `organization`. They are easy to define for features in most systems and help reason out the other types. ##### Relation: Member -The member relation is used to tell about the members of an organization. +The member relation tells about the members of an organization. :::info Important -Relation names in are arbitrary strings. There are no reserved relation names. You can use "member" or "part_of" or anything else to refer to a user that is part of a team/organization. +Relation names in are arbitrary strings. There are no reserved relation names; you can use `member` or `part_of` or anything else to refer to a user that is part of a team/organization. ::: -Remember _"How a user is added as a member to an organization is beyond the scope of this feature."_ For the purposes of this model the relation definition should be: +Remember that how a user is added as a member to an organization is beyond the scope of this feature. For the purposes of this model the relation definition should be: -Why? This relation definition states: +This relation definition states: - That organizations have members -- That the members of an organization with id \{id\} are all users described by tuples of the form: +- That the members of an organization with id \{id\} are all users described by tuples of the form below: `{ user: {user-id}, relation: "member", object: "organization:{id}" }` :::info Important -Relation definitions of the form “define \{relation\}: [user, organization#member]" are fairly common. They are used to express that relationships "to the object with that relation" (e.g. "users" of type user or "member of organization") can be assigned by your system and that only the users that have that relation are those with a [direct relationship](./building-blocks/direct-relationships.mdx). +Relation definitions of the form `define \{relation\}: [user, organization#member]` are common and are used to express that relationships to the object with that relation (meaning users of type `user` or `member of organization`) can be assigned by your system. The only users with that relation are those with a [direct relationship](./building-blocks/direct-relationships.mdx). ::: You can read more about group membership and types in [Modeling User Groups](./user-groups.mdx). -For the direct relationships, we need to figure out the object types that makes sense for the relationship tuples' user. In our organization example, it makes sense for member relations to have user of type +You must determine the object types that makes sense for the relationship tuples' user when creating direct relationships. In the organization example, it makes sense for member relations to have user of type - user - organization#member (i.e., other organization's member) -However, it will not make sense for organization member's user to be of type document, folder or drive. - -We will specify this logic as part of directly . +However, it does not make sense for organization member's user to be of type `document`, `folder`, or `drive`. We specify this logic as part of a . -:::note Side note -This also automatically supports nested organizational membership if you want such a feature in your system. You could use relationship tuples like the following one to express that "members of organization A are members of organization B": +:::note Note +This also automatically supports nested organizational membership. You can use relationship tuples like the following to express that members of organization A are members of organization B: ``` { user: "organization:A#member", relation: "member", object: "organization:B"} ``` -If you want to learn more, you can read further about this in [Modeling User Groups](./user-groups.mdx) and [Managing Relationships Between Objects](../interacting/managing-relationships-between-objects.mdx). +To learn more, see [Modeling User Groups](./user-groups.mdx) and [Managing Relationships Between Objects](../interacting/managing-relationships-between-objects.mdx). ::: ##### Complete Type Definition From 80d32f4166282a9b9ca717409b4953b571d54307 Mon Sep 17 00:00:00 2001 From: Andrew <109249228+pavokta@users.noreply.github.com> Date: Wed, 13 Mar 2024 11:14:26 -0700 Subject: [PATCH 2/7] Update docs/content/modeling/getting-started.mdx Co-authored-by: Raghd Hamzeh --- docs/content/modeling/getting-started.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/modeling/getting-started.mdx b/docs/content/modeling/getting-started.mdx index 6133793a2..e5faaa226 100644 --- a/docs/content/modeling/getting-started.mdx +++ b/docs/content/modeling/getting-started.mdx @@ -570,7 +570,7 @@ You must determine the object types that makes sense for the relationship tuples - user - organization#member (i.e., other organization's member) -However, it does not make sense for organization member's user to be of type `document`, `folder`, or `drive`. We specify this logic as part of a . +However, it does not make sense for an organization member's user to be of type `document`, `folder`, or `drive`. We specify this logic as part of a . :::note Note This also automatically supports nested organizational membership. You can use relationship tuples like the following to express that members of organization A are members of organization B: From 72cdd5e7b79f8fb7000630362c7726853fef7739 Mon Sep 17 00:00:00 2001 From: Andrew <109249228+pavokta@users.noreply.github.com> Date: Wed, 13 Mar 2024 11:22:00 -0700 Subject: [PATCH 3/7] Update docs/content/modeling/getting-started.mdx Co-authored-by: Raghd Hamzeh --- docs/content/modeling/getting-started.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/modeling/getting-started.mdx b/docs/content/modeling/getting-started.mdx index e5faaa226..6141170c0 100644 --- a/docs/content/modeling/getting-started.mdx +++ b/docs/content/modeling/getting-started.mdx @@ -78,7 +78,7 @@ Answering that question for all object types in your system codifies your author ## A Process For Defining Authorization Models -Below is one iteration of the codification process, using a simplified Google Drive-like system as an example. The following steps define your authorization model: +Below is one iteration of defining an authorization model for your system, using a simplified Google Drive-like system as an example. The following are the steps for this iteration: 1. [Pick the most important feature](#01-pick-the-most-important-feature) 2. [List the object types](#02-list-the-object-types) From c768078e5317e7b18ddfb91db0e519b2e321a354 Mon Sep 17 00:00:00 2001 From: Andrew <109249228+pavokta@users.noreply.github.com> Date: Wed, 13 Mar 2024 11:22:16 -0700 Subject: [PATCH 4/7] Update docs/content/modeling/getting-started.mdx Co-authored-by: Raghd Hamzeh --- docs/content/modeling/getting-started.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/content/modeling/getting-started.mdx b/docs/content/modeling/getting-started.mdx index 6141170c0..5549c38e4 100644 --- a/docs/content/modeling/getting-started.mdx +++ b/docs/content/modeling/getting-started.mdx @@ -337,7 +337,6 @@ Now we define them using the : From 486b236c2f918c476c93cb49f3ab2bbb26ac24b2 Mon Sep 17 00:00:00 2001 From: Andrew <109249228+pavokta@users.noreply.github.com> Date: Wed, 13 Mar 2024 11:30:34 -0700 Subject: [PATCH 6/7] Update docs/content/modeling/getting-started.mdx Co-authored-by: Raghd Hamzeh --- docs/content/modeling/getting-started.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/modeling/getting-started.mdx b/docs/content/modeling/getting-started.mdx index 3bdb61858..f529c96ab 100644 --- a/docs/content/modeling/getting-started.mdx +++ b/docs/content/modeling/getting-started.mdx @@ -456,7 +456,7 @@ The resulting list is: In , relations may only use alphanumeric characters, underscores and hyphens. We recommend using underscore (\_) to separate words and removing prepositions, so `can create a document` becomes `can_create_document`. ::: -Enumerate relations for each type with the: +Enumerate relations for each type with the : ```dsl.openfga model From 5a0d80f0a2454a788ae53cabba2948fca8a2388a Mon Sep 17 00:00:00 2001 From: Ryan Quinn Date: Wed, 21 Aug 2024 09:23:59 -0500 Subject: [PATCH 7/7] Updated language recommended by @pavokta Change as specified at https://github.com/openfga/openfga.dev/pull/656#discussion_r1523717725 --- docs/content/modeling/getting-started.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/modeling/getting-started.mdx b/docs/content/modeling/getting-started.mdx index f529c96ab..5285bd9d2 100644 --- a/docs/content/modeling/getting-started.mdx +++ b/docs/content/modeling/getting-started.mdx @@ -72,7 +72,7 @@ While modeling, the general question to answer is: /> -Answering that question for all object types in your system codifies your authorization model. +Answering that question for all object types in your system means your authorization model can be codified. ---