Skip to content

Commit ed27e87

Browse files
fga-p2
1 parent a5d3ce2 commit ed27e87

File tree

4 files changed

+498
-33
lines changed

4 files changed

+498
-33
lines changed

src/workos/authorization.py

Lines changed: 223 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Dict, Optional, Protocol, Sequence, Union
1+
from typing import Any, Dict, Mapping, Optional, Protocol, Sequence, Union
22

33
from pydantic import TypeAdapter
44
from typing_extensions import TypedDict
@@ -11,6 +11,7 @@
1111
from workos.types.authorization.permission import Permission
1212
from workos.types.authorization.resource import Resource
1313
from workos.types.authorization.role import Role, RoleList
14+
from workos.types.fga import AuthorizationResource
1415
from workos.types.list_resource import (
1516
ListArgs,
1617
ListMetadata,
@@ -56,6 +57,15 @@ class PermissionListFilters(ListArgs, total=False):
5657
]
5758

5859

60+
class ResourceByExternalIdListFilters(ListArgs, total=False):
61+
resource_type_slug: Optional[str]
62+
63+
64+
ResourceByExternalIdListResource = WorkOSListResource[
65+
AuthorizationResource, ResourceByExternalIdListFilters, ListMetadata
66+
]
67+
68+
5969
class AuthorizationModule(Protocol):
6070
"""Offers methods through the WorkOS Authorization service."""
6171

@@ -206,6 +216,44 @@ def delete_resource(
206216
cascade_delete: Optional[bool] = None,
207217
) -> SyncOrAsync[None]: ...
208218

219+
# Resources by External ID
220+
221+
def get_resource_by_external_id(
222+
self,
223+
organization_id: str,
224+
resource_type: str,
225+
external_id: str,
226+
) -> SyncOrAsync[AuthorizationResource]: ...
227+
228+
def update_resource_by_external_id(
229+
self,
230+
organization_id: str,
231+
resource_type: str,
232+
external_id: str,
233+
*,
234+
meta: Optional[Mapping[str, Any]] = None,
235+
) -> SyncOrAsync[AuthorizationResource]: ...
236+
237+
def delete_resource_by_external_id(
238+
self,
239+
organization_id: str,
240+
resource_type: str,
241+
external_id: str,
242+
*,
243+
cascade_delete: Optional[bool] = None,
244+
) -> SyncOrAsync[None]: ...
245+
246+
def list_resources(
247+
self,
248+
organization_id: str,
249+
*,
250+
resource_type_slug: Optional[str] = None,
251+
limit: int = DEFAULT_LIST_RESPONSE_LIMIT,
252+
before: Optional[str] = None,
253+
after: Optional[str] = None,
254+
order: PaginationOrder = "desc",
255+
) -> SyncOrAsync[ResourceByExternalIdListResource]: ...
256+
209257

210258
class Authorization(AuthorizationModule):
211259
_http_client: SyncHTTPClient
@@ -522,8 +570,8 @@ def create_resource(
522570

523571
def update_resource(
524572
self,
525-
*,
526573
resource_id: str,
574+
*,
527575
name: Optional[str] = None,
528576
description: Optional[str] = None,
529577
) -> Resource:
@@ -543,8 +591,8 @@ def update_resource(
543591

544592
def delete_resource(
545593
self,
546-
*,
547594
resource_id: str,
595+
*,
548596
cascade_delete: Optional[bool] = None,
549597
) -> None:
550598
if cascade_delete is not None:
@@ -558,6 +606,92 @@ def delete_resource(
558606
method=REQUEST_METHOD_DELETE,
559607
)
560608

609+
# Resources by External ID
610+
611+
def get_resource_by_external_id(
612+
self,
613+
organization_id: str,
614+
resource_type: str,
615+
external_id: str,
616+
) -> AuthorizationResource:
617+
response = self._http_client.request(
618+
f"authorization/organizations/{organization_id}/resources/{resource_type}/{external_id}",
619+
method=REQUEST_METHOD_GET,
620+
)
621+
622+
return AuthorizationResource.model_validate(response)
623+
624+
def update_resource_by_external_id(
625+
self,
626+
organization_id: str,
627+
resource_type: str,
628+
external_id: str,
629+
*,
630+
meta: Optional[Mapping[str, Any]] = None,
631+
) -> AuthorizationResource:
632+
json: Dict[str, Any] = {}
633+
if meta is not None:
634+
json["meta"] = meta
635+
636+
response = self._http_client.request(
637+
f"authorization/organizations/{organization_id}/resources/{resource_type}/{external_id}",
638+
method=REQUEST_METHOD_PATCH,
639+
json=json,
640+
)
641+
642+
return AuthorizationResource.model_validate(response)
643+
644+
def delete_resource_by_external_id(
645+
self,
646+
organization_id: str,
647+
resource_type: str,
648+
external_id: str,
649+
*,
650+
cascade_delete: Optional[bool] = None,
651+
) -> None:
652+
path = f"authorization/organizations/{organization_id}/resources/{resource_type}/{external_id}"
653+
if cascade_delete is not None:
654+
self._http_client.delete_with_body(
655+
path,
656+
json={"cascade_delete": cascade_delete},
657+
)
658+
else:
659+
self._http_client.request(
660+
path,
661+
method=REQUEST_METHOD_DELETE,
662+
)
663+
664+
def list_resources(
665+
self,
666+
organization_id: str,
667+
*,
668+
resource_type_slug: Optional[str] = None,
669+
limit: int = DEFAULT_LIST_RESPONSE_LIMIT,
670+
before: Optional[str] = None,
671+
after: Optional[str] = None,
672+
order: PaginationOrder = "desc",
673+
) -> ResourceByExternalIdListResource:
674+
list_params: ResourceByExternalIdListFilters = {
675+
"limit": limit,
676+
"before": before,
677+
"after": after,
678+
"order": order,
679+
}
680+
if resource_type_slug is not None:
681+
list_params["resource_type_slug"] = resource_type_slug
682+
683+
response = self._http_client.request(
684+
f"authorization/organizations/{organization_id}/resources",
685+
method=REQUEST_METHOD_GET,
686+
params=list_params,
687+
)
688+
689+
return ResourceByExternalIdListResource(
690+
list_method=self.list_resources,
691+
list_args=list_params,
692+
**ListPage[AuthorizationResource](**response).model_dump(),
693+
)
694+
561695

562696
class AsyncAuthorization(AuthorizationModule):
563697
_http_client: AsyncHTTPClient
@@ -909,3 +1043,89 @@ async def delete_resource(
9091043
f"{AUTHORIZATION_RESOURCES_PATH}/{resource_id}",
9101044
method=REQUEST_METHOD_DELETE,
9111045
)
1046+
1047+
# Resources by External ID
1048+
1049+
async def get_resource_by_external_id(
1050+
self,
1051+
organization_id: str,
1052+
resource_type: str,
1053+
external_id: str,
1054+
) -> AuthorizationResource:
1055+
response = await self._http_client.request(
1056+
f"authorization/organizations/{organization_id}/resources/{resource_type}/{external_id}",
1057+
method=REQUEST_METHOD_GET,
1058+
)
1059+
1060+
return AuthorizationResource.model_validate(response)
1061+
1062+
async def update_resource_by_external_id(
1063+
self,
1064+
organization_id: str,
1065+
resource_type: str,
1066+
external_id: str,
1067+
*,
1068+
meta: Optional[Mapping[str, Any]] = None,
1069+
) -> AuthorizationResource:
1070+
json: Dict[str, Any] = {}
1071+
if meta is not None:
1072+
json["meta"] = meta
1073+
1074+
response = await self._http_client.request(
1075+
f"authorization/organizations/{organization_id}/resources/{resource_type}/{external_id}",
1076+
method=REQUEST_METHOD_PATCH,
1077+
json=json,
1078+
)
1079+
1080+
return AuthorizationResource.model_validate(response)
1081+
1082+
async def delete_resource_by_external_id(
1083+
self,
1084+
organization_id: str,
1085+
resource_type: str,
1086+
external_id: str,
1087+
*,
1088+
cascade_delete: Optional[bool] = None,
1089+
) -> None:
1090+
path = f"authorization/organizations/{organization_id}/resources/{resource_type}/{external_id}"
1091+
if cascade_delete is not None:
1092+
await self._http_client.delete_with_body(
1093+
path,
1094+
json={"cascade_delete": cascade_delete},
1095+
)
1096+
else:
1097+
await self._http_client.request(
1098+
path,
1099+
method=REQUEST_METHOD_DELETE,
1100+
)
1101+
1102+
async def list_resources(
1103+
self,
1104+
organization_id: str,
1105+
*,
1106+
resource_type_slug: Optional[str] = None,
1107+
limit: int = DEFAULT_LIST_RESPONSE_LIMIT,
1108+
before: Optional[str] = None,
1109+
after: Optional[str] = None,
1110+
order: PaginationOrder = "desc",
1111+
) -> ResourceByExternalIdListResource:
1112+
list_params: ResourceByExternalIdListFilters = {
1113+
"limit": limit,
1114+
"before": before,
1115+
"after": after,
1116+
"order": order,
1117+
}
1118+
if resource_type_slug is not None:
1119+
list_params["resource_type_slug"] = resource_type_slug
1120+
1121+
response = await self._http_client.request(
1122+
f"authorization/organizations/{organization_id}/resources",
1123+
method=REQUEST_METHOD_GET,
1124+
params=list_params,
1125+
)
1126+
1127+
return ResourceByExternalIdListResource(
1128+
list_method=self.list_resources,
1129+
list_args=list_params,
1130+
**ListPage[AuthorizationResource](**response).model_dump(),
1131+
)

src/workos/types/authorization/resource.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Literal, Mapping, Optional
1+
from typing import Literal, Optional
22

33
from workos.types.workos_model import WorkOSModel
44

0 commit comments

Comments
 (0)