sidebar_position | slug | description |
---|---|---|
7 |
/modeling/parent-child |
Indicating relationships between objects, and how users' relationships to one object can affect their relationship with another |
import { AuthzModelSnippetViewer, CardBox, CheckRequestViewer, DocumentationNotice, Playground, ProductConcept, ProductName, ProductNameFormat, RelatedSection, WriteRequestViewer, } from '@components/Docs';
In this guide you will learn how to indicate between , and how users' relationships to one object can affect their relationship with another. For example: how a editor
of a folder
can be an editor
of all documents
the folder
is a parent
of.
Object-to-Object relationships, combined with a configured authorization model can be used to indicate that a user's relation with one object can influence their relationship with another object. This can also be used in some cases to remove the need to modify relations between objects using user groups.
Object-to-object relationships can be used:
- To indicate that
managers
of anemployee
have access toapprove
requests theemployee
has made - To indicate that users who have a repository admin role (
repo_admin
) in an organization automatically haveadmin
access to all repositories in that organization - To indicate that users who are
subscribed
to aplan
, get access to all thefeatures
in thatplan
In order to understand this guide correctly you must be familiar with some and know how to develop the things that we will list below.
Assume that you have the following .
You have two types:
folder
that users can be related to as an editor
document
that users can be related to as an editor
You have two types:
folder
that users can be related to as an editor
document
that users can be related to as an editor
<AuthzModelSnippetViewer configuration={{ schema_version: '1.1', type_definitions: [ { type: 'user', }, { type: 'folder', relations: { editor: { this: {}, }, }, metadata: { relations: { editor: { directly_related_user_types: [{ type: 'user' }] }, }, }, }, { type: 'document', relations: { editor: { this: {}, }, }, metadata: { relations: { editor: { directly_related_user_types: [{ type: 'user' }] }, }, }, }, ], }} />
In addition, you will need to know the following:
You need to know how to create an authorization model and create a relationship tuple to grant a user access to an object. Learn more →
- A : a class of objects that have similar characteristics
- A : an entity in the system that can be related to an object
- A : is a string defined in the type definition of an authorization model that defines the possibility of a relationship between an object of the same type as the type definition and a user in the system
- An : represents an entity in the system. Users' relationships to it can be define through relationship tuples and the authorization model
- A : a grouping consisting of a user, a relation and an object stored in
- Union Operator: the union operator can be used to indicate that the user has multiple ways of being related to an object
We would like to model folders that contain documents and that a user having editor access to the folder, has editor access to all documents in that folder.
For editors
of a folder
to be editors
of a containing document
, we need to:
- Update the authorization model to allow a
parent
relationship betweenfolder
anddocument
- Update the
editor
relation in thedocument
type definition to support cascading fromfolder
and then to indicate and verify that bob is an editor
of document:meeting_notes.doc because bob is an editor
of folder:notes, we then need to:
- Create a new relationship tuple to indicate that bob is a
editor
of folder:notes - Create a new relationship tuple to indicate that folder:notes is a
parent
of document:meeting_notes.doc - Check to see if bob is an
editor
of document:meeting_notes.doc
To allow a parent
relation between a folder
and a document
, we need to update the authorization model to be the following (this is to allow creating relationship tuples that can indicate a relationship between folder
and document
. Refer to Modeling Concepts: Object to Object Relationships to understand why):
<AuthzModelSnippetViewer configuration={{ schema_version: '1.1', type_definitions: [ { type: 'user', }, { type: 'folder', relations: { editor: { this: {}, }, }, metadata: { relations: { editor: { directly_related_user_types: [{ type: 'user' }] }, }, }, }, { type: 'document', relations: { // A folder can be a parent of a document parent: { this: {}, }, editor: { this: {}, }, }, metadata: { relations: { parent: { directly_related_user_types: [{ type: 'folder' }] }, editor: { directly_related_user_types: [{ type: 'user' }] }, }, }, }, ], }} />
:::info
Notice that the document
type now has a parent
relation, indicating that other objects can be parent
s of document
s
:::
To allow cascading relations between folder
and document
, we can update our authorization model as the following:
<AuthzModelSnippetViewer configuration={{ schema_version: '1.1', type_definitions: [ { type: 'user', }, { type: 'folder', relations: { editor: { this: {}, }, }, metadata: { relations: { editor: { directly_related_user_types: [{ type: 'user' }] }, }, }, }, { type: 'document', relations: { parent: { this: {}, }, editor: { union: { child: [ { this: {}, }, { tupleToUserset: { tupleset: { relation: 'parent', }, computedUserset: { relation: 'editor', }, }, }, ], }, }, }, metadata: { relations: { parent: { directly_related_user_types: [{ type: 'folder' }] }, editor: { directly_related_user_types: [{ type: 'user' }] }, }, }, }, ], }} />
:::info
editor
of a document
are any of:
- users that are directly assigned as editors
- users that are related to any
parent
of this document aseditor
(editors of the parent)
:::
So with this change, anyone related to a folder
that is a parent
of a document
as an editor
is also an editor
of said document
.
To leverage our cascading relation, we need to create a relationship tuple that states: bob is an editor
of folder:notes
<WriteRequestViewer relationshipTuples={[ { user: 'user:bob', relation: 'editor', object: 'folder:notes', }, ]} />
:::caution Note: Make sure to use unique ids for each object and user within your application domain when creating relationship tuples for . We are using first names and simple ids to illustrate an easy-to-follow example. :::
04. Create A New Relationship Tuple To Indicate That folder:notes Is A Parent Of document:meeting_notes.doc
Now that bob is an editor
of folder:notes, we need to indicate that folder:notes is a parent
of document
:meeting_notes.doc
<WriteRequestViewer relationshipTuples={[ { _description: 'the notes folder is a parent of the meeting notes document', user: 'folder:notes', relation: 'parent', object: 'document:meeting_notes.doc', }, ]} />
Now that we have done the changes to the authorization model and the addition of the two new relationship tuples, we can verify if our configuration is correct by running the following check: is bob an editor of document:meeting_notes.doc.
<CheckRequestViewer user={'user:bob'} relation={'editor'} object={'document:meeting_notes.doc'} allowed={true} />
Note: There are no other relationship tuples within the store that dictate any direct relation between bob and document:meeting_notes.doc. The check succeeds because of the cascading relation applied.
The chain of resolution becomes:
- bob is an
editor
of folder:notes - folder:notes is a
parent
of document:meeting_notes.doc editors
of anyparent
folder
of document:meeting_notes.doc are alsoeditors
of thedocument
- Therefore, bob is an
editor
of document:meeting_notes.doc
:::caution
Note that when searching tuples that are related to the object (the word after from
, also called the tupleset), will not do any evaluation and will only consider concrete objects (of the form <object_type>:<object_id>
) that were directly assigned, and will throw an error if it encounters any rewrites, or a *
, a type bound public access (<object_type>:*
) or a userset (<object_type>:<object_id>#<relation>
).
See Referencing Relations on Related Objects for more. :::
<RelatedSection description="Check the following sections for more on how to model for parent and child objects." relatedLinks={[ { title: 'Modeling Concepts: Object to Object Relationships', description: 'Learn about how to model object to object relationships in {ProductName}.', link: './building-blocks/object-to-object-relationships', id: './building-blocks/object-to-object-relationships', }, { title: 'Modeling Google Drive', description: 'See how to make folders parents of documents, and to make editors on the parent folders editors on documents inside them..', link: './advanced/gdrive#01-individual-permissions', id: './advanced/gdrive.mdx#01-individual-permissions', }, { title: 'Modeling GitHub', description: 'See how to grant users access to all repositories owned by an organization.', link: './advanced/github#01-permissions-for-individuals-in-an-org', id: './advanced/github.mdx#01-permissions-for-individuals-in-an-org', }, ]} />