Skip to content

Commit 95b032e

Browse files
committed
add list, create, get, delete api in user+invite
1 parent 2e05510 commit 95b032e

File tree

4 files changed

+463
-10
lines changed

4 files changed

+463
-10
lines changed

permit/api/base.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,11 @@ def _prepare_json(self, json: Optional[Union[TData, dict, list]] = None) -> Opti
6262
if isinstance(json, list):
6363
return [self._prepare_json(item) for item in json]
6464

65-
return json.dict(exclude_unset=True, exclude_none=True)
65+
# Use json() method which properly handles UUID serialization
66+
# Then parse it back to dict to avoid double JSON encoding
67+
import json as json_module
68+
json_str = json.json(exclude_unset=True, exclude_none=True)
69+
return json_module.loads(json_str)
6670

6771
@handle_client_error
6872
async def get(self, url, model: Type[TModel], **kwargs) -> TModel:

permit/api/models.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@
99
from typing import Any, Dict, List, Literal, Optional, Union
1010
from uuid import UUID
1111

12-
from pydantic import AnyUrl, BaseModel, EmailStr, Extra, Field, conint, constr
12+
from ..utils.pydantic_version import PYDANTIC_VERSION
13+
14+
if PYDANTIC_VERSION < (2, 0):
15+
from pydantic import AnyUrl, BaseModel, EmailStr, Extra, Field, conint, constr
16+
else:
17+
from pydantic.v1 import AnyUrl, BaseModel, EmailStr, Extra, Field, conint, constr # type: ignore
1318

1419

1520
class APIHistoryEventFullRead(BaseModel):
@@ -3974,20 +3979,20 @@ class Config:
39743979
description='Date and time when the elements_user_invite was last updated/modified (ISO_8601 format).',
39753980
title='Updated At',
39763981
)
3977-
key: constr(regex=r'^[A-Za-z0-9|@+\-\._]+$') = Field(
3978-
..., description='The key of the user that is being invited', title='Key'
3982+
key: Optional[constr(regex=r'^[A-Za-z0-9|@+\-\._]+$')] = Field(
3983+
None, description='The key of the user that is being invited', title='Key'
39793984
)
39803985
status: UserInviteStatus = Field(..., description='The status of the user invite')
39813986
email: EmailStr = Field(
39823987
..., description='The email of the user that being invited', title='Email'
39833988
)
3984-
first_name: str = Field(
3985-
...,
3989+
first_name: Optional[str] = Field(
3990+
None,
39863991
description='The first name of the user that is being invited',
39873992
title='First Name',
39883993
)
3989-
last_name: str = Field(
3990-
...,
3994+
last_name: Optional[str] = Field(
3995+
None,
39913996
description='The last name of the user that is being invited',
39923997
title='Last Name',
39933998
)
@@ -3999,8 +4004,8 @@ class Config:
39994004
description='The tenant id of the user that is being invited',
40004005
title='Tenant Id',
40014006
)
4002-
resource_instance_id: UUID = Field(
4003-
...,
4007+
resource_instance_id: Optional[UUID] = Field(
4008+
None,
40044009
description='The resource instance id of the user that is being invited',
40054010
title='Resource Instance Id',
40064011
)

permit/api/user_invites.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@
88
from .base import (
99
BasePermitApi,
1010
SimpleHttpClient,
11+
pagination_params,
1112
)
1213
from .context import ApiContextLevel, ApiKeyAccessLevel
1314
from .models import (
1415
ElementsUserInviteApprove,
16+
ElementsUserInviteCreate,
17+
ElementsUserInviteRead,
18+
PaginatedResultElementsUserInviteRead,
1519
UserRead,
1620
)
1721

@@ -23,6 +27,87 @@ def __user_invites(self) -> SimpleHttpClient:
2327
f"/v2/facts/{self.config.api_context.project}/{self.config.api_context.environment}/user_invites"
2428
)
2529

30+
@validate_arguments # type: ignore[operator]
31+
async def list(self, page: int = 1, per_page: int = 100) -> PaginatedResultElementsUserInviteRead:
32+
"""
33+
Retrieves a list of user invites.
34+
35+
Args:
36+
page: The page number to retrieve (default: 1).
37+
per_page: The number of invites per page (default: 100).
38+
39+
Returns:
40+
A paginated list of user invites.
41+
42+
Raises:
43+
PermitApiError: If the API returns an error HTTP status code.
44+
PermitContextError: If the configured ApiContext does not match the required endpoint context.
45+
"""
46+
await self._ensure_access_level(ApiKeyAccessLevel.ENVIRONMENT_LEVEL_API_KEY)
47+
await self._ensure_context(ApiContextLevel.ENVIRONMENT)
48+
return await self.__user_invites.get(
49+
"",
50+
model=PaginatedResultElementsUserInviteRead,
51+
params=pagination_params(page, per_page),
52+
)
53+
54+
@validate_arguments # type: ignore[operator]
55+
async def get(self, user_invite_id: str) -> ElementsUserInviteRead:
56+
"""
57+
Retrieves a single user invite by ID.
58+
59+
Args:
60+
user_invite_id: The ID of the user invite to retrieve.
61+
62+
Returns:
63+
The user invite details.
64+
65+
Raises:
66+
PermitApiError: If the API returns an error HTTP status code.
67+
PermitContextError: If the configured ApiContext does not match the required endpoint context.
68+
"""
69+
await self._ensure_access_level(ApiKeyAccessLevel.ENVIRONMENT_LEVEL_API_KEY)
70+
await self._ensure_context(ApiContextLevel.ENVIRONMENT)
71+
return await self.__user_invites.get(f"/{user_invite_id}", model=ElementsUserInviteRead)
72+
73+
@validate_arguments # type: ignore[operator]
74+
async def create(self, user_invite_data: ElementsUserInviteCreate) -> ElementsUserInviteRead:
75+
"""
76+
Creates a new user invite.
77+
78+
Args:
79+
user_invite_data: The user invite data to create.
80+
81+
Returns:
82+
The created user invite.
83+
84+
Raises:
85+
PermitApiError: If the API returns an error HTTP status code.
86+
PermitContextError: If the configured ApiContext does not match the required endpoint context.
87+
"""
88+
await self._ensure_access_level(ApiKeyAccessLevel.ENVIRONMENT_LEVEL_API_KEY)
89+
await self._ensure_context(ApiContextLevel.ENVIRONMENT)
90+
return await self.__user_invites.post("", model=ElementsUserInviteRead, json=user_invite_data)
91+
92+
@validate_arguments # type: ignore[operator]
93+
async def delete(self, user_invite_id: str) -> None:
94+
"""
95+
Deletes a user invite.
96+
97+
Args:
98+
user_invite_id: The ID of the user invite to delete.
99+
100+
Returns:
101+
None
102+
103+
Raises:
104+
PermitApiError: If the API returns an error HTTP status code.
105+
PermitContextError: If the configured ApiContext does not match the required endpoint context.
106+
"""
107+
await self._ensure_access_level(ApiKeyAccessLevel.ENVIRONMENT_LEVEL_API_KEY)
108+
await self._ensure_context(ApiContextLevel.ENVIRONMENT)
109+
await self.__user_invites.delete(f"/{user_invite_id}")
110+
26111
@validate_arguments # type: ignore[operator]
27112
async def approve(self, user_invite_id: str, approve_data: ElementsUserInviteApprove) -> UserRead:
28113
"""

0 commit comments

Comments
 (0)