Skip to content
88 changes: 48 additions & 40 deletions permit/_sync_types.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ class SyncConditionSetRulesApi(BasePermitApi):
Args:
user_set_key: the key of the userset, if used only rules matching that userset will be
fetched.
permission_key: the key of the permission, formatted as <resource>:<action>.
permission_key: the key of the permission, formatted as `<resource>:<action>`.
if used, only rules granting that permission will be fetched.
resource_set_key: the key of the resourceset, if used only rules matching that
resourceset will be fetched.
Expand Down Expand Up @@ -546,7 +546,7 @@ class SyncGroupsApi(BasePermitApi):

Returns:
One page of groups, with the total count. Each group's ``group_instance_key`` is
its instance key alone, and ``id`` is its instance id.
its instance key alone, and ``id`` is its instance id.

Raises:
PermitApiError: If the API returns an error HTTP status code.
Expand All @@ -566,7 +566,7 @@ class SyncGroupsApi(BasePermitApi):

Returns:
The group. Its ``group_instance_key`` is its instance key alone, and ``id`` is
its instance id.
its instance id.

Raises:
PermitApiError: If the API returns an error HTTP status code, such as 404 when no
Expand Down Expand Up @@ -813,7 +813,7 @@ class SyncPdpsApi(BasePermitApi):

Returns:
The id of the data update that carries the refresh, and the ids of the PDP
configurations it was sent to.
configurations it was sent to.

Raises:
pydantic.v1.ValidationError: If ``reason`` is longer than 512 characters. Nothing
Expand Down Expand Up @@ -1689,9 +1689,9 @@ class SyncResourceInstancesApi(BasePermitApi):
this method raises as a ``PermitApiError`` that says so.

Args:
resource_instances: The resource instance identities to delete.
Each identity can be either `resource_type:instance_key` (like Repository:react) or the
resource instance uuid.
resource_instances: The resource instance identities to delete. Each identity can
be either `resource_type:instance_key` (like Repository:react) or the resource
instance uuid.

Returns:
the bulk delete report.
Expand All @@ -1716,7 +1716,7 @@ class SyncResourceRelationsApi(BasePermitApi):

Returns:
a PaginatedResultRelationRead holding the relations in ``.data`` and the
total number of relations on the resource in ``.total_count``.
total number of relations on the resource in ``.total_count``.

Raises:
PermitApiError: If the API returns an error HTTP status code.
Expand Down Expand Up @@ -2416,8 +2416,8 @@ class SyncRolesApi(BasePermitApi):

Args:
role_key: The key of the role.
permissions: An array of permission keys (<resourceKey:actionKey>) to be assigned to the
role.
permissions: An array of permission keys (`<resourceKey:actionKey>`) to be assigned
to the role.

Returns:
A RoleRead object representing the updated role.
Expand All @@ -2432,8 +2432,8 @@ class SyncRolesApi(BasePermitApi):

Args:
role_key: The key of the role.
permissions: An array of permission keys (<resourceKey:actionKey>) to be removed from
the role.
permissions: An array of permission keys (`<resourceKey:actionKey>`) to be removed
from the role.

Returns:
A RoleRead object representing the updated role.
Expand Down Expand Up @@ -3079,23 +3079,25 @@ class SyncEnforcer:
Defaults to None.

Returns:
AuthorizedUsersResult: Contains all the authorized users and the role assignments that
Contains all the authorized users and the role assignments that
granted the permission.

Raises:
PermitConnectionError: If an error occurs while sending the authorization request to the
PDP.

Examples:
```python
# all the users that can close any issue?
await permit.authorized_users('close', 'issue')
await permit.authorized_users("close", "issue")

# all the users that can close an issue who's id is 1234?
await permit.authorized_users('close', 'issue:1234')
await permit.authorized_users("close", "issue:1234")

# all the users that can close (any) issues belonging to the 't1' tenant?
# (in a multi tenant application)
await permit.authorized_users('close', {'type': 'issue', 'tenant': 't1'})
await permit.authorized_users("close", {"type": "issue", "tenant": "t1"})
```
"""
def bulk_check(self, checks: list[CheckQuery], context: Context | None = None) -> list[bool]:
"""Checks if a user is authorized to perform an action on a resource in a context.
Expand All @@ -3109,32 +3111,36 @@ class SyncEnforcer:
Defaults to None.

Returns:
list[bool]: A list of booleans indicating whether the user is authorized for each
A list of booleans indicating whether the user is authorized for each
resource.

Raises:
PermitConnectionError: If an error occurs while sending the authorization request to the
PDP.

Examples:
```python
# Bulk query of multiple check conventions
await permit.bulk_check([
{
"user": user,
"action": "close",
"resource": {type: "issue", key: "1234"},
},
{
"user": {key: "user"},
"action": "close",
"resource": "issue:1235",
},
{
"user": "user_a",
"action": "close",
"resource": "issue",
},
])
await permit.bulk_check(
[
{
"user": user,
"action": "close",
"resource": {"type": "issue", "key": "1234"},
},
{
"user": {"key": "user"},
"action": "close",
"resource": "issue:1235",
},
{
"user": "user_a",
"action": "close",
"resource": "issue",
},
]
)
```
"""
def check(
self, user: User, action: Action, resource: Resource, context: Context | None = None
Expand All @@ -3149,22 +3155,24 @@ class SyncEnforcer:
Defaults to None.

Returns:
bool: True if the user is authorized, False otherwise.
True if the user is authorized, False otherwise.

Raises:
PermitConnectionError: If an error occurs while sending the authorization request to the
PDP.

Examples:
```python
# can the user close any issue?
await permit.check(user, 'close', 'issue')
await permit.check(user, "close", "issue")

# can the user close any issue who's id is 1234?
await permit.check(user, 'close', 'issue:1234')
await permit.check(user, "close", "issue:1234")

# can the user close (any) issues belonging to the 't1' tenant?
# (in a multi tenant application)
await permit.check(user, 'close', {'type': 'issue', 'tenant': 't1'})
await permit.check(user, "close", {"type": "issue", "tenant": "t1"})
```
"""
def get_user_permissions(
self,
Expand Down Expand Up @@ -3212,7 +3220,7 @@ class SyncEnforcer:

Returns:
The user's tenants, each with its key and attributes. Empty when the user has no
tenant-level role or the PDP does not know the user.
tenant-level role or the PDP does not know the user.

Raises:
PermitConnectionError: If the PDP answers 404 (as the cloud PDP does), answers any
Expand All @@ -3231,7 +3239,7 @@ class SyncEnforcer:
key, which is sent as the resource context of that check.

Returns:
list[dict]: The subset of ``resources`` the user is authorized for, in input order.
The subset of ``resources`` the user is authorized for, in input order.
"""

class SyncPdpRoleAssignmentsApi(BasePdpPermitApi):
Expand Down
2 changes: 1 addition & 1 deletion permit/api/condition_set_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ async def list(
Args:
user_set_key: the key of the userset, if used only rules matching that userset will be
fetched.
permission_key: the key of the permission, formatted as <resource>:<action>.
permission_key: the key of the permission, formatted as `<resource>:<action>`.
if used, only rules granting that permission will be fetched.
resource_set_key: the key of the resourceset, if used only rules matching that
resourceset will be fetched.
Expand Down
4 changes: 3 additions & 1 deletion permit/api/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class ApiContext:
the full object hierarchy in every request.

For example, in order to list roles, the user need to specify the (id or key) of the:

- the org
- the project
- then environment
Expand All @@ -78,7 +79,8 @@ class ApiContext:
from that context.

We then get this kind of experience:
```

```python
await permit.api.roles.list()
```

Expand Down
16 changes: 10 additions & 6 deletions permit/api/encoders.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,19 @@ def decimal_encoder(dec_value: Decimal) -> int | float:
results in failed round-tripping between encode and parse.
Our Id type is a prime example of this.

>>> decimal_encoder(Decimal("1.0"))
1.0

>>> decimal_encoder(Decimal("1"))
1

Raises:
TypeError: If ``dec_value`` is NaN or infinite. JSON has no such values, so
encoding one would send the API an invalid request body.

Examples:
```pycon
>>> decimal_encoder(Decimal("1.0"))
1.0

>>> decimal_encoder(Decimal("1"))
1

```
"""
exponent = dec_value.as_tuple().exponent
if not isinstance(exponent, int):
Expand Down
4 changes: 2 additions & 2 deletions permit/api/groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ async def list(self, page: int = 1, per_page: int = 100) -> PaginatedResultGroup

Returns:
One page of groups, with the total count. Each group's ``group_instance_key`` is
its instance key alone, and ``id`` is its instance id.
its instance key alone, and ``id`` is its instance id.

Raises:
PermitApiError: If the API returns an error HTTP status code.
Expand Down Expand Up @@ -104,7 +104,7 @@ async def get(self, group_instance_key: str) -> GroupReadSchema:

Returns:
The group. Its ``group_instance_key`` is its instance key alone, and ``id`` is
its instance id.
its instance id.

Raises:
PermitApiError: If the API returns an error HTTP status code, such as 404 when no
Expand Down
2 changes: 1 addition & 1 deletion permit/api/pdps.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ async def refresh(self, reason: str | None = None) -> PDPDataRefreshResponse:

Returns:
The id of the data update that carries the refresh, and the ids of the PDP
configurations it was sent to.
configurations it was sent to.

Raises:
pydantic.v1.ValidationError: If ``reason`` is longer than 512 characters. Nothing
Expand Down
6 changes: 3 additions & 3 deletions permit/api/resource_instances.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,9 +392,9 @@ async def bulk_delete(
this method raises as a ``PermitApiError`` that says so.

Args:
resource_instances: The resource instance identities to delete.
Each identity can be either `resource_type:instance_key` (like Repository:react) or the
resource instance uuid.
resource_instances: The resource instance identities to delete. Each identity can
be either `resource_type:instance_key` (like Repository:react) or the resource
instance uuid.

Returns:
the bulk delete report.
Expand Down
2 changes: 1 addition & 1 deletion permit/api/resource_relations.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ async def list(

Returns:
a PaginatedResultRelationRead holding the relations in ``.data`` and the
total number of relations on the resource in ``.total_count``.
total number of relations on the resource in ``.total_count``.

Raises:
PermitApiError: If the API returns an error HTTP status code.
Expand Down
8 changes: 4 additions & 4 deletions permit/api/roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,8 @@ async def assign_permissions(self, role_key: str, permissions: builtins.list[str

Args:
role_key: The key of the role.
permissions: An array of permission keys (<resourceKey:actionKey>) to be assigned to the
role.
permissions: An array of permission keys (`<resourceKey:actionKey>`) to be assigned
to the role.

Returns:
A RoleRead object representing the updated role.
Expand All @@ -205,8 +205,8 @@ async def remove_permissions(self, role_key: str, permissions: builtins.list[str

Args:
role_key: The key of the role.
permissions: An array of permission keys (<resourceKey:actionKey>) to be removed from
the role.
permissions: An array of permission keys (`<resourceKey:actionKey>`) to be removed
from the role.

Returns:
A RoleRead object representing the updated role.
Expand Down
Loading
Loading