workos 1.13.0__py3-none-any.whl → 5.38.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- workos/__about__.py +1 -1
- workos/__init__.py +3 -7
- workos/_base_client.py +138 -0
- workos/_client_configuration.py +10 -0
- workos/api_keys.py +53 -0
- workos/async_client.py +144 -0
- workos/audit_logs.py +125 -0
- workos/client.py +105 -20
- workos/directory_sync.py +369 -146
- workos/events.py +111 -0
- workos/exceptions.py +53 -26
- workos/fga.py +649 -0
- workos/mfa.py +152 -116
- workos/organization_domains.py +179 -0
- workos/organizations.py +401 -86
- workos/passwordless.py +67 -43
- workos/pipes.py +93 -0
- workos/portal.py +51 -28
- workos/session.py +337 -0
- workos/sso.py +305 -149
- workos/types/__init__.py +4 -0
- workos/types/api_keys/__init__.py +1 -0
- workos/types/api_keys/api_keys.py +20 -0
- workos/types/audit_logs/__init__.py +6 -0
- workos/types/audit_logs/audit_log_event.py +16 -0
- workos/types/audit_logs/audit_log_event_actor.py +12 -0
- workos/types/audit_logs/audit_log_event_context.py +8 -0
- workos/types/audit_logs/audit_log_event_target.py +12 -0
- workos/types/audit_logs/audit_log_export.py +18 -0
- workos/types/audit_logs/audit_log_metadata.py +4 -0
- workos/types/directory_sync/__init__.py +5 -0
- workos/types/directory_sync/directory.py +31 -0
- workos/types/directory_sync/directory_group.py +16 -0
- workos/types/directory_sync/directory_state.py +28 -0
- workos/types/directory_sync/directory_type.py +24 -0
- workos/types/directory_sync/directory_user.py +50 -0
- workos/types/directory_sync/list_filters.py +21 -0
- workos/types/events/__init__.py +13 -0
- workos/types/events/authentication_payload.py +70 -0
- workos/types/events/connection_payload_with_legacy_fields.py +5 -0
- workos/types/events/directory_group_membership_payload.py +9 -0
- workos/types/events/directory_group_with_previous_attributes.py +6 -0
- workos/types/events/directory_payload.py +16 -0
- workos/types/events/directory_payload_with_legacy_fields.py +29 -0
- workos/types/events/directory_user_with_previous_attributes.py +6 -0
- workos/types/events/event.py +324 -0
- workos/types/events/event_model.py +103 -0
- workos/types/events/event_type.py +59 -0
- workos/types/events/list_filters.py +10 -0
- workos/types/events/organization_domain_verification_failed_payload.py +14 -0
- workos/types/events/previous_attributes.py +3 -0
- workos/types/events/session_payload.py +27 -0
- workos/types/feature_flags/__init__.py +3 -0
- workos/types/feature_flags/feature_flag.py +12 -0
- workos/types/feature_flags/list_filters.py +5 -0
- workos/types/fga/__init__.py +5 -0
- workos/types/fga/authorization_resource_types.py +9 -0
- workos/types/fga/authorization_resources.py +10 -0
- workos/types/fga/check.py +51 -0
- workos/types/fga/list_filters.py +24 -0
- workos/types/fga/warnings.py +33 -0
- workos/types/fga/warrant.py +49 -0
- workos/types/list_resource.py +198 -0
- workos/types/metadata.py +4 -0
- workos/types/mfa/__init__.py +5 -0
- workos/types/mfa/authentication_challenge.py +14 -0
- workos/types/mfa/authentication_challenge_verification_response.py +9 -0
- workos/types/mfa/authentication_factor.py +70 -0
- workos/types/mfa/authentication_factor_totp_and_challenge_response.py +10 -0
- workos/types/mfa/enroll_authentication_factor_type.py +8 -0
- workos/types/organization_domains/__init__.py +1 -0
- workos/types/organization_domains/organization_domain.py +18 -0
- workos/types/organizations/__init__.py +6 -0
- workos/types/organizations/domain_data_input.py +7 -0
- workos/types/organizations/list_filters.py +6 -0
- workos/types/organizations/organization.py +13 -0
- workos/types/organizations/organization_common.py +12 -0
- workos/types/passwordless/__init__.py +2 -0
- workos/types/passwordless/passwordless_session.py +12 -0
- workos/types/passwordless/passwordless_session_type.py +3 -0
- workos/types/pipes/__init__.py +6 -0
- workos/types/pipes/pipes.py +34 -0
- workos/types/portal/__init__.py +2 -0
- workos/types/portal/portal_link.py +7 -0
- workos/types/portal/portal_link_intent.py +11 -0
- workos/types/portal/portal_link_intent_options.py +9 -0
- workos/types/roles/__init__.py +0 -0
- workos/types/roles/role.py +27 -0
- workos/types/sso/__init__.py +4 -0
- workos/types/sso/connection.py +70 -0
- workos/types/sso/connection_domain.py +8 -0
- workos/types/sso/profile.py +35 -0
- workos/types/sso/sso_provider_type.py +10 -0
- workos/types/user_management/__init__.py +12 -0
- workos/types/user_management/authenticate_with_common.py +66 -0
- workos/types/user_management/authentication_response.py +53 -0
- workos/types/user_management/email_verification.py +18 -0
- workos/types/user_management/impersonator.py +8 -0
- workos/types/user_management/invitation.py +26 -0
- workos/types/user_management/list_filters.py +29 -0
- workos/types/user_management/magic_auth.py +18 -0
- workos/types/user_management/oauth_tokens.py +21 -0
- workos/types/user_management/organization_membership.py +25 -0
- workos/types/user_management/password_hash_type.py +4 -0
- workos/types/user_management/password_reset.py +18 -0
- workos/types/user_management/screen_hint.py +3 -0
- workos/types/user_management/session.py +79 -0
- workos/types/user_management/user.py +22 -0
- workos/types/user_management/user_management_provider_type.py +11 -0
- workos/types/vault/__init__.py +2 -0
- workos/types/vault/key.py +25 -0
- workos/types/vault/object.py +38 -0
- workos/types/webhooks/__init__.py +0 -0
- workos/types/webhooks/webhook.py +330 -0
- workos/types/webhooks/webhook_model.py +14 -0
- workos/types/webhooks/webhook_payload.py +4 -0
- workos/types/widgets/__init__.py +2 -0
- workos/types/widgets/widget_scope.py +4 -0
- workos/types/widgets/widget_token_response.py +7 -0
- workos/types/workos_model.py +26 -0
- workos/typing/__init__.py +1 -0
- workos/typing/literals.py +32 -0
- workos/typing/sync_or_async.py +5 -0
- workos/typing/untyped_literal.py +37 -0
- workos/typing/webhooks.py +18 -0
- workos/user_management.py +2400 -0
- workos/utils/_base_http_client.py +252 -0
- workos/utils/crypto_provider.py +39 -0
- workos/utils/http_client.py +214 -0
- workos/utils/pagination_order.py +4 -0
- workos/utils/request_helper.py +27 -0
- workos/vault.py +544 -0
- workos/webhooks.py +96 -39
- workos/widgets.py +55 -0
- {workos-1.13.0.dist-info → workos-5.38.0.dist-info}/LICENSE +1 -1
- {workos-1.13.0.dist-info → workos-5.38.0.dist-info}/METADATA +47 -22
- workos-5.38.0.dist-info/RECORD +141 -0
- {workos-1.13.0.dist-info → workos-5.38.0.dist-info}/WHEEL +1 -1
- workos/audit_trail.py +0 -179
- workos/resources/base.py +0 -36
- workos/resources/directory_sync.py +0 -28
- workos/resources/event.py +0 -42
- workos/resources/event_action.py +0 -11
- workos/resources/mfa.py +0 -32
- workos/resources/sso.py +0 -53
- workos/utils/connection_types.py +0 -35
- workos/utils/pagiantion_order.py +0 -6
- workos/utils/request.py +0 -100
- workos/utils/validation.py +0 -60
- workos-1.13.0.dist-info/RECORD +0 -29
- /workos/{resources/__init__.py → py.typed} +0 -0
- {workos-1.13.0.dist-info → workos-5.38.0.dist-info}/top_level.txt +0 -0
workos/__about__.py
CHANGED
workos/__init__.py
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
from workos.client import SyncClient as WorkOSClient
|
|
2
|
+
from workos.async_client import AsyncClient as AsyncWorkOSClient
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
from workos.client import client
|
|
5
|
-
|
|
6
|
-
api_key = os.getenv("WORKOS_API_KEY")
|
|
7
|
-
client_id = os.getenv("WORKOS_CLIENT_ID")
|
|
8
|
-
base_api_url = "https://api.workos.com/"
|
|
4
|
+
__all__ = ["WorkOSClient", "AsyncWorkOSClient"]
|
workos/_base_client.py
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from abc import abstractmethod
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from workos._client_configuration import ClientConfiguration
|
|
6
|
+
from workos.api_keys import ApiKeysModule
|
|
7
|
+
from workos.audit_logs import AuditLogsModule
|
|
8
|
+
from workos.directory_sync import DirectorySyncModule
|
|
9
|
+
from workos.events import EventsModule
|
|
10
|
+
from workos.fga import FGAModule
|
|
11
|
+
from workos.mfa import MFAModule
|
|
12
|
+
from workos.organization_domains import OrganizationDomainsModule
|
|
13
|
+
from workos.pipes import PipesModule
|
|
14
|
+
from workos.organizations import OrganizationsModule
|
|
15
|
+
from workos.passwordless import PasswordlessModule
|
|
16
|
+
from workos.portal import PortalModule
|
|
17
|
+
from workos.sso import SSOModule
|
|
18
|
+
from workos.user_management import UserManagementModule
|
|
19
|
+
from workos.utils._base_http_client import DEFAULT_REQUEST_TIMEOUT
|
|
20
|
+
from workos.webhooks import WebhooksModule
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class BaseClient(ClientConfiguration):
|
|
24
|
+
"""Base client for accessing the WorkOS feature set."""
|
|
25
|
+
|
|
26
|
+
_api_key: str
|
|
27
|
+
_base_url: str
|
|
28
|
+
_client_id: str
|
|
29
|
+
_request_timeout: int
|
|
30
|
+
|
|
31
|
+
def __init__(
|
|
32
|
+
self,
|
|
33
|
+
*,
|
|
34
|
+
api_key: Optional[str],
|
|
35
|
+
client_id: Optional[str],
|
|
36
|
+
base_url: Optional[str] = None,
|
|
37
|
+
request_timeout: Optional[int] = None,
|
|
38
|
+
) -> None:
|
|
39
|
+
api_key = api_key or os.getenv("WORKOS_API_KEY")
|
|
40
|
+
if api_key is None:
|
|
41
|
+
raise ValueError(
|
|
42
|
+
"WorkOS API key must be provided when instantiating the client or via the WORKOS_API_KEY environment variable."
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
self._api_key = api_key
|
|
46
|
+
|
|
47
|
+
client_id = client_id or os.getenv("WORKOS_CLIENT_ID")
|
|
48
|
+
if client_id is None:
|
|
49
|
+
raise ValueError(
|
|
50
|
+
"WorkOS client ID must be provided when instantiating the client or via the WORKOS_CLIENT_ID environment variable."
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
self._client_id = client_id
|
|
54
|
+
|
|
55
|
+
self._base_url = self._enforce_trailing_slash(
|
|
56
|
+
url=(
|
|
57
|
+
base_url
|
|
58
|
+
if base_url
|
|
59
|
+
else os.getenv("WORKOS_BASE_URL", "https://api.workos.com/")
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
self._request_timeout = (
|
|
64
|
+
request_timeout
|
|
65
|
+
if request_timeout
|
|
66
|
+
else int(os.getenv("WORKOS_REQUEST_TIMEOUT", DEFAULT_REQUEST_TIMEOUT))
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
@abstractmethod
|
|
71
|
+
def api_keys(self) -> ApiKeysModule: ...
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
@abstractmethod
|
|
75
|
+
def audit_logs(self) -> AuditLogsModule: ...
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
@abstractmethod
|
|
79
|
+
def directory_sync(self) -> DirectorySyncModule: ...
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
@abstractmethod
|
|
83
|
+
def events(self) -> EventsModule: ...
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
@abstractmethod
|
|
87
|
+
def fga(self) -> FGAModule: ...
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
@abstractmethod
|
|
91
|
+
def mfa(self) -> MFAModule: ...
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
@abstractmethod
|
|
95
|
+
def organizations(self) -> OrganizationsModule: ...
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
@abstractmethod
|
|
99
|
+
def organization_domains(self) -> OrganizationDomainsModule: ...
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
@abstractmethod
|
|
103
|
+
def passwordless(self) -> PasswordlessModule: ...
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
@abstractmethod
|
|
107
|
+
def pipes(self) -> PipesModule: ...
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
@abstractmethod
|
|
111
|
+
def portal(self) -> PortalModule: ...
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
@abstractmethod
|
|
115
|
+
def sso(self) -> SSOModule: ...
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
@abstractmethod
|
|
119
|
+
def user_management(self) -> UserManagementModule: ...
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
@abstractmethod
|
|
123
|
+
def webhooks(self) -> WebhooksModule: ...
|
|
124
|
+
|
|
125
|
+
def _enforce_trailing_slash(self, url: str) -> str:
|
|
126
|
+
return url if url.endswith("/") else url + "/"
|
|
127
|
+
|
|
128
|
+
@property
|
|
129
|
+
def base_url(self) -> str:
|
|
130
|
+
return self._base_url
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def client_id(self) -> str:
|
|
134
|
+
return self._client_id
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def request_timeout(self) -> int:
|
|
138
|
+
return self._request_timeout
|
workos/api_keys.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from typing import Optional, Protocol
|
|
2
|
+
|
|
3
|
+
from workos.types.api_keys import ApiKey
|
|
4
|
+
from workos.typing.sync_or_async import SyncOrAsync
|
|
5
|
+
from workos.utils.http_client import AsyncHTTPClient, SyncHTTPClient
|
|
6
|
+
from workos.utils.request_helper import REQUEST_METHOD_POST
|
|
7
|
+
|
|
8
|
+
API_KEY_VALIDATION_PATH = "api_keys/validations"
|
|
9
|
+
RESOURCE_OBJECT_ATTRIBUTE_NAME = "api_key"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ApiKeysModule(Protocol):
|
|
13
|
+
def validate_api_key(self, *, value: str) -> SyncOrAsync[Optional[ApiKey]]:
|
|
14
|
+
"""Validate an API key.
|
|
15
|
+
|
|
16
|
+
Kwargs:
|
|
17
|
+
value (str): API key value
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
Optional[ApiKey]: Returns ApiKey resource object
|
|
21
|
+
if supplied value was valid, None if it was not
|
|
22
|
+
"""
|
|
23
|
+
...
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ApiKeys(ApiKeysModule):
|
|
27
|
+
_http_client: SyncHTTPClient
|
|
28
|
+
|
|
29
|
+
def __init__(self, http_client: SyncHTTPClient):
|
|
30
|
+
self._http_client = http_client
|
|
31
|
+
|
|
32
|
+
def validate_api_key(self, *, value: str) -> Optional[ApiKey]:
|
|
33
|
+
response = self._http_client.request(
|
|
34
|
+
API_KEY_VALIDATION_PATH, method=REQUEST_METHOD_POST, json={"value": value}
|
|
35
|
+
)
|
|
36
|
+
if response.get(RESOURCE_OBJECT_ATTRIBUTE_NAME) is None:
|
|
37
|
+
return None
|
|
38
|
+
return ApiKey.model_validate(response[RESOURCE_OBJECT_ATTRIBUTE_NAME])
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class AsyncApiKeys(ApiKeysModule):
|
|
42
|
+
_http_client: AsyncHTTPClient
|
|
43
|
+
|
|
44
|
+
def __init__(self, http_client: AsyncHTTPClient):
|
|
45
|
+
self._http_client = http_client
|
|
46
|
+
|
|
47
|
+
async def validate_api_key(self, *, value: str) -> Optional[ApiKey]:
|
|
48
|
+
response = await self._http_client.request(
|
|
49
|
+
API_KEY_VALIDATION_PATH, method=REQUEST_METHOD_POST, json={"value": value}
|
|
50
|
+
)
|
|
51
|
+
if response.get(RESOURCE_OBJECT_ATTRIBUTE_NAME) is None:
|
|
52
|
+
return None
|
|
53
|
+
return ApiKey.model_validate(response[RESOURCE_OBJECT_ATTRIBUTE_NAME])
|
workos/async_client.py
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from workos.__about__ import __version__
|
|
3
|
+
from workos._base_client import BaseClient
|
|
4
|
+
from workos.api_keys import AsyncApiKeys
|
|
5
|
+
from workos.audit_logs import AuditLogsModule
|
|
6
|
+
from workos.directory_sync import AsyncDirectorySync
|
|
7
|
+
from workos.events import AsyncEvents
|
|
8
|
+
from workos.fga import FGAModule
|
|
9
|
+
from workos.mfa import MFAModule
|
|
10
|
+
from workos.organizations import AsyncOrganizations
|
|
11
|
+
from workos.organization_domains import AsyncOrganizationDomains
|
|
12
|
+
from workos.passwordless import PasswordlessModule
|
|
13
|
+
from workos.pipes import AsyncPipes
|
|
14
|
+
from workos.portal import PortalModule
|
|
15
|
+
from workos.sso import AsyncSSO
|
|
16
|
+
from workos.user_management import AsyncUserManagement
|
|
17
|
+
from workos.utils.http_client import AsyncHTTPClient
|
|
18
|
+
from workos.webhooks import WebhooksModule
|
|
19
|
+
from workos.widgets import WidgetsModule
|
|
20
|
+
from workos.vault import VaultModule
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class AsyncClient(BaseClient):
|
|
24
|
+
"""Client for a convenient way to access the WorkOS feature set."""
|
|
25
|
+
|
|
26
|
+
_http_client: AsyncHTTPClient
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
*,
|
|
31
|
+
api_key: Optional[str] = None,
|
|
32
|
+
client_id: Optional[str] = None,
|
|
33
|
+
base_url: Optional[str] = None,
|
|
34
|
+
request_timeout: Optional[int] = None,
|
|
35
|
+
):
|
|
36
|
+
super().__init__(
|
|
37
|
+
api_key=api_key,
|
|
38
|
+
client_id=client_id,
|
|
39
|
+
base_url=base_url,
|
|
40
|
+
request_timeout=request_timeout,
|
|
41
|
+
)
|
|
42
|
+
self._http_client = AsyncHTTPClient(
|
|
43
|
+
api_key=self._api_key,
|
|
44
|
+
base_url=self.base_url,
|
|
45
|
+
client_id=self._client_id,
|
|
46
|
+
version=__version__,
|
|
47
|
+
timeout=self.request_timeout,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def api_keys(self) -> AsyncApiKeys:
|
|
52
|
+
if not getattr(self, "_api_keys", None):
|
|
53
|
+
self._api_keys = AsyncApiKeys(self._http_client)
|
|
54
|
+
return self._api_keys
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def sso(self) -> AsyncSSO:
|
|
58
|
+
if not getattr(self, "_sso", None):
|
|
59
|
+
self._sso = AsyncSSO(
|
|
60
|
+
http_client=self._http_client, client_configuration=self
|
|
61
|
+
)
|
|
62
|
+
return self._sso
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def audit_logs(self) -> AuditLogsModule:
|
|
66
|
+
raise NotImplementedError(
|
|
67
|
+
"Audit logs APIs are not yet supported in the async client."
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def directory_sync(self) -> AsyncDirectorySync:
|
|
72
|
+
if not getattr(self, "_directory_sync", None):
|
|
73
|
+
self._directory_sync = AsyncDirectorySync(self._http_client)
|
|
74
|
+
return self._directory_sync
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def events(self) -> AsyncEvents:
|
|
78
|
+
if not getattr(self, "_events", None):
|
|
79
|
+
self._events = AsyncEvents(self._http_client)
|
|
80
|
+
return self._events
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def fga(self) -> FGAModule:
|
|
84
|
+
raise NotImplementedError("FGA APIs are not yet supported in the async client.")
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def organizations(self) -> AsyncOrganizations:
|
|
88
|
+
if not getattr(self, "_organizations", None):
|
|
89
|
+
self._organizations = AsyncOrganizations(self._http_client)
|
|
90
|
+
return self._organizations
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def organization_domains(self) -> AsyncOrganizationDomains:
|
|
94
|
+
if not getattr(self, "_organization_domains", None):
|
|
95
|
+
self._organization_domains = AsyncOrganizationDomains(
|
|
96
|
+
http_client=self._http_client, client_configuration=self
|
|
97
|
+
)
|
|
98
|
+
return self._organization_domains
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def passwordless(self) -> PasswordlessModule:
|
|
102
|
+
raise NotImplementedError(
|
|
103
|
+
"Passwordless APIs are not yet supported in the async client."
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def pipes(self) -> AsyncPipes:
|
|
108
|
+
if not getattr(self, "_pipes", None):
|
|
109
|
+
self._pipes = AsyncPipes(self._http_client)
|
|
110
|
+
return self._pipes
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def portal(self) -> PortalModule:
|
|
114
|
+
raise NotImplementedError(
|
|
115
|
+
"Portal APIs are not yet supported in the async client."
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def webhooks(self) -> WebhooksModule:
|
|
120
|
+
raise NotImplementedError("Webhooks are not yet supported in the async client.")
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def mfa(self) -> MFAModule:
|
|
124
|
+
raise NotImplementedError("MFA APIs are not yet supported in the async client.")
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def user_management(self) -> AsyncUserManagement:
|
|
128
|
+
if not getattr(self, "_user_management", None):
|
|
129
|
+
self._user_management = AsyncUserManagement(
|
|
130
|
+
http_client=self._http_client, client_configuration=self
|
|
131
|
+
)
|
|
132
|
+
return self._user_management
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def widgets(self) -> WidgetsModule:
|
|
136
|
+
raise NotImplementedError(
|
|
137
|
+
"Widgets APIs are not yet supported in the async client."
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
def vault(self) -> VaultModule:
|
|
142
|
+
raise NotImplementedError(
|
|
143
|
+
"Vault APIs are not yet supported in the async client."
|
|
144
|
+
)
|
workos/audit_logs.py
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
from typing import Optional, Protocol, Sequence
|
|
2
|
+
|
|
3
|
+
from workos.types.audit_logs import AuditLogExport
|
|
4
|
+
from workos.types.audit_logs.audit_log_event import AuditLogEvent
|
|
5
|
+
from workos.utils.http_client import SyncHTTPClient
|
|
6
|
+
from workos.utils.request_helper import REQUEST_METHOD_GET, REQUEST_METHOD_POST
|
|
7
|
+
|
|
8
|
+
EVENTS_PATH = "audit_logs/events"
|
|
9
|
+
EXPORTS_PATH = "audit_logs/exports"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AuditLogsModule(Protocol):
|
|
13
|
+
"""Offers methods through the WorkOS Audit Logs service."""
|
|
14
|
+
|
|
15
|
+
def create_event(
|
|
16
|
+
self,
|
|
17
|
+
*,
|
|
18
|
+
organization_id: str,
|
|
19
|
+
event: AuditLogEvent,
|
|
20
|
+
idempotency_key: Optional[str] = None,
|
|
21
|
+
) -> None:
|
|
22
|
+
"""Create an Audit Logs event.
|
|
23
|
+
|
|
24
|
+
Kwargs:
|
|
25
|
+
organization_id (str): Organization's unique identifier.
|
|
26
|
+
event (AuditLogEvent): An AuditLogEvent object.
|
|
27
|
+
idempotency_key (str): Idempotency key. (Optional)
|
|
28
|
+
Returns:
|
|
29
|
+
None
|
|
30
|
+
"""
|
|
31
|
+
...
|
|
32
|
+
|
|
33
|
+
def create_export(
|
|
34
|
+
self,
|
|
35
|
+
*,
|
|
36
|
+
organization_id: str,
|
|
37
|
+
range_start: str,
|
|
38
|
+
range_end: str,
|
|
39
|
+
actions: Optional[Sequence[str]] = None,
|
|
40
|
+
targets: Optional[Sequence[str]] = None,
|
|
41
|
+
actor_names: Optional[Sequence[str]] = None,
|
|
42
|
+
actor_ids: Optional[Sequence[str]] = None,
|
|
43
|
+
) -> AuditLogExport:
|
|
44
|
+
"""Trigger the creation of an export of audit logs.
|
|
45
|
+
|
|
46
|
+
Kwargs:
|
|
47
|
+
organization_id (str): Organization's unique identifier.
|
|
48
|
+
range_start (str): Start date of the date range filter.
|
|
49
|
+
range_end (str): End date of the date range filter.
|
|
50
|
+
actions (list): Optional list of actions to filter. (Optional)
|
|
51
|
+
actor_names (list): Optional list of actors to filter by name. (Optional)
|
|
52
|
+
targets (list): Optional list of targets to filter. (Optional)
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
AuditLogExport: Object that describes the audit log export
|
|
56
|
+
"""
|
|
57
|
+
...
|
|
58
|
+
|
|
59
|
+
def get_export(self, audit_log_export_id: str) -> AuditLogExport:
|
|
60
|
+
"""Retrieve an created export.
|
|
61
|
+
Args:
|
|
62
|
+
audit_log_export_id (str): Audit log export unique identifier.
|
|
63
|
+
Returns:
|
|
64
|
+
AuditLogExport: Object that describes the audit log export
|
|
65
|
+
"""
|
|
66
|
+
...
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class AuditLogs(AuditLogsModule):
|
|
70
|
+
_http_client: SyncHTTPClient
|
|
71
|
+
|
|
72
|
+
def __init__(self, http_client: SyncHTTPClient):
|
|
73
|
+
self._http_client = http_client
|
|
74
|
+
|
|
75
|
+
def create_event(
|
|
76
|
+
self,
|
|
77
|
+
*,
|
|
78
|
+
organization_id: str,
|
|
79
|
+
event: AuditLogEvent,
|
|
80
|
+
idempotency_key: Optional[str] = None,
|
|
81
|
+
) -> None:
|
|
82
|
+
json = {"organization_id": organization_id, "event": event}
|
|
83
|
+
|
|
84
|
+
headers = {}
|
|
85
|
+
if idempotency_key:
|
|
86
|
+
headers["idempotency-key"] = idempotency_key
|
|
87
|
+
|
|
88
|
+
self._http_client.request(
|
|
89
|
+
EVENTS_PATH, method=REQUEST_METHOD_POST, json=json, headers=headers
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
def create_export(
|
|
93
|
+
self,
|
|
94
|
+
*,
|
|
95
|
+
organization_id: str,
|
|
96
|
+
range_start: str,
|
|
97
|
+
range_end: str,
|
|
98
|
+
actions: Optional[Sequence[str]] = None,
|
|
99
|
+
targets: Optional[Sequence[str]] = None,
|
|
100
|
+
actor_names: Optional[Sequence[str]] = None,
|
|
101
|
+
actor_ids: Optional[Sequence[str]] = None,
|
|
102
|
+
) -> AuditLogExport:
|
|
103
|
+
json = {
|
|
104
|
+
"actions": actions,
|
|
105
|
+
"actor_ids": actor_ids,
|
|
106
|
+
"actor_names": actor_names,
|
|
107
|
+
"organization_id": organization_id,
|
|
108
|
+
"range_start": range_start,
|
|
109
|
+
"range_end": range_end,
|
|
110
|
+
"targets": targets,
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
response = self._http_client.request(
|
|
114
|
+
EXPORTS_PATH, method=REQUEST_METHOD_POST, json=json
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
return AuditLogExport.model_validate(response)
|
|
118
|
+
|
|
119
|
+
def get_export(self, audit_log_export_id: str) -> AuditLogExport:
|
|
120
|
+
response = self._http_client.request(
|
|
121
|
+
"{0}/{1}".format(EXPORTS_PATH, audit_log_export_id),
|
|
122
|
+
method=REQUEST_METHOD_GET,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
return AuditLogExport.model_validate(response)
|
workos/client.py
CHANGED
|
@@ -1,63 +1,148 @@
|
|
|
1
|
-
from
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from workos.__about__ import __version__
|
|
3
|
+
from workos._base_client import BaseClient
|
|
4
|
+
from workos.api_keys import ApiKeys
|
|
5
|
+
from workos.audit_logs import AuditLogs
|
|
2
6
|
from workos.directory_sync import DirectorySync
|
|
7
|
+
from workos.fga import FGA
|
|
3
8
|
from workos.organizations import Organizations
|
|
9
|
+
from workos.organization_domains import OrganizationDomains
|
|
4
10
|
from workos.passwordless import Passwordless
|
|
11
|
+
from workos.pipes import Pipes
|
|
5
12
|
from workos.portal import Portal
|
|
6
13
|
from workos.sso import SSO
|
|
7
14
|
from workos.webhooks import Webhooks
|
|
8
15
|
from workos.mfa import Mfa
|
|
16
|
+
from workos.events import Events
|
|
17
|
+
from workos.user_management import UserManagement
|
|
18
|
+
from workos.utils.http_client import SyncHTTPClient
|
|
19
|
+
from workos.widgets import Widgets
|
|
20
|
+
from workos.vault import Vault
|
|
9
21
|
|
|
10
22
|
|
|
11
|
-
class
|
|
23
|
+
class SyncClient(BaseClient):
|
|
12
24
|
"""Client for a convenient way to access the WorkOS feature set."""
|
|
13
25
|
|
|
26
|
+
_http_client: SyncHTTPClient
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
*,
|
|
31
|
+
api_key: Optional[str] = None,
|
|
32
|
+
client_id: Optional[str] = None,
|
|
33
|
+
base_url: Optional[str] = None,
|
|
34
|
+
request_timeout: Optional[int] = None,
|
|
35
|
+
):
|
|
36
|
+
super().__init__(
|
|
37
|
+
api_key=api_key,
|
|
38
|
+
client_id=client_id,
|
|
39
|
+
base_url=base_url,
|
|
40
|
+
request_timeout=request_timeout,
|
|
41
|
+
)
|
|
42
|
+
self._http_client = SyncHTTPClient(
|
|
43
|
+
api_key=self._api_key,
|
|
44
|
+
base_url=self.base_url,
|
|
45
|
+
client_id=self._client_id,
|
|
46
|
+
version=__version__,
|
|
47
|
+
timeout=self.request_timeout,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def api_keys(self) -> ApiKeys:
|
|
52
|
+
if not getattr(self, "_api_keys", None):
|
|
53
|
+
self._api_keys = ApiKeys(self._http_client)
|
|
54
|
+
return self._api_keys
|
|
55
|
+
|
|
14
56
|
@property
|
|
15
|
-
def sso(self):
|
|
57
|
+
def sso(self) -> SSO:
|
|
16
58
|
if not getattr(self, "_sso", None):
|
|
17
|
-
self._sso = SSO()
|
|
59
|
+
self._sso = SSO(http_client=self._http_client, client_configuration=self)
|
|
18
60
|
return self._sso
|
|
19
61
|
|
|
20
62
|
@property
|
|
21
|
-
def
|
|
22
|
-
if not getattr(self, "
|
|
23
|
-
self.
|
|
24
|
-
return self.
|
|
63
|
+
def audit_logs(self) -> AuditLogs:
|
|
64
|
+
if not getattr(self, "_audit_logs", None):
|
|
65
|
+
self._audit_logs = AuditLogs(self._http_client)
|
|
66
|
+
return self._audit_logs
|
|
25
67
|
|
|
26
68
|
@property
|
|
27
|
-
def directory_sync(self):
|
|
69
|
+
def directory_sync(self) -> DirectorySync:
|
|
28
70
|
if not getattr(self, "_directory_sync", None):
|
|
29
|
-
self._directory_sync = DirectorySync()
|
|
71
|
+
self._directory_sync = DirectorySync(self._http_client)
|
|
30
72
|
return self._directory_sync
|
|
31
73
|
|
|
32
74
|
@property
|
|
33
|
-
def
|
|
75
|
+
def events(self) -> Events:
|
|
76
|
+
if not getattr(self, "_events", None):
|
|
77
|
+
self._events = Events(self._http_client)
|
|
78
|
+
return self._events
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def fga(self) -> FGA:
|
|
82
|
+
if not getattr(self, "_fga", None):
|
|
83
|
+
self._fga = FGA(self._http_client)
|
|
84
|
+
return self._fga
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def organizations(self) -> Organizations:
|
|
34
88
|
if not getattr(self, "_organizations", None):
|
|
35
|
-
self._organizations = Organizations()
|
|
89
|
+
self._organizations = Organizations(self._http_client)
|
|
36
90
|
return self._organizations
|
|
37
91
|
|
|
38
92
|
@property
|
|
39
|
-
def
|
|
93
|
+
def organization_domains(self) -> OrganizationDomains:
|
|
94
|
+
if not getattr(self, "_organization_domains", None):
|
|
95
|
+
self._organization_domains = OrganizationDomains(
|
|
96
|
+
http_client=self._http_client, client_configuration=self
|
|
97
|
+
)
|
|
98
|
+
return self._organization_domains
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def passwordless(self) -> Passwordless:
|
|
40
102
|
if not getattr(self, "_passwordless", None):
|
|
41
|
-
self._passwordless = Passwordless()
|
|
103
|
+
self._passwordless = Passwordless(self._http_client)
|
|
42
104
|
return self._passwordless
|
|
43
105
|
|
|
44
106
|
@property
|
|
45
|
-
def
|
|
107
|
+
def pipes(self) -> Pipes:
|
|
108
|
+
if not getattr(self, "_pipes", None):
|
|
109
|
+
self._pipes = Pipes(self._http_client)
|
|
110
|
+
return self._pipes
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def portal(self) -> Portal:
|
|
46
114
|
if not getattr(self, "_portal", None):
|
|
47
|
-
self._portal = Portal()
|
|
115
|
+
self._portal = Portal(self._http_client)
|
|
48
116
|
return self._portal
|
|
49
117
|
|
|
50
118
|
@property
|
|
51
|
-
def webhooks(self):
|
|
119
|
+
def webhooks(self) -> Webhooks:
|
|
52
120
|
if not getattr(self, "_webhooks", None):
|
|
53
121
|
self._webhooks = Webhooks()
|
|
54
122
|
return self._webhooks
|
|
55
123
|
|
|
56
124
|
@property
|
|
57
|
-
def mfa(self):
|
|
125
|
+
def mfa(self) -> Mfa:
|
|
58
126
|
if not getattr(self, "_mfa", None):
|
|
59
|
-
self._mfa = Mfa()
|
|
127
|
+
self._mfa = Mfa(self._http_client)
|
|
60
128
|
return self._mfa
|
|
61
129
|
|
|
130
|
+
@property
|
|
131
|
+
def user_management(self) -> UserManagement:
|
|
132
|
+
if not getattr(self, "_user_management", None):
|
|
133
|
+
self._user_management = UserManagement(
|
|
134
|
+
http_client=self._http_client, client_configuration=self
|
|
135
|
+
)
|
|
136
|
+
return self._user_management
|
|
137
|
+
|
|
138
|
+
@property
|
|
139
|
+
def widgets(self) -> Widgets:
|
|
140
|
+
if not getattr(self, "_widgets", None):
|
|
141
|
+
self._widgets = Widgets(http_client=self._http_client)
|
|
142
|
+
return self._widgets
|
|
62
143
|
|
|
63
|
-
|
|
144
|
+
@property
|
|
145
|
+
def vault(self) -> Vault:
|
|
146
|
+
if not getattr(self, "_vault", None):
|
|
147
|
+
self._vault = Vault(http_client=self._http_client)
|
|
148
|
+
return self._vault
|