Skip to content

Commit

Permalink
Merge pull request #1532 from Permify/docs
Browse files Browse the repository at this point in the history
docs: add modeling guides section
  • Loading branch information
EgeAytin committed Sep 6, 2024
2 parents 692d73b + 551ea75 commit 1843533
Show file tree
Hide file tree
Showing 13 changed files with 912 additions and 218 deletions.
2 changes: 1 addition & 1 deletion docs/getting-started/examples/google-docs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ The organization entity has two permissions defined:

**admin:** An permission that can be performed by users who are authorized to manage the organization, as determined by the administrator relationship.

**member:** An permission that can be performed by users who are directly members of the organization, or who have administrator relationship, or who are members of groups that are part of the organization,
**member:** An permission that can be performed by users who are directly members of the organization, or who have administrator relationship, or who are members of groups that are part of the organization.

## Relationships

Expand Down
232 changes: 18 additions & 214 deletions docs/getting-started/modeling.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ icon: "code"
title: "Modeling Authorization"
---

Permify was designed and structured as a true ReBAC solution, so besides roles and attributes Permify also supports indirect permission granting through relationships.

With Permify, you can define that a user has certain permissions because of their relation to other entities. An example of this would be granting a manager the same permissions as their subordinates, or giving a user access to a resource because they belong to a certain group.
In Permify, you can define that a user has certain permissions because of their relation to other entities. An example of this would be granting a manager the same permissions as their subordinates, or giving a user access to a resource because they belong to a certain group.

This is facilitated by our relationship-based access control, which allows the definition of complex permission structures based on the relationships between users, roles, and resources.

Expand Down Expand Up @@ -202,7 +200,7 @@ You can think of these definitions as a precaution taken against creating undesi

Defining multiple relation types totally optional. The goal behind it to improve validation and reasonability. And for complex models, it allows you to model your entities in a more structured way.

## Defining Actions and Permissions
## Defining Permissions

Actions describe what relations, or relation’s relation can do. Think of actions as permissions of the entity it belongs. So actions defines who can perform a specific action on a resource in which circumstances.

Expand Down Expand Up @@ -290,114 +288,7 @@ The `delete` action inherits the rules from the `edit` action. By doing that, we

Permission union is super beneficial in scenarios where a user needs to have varied access across different departments or roles.

### Nested Hierarchies

The reason we have two keywords for defining permissions (`action` and `permission`) is that while most permissions are based on actions (such as view, read, edit, etc.), there are still cases where we need to define permissions based on roles or user types, such as admin or member.

Additionally, there may be permissions that need to be inherited by child entities. Using the `permission` keyword in these cases is more convenient and provides better reasoning of the schema.

Here is a simple example to demonstrate inherited permissions.

Let's examine a small snippet from our [Facebook Groups](./examples/google-docs) real world example. Let's create a permission called 'view' in the comment entity (which represents the comments of the post in Facebook Groups)

Users can only view a comment if:

- The user is the owner of that comment
**or**
- The user is a member of the group to which the comment's post belongs.

```perm
// Represents a post in a Facebook group
entity post {
..
..
// Relation to represent the group that the post belongs to
relation group @group
// Permissions for the post entity
..
..
permission group_member = group.member
}
// Represents a comment on a post in a Facebook group
entity comment {
// Relation to represent the owner of the comment
relation owner @user
// Relation to represent the post that the comment belongs to
relation post @post
relation comment @comment
..
..
// Permissions
action view = owner or post.group_member
..
..
}
```

The `post.group_member` refers to the members of the group to which the post belongs. We defined it as action in **post** entity as,

```perm
permission group_member = group.member
```

Permissions can be inherited as relations in other entities. This allows to form nested hierarchical relationships between entities.

In this example, a comment belongs to a post which is part of a group. Since there is a **'member'** relation defined for the group entity, we can use the **'group_member'** permission to inherit the **member** relation from the group in the post and then use it in the comment.

### Recursive ReBAC

With Permify DSL, you can define recursive relationship-based permissions within the same entity.

As an example, consider a system where there are multiple organizations within a company, some of which may have a parent-child relationship between them.

As expected, organization members are also granted permission to view their organization details. You can model that as follows:

```perm
entity user {}
entity organization {
relation parent @organization
relation member @user @organization#member
action view = member or parent.member
}
```

Let's extend the scenario by adding a rule allowing parent organization members to view details of child organizations. Specifically, a member of **Organization Alpha** could view the details of **Organization Beta** if **Organization Beta** belongs to **Organization Alpha**.

![modeling-authorization](https://user-images.githubusercontent.com/58391988/279456032-485a0aef-b83b-4257-af48-0fcbe6fa2e64.png)

First authorization schema that we provide won't solve this issue because `parent.member` accommodate single upward traversal in a hierarchy.

Instead of `parent.member` we can call the parent view permission on the same entity - `parent.view` to achieve multiple levels of upward traversal, as follows:

```perm
entity user {}
entity organization {
relation parent @organization
relation member @user @organization#member
action view = member or parent.view
}
```

This way, we achieve a recursive relationship between parent-child organizations.

<Note>
*Credits to [Léo](https://github.com/LeoFVO) for the illustration and for
[highlighting](https://github.com/Permify/permify/issues/790) this use case.*
</Note>
Let's examine our modeling guides for common permission use cases.

## Attribute Based Permissions (ABAC)

Expand Down Expand Up @@ -469,112 +360,25 @@ Please let us know via our [Discord channel](https://discord.gg/n6KfzYxhPp) if y

</Note>

Let's examine some of common usage of ABAC with small schema examples.

### Boolean - True/False Conditions

For attributes that represent a binary choice or state, such as a yes/no question, the `Boolean` data type is an excellent choice.

```perm
entity post {
attribute is_public boolean
permission view = is_public
}
```

<Warning>
⛔ If you don’t create the related attribute data, Permify accounts boolean as
`FALSE`
</Warning>

### Text & Object Based Conditions

String can be used as attribute data type in a variety of scenarios where text-based information is needed to make access control decisions. Here are a few examples:

- **Location:** If you need to control access based on geographical location, you might have a location attribute (e.g., "USA", "EU", "Asia") stored as a string.
- **Device Type**: If access control decisions need to consider the type of device being used, a device type attribute (e.g., "mobile", "desktop", "tablet") could be stored as a string.
- **Time Zone**: If access needs to be controlled based on time zones, a time zone attribute (e.g., "EST", "PST", "GMT") could be stored as a string.
- **Day of the Week:** In a scenario where access to certain resources is determined by the day of the week, the string data type can be used to represent these days (e.g., "Monday", "Tuesday", etc.) as attributes!

```perm
entity user {}
entity organization {
relation admin @user
attribute location string[]
permission view = check_location(request.current_location, location) or admin
}
rule check_location(current_location string, location string[]) {
current_location in location
}
```

<Warning>
⛔ If you don’t create the related attribute data, Permify accounts string as
`""`
</Warning>

### Numerical Conditions

#### Integers

Integer can be used as attribute data type in several scenarios where numerical information is needed to make access control decisions. Here are a few examples:

- **Age:** If access to certain resources is age-restricted, an age attribute stored as an integer can be used to control access.
- **Security Clearance Level:** In a system where users have different security clearance levels, these levels can be stored as integer attributes (e.g., 1, 2, 3 with 3 being the highest clearance).
- **Resource Size or Length:** If access to resources is controlled based on their size or length (like a document's length or a file's size), these can be stored as integer attributes.
- **Version Number:** If access control decisions need to consider the version number of a resource (like a software version or a document revision), these can be stored as integer attributes.

```perm
entity content {
permission view = check_age(request.age)
}
rule check_age(age integer) {
age >= 18
}
```

<Warning>
⛔ If you don’t create the related attribute data, Permify accounts integer as
`0`
</Warning>

#### Double - Precise numerical information

Double can be used as attribute data type in several scenarios where precise numerical information is needed to make access control decisions. Here are a few examples:

- **Usage Limit:** If a user has a usage limit (like the amount of storage they can use or the amount of data they can download), and this limit needs to be represented with decimal precision, it can be stored as a double attribute.
- **Transaction Amount:** In a financial system, if access control decisions need to consider the amount of a transaction, and this amount needs to be represented with decimal precision (like $100.50), these amounts can be stored as double attributes.
- **User Rating:** If access control decisions need to consider a user's rating (like a rating out of 5 with decimal points, such as 4.7), these ratings can be stored as double attributes.
- **Geolocation:** If access control decisions need to consider precise geographical coordinates (like latitude and longitude, which are often represented with decimal points), these coordinates can be stored as double attributes.
## Modeling Guides

```perm
entity user {}
Let’s examine our modeling guides for common permission use cases.

entity account {
relation owner @user
attribute balance double
permission withdraw = check_balance(request.amount, balance) and owner
}
rule check_balance(amount double, balance double) {
(balance >= amount) && (amount <= 5000)
}
```
**Role-Based Access Control (RBAC)**
- [Global Roles](/modeling-guides/rbac/global-roles)
- [Resource Specific Roles](/modeling-guides/rbac/resource-specific-roles)
- [Custom Roles](/modeling-guides/rbac/custom-roles)

<Warning>
⛔ If you don’t create the related attribute data, Permify accounts double as
`0.0`
</Warning>
**Relationship Based Access Control (ReBAC)**
- [User Groups](/modeling-guides/rebac/user-groups)
- [Hierarchies](/modeling-guides/rebac/hierarchies)
- [Nested/Inherited Permissions](/modeling-guides/rebac/impersonation)
- [Recursive Relationships](/modeling-guides/rebac/recursive-rebac)

See more details on [Attribute Based Access Control](#attribute-based-permissions-abac) section to learn our approach on ABAC as well as how it operates in Permify. you can see more comprehensive ABAC examples in the [Example ABAC Use Cases](../use-cases/abac/#example-use-cases) section in related page.
**Attribute Based Access Control (ABAC)**
- [Public or Private Resources](/modeling-guides/abac/public-private)
- [Text & Object Based Conditions](/modeling-guides/abac/text-object-based-conditions)
- [Numerical Conditions](/modeling-guides/abac/numerical-conditions)

## More Comprehensive Examples

Expand Down
41 changes: 38 additions & 3 deletions docs/mint.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,11 @@
},
{
"source": "/permify-overview/getting-started/modeling",
"destination": "/getting-started/modeling"
"destination": "/getting-started/modeling/intro"
},
{
"source": "/getting-started/modeling",
"destination": "/getting-started/modeling/intro"
},
{
"source": "/installation/installation/azure",
Expand Down Expand Up @@ -108,7 +112,7 @@
},
{
"source": "/use-cases/getting-started/modeling",
"destination": "/getting-started/modeling"
"destination": "/getting-started/modeling/intro"
},
{
"source": "/api-reference/api-overview/:slug*",
Expand Down Expand Up @@ -192,7 +196,7 @@
},
{
"source": "/example-use-cases/getting-started/modeling",
"destination": "/getting-started/modeling"
"destination": "/getting-started/modeling/intro"
},
{
"source": "/getting-started/reference/configuration",
Expand Down Expand Up @@ -261,6 +265,37 @@
}
]
},
{
"group": "Modeling Guides",
"icon": "code",
"pages": [
{
"group": "Model Role Based Access Control (RBAC)",
"pages": [
"modeling-guides/rbac/global-roles",
"modeling-guides/rbac/resource-specific-roles",
"modeling-guides/rbac/custom-roles"
]
},
{
"group": "Model Attribute Based Access Control (ABAC)",
"pages": [
"modeling-guides/abac/public-private",
"modeling-guides/abac/text-object-based-conditions",
"modeling-guides/abac/numerical-conditions"
]
},
{
"group": "Model Relationship Based Access Control (ReBAC)",
"pages": [
"modeling-guides/rebac/user-groups",
"modeling-guides/rebac/hierarchies",
"modeling-guides/rebac/impersonation",
"modeling-guides/rebac/recursive-rebac"
]
}
]
},
{
"group": "Setting Up",
"icon": "cloud-arrow-up",
Expand Down
Loading

0 comments on commit 1843533

Please sign in to comment.