workos 1.5.1__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.
Files changed (150) hide show
  1. workos/__about__.py +1 -1
  2. workos/__init__.py +3 -7
  3. workos/_base_client.py +138 -0
  4. workos/_client_configuration.py +10 -0
  5. workos/api_keys.py +53 -0
  6. workos/async_client.py +144 -0
  7. workos/audit_logs.py +125 -0
  8. workos/client.py +110 -18
  9. workos/directory_sync.py +379 -99
  10. workos/events.py +111 -0
  11. workos/exceptions.py +53 -26
  12. workos/fga.py +649 -0
  13. workos/mfa.py +205 -0
  14. workos/organization_domains.py +179 -0
  15. workos/organizations.py +403 -73
  16. workos/passwordless.py +67 -43
  17. workos/pipes.py +93 -0
  18. workos/portal.py +51 -28
  19. workos/session.py +337 -0
  20. workos/sso.py +311 -101
  21. workos/types/__init__.py +4 -0
  22. workos/types/api_keys/__init__.py +1 -0
  23. workos/types/api_keys/api_keys.py +20 -0
  24. workos/types/audit_logs/__init__.py +6 -0
  25. workos/types/audit_logs/audit_log_event.py +16 -0
  26. workos/types/audit_logs/audit_log_event_actor.py +12 -0
  27. workos/types/audit_logs/audit_log_event_context.py +8 -0
  28. workos/types/audit_logs/audit_log_event_target.py +12 -0
  29. workos/types/audit_logs/audit_log_export.py +18 -0
  30. workos/types/audit_logs/audit_log_metadata.py +4 -0
  31. workos/types/directory_sync/__init__.py +5 -0
  32. workos/types/directory_sync/directory.py +31 -0
  33. workos/types/directory_sync/directory_group.py +16 -0
  34. workos/types/directory_sync/directory_state.py +28 -0
  35. workos/types/directory_sync/directory_type.py +24 -0
  36. workos/types/directory_sync/directory_user.py +50 -0
  37. workos/types/directory_sync/list_filters.py +21 -0
  38. workos/types/events/__init__.py +13 -0
  39. workos/types/events/authentication_payload.py +70 -0
  40. workos/types/events/connection_payload_with_legacy_fields.py +5 -0
  41. workos/types/events/directory_group_membership_payload.py +9 -0
  42. workos/types/events/directory_group_with_previous_attributes.py +6 -0
  43. workos/types/events/directory_payload.py +16 -0
  44. workos/types/events/directory_payload_with_legacy_fields.py +29 -0
  45. workos/types/events/directory_user_with_previous_attributes.py +6 -0
  46. workos/types/events/event.py +324 -0
  47. workos/types/events/event_model.py +103 -0
  48. workos/types/events/event_type.py +59 -0
  49. workos/types/events/list_filters.py +10 -0
  50. workos/types/events/organization_domain_verification_failed_payload.py +14 -0
  51. workos/types/events/previous_attributes.py +3 -0
  52. workos/types/events/session_payload.py +27 -0
  53. workos/types/feature_flags/__init__.py +3 -0
  54. workos/types/feature_flags/feature_flag.py +12 -0
  55. workos/types/feature_flags/list_filters.py +5 -0
  56. workos/types/fga/__init__.py +5 -0
  57. workos/types/fga/authorization_resource_types.py +9 -0
  58. workos/types/fga/authorization_resources.py +10 -0
  59. workos/types/fga/check.py +51 -0
  60. workos/types/fga/list_filters.py +24 -0
  61. workos/types/fga/warnings.py +33 -0
  62. workos/types/fga/warrant.py +49 -0
  63. workos/types/list_resource.py +198 -0
  64. workos/types/metadata.py +4 -0
  65. workos/types/mfa/__init__.py +5 -0
  66. workos/types/mfa/authentication_challenge.py +14 -0
  67. workos/types/mfa/authentication_challenge_verification_response.py +9 -0
  68. workos/types/mfa/authentication_factor.py +70 -0
  69. workos/types/mfa/authentication_factor_totp_and_challenge_response.py +10 -0
  70. workos/types/mfa/enroll_authentication_factor_type.py +8 -0
  71. workos/types/organization_domains/__init__.py +1 -0
  72. workos/types/organization_domains/organization_domain.py +18 -0
  73. workos/types/organizations/__init__.py +6 -0
  74. workos/types/organizations/domain_data_input.py +7 -0
  75. workos/types/organizations/list_filters.py +6 -0
  76. workos/types/organizations/organization.py +13 -0
  77. workos/types/organizations/organization_common.py +12 -0
  78. workos/types/passwordless/__init__.py +2 -0
  79. workos/types/passwordless/passwordless_session.py +12 -0
  80. workos/types/passwordless/passwordless_session_type.py +3 -0
  81. workos/types/pipes/__init__.py +6 -0
  82. workos/types/pipes/pipes.py +34 -0
  83. workos/types/portal/__init__.py +2 -0
  84. workos/types/portal/portal_link.py +7 -0
  85. workos/types/portal/portal_link_intent.py +11 -0
  86. workos/types/portal/portal_link_intent_options.py +9 -0
  87. workos/types/roles/__init__.py +0 -0
  88. workos/types/roles/role.py +27 -0
  89. workos/types/sso/__init__.py +4 -0
  90. workos/types/sso/connection.py +70 -0
  91. workos/types/sso/connection_domain.py +8 -0
  92. workos/types/sso/profile.py +35 -0
  93. workos/types/sso/sso_provider_type.py +10 -0
  94. workos/types/user_management/__init__.py +12 -0
  95. workos/types/user_management/authenticate_with_common.py +66 -0
  96. workos/types/user_management/authentication_response.py +53 -0
  97. workos/types/user_management/email_verification.py +18 -0
  98. workos/types/user_management/impersonator.py +8 -0
  99. workos/types/user_management/invitation.py +26 -0
  100. workos/types/user_management/list_filters.py +29 -0
  101. workos/types/user_management/magic_auth.py +18 -0
  102. workos/types/user_management/oauth_tokens.py +21 -0
  103. workos/types/user_management/organization_membership.py +25 -0
  104. workos/types/user_management/password_hash_type.py +4 -0
  105. workos/types/user_management/password_reset.py +18 -0
  106. workos/types/user_management/screen_hint.py +3 -0
  107. workos/types/user_management/session.py +79 -0
  108. workos/types/user_management/user.py +22 -0
  109. workos/types/user_management/user_management_provider_type.py +11 -0
  110. workos/types/vault/__init__.py +2 -0
  111. workos/types/vault/key.py +25 -0
  112. workos/types/vault/object.py +38 -0
  113. workos/types/webhooks/__init__.py +0 -0
  114. workos/types/webhooks/webhook.py +330 -0
  115. workos/types/webhooks/webhook_model.py +14 -0
  116. workos/types/webhooks/webhook_payload.py +4 -0
  117. workos/types/widgets/__init__.py +2 -0
  118. workos/types/widgets/widget_scope.py +4 -0
  119. workos/types/widgets/widget_token_response.py +7 -0
  120. workos/types/workos_model.py +26 -0
  121. workos/typing/__init__.py +1 -0
  122. workos/typing/literals.py +32 -0
  123. workos/typing/sync_or_async.py +5 -0
  124. workos/typing/untyped_literal.py +37 -0
  125. workos/typing/webhooks.py +18 -0
  126. workos/user_management.py +2400 -0
  127. workos/utils/_base_http_client.py +252 -0
  128. workos/utils/crypto_provider.py +39 -0
  129. workos/utils/http_client.py +214 -0
  130. workos/utils/pagination_order.py +4 -0
  131. workos/utils/request_helper.py +27 -0
  132. workos/vault.py +544 -0
  133. workos/webhooks.py +96 -39
  134. workos/widgets.py +55 -0
  135. {workos-1.5.1.dist-info → workos-5.38.0.dist-info}/LICENSE +1 -1
  136. workos-5.38.0.dist-info/METADATA +107 -0
  137. workos-5.38.0.dist-info/RECORD +141 -0
  138. {workos-1.5.1.dist-info → workos-5.38.0.dist-info}/WHEEL +1 -1
  139. workos/audit_trail.py +0 -172
  140. workos/resources/base.py +0 -36
  141. workos/resources/event.py +0 -42
  142. workos/resources/event_action.py +0 -11
  143. workos/resources/sso.py +0 -53
  144. workos/utils/connection_types.py +0 -17
  145. workos/utils/request.py +0 -95
  146. workos/utils/validation.py +0 -45
  147. workos-1.5.1.dist-info/METADATA +0 -77
  148. workos-1.5.1.dist-info/RECORD +0 -25
  149. /workos/{resources/__init__.py → py.typed} +0 -0
  150. {workos-1.5.1.dist-info → workos-5.38.0.dist-info}/top_level.txt +0 -0
workos/sso.py CHANGED
@@ -1,20 +1,27 @@
1
- import json
2
-
3
- from requests import Request
4
- from warnings import warn
5
-
6
- import workos
7
- from workos.exceptions import ConfigurationException
8
- from workos.resources.sso import WorkOSProfile, WorkOSProfileAndToken
9
- from workos.utils.connection_types import ConnectionType
10
- from workos.utils.request import (
11
- RequestHelper,
1
+ from typing import Optional, Protocol
2
+ from workos._client_configuration import ClientConfiguration
3
+ from workos.types.sso.connection import ConnectionType
4
+ from workos.types.sso.sso_provider_type import SsoProviderType
5
+ from workos.typing.sync_or_async import SyncOrAsync
6
+ from workos.utils.http_client import AsyncHTTPClient, SyncHTTPClient
7
+ from workos.utils.pagination_order import PaginationOrder
8
+ from workos.types.sso import ConnectionWithDomains, Profile, ProfileAndToken
9
+ from workos.utils.request_helper import (
10
+ DEFAULT_LIST_RESPONSE_LIMIT,
12
11
  RESPONSE_TYPE_CODE,
13
12
  REQUEST_METHOD_DELETE,
14
13
  REQUEST_METHOD_GET,
15
14
  REQUEST_METHOD_POST,
15
+ QueryParameters,
16
+ RequestHelper,
17
+ REQUEST_METHOD_PUT,
18
+ )
19
+ from workos.types.list_resource import (
20
+ ListArgs,
21
+ ListMetadata,
22
+ ListPage,
23
+ WorkOSListResource,
16
24
  )
17
- from workos.utils.validation import SSO_MODULE, validate_settings
18
25
 
19
26
  AUTHORIZATION_PATH = "sso/authorize"
20
27
  TOKEN_PATH = "sso/token"
@@ -22,174 +29,377 @@ PROFILE_PATH = "sso/profile"
22
29
 
23
30
  OAUTH_GRANT_TYPE = "authorization_code"
24
31
 
25
- RESPONSE_LIMIT = 10
26
32
 
33
+ class ConnectionsListFilters(ListArgs, total=False):
34
+ connection_type: Optional[ConnectionType]
35
+ domain: Optional[str]
36
+ organization_id: Optional[str]
27
37
 
28
- class SSO(object):
29
- """Offers methods to assist in authenticating through the WorkOS SSO service."""
30
38
 
31
- @validate_settings(SSO_MODULE)
32
- def __init__(self):
33
- pass
39
+ ConnectionsListResource = WorkOSListResource[
40
+ ConnectionWithDomains, ConnectionsListFilters, ListMetadata
41
+ ]
34
42
 
35
- @property
36
- def request_helper(self):
37
- if not getattr(self, "_request_helper", None):
38
- self._request_helper = RequestHelper()
39
- return self._request_helper
43
+
44
+ class SSOModule(Protocol):
45
+ """Offers methods to assist in authenticating through the WorkOS SSO service."""
46
+
47
+ _client_configuration: ClientConfiguration
40
48
 
41
49
  def get_authorization_url(
42
- self, domain=None, redirect_uri=None, state=None, provider=None, connection=None
43
- ):
50
+ self,
51
+ *,
52
+ redirect_uri: str,
53
+ domain_hint: Optional[str] = None,
54
+ login_hint: Optional[str] = None,
55
+ state: Optional[str] = None,
56
+ provider: Optional[SsoProviderType] = None,
57
+ connection_id: Optional[str] = None,
58
+ organization_id: Optional[str] = None,
59
+ ) -> str:
44
60
  """Generate an OAuth 2.0 authorization URL.
45
61
 
46
62
  The URL generated will redirect a User to the Identity Provider configured through
47
63
  WorkOS.
48
64
 
65
+ This method is purposefully designed as synchronous as it does not make any HTTP requests.
66
+
49
67
  Kwargs:
50
- domain (str) - The domain a user is associated with, as configured on WorkOS
51
- redirect_uri (str) - A valid redirect URI, as specified on WorkOS
52
- state (str) - An encoded string passed to WorkOS that'd be preserved through the authentication workflow, passed
68
+ redirect_uri (str) : A valid redirect URI, as specified on WorkOS
69
+ state (str) : An encoded string passed to WorkOS that'd be preserved through the authentication workflow, passed
53
70
  back as a query parameter
54
- provider (ConnectionType) - Authentication service provider descriptor
55
- connection (string) - Unique identifier for a WorkOS Connection
71
+ provider (SSOProviderType) : Authentication service provider descriptor
72
+ connection_id (string) : Unique identifier for a WorkOS Connection
73
+ organization_id (string) : Unique identifier for a WorkOS Organization
56
74
 
57
75
  Returns:
58
76
  str: URL to redirect a User to to begin the OAuth workflow with WorkOS
59
77
  """
60
- params = {
61
- "client_id": workos.client_id,
78
+ params: QueryParameters = {
79
+ "client_id": self._client_configuration.client_id,
62
80
  "redirect_uri": redirect_uri,
63
81
  "response_type": RESPONSE_TYPE_CODE,
64
82
  }
65
83
 
66
- if domain is None and provider is None and connection is None:
84
+ if connection_id is None and organization_id is None and provider is None:
67
85
  raise ValueError(
68
- "Incomplete arguments. Need to specify either a 'connection', 'domain' or 'provider'"
86
+ "Incomplete arguments. Need to specify either a 'connection', 'organization', or 'provider'"
69
87
  )
70
88
  if provider is not None:
71
- if not isinstance(provider, ConnectionType):
72
- raise ValueError("'provider' must be of type ConnectionType")
73
- params["provider"] = str(provider.value)
74
- if domain is not None:
75
- params["domain"] = domain
76
- if connection is not None:
77
- params["connection"] = connection
89
+ params["provider"] = provider
90
+ if domain_hint is not None:
91
+ params["domain_hint"] = domain_hint
92
+ if login_hint is not None:
93
+ params["login_hint"] = login_hint
94
+ if connection_id is not None:
95
+ params["connection"] = connection_id
96
+ if organization_id is not None:
97
+ params["organization"] = organization_id
78
98
 
79
99
  if state is not None:
80
100
  params["state"] = state
81
101
 
82
- prepared_request = Request(
83
- "GET",
84
- self.request_helper.generate_api_url(AUTHORIZATION_PATH),
85
- params=params,
86
- ).prepare()
87
-
88
- return prepared_request.url
102
+ return RequestHelper.build_url_with_query_params(
103
+ base_url=self._client_configuration.base_url,
104
+ path=AUTHORIZATION_PATH,
105
+ **params,
106
+ )
89
107
 
90
- def get_profile(self, accessToken):
108
+ def get_profile(self, access_token: str) -> SyncOrAsync[Profile]:
91
109
  """
92
110
  Verify that SSO has been completed successfully and retrieve the identity of the user.
93
111
 
94
112
  Args:
95
- accessToken (str): the token used to authenticate the API call
113
+ access_token (str): The token used to authenticate the API call
96
114
 
97
115
  Returns:
98
- WorkOSProfile
116
+ Profile
99
117
  """
118
+ ...
100
119
 
101
- token = accessToken
102
-
103
- response = self.request_helper.request(
104
- PROFILE_PATH, method=REQUEST_METHOD_GET, token=token
105
- )
106
-
107
- return WorkOSProfile.construct_from_response(response)
108
-
109
- def get_profile_and_token(self, code):
120
+ def get_profile_and_token(self, code: str) -> SyncOrAsync[ProfileAndToken]:
110
121
  """Get the profile of an authenticated User
111
122
 
112
123
  Once authenticated, using the code returned having followed the authorization URL,
113
124
  get the WorkOS profile of the User.
114
125
 
115
126
  Args:
116
- code (str): Code returned by WorkOS on completion of OAuth 2.0 workflow
127
+ code (str): Code returned by WorkOS on completion of OAuth 2.0 workflow.
117
128
 
118
129
  Returns:
119
- WorkOSProfileAndToken: WorkOSProfileAndToken object representing the User
130
+ ProfileAndToken: WorkOSProfileAndToken object representing the User.
120
131
  """
121
- params = {
122
- "client_id": workos.client_id,
123
- "client_secret": workos.api_key,
124
- "code": code,
125
- "grant_type": OAUTH_GRANT_TYPE,
126
- }
132
+ ...
127
133
 
128
- response = self.request_helper.request(
129
- TOKEN_PATH, method=REQUEST_METHOD_POST, params=params
130
- )
131
-
132
- return WorkOSProfileAndToken.construct_from_response(response)
133
-
134
- def get_connection(self, connection):
134
+ def get_connection(self, connection_id: str) -> SyncOrAsync[ConnectionWithDomains]:
135
135
  """Gets details for a single Connection
136
136
 
137
137
  Args:
138
138
  connection (str): Connection unique identifier
139
139
 
140
140
  Returns:
141
- dict: Connection response from WorkOS.
141
+ ConnectionWithDomains: Connection response from WorkOS.
142
142
  """
143
- return self.request_helper.request(
144
- "connections/{connection}".format(connection=connection),
145
- method=REQUEST_METHOD_GET,
146
- token=workos.api_key,
147
- )
143
+ ...
148
144
 
149
145
  def list_connections(
150
146
  self,
151
- connection_type=None,
152
- domain=None,
153
- organization_id=None,
154
- limit=RESPONSE_LIMIT,
155
- before=None,
156
- after=None,
157
- ):
147
+ *,
148
+ connection_type: Optional[ConnectionType] = None,
149
+ domain: Optional[str] = None,
150
+ organization_id: Optional[str] = None,
151
+ limit: int = DEFAULT_LIST_RESPONSE_LIMIT,
152
+ before: Optional[str] = None,
153
+ after: Optional[str] = None,
154
+ order: PaginationOrder = "desc",
155
+ ) -> SyncOrAsync[ConnectionsListResource]:
158
156
  """Gets details for existing Connections.
159
157
 
160
- Args:
158
+ Kwargs:
161
159
  connection_type (ConnectionType): Authentication service provider descriptor. (Optional)
162
160
  domain (str): Domain of a Connection. (Optional)
163
161
  limit (int): Maximum number of records to return. (Optional)
164
162
  before (str): Pagination cursor to receive records before a provided Connection ID. (Optional)
165
163
  after (str): Pagination cursor to receive records after a provided Connection ID. (Optional)
164
+ order (Literal["asc","desc"]): Sort records in either ascending or descending (default) order by created_at timestamp. (Optional)
166
165
 
167
166
  Returns:
168
- dict: Connections response from WorkOS.
167
+ ConnectionsListResource: Connections response from WorkOS.
169
168
  """
170
- params = {
169
+ ...
170
+
171
+ def update_connection(
172
+ self,
173
+ *,
174
+ connection_id: str,
175
+ saml_options_signing_key: Optional[str] = None,
176
+ saml_options_signing_cert: Optional[str] = None,
177
+ ) -> SyncOrAsync[ConnectionWithDomains]:
178
+ """Updates a single connection
179
+
180
+ Args:
181
+ connection_id (str): Connection unique identifier
182
+ saml_options_signing_key (str): Signing key for the connection (Optional)
183
+ saml_options_signing_cert (str): Signing certificate for the connection (Optional)
184
+ Returns:
185
+ None
186
+ """
187
+ ...
188
+
189
+ def delete_connection(self, connection_id: str) -> SyncOrAsync[None]:
190
+ """Deletes a single Connection
191
+
192
+ Args:
193
+ connection_id (str): Connection unique identifier
194
+
195
+ Returns:
196
+ None
197
+ """
198
+ ...
199
+
200
+
201
+ class SSO(SSOModule):
202
+ _http_client: SyncHTTPClient
203
+
204
+ def __init__(
205
+ self, http_client: SyncHTTPClient, client_configuration: ClientConfiguration
206
+ ):
207
+ self._client_configuration = client_configuration
208
+ self._http_client = http_client
209
+
210
+ def get_profile(self, access_token: str) -> Profile:
211
+ response = self._http_client.request(
212
+ PROFILE_PATH,
213
+ method=REQUEST_METHOD_GET,
214
+ headers={**self._http_client.auth_header_from_token(access_token)},
215
+ exclude_default_auth_headers=True,
216
+ )
217
+
218
+ return Profile.model_validate(response)
219
+
220
+ def get_profile_and_token(self, code: str) -> ProfileAndToken:
221
+ json = {
222
+ "client_id": self._http_client.client_id,
223
+ "client_secret": self._http_client.api_key,
224
+ "code": code,
225
+ "grant_type": OAUTH_GRANT_TYPE,
226
+ }
227
+
228
+ response = self._http_client.request(
229
+ TOKEN_PATH, method=REQUEST_METHOD_POST, json=json
230
+ )
231
+
232
+ return ProfileAndToken.model_validate(response)
233
+
234
+ def get_connection(self, connection_id: str) -> ConnectionWithDomains:
235
+ response = self._http_client.request(
236
+ f"connections/{connection_id}",
237
+ method=REQUEST_METHOD_GET,
238
+ )
239
+
240
+ return ConnectionWithDomains.model_validate(response)
241
+
242
+ def list_connections(
243
+ self,
244
+ *,
245
+ connection_type: Optional[ConnectionType] = None,
246
+ domain: Optional[str] = None,
247
+ organization_id: Optional[str] = None,
248
+ limit: int = DEFAULT_LIST_RESPONSE_LIMIT,
249
+ before: Optional[str] = None,
250
+ after: Optional[str] = None,
251
+ order: PaginationOrder = "desc",
252
+ ) -> ConnectionsListResource:
253
+ params: ConnectionsListFilters = {
171
254
  "connection_type": connection_type,
172
255
  "domain": domain,
173
256
  "organization_id": organization_id,
174
257
  "limit": limit,
175
258
  "before": before,
176
259
  "after": after,
260
+ "order": order,
177
261
  }
178
- return self.request_helper.request(
262
+
263
+ response = self._http_client.request(
179
264
  "connections",
180
265
  method=REQUEST_METHOD_GET,
181
266
  params=params,
182
- token=workos.api_key,
183
267
  )
184
268
 
185
- def delete_connection(self, connection):
186
- """Deletes a single Connection
269
+ return WorkOSListResource[
270
+ ConnectionWithDomains, ConnectionsListFilters, ListMetadata
271
+ ](
272
+ list_method=self.list_connections,
273
+ list_args=params,
274
+ **ListPage[ConnectionWithDomains](**response).model_dump(),
275
+ )
187
276
 
188
- Args:
189
- connection (str): Connection unique identifier
190
- """
191
- return self.request_helper.request(
192
- "connections/{connection}".format(connection=connection),
277
+ def update_connection(
278
+ self,
279
+ *,
280
+ connection_id: str,
281
+ saml_options_signing_key: Optional[str] = None,
282
+ saml_options_signing_cert: Optional[str] = None,
283
+ ) -> ConnectionWithDomains:
284
+ json = {
285
+ "options": {
286
+ "signing_key": saml_options_signing_key,
287
+ "signing_cert": saml_options_signing_cert,
288
+ }
289
+ }
290
+
291
+ response = self._http_client.request(
292
+ f"connections/{connection_id}",
293
+ method=REQUEST_METHOD_PUT,
294
+ json=json,
295
+ )
296
+
297
+ return ConnectionWithDomains.model_validate(response)
298
+
299
+ def delete_connection(self, connection_id: str) -> None:
300
+ self._http_client.request(
301
+ f"connections/{connection_id}", method=REQUEST_METHOD_DELETE
302
+ )
303
+
304
+
305
+ class AsyncSSO(SSOModule):
306
+ _http_client: AsyncHTTPClient
307
+
308
+ def __init__(
309
+ self, http_client: AsyncHTTPClient, client_configuration: ClientConfiguration
310
+ ):
311
+ self._client_configuration = client_configuration
312
+ self._http_client = http_client
313
+
314
+ async def get_profile(self, access_token: str) -> Profile:
315
+ response = await self._http_client.request(
316
+ PROFILE_PATH,
317
+ method=REQUEST_METHOD_GET,
318
+ headers={**self._http_client.auth_header_from_token(access_token)},
319
+ exclude_default_auth_headers=True,
320
+ )
321
+
322
+ return Profile.model_validate(response)
323
+
324
+ async def get_profile_and_token(self, code: str) -> ProfileAndToken:
325
+ json = {
326
+ "client_id": self._http_client.client_id,
327
+ "client_secret": self._http_client.api_key,
328
+ "code": code,
329
+ "grant_type": OAUTH_GRANT_TYPE,
330
+ }
331
+
332
+ response = await self._http_client.request(
333
+ TOKEN_PATH, method=REQUEST_METHOD_POST, json=json
334
+ )
335
+
336
+ return ProfileAndToken.model_validate(response)
337
+
338
+ async def get_connection(self, connection_id: str) -> ConnectionWithDomains:
339
+ response = await self._http_client.request(
340
+ f"connections/{connection_id}",
341
+ method=REQUEST_METHOD_GET,
342
+ )
343
+
344
+ return ConnectionWithDomains.model_validate(response)
345
+
346
+ async def list_connections(
347
+ self,
348
+ *,
349
+ connection_type: Optional[ConnectionType] = None,
350
+ domain: Optional[str] = None,
351
+ organization_id: Optional[str] = None,
352
+ limit: int = DEFAULT_LIST_RESPONSE_LIMIT,
353
+ before: Optional[str] = None,
354
+ after: Optional[str] = None,
355
+ order: PaginationOrder = "desc",
356
+ ) -> ConnectionsListResource:
357
+ params: ConnectionsListFilters = {
358
+ "connection_type": connection_type,
359
+ "domain": domain,
360
+ "organization_id": organization_id,
361
+ "limit": limit,
362
+ "before": before,
363
+ "after": after,
364
+ "order": order,
365
+ }
366
+
367
+ response = await self._http_client.request(
368
+ "connections", method=REQUEST_METHOD_GET, params=params
369
+ )
370
+
371
+ return WorkOSListResource[
372
+ ConnectionWithDomains, ConnectionsListFilters, ListMetadata
373
+ ](
374
+ list_method=self.list_connections,
375
+ list_args=params,
376
+ **ListPage[ConnectionWithDomains](**response).model_dump(),
377
+ )
378
+
379
+ async def update_connection(
380
+ self,
381
+ *,
382
+ connection_id: str,
383
+ saml_options_signing_key: Optional[str] = None,
384
+ saml_options_signing_cert: Optional[str] = None,
385
+ ) -> ConnectionWithDomains:
386
+ json = {
387
+ "options": {
388
+ "signing_key": saml_options_signing_key,
389
+ "signing_cert": saml_options_signing_cert,
390
+ }
391
+ }
392
+
393
+ response = await self._http_client.request(
394
+ f"connections/{connection_id}",
395
+ method=REQUEST_METHOD_PUT,
396
+ json=json,
397
+ )
398
+
399
+ return ConnectionWithDomains.model_validate(response)
400
+
401
+ async def delete_connection(self, connection_id: str) -> None:
402
+ await self._http_client.request(
403
+ f"connections/{connection_id}",
193
404
  method=REQUEST_METHOD_DELETE,
194
- token=workos.api_key,
195
405
  )
@@ -0,0 +1,4 @@
1
+ from .audit_logs.audit_log_event import AuditLogEvent as AuditLogEvent
2
+ from .organizations.domain_data_input import DomainDataInput as DomainDataInput
3
+ from .fga.warrant import WarrantWrite as WarrantWrite
4
+ from .fga.check import WarrantCheckInput as WarrantCheckInput
@@ -0,0 +1 @@
1
+ from .api_keys import ApiKey as ApiKey # noqa: F401
@@ -0,0 +1,20 @@
1
+ from typing import Literal, Optional, Sequence
2
+
3
+ from workos.types.workos_model import WorkOSModel
4
+
5
+
6
+ class ApiKeyOwner(WorkOSModel):
7
+ type: str
8
+ id: str
9
+
10
+
11
+ class ApiKey(WorkOSModel):
12
+ object: Literal["api_key"]
13
+ id: str
14
+ owner: ApiKeyOwner
15
+ name: str
16
+ obfuscated_value: str
17
+ last_used_at: Optional[str] = None
18
+ permissions: Sequence[str]
19
+ created_at: str
20
+ updated_at: str
@@ -0,0 +1,6 @@
1
+ from .audit_log_event_actor import *
2
+ from .audit_log_event_context import *
3
+ from .audit_log_event_target import *
4
+ from .audit_log_event import *
5
+ from .audit_log_export import *
6
+ from .audit_log_metadata import *
@@ -0,0 +1,16 @@
1
+ from typing_extensions import NotRequired, Sequence, TypedDict
2
+
3
+ from workos.types.audit_logs.audit_log_event_actor import AuditLogEventActor
4
+ from workos.types.audit_logs.audit_log_event_context import AuditLogEventContext
5
+ from workos.types.audit_logs.audit_log_metadata import AuditLogMetadata
6
+ from workos.types.audit_logs.audit_log_event_target import AuditLogEventTarget
7
+
8
+
9
+ class AuditLogEvent(TypedDict):
10
+ action: str
11
+ version: NotRequired[int]
12
+ occurred_at: str # ISO-8601 datetime of when an event occurred
13
+ actor: AuditLogEventActor
14
+ targets: Sequence[AuditLogEventTarget]
15
+ context: AuditLogEventContext
16
+ metadata: NotRequired[AuditLogMetadata]
@@ -0,0 +1,12 @@
1
+ from typing_extensions import NotRequired, TypedDict
2
+
3
+ from workos.types.audit_logs.audit_log_metadata import AuditLogMetadata
4
+
5
+
6
+ class AuditLogEventActor(TypedDict):
7
+ """Describes the entity that generated the event."""
8
+
9
+ id: str
10
+ metadata: NotRequired[AuditLogMetadata]
11
+ name: NotRequired[str]
12
+ type: str
@@ -0,0 +1,8 @@
1
+ from typing_extensions import NotRequired, TypedDict
2
+
3
+
4
+ class AuditLogEventContext(TypedDict):
5
+ """Attributes of audit log event context."""
6
+
7
+ location: str
8
+ user_agent: NotRequired[str]
@@ -0,0 +1,12 @@
1
+ from typing_extensions import NotRequired, TypedDict
2
+
3
+ from workos.types.audit_logs.audit_log_metadata import AuditLogMetadata
4
+
5
+
6
+ class AuditLogEventTarget(TypedDict):
7
+ """Describes the entity that was targeted by the event."""
8
+
9
+ id: str
10
+ metadata: NotRequired[AuditLogMetadata]
11
+ name: NotRequired[str]
12
+ type: str
@@ -0,0 +1,18 @@
1
+ from typing import Literal, Optional
2
+
3
+ from workos.types.workos_model import WorkOSModel
4
+ from workos.typing.literals import LiteralOrUntyped
5
+
6
+
7
+ AuditLogExportState = Literal["error", "pending", "ready"]
8
+
9
+
10
+ class AuditLogExport(WorkOSModel):
11
+ """Representation of a WorkOS audit logs export."""
12
+
13
+ object: Literal["audit_log_export"]
14
+ id: str
15
+ created_at: str
16
+ updated_at: str
17
+ state: LiteralOrUntyped[AuditLogExportState]
18
+ url: Optional[str] = None
@@ -0,0 +1,4 @@
1
+ from typing import Any, Mapping
2
+
3
+
4
+ AuditLogMetadata = Mapping[str, Any]
@@ -0,0 +1,5 @@
1
+ from .directory_group import *
2
+ from .directory_state import *
3
+ from .directory_type import *
4
+ from .directory_user import *
5
+ from .directory import *
@@ -0,0 +1,31 @@
1
+ from typing import Literal, Optional
2
+ from workos.types.workos_model import WorkOSModel
3
+ from workos.types.directory_sync.directory_state import DirectoryState
4
+ from workos.types.directory_sync.directory_type import DirectoryType
5
+ from workos.typing.literals import LiteralOrUntyped
6
+
7
+
8
+ class DirectoryUsersMetadata(WorkOSModel):
9
+ active: int
10
+ inactive: int
11
+
12
+
13
+ class DirectoryMetadata(WorkOSModel):
14
+ users: DirectoryUsersMetadata
15
+ groups: int
16
+
17
+
18
+ class Directory(WorkOSModel):
19
+ """Representation of a Directory Response as returned by WorkOS through the Directory Sync feature."""
20
+
21
+ id: str
22
+ object: Literal["directory"]
23
+ domain: Optional[str] = None
24
+ name: str
25
+ organization_id: str
26
+ external_key: str
27
+ state: LiteralOrUntyped[DirectoryState]
28
+ type: LiteralOrUntyped[DirectoryType]
29
+ metadata: Optional[DirectoryMetadata] = None
30
+ created_at: str
31
+ updated_at: str
@@ -0,0 +1,16 @@
1
+ from typing import Any, Literal, Mapping
2
+ from workos.types.workos_model import WorkOSModel
3
+
4
+
5
+ class DirectoryGroup(WorkOSModel):
6
+ """Representation of a Directory Group as returned by WorkOS through the Directory Sync feature."""
7
+
8
+ id: str
9
+ object: Literal["directory_group"]
10
+ idp_id: str
11
+ name: str
12
+ directory_id: str
13
+ organization_id: str
14
+ raw_attributes: Mapping[str, Any]
15
+ created_at: str
16
+ updated_at: str