|
1 | | -from typing import Any, Dict, Optional, Protocol, Sequence |
| 1 | +from enum import Enum |
| 2 | +from typing import Any, Dict, Optional, Protocol, Sequence, Union |
2 | 3 |
|
3 | 4 | from pydantic import TypeAdapter |
| 5 | +from typing_extensions import TypedDict |
4 | 6 |
|
5 | 7 | from workos.types.authorization.environment_role import ( |
6 | 8 | EnvironmentRole, |
7 | 9 | EnvironmentRoleList, |
8 | 10 | ) |
9 | 11 | from workos.types.authorization.organization_role import OrganizationRole |
10 | 12 | from workos.types.authorization.permission import Permission |
| 13 | +from workos.types.authorization.resource import Resource |
11 | 14 | from workos.types.authorization.role import Role, RoleList |
12 | 15 | from workos.types.list_resource import ( |
13 | 16 | ListArgs, |
|
27 | 30 | REQUEST_METHOD_PUT, |
28 | 31 | ) |
29 | 32 |
|
| 33 | + |
| 34 | +class _Unset(Enum): |
| 35 | + TOKEN = 0 |
| 36 | + |
| 37 | + |
| 38 | +UNSET: _Unset = _Unset.TOKEN |
| 39 | + |
30 | 40 | AUTHORIZATION_PERMISSIONS_PATH = "authorization/permissions" |
31 | 41 | AUTHORIZATION_RESOURCES_PATH = "authorization/resources" |
32 | 42 |
|
| 43 | + |
| 44 | +class ParentResourceById(TypedDict): |
| 45 | + parent_resource_id: str |
| 46 | + |
| 47 | + |
| 48 | +class ParentResourceByExternalId(TypedDict): |
| 49 | + parent_resource_external_id: str |
| 50 | + parent_resource_type_slug: str |
| 51 | + |
| 52 | + |
| 53 | +ParentResource = Union[ParentResourceById, ParentResourceByExternalId] |
| 54 | + |
33 | 55 | _role_adapter: TypeAdapter[Role] = TypeAdapter(Role) |
34 | 56 |
|
35 | 57 |
|
@@ -162,6 +184,36 @@ def add_environment_role_permission( |
162 | 184 | permission_slug: str, |
163 | 185 | ) -> SyncOrAsync[EnvironmentRole]: ... |
164 | 186 |
|
| 187 | + # Resources |
| 188 | + |
| 189 | + def get_resource(self, resource_id: str) -> SyncOrAsync[Resource]: ... |
| 190 | + |
| 191 | + def create_resource( |
| 192 | + self, |
| 193 | + *, |
| 194 | + resource_type_slug: str, |
| 195 | + organization_id: str, |
| 196 | + external_id: str, |
| 197 | + name: str, |
| 198 | + parent: Optional[ParentResource] = None, |
| 199 | + description: Optional[str] = None, |
| 200 | + ) -> SyncOrAsync[Resource]: ... |
| 201 | + |
| 202 | + def update_resource( |
| 203 | + self, |
| 204 | + resource_id: str, |
| 205 | + *, |
| 206 | + name: Optional[str] = None, |
| 207 | + description: Union[str, None, _Unset] = UNSET, |
| 208 | + ) -> SyncOrAsync[Resource]: ... |
| 209 | + |
| 210 | + def delete_resource( |
| 211 | + self, |
| 212 | + resource_id: str, |
| 213 | + *, |
| 214 | + cascade_delete: Optional[bool] = None, |
| 215 | + ) -> SyncOrAsync[None]: ... |
| 216 | + |
165 | 217 |
|
166 | 218 | class Authorization(AuthorizationModule): |
167 | 219 | _http_client: SyncHTTPClient |
@@ -438,6 +490,84 @@ def add_environment_role_permission( |
438 | 490 |
|
439 | 491 | return EnvironmentRole.model_validate(response) |
440 | 492 |
|
| 493 | + # Resources |
| 494 | + |
| 495 | + def get_resource(self, resource_id: str) -> Resource: |
| 496 | + response = self._http_client.request( |
| 497 | + f"{AUTHORIZATION_RESOURCES_PATH}/{resource_id}", |
| 498 | + method=REQUEST_METHOD_GET, |
| 499 | + ) |
| 500 | + |
| 501 | + return Resource.model_validate(response) |
| 502 | + |
| 503 | + def create_resource( |
| 504 | + self, |
| 505 | + *, |
| 506 | + resource_type_slug: str, |
| 507 | + organization_id: str, |
| 508 | + external_id: str, |
| 509 | + name: str, |
| 510 | + parent: Optional[ParentResource] = None, |
| 511 | + description: Optional[str] = None, |
| 512 | + ) -> Resource: |
| 513 | + json: Dict[str, Any] = { |
| 514 | + "resource_type_slug": resource_type_slug, |
| 515 | + "organization_id": organization_id, |
| 516 | + "external_id": external_id, |
| 517 | + "name": name, |
| 518 | + } |
| 519 | + if parent is not None: |
| 520 | + json.update(parent) |
| 521 | + if description is not None: |
| 522 | + json["description"] = description |
| 523 | + |
| 524 | + response = self._http_client.request( |
| 525 | + AUTHORIZATION_RESOURCES_PATH, |
| 526 | + method=REQUEST_METHOD_POST, |
| 527 | + json=json, |
| 528 | + ) |
| 529 | + |
| 530 | + return Resource.model_validate(response) |
| 531 | + |
| 532 | + def update_resource( |
| 533 | + self, |
| 534 | + resource_id: str, |
| 535 | + *, |
| 536 | + name: Optional[str] = None, |
| 537 | + description: Union[str, None, _Unset] = UNSET, |
| 538 | + ) -> Resource: |
| 539 | + json: Dict[str, Any] = {} |
| 540 | + if name is not None: |
| 541 | + json["name"] = name |
| 542 | + if not isinstance(description, _Unset): |
| 543 | + json["description"] = description |
| 544 | + |
| 545 | + response = self._http_client.request( |
| 546 | + f"{AUTHORIZATION_RESOURCES_PATH}/{resource_id}", |
| 547 | + method=REQUEST_METHOD_PATCH, |
| 548 | + json=json, |
| 549 | + exclude_none=False, |
| 550 | + ) |
| 551 | + |
| 552 | + return Resource.model_validate(response) |
| 553 | + |
| 554 | + def delete_resource( |
| 555 | + self, |
| 556 | + resource_id: str, |
| 557 | + *, |
| 558 | + cascade_delete: Optional[bool] = None, |
| 559 | + ) -> None: |
| 560 | + if cascade_delete is not None: |
| 561 | + self._http_client.delete_with_body( |
| 562 | + f"{AUTHORIZATION_RESOURCES_PATH}/{resource_id}", |
| 563 | + json={"cascade_delete": cascade_delete}, |
| 564 | + ) |
| 565 | + else: |
| 566 | + self._http_client.request( |
| 567 | + f"{AUTHORIZATION_RESOURCES_PATH}/{resource_id}", |
| 568 | + method=REQUEST_METHOD_DELETE, |
| 569 | + ) |
| 570 | + |
441 | 571 |
|
442 | 572 | class AsyncAuthorization(AuthorizationModule): |
443 | 573 | _http_client: AsyncHTTPClient |
@@ -713,3 +843,81 @@ async def add_environment_role_permission( |
713 | 843 | ) |
714 | 844 |
|
715 | 845 | return EnvironmentRole.model_validate(response) |
| 846 | + |
| 847 | + # Resources |
| 848 | + |
| 849 | + async def get_resource(self, resource_id: str) -> Resource: |
| 850 | + response = await self._http_client.request( |
| 851 | + f"{AUTHORIZATION_RESOURCES_PATH}/{resource_id}", |
| 852 | + method=REQUEST_METHOD_GET, |
| 853 | + ) |
| 854 | + |
| 855 | + return Resource.model_validate(response) |
| 856 | + |
| 857 | + async def create_resource( |
| 858 | + self, |
| 859 | + *, |
| 860 | + resource_type_slug: str, |
| 861 | + organization_id: str, |
| 862 | + external_id: str, |
| 863 | + name: str, |
| 864 | + parent: Optional[ParentResource] = None, |
| 865 | + description: Optional[str] = None, |
| 866 | + ) -> Resource: |
| 867 | + json: Dict[str, Any] = { |
| 868 | + "resource_type_slug": resource_type_slug, |
| 869 | + "organization_id": organization_id, |
| 870 | + "external_id": external_id, |
| 871 | + "name": name, |
| 872 | + } |
| 873 | + if parent is not None: |
| 874 | + json.update(parent) |
| 875 | + if description is not None: |
| 876 | + json["description"] = description |
| 877 | + |
| 878 | + response = await self._http_client.request( |
| 879 | + AUTHORIZATION_RESOURCES_PATH, |
| 880 | + method=REQUEST_METHOD_POST, |
| 881 | + json=json, |
| 882 | + ) |
| 883 | + |
| 884 | + return Resource.model_validate(response) |
| 885 | + |
| 886 | + async def update_resource( |
| 887 | + self, |
| 888 | + resource_id: str, |
| 889 | + *, |
| 890 | + name: Optional[str] = None, |
| 891 | + description: Union[str, None, _Unset] = UNSET, |
| 892 | + ) -> Resource: |
| 893 | + json: Dict[str, Any] = {} |
| 894 | + if name is not None: |
| 895 | + json["name"] = name |
| 896 | + if not isinstance(description, _Unset): |
| 897 | + json["description"] = description |
| 898 | + |
| 899 | + response = await self._http_client.request( |
| 900 | + f"{AUTHORIZATION_RESOURCES_PATH}/{resource_id}", |
| 901 | + method=REQUEST_METHOD_PATCH, |
| 902 | + json=json, |
| 903 | + exclude_none=False, |
| 904 | + ) |
| 905 | + |
| 906 | + return Resource.model_validate(response) |
| 907 | + |
| 908 | + async def delete_resource( |
| 909 | + self, |
| 910 | + resource_id: str, |
| 911 | + *, |
| 912 | + cascade_delete: Optional[bool] = None, |
| 913 | + ) -> None: |
| 914 | + if cascade_delete is not None: |
| 915 | + await self._http_client.delete_with_body( |
| 916 | + f"{AUTHORIZATION_RESOURCES_PATH}/{resource_id}", |
| 917 | + json={"cascade_delete": cascade_delete}, |
| 918 | + ) |
| 919 | + else: |
| 920 | + await self._http_client.request( |
| 921 | + f"{AUTHORIZATION_RESOURCES_PATH}/{resource_id}", |
| 922 | + method=REQUEST_METHOD_DELETE, |
| 923 | + ) |
0 commit comments