Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 33 additions & 40 deletions docs/RBACWithConditions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ authors: [PokIsemaine]

## Conditional RoleManager

`ConditionalRoleManager` supports custom condition functions at the policy level.
The `ConditionalRoleManager` allows you to apply custom condition functions at the policy level.

For example, when we need a temporary role policy, we can follow the following approach:
When you need role policies that are valid only under certain conditions—such as time-based temporary roles—you can configure this as shown below:

`model.conf`

Expand All @@ -31,8 +31,7 @@ e = some(where (p.eft == allow))
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
```

`g = _, _, (_, _)` uses `(_, _)` to contain a list of arguments to pass to the condition function
and `_` as a parameter placeholder
The syntax `g = _, _, (_, _)` defines a role relationship with additional parameters. The underscores `_` serve as placeholders, while the parentheses `(_, _)` specify the list of arguments that will be passed to the condition function.

`policy.csv`

Expand All @@ -57,10 +56,7 @@ g, alice, data8_admin, 9999-12-30 00:00:00, _

### Basic Usage

Add a conditional function for the role policy(`g`type policy) through `AddNamedLinkConditionFunc`,
and when enforcing is executed, the corresponding parameters will be automatically obtained
and passed in the conditional function for checking.
If the check passes, then the corresponding role policy(`g` type policy) is valid, otherwise it is invalid
Use `AddNamedLinkConditionFunc` to attach a condition function to a role policy (of type `g`). During enforcement, the system automatically retrieves the corresponding parameters and passes them to the condition function. The role policy is considered valid only if the function returns true.

```go
e.AddNamedLinkConditionFunc("g", "alice", "data2_admin", util.TimeMatchFunc)
Expand All @@ -72,25 +68,25 @@ e.AddNamedLinkConditionFunc("g", "alice", "data7_admin", util.TimeMatchFunc)
e.AddNamedLinkConditionFunc("g", "alice", "data8_admin", util.TimeMatchFunc)


e.enforce("alice", "data1", "read") // except: true
e.enforce("alice", "data2", "write") // except: false
e.enforce("alice", "data3", "read") // except: true
e.enforce("alice", "data4", "write") // except: true
e.enforce("alice", "data5", "read") // except: true
e.enforce("alice", "data6", "write") // except: false
e.enforce("alice", "data7", "read") // except: true
e.enforce("alice", "data8", "write") // except: false
e.enforce("alice", "data1", "read") // expect: true
e.enforce("alice", "data2", "write") // expect: false
e.enforce("alice", "data3", "read") // expect: true
e.enforce("alice", "data4", "write") // expect: true
e.enforce("alice", "data5", "read") // expect: true
e.enforce("alice", "data6", "write") // expect: false
e.enforce("alice", "data7", "read") // expect: true
e.enforce("alice", "data8", "write") // expect: false
```

### Custom condition functions

Custom conditional functions need to conform to the following function types
Condition functions must follow this signature:

```go
type LinkConditionFunc = func(args ...string) (bool, error)
```

for example:
Example implementation:

```go
// TimeMatchFunc is the wrapper for TimeMatch.
Expand Down Expand Up @@ -169,10 +165,7 @@ g, alice, data8_admin, domain8, 9999-12-30 00:00:00, _

### Basic Usage

Add a conditional function for the role policy(`g`type policy) through `AddNamedDomainLinkConditionFunc`,
and when enforcing is executed, the corresponding parameters will be automatically obtained
and passed in the conditional function for checking.
If the check passes, then the corresponding role policy(`g` type policy) is valid, otherwise it is invalid
Use `AddNamedDomainLinkConditionFunc` to attach a condition function to a domain-specific role policy (of type `g`). During enforcement, the system automatically retrieves the corresponding parameters and passes them to the condition function. The role policy is considered valid only if the function returns true.

```go
e.AddNamedDomainLinkConditionFunc("g", "alice", "data2_admin", "domain2", util.TimeMatchFunc)
Expand All @@ -184,28 +177,28 @@ e.AddNamedDomainLinkConditionFunc("g", "alice", "data7_admin", "domain7", util.T
e.AddNamedDomainLinkConditionFunc("g", "alice", "data8_admin", "domain8", util.TimeMatchFunc)


e.enforce("alice", "domain1", "data1", "read") // except: true
e.enforce("alice", "domain2", "data2", "write") // except: false
e.enforce("alice", "domain3", "data3", "read") // except: true
e.enforce("alice", "domain4", "data4", "write") // except: true
e.enforce("alice", "domain5", "data5", "read") // except: true
e.enforce("alice", "domain6", "data6", "write") // except: false
e.enforce("alice", "domain7", "data7", "read") // except: true
e.enforce("alice", "domain8", "data8", "write") // except: false
e.enforce("alice", "domain_not_exist", "data1", "write") // except: false
e.enforce("alice", "domain_not_exist", "data2", "read") // except: false
e.enforce("alice", "domain_not_exist", "data3", "write") // except: false
e.enforce("alice", "domain_not_exist", "data4", "read") // except: false
e.enforce("alice", "domain_not_exist", "data5", "write") // except: false
e.enforce("alice", "domain_not_exist", "data6", "read") // except: false
e.enforce("alice", "domain_not_exist", "data7", "write") // except: false
e.enforce("alice", "domain_not_exist", "data8", "read") // except: false
e.enforce("alice", "domain1", "data1", "read") // expect: true
e.enforce("alice", "domain2", "data2", "write") // expect: false
e.enforce("alice", "domain3", "data3", "read") // expect: true
e.enforce("alice", "domain4", "data4", "write") // expect: true
e.enforce("alice", "domain5", "data5", "read") // expect: true
e.enforce("alice", "domain6", "data6", "write") // expect: false
e.enforce("alice", "domain7", "data7", "read") // expect: true
e.enforce("alice", "domain8", "data8", "write") // expect: false
e.enforce("alice", "domain_not_exist", "data1", "write") // expect: false
e.enforce("alice", "domain_not_exist", "data2", "read") // expect: false
e.enforce("alice", "domain_not_exist", "data3", "write") // expect: false
e.enforce("alice", "domain_not_exist", "data4", "read") // expect: false
e.enforce("alice", "domain_not_exist", "data5", "write") // expect: false
e.enforce("alice", "domain_not_exist", "data6", "read") // expect: false
e.enforce("alice", "domain_not_exist", "data7", "write") // expect: false
e.enforce("alice", "domain_not_exist", "data8", "read") // expect: false
```

### Custom condition functions

Like the basic `Conditional RoleManager`, custom functions are supported, and there is no difference in use.
Custom condition functions work the same way as in the basic `Conditional RoleManager`.

Note that `DomainMatchingFunc`, `MatchingFunc`, and `LinkConditionFunc` are at different levels and are used in different situations.
Keep in mind that `DomainMatchingFunc`, `MatchingFunc`, and `LinkConditionFunc` operate at different levels and serve distinct purposes.

![conditional_rolemanager_with_domains](/img/rbac/conditional_rolemanager_with_domains.png)
13 changes: 5 additions & 8 deletions docs/RBACWithConditionsAPI.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ keywords: [RBAC with conditions, API]
authors: [PokIsemaine]
---

A more user-friendly API for [RBAC with conditions](RBACWithConditions.mdx).
This API provides a simplified interface for working with [RBAC with conditions](RBACWithConditions.mdx).

## Reference

### AddNamedLinkConditionFunc

`AddNamedLinkConditionFunc` Add condition function fn for Link `userName->roleName`,
when fn returns true, Link is valid, otherwise invalid
`AddNamedLinkConditionFunc` attaches a condition function to a link between `userName` and `roleName`. The link is valid only when the function returns true.

```mdx-code-block
<Tabs groupId="langs">
Expand All @@ -31,8 +30,7 @@ e.AddNamedLinkConditionFunc("g", "userName", "roleName", YourLinkConditionFunc)

### AddNamedDomainLinkConditionFunc

`AddNamedDomainLinkConditionFunc` Add condition function fn for Link `userName-> {roleName, domain}`,
when fn returns true, Link is valid, otherwise invalid
`AddNamedDomainLinkConditionFunc` attaches a condition function to a link between `userName` and `{roleName, domain}`. The link is valid only when the function returns true.

```mdx-code-block
<Tabs groupId="langs">
Expand All @@ -50,7 +48,7 @@ e.AddNamedDomainLinkConditionFunc("g", "userName", "roleName", "domainName", You

### SetNamedLinkConditionFuncParams

`SetNamedLinkConditionFuncParams` Sets the parameters of the condition function fn for Link `userName->roleName`
`SetNamedLinkConditionFuncParams` configures the parameters passed to the condition function for a link between `userName` and `roleName`.

```mdx-code-block
<Tabs groupId="langs">
Expand All @@ -69,8 +67,7 @@ e.SetNamedLinkConditionFuncParams("g", "userName2", "roleName2", "YourConditionF

### SetNamedDomainLinkConditionFuncParams

`SetNamedDomainLinkConditionFuncParams` Sets the parameters of the condition function fn
for Link `userName->{roleName, domain}`
`SetNamedDomainLinkConditionFuncParams` configures the parameters passed to the condition function for a link between `userName` and `{roleName, domain}`.

```mdx-code-block
<Tabs groupId="langs">
Expand Down
19 changes: 9 additions & 10 deletions docs/RBACWithDomains.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ authors: [hsluoyz]

## Role Definition with Domain Tenants

The RBAC roles in Casbin can be global or domain-specific. Domain-specific roles mean that the roles for a user can be different when the user is in different domains/tenants. This is very useful for large systems like a cloud, as users are usually in different tenants.
In Casbin, RBAC roles can be either global or domain-specific. Domain-specific roles allow a user to hold different roles across different domains or tenants. This capability is particularly valuable in large-scale systems such as cloud platforms, where users frequently operate within multiple distinct tenants.

The role definition with domains/tenants should look like this:
The role definition for domains or tenants should be structured as follows:

```ini
[role_definition]
g = _, _, _
```

The third `_` represents the name of the domain/tenant, and this part should not be changed. Then the policy can be:
The third underscore `_` denotes the domain or tenant name and must remain unchanged. With this setup, policies can be written like this:

```csv
p, admin, tenant1, data1, read
Expand All @@ -27,31 +27,30 @@ g, alice, admin, tenant1
g, alice, user, tenant2
```

This means that the `admin` role in `tenant1` can read `data1`. And `alice` has the `admin` role in `tenant1` and the `user` role in `tenant2`. Therefore, she can read `data1`. However, since `alice` is not an `admin` in `tenant2`, she cannot read `data2`.
This configuration means that the `admin` role in `tenant1` has read access to `data1`. Alice holds the `admin` role in `tenant1` and the `user` role in `tenant2`, so she can read `data1`. However, because Alice is not an `admin` in `tenant2`, she cannot read `data2`.

Then, in a matcher, you should check the role as follows:
In your matcher, verify the role as follows:

```ini
[matchers]
m = g(r.sub, p.sub, r.dom) && r.dom == p.dom && r.obj == p.obj && r.act == p.act
```

Please refer to the [rbac_with_domains_model.conf](https://github.com/casbin/casbin/blob/master/examples/rbac_with_domains_model.conf) for examples.
For additional examples, refer to [rbac_with_domains_model.conf](https://github.com/casbin/casbin/blob/master/examples/rbac_with_domains_model.conf).

:::info Token Name Convention

Note: Conventionally, the domain token name in policy definition is `dom` and is placed as the second token (`sub, dom, obj, act`).
Now, Golang Casbin supports customized token names and placement. If the domain token name is `dom`, the domain token can be placed at an arbitrary position without any additional action. If the domain token name is not `dom`, `e.SetFieldIndex()` for `constant.DomainIndex` should be called after the enforcer is initialized, regardless of its position.
By convention, the domain token in policy definitions is named `dom` and is typically positioned as the second token (e.g., `sub, dom, obj, act`). Golang Casbin now supports custom token names and positions. If the domain token is named `dom`, it can be placed anywhere without extra configuration. For other names, call `e.SetFieldIndex()` with `constant.DomainIndex` after initializing the enforcer, regardless of token position.

```ini
# `domain` here for `dom`
# Using `domain` instead of `dom`
[policy_definition]
p = sub, obj, act, domain
```

```go
e.SetFieldIndex("p", constant.DomainIndex, 3) // index starts from 0
users := e.GetAllUsersByDomain("domain1") // without SetFieldIndex, it will raise an error
users := e.GetAllUsersByDomain("domain1") // without SetFieldIndex, this will raise an error
```

:::
29 changes: 14 additions & 15 deletions docs/RBACWithDomainsAPI.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ keywords: [RBAC with domains, API]
authors: [hsluoyz]
---

A more user-friendly API for RBAC with domains. This API is a subset of the Management API. RBAC users can use this API to simplify their code.
This simplified API is designed for RBAC with domains. It is a subset of the Management API, making it easier for RBAC users to work with domain-based policies.

## Reference

Expand Down Expand Up @@ -82,7 +82,7 @@ Enforcer e = new Enforcer("examples/rbac_with_domains_model.conf", "examples/rba

### `GetUsersForRoleInDomain()`

The `GetUsersForRoleInDomain()` function retrieves the users that have a role within a domain.
`GetUsersForRoleInDomain()` retrieves all users assigned to a specific role within a domain.

For example:

Expand Down Expand Up @@ -120,7 +120,7 @@ res = e.get_users_for_role_in_domain("admin", "domain1")

### `GetRolesForUserInDomain()`

The `GetRolesForUserInDomain()` function retrieves the roles that a user has within a domain.
`GetRolesForUserInDomain()` retrieves all roles assigned to a user within a domain.

For example:

Expand Down Expand Up @@ -167,7 +167,7 @@ List<String> res = e.getRolesForUserInDomain("admin", "domain1");

### `GetPermissionsForUserInDomain()`

The `GetPermissionsForUserInDomain()` function retrieves the permissions for a user or role within a domain.
`GetPermissionsForUserInDomain()` retrieves all permissions for a user or role within a domain.

For example:

Expand Down Expand Up @@ -196,7 +196,7 @@ List<List<String>> res = e.getPermissionsForUserInDomain("alice", "domain1");

### `AddRoleForUserInDomain()`

The `AddRoleForUserInDomain()` function adds a role for a user within a domain. It returns `false` if the user already has the role (no changes made).
`AddRoleForUserInDomain()` assigns a role to a user within a domain. Returns `false` if the user already has the role (no changes made).

For example:

Expand Down Expand Up @@ -234,7 +234,7 @@ boolean ok = e.addRoleForUserInDomain("alice", "admin", "domain1");

### `DeleteRoleForUserInDomain()`

The `DeleteRoleForUserInDomain()` function removes a role for a user within a domain. It returns `false` if the user does not have the role (no changes made).
`DeleteRoleForUserInDomain()` removes a role from a user within a domain. Returns `false` if the user does not have the role (no changes made).

For example:

Expand Down Expand Up @@ -263,7 +263,7 @@ boolean ok = e.deleteRoleForUserInDomain("alice", "admin", "domain1");

### `DeleteRolesForUserInDomain()`

The `DeleteRolesForUserInDomain()` function removes all roles for a user within a domain. It returns `false` if the user does not have any roles (no changes made).
`DeleteRolesForUserInDomain()` removes all roles from a user within a domain. Returns `false` if the user has no roles (no changes made).

For example:

Expand All @@ -283,7 +283,7 @@ ok, err := e.DeleteRolesForUserInDomain("alice", "domain1")

### `GetAllUsersByDomain()`

The `GetAllUsersByDomain()` function retrieves all users associated with the given domain. It returns an empty string array if no domain is defined in the model.
`GetAllUsersByDomain()` retrieves all users associated with the specified domain. Returns an empty string array if no domain is defined in the model.

For example:

Expand All @@ -303,7 +303,7 @@ res := e.GetAllUsersByDomain("domain1")

### `DeleteAllUsersByDomain()`

The `DeleteAllUsersByDomain()` function deletes all users associated with the given domain. It returns `false` if no domain is defined in the model.
`DeleteAllUsersByDomain()` removes all users associated with the specified domain. Returns `false` if no domain is defined in the model.

For example:

Expand All @@ -323,8 +323,7 @@ ok, err := e.DeleteAllUsersByDomain("domain1")

### `DeleteDomains()`

DeleteDomains would delete all associated users and roles.
It would delete all domains if parameter is not provided.
`DeleteDomains()` removes all associated users and roles for the specified domains. If no parameters are provided, all domains are deleted.

For example:

Expand All @@ -344,7 +343,7 @@ ok, err := e.DeleteDomains("domain1", "domain2")

### `GetAllDomains()`

GetAllDomains would get all domains.
`GetAllDomains()` retrieves all domains.

For example:

Expand All @@ -364,13 +363,13 @@ res, _ := e.GetAllDomains()

:::note

If you are handling a domain like ```name::domain```, it may lead to unexpected behavior. In Casbin, ```::``` is a reserved keyword, just like ```for```, ```if``` in a programming language, we should never put ```::``` in a domain.
When handling domain names that contain `::`, unexpected behavior may occur. In Casbin, `::` is a reserved keyword, similar to `for` or `if` in programming languages. Never use `::` within a domain name.

:::

### `GetAllRolesByDomain()`

GetAllRolesByDomain would get all roles associated with the domain.
`GetAllRolesByDomain()` retrieves all roles associated with the specified domain.

For example:

Expand All @@ -396,7 +395,7 @@ This method does not apply to domains that have an inheritance relationship, als

### `GetImplicitUsersForResourceByDomain()`

GetImplicitUsersForResourceByDomain return implicit user based on resource and domain.
`GetImplicitUsersForResourceByDomain()` returns implicit users based on resource and domain.

For example:

Expand Down
Loading