workos 5.29.0__tar.gz → 5.31.0__tar.gz
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-5.29.0 → workos-5.31.0}/PKG-INFO +1 -1
- {workos-5.29.0 → workos-5.31.0}/tests/test_session.py +7 -0
- {workos-5.29.0 → workos-5.31.0}/tests/test_user_management.py +31 -0
- workos-5.31.0/tests/test_user_management_list_sessions.py +73 -0
- workos-5.31.0/tests/test_user_management_revoke_session.py +47 -0
- {workos-5.29.0 → workos-5.31.0}/workos/__about__.py +1 -1
- {workos-5.29.0 → workos-5.31.0}/workos/session.py +4 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/list_resource.py +2 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/user_management/__init__.py +1 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/user_management/authenticate_with_common.py +1 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/user_management/list_filters.py +4 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/user_management/session.py +32 -0
- {workos-5.29.0 → workos-5.31.0}/workos/user_management.py +125 -0
- {workos-5.29.0 → workos-5.31.0}/workos.egg-info/PKG-INFO +1 -1
- {workos-5.29.0 → workos-5.31.0}/workos.egg-info/SOURCES.txt +2 -0
- {workos-5.29.0 → workos-5.31.0}/LICENSE +0 -0
- {workos-5.29.0 → workos-5.31.0}/README.md +0 -0
- {workos-5.29.0 → workos-5.31.0}/setup.cfg +0 -0
- {workos-5.29.0 → workos-5.31.0}/setup.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/tests/test_async_http_client.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/tests/test_audit_logs.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/tests/test_client.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/tests/test_directory_sync.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/tests/test_events.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/tests/test_fga.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/tests/test_mfa.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/tests/test_organization_domains.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/tests/test_organizations.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/tests/test_passwordless.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/tests/test_portal.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/tests/test_sso.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/tests/test_sync_http_client.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/tests/test_vault.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/tests/test_webhooks.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/tests/test_widgets.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/__init__.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/_base_client.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/_client_configuration.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/async_client.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/audit_logs.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/client.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/directory_sync.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/events.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/exceptions.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/fga.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/mfa.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/organization_domains.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/organizations.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/passwordless.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/portal.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/py.typed +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/sso.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/__init__.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/audit_logs/__init__.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/audit_logs/audit_log_event.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/audit_logs/audit_log_event_actor.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/audit_logs/audit_log_event_context.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/audit_logs/audit_log_event_target.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/audit_logs/audit_log_export.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/audit_logs/audit_log_metadata.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/directory_sync/__init__.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/directory_sync/directory.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/directory_sync/directory_group.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/directory_sync/directory_state.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/directory_sync/directory_type.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/directory_sync/directory_user.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/directory_sync/list_filters.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/events/__init__.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/events/authentication_payload.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/events/connection_payload_with_legacy_fields.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/events/directory_group_membership_payload.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/events/directory_group_with_previous_attributes.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/events/directory_payload.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/events/directory_payload_with_legacy_fields.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/events/directory_user_with_previous_attributes.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/events/event.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/events/event_model.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/events/event_type.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/events/list_filters.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/events/organization_domain_verification_failed_payload.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/events/previous_attributes.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/events/session_created_payload.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/feature_flags/__init__.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/feature_flags/feature_flag.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/feature_flags/list_filters.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/fga/__init__.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/fga/authorization_resource_types.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/fga/authorization_resources.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/fga/check.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/fga/list_filters.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/fga/warnings.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/fga/warrant.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/metadata.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/mfa/__init__.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/mfa/authentication_challenge.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/mfa/authentication_challenge_verification_response.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/mfa/authentication_factor.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/mfa/authentication_factor_totp_and_challenge_response.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/mfa/enroll_authentication_factor_type.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/organization_domains/__init__.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/organization_domains/organization_domain.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/organizations/__init__.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/organizations/domain_data_input.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/organizations/list_filters.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/organizations/organization.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/organizations/organization_common.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/passwordless/__init__.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/passwordless/passwordless_session.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/passwordless/passwordless_session_type.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/portal/__init__.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/portal/portal_link.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/portal/portal_link_intent.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/portal/portal_link_intent_options.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/roles/__init__.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/roles/role.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/sso/__init__.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/sso/connection.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/sso/connection_domain.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/sso/profile.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/sso/sso_provider_type.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/user_management/authentication_response.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/user_management/email_verification.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/user_management/impersonator.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/user_management/invitation.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/user_management/magic_auth.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/user_management/oauth_tokens.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/user_management/organization_membership.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/user_management/password_hash_type.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/user_management/password_reset.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/user_management/screen_hint.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/user_management/user.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/user_management/user_management_provider_type.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/vault/__init__.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/vault/key.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/vault/object.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/webhooks/__init__.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/webhooks/webhook.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/webhooks/webhook_model.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/webhooks/webhook_payload.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/widgets/__init__.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/widgets/widget_scope.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/widgets/widget_token_response.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/types/workos_model.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/typing/__init__.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/typing/literals.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/typing/sync_or_async.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/typing/untyped_literal.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/typing/webhooks.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/utils/__init__.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/utils/_base_http_client.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/utils/crypto_provider.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/utils/http_client.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/utils/pagination_order.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/utils/request_helper.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/vault.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/webhooks.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos/widgets.py +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos.egg-info/dependency_links.txt +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos.egg-info/not-zip-safe +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos.egg-info/requires.txt +0 -0
- {workos-5.29.0 → workos-5.31.0}/workos.egg-info/top_level.txt +0 -0
|
@@ -51,6 +51,7 @@ class SessionFixtures:
|
|
|
51
51
|
"roles": ["admin"],
|
|
52
52
|
"permissions": ["read"],
|
|
53
53
|
"entitlements": ["feature_1"],
|
|
54
|
+
"feature_flags": ["flag1", "flag2"],
|
|
54
55
|
"exp": int(current_datetime.timestamp()) + 3600,
|
|
55
56
|
"iat": int(current_datetime.timestamp()),
|
|
56
57
|
}
|
|
@@ -244,6 +245,7 @@ class TestSessionBase(SessionFixtures):
|
|
|
244
245
|
"roles": ["admin"],
|
|
245
246
|
"permissions": ["read"],
|
|
246
247
|
"entitlements": ["feature_1"],
|
|
248
|
+
"feature_flags": ["flag1", "flag2"],
|
|
247
249
|
}
|
|
248
250
|
|
|
249
251
|
with patch.object(Session, "unseal_data", return_value=mock_session), patch(
|
|
@@ -263,6 +265,7 @@ class TestSessionBase(SessionFixtures):
|
|
|
263
265
|
assert response.roles == ["admin"]
|
|
264
266
|
assert response.permissions == ["read"]
|
|
265
267
|
assert response.entitlements == ["feature_1"]
|
|
268
|
+
assert response.feature_flags == ["flag1", "flag2"]
|
|
266
269
|
assert response.user.id == session_constants["USER_ID"]
|
|
267
270
|
assert response.impersonator is None
|
|
268
271
|
|
|
@@ -312,6 +315,7 @@ class TestSessionBase(SessionFixtures):
|
|
|
312
315
|
"roles": ["admin", "member"],
|
|
313
316
|
"permissions": ["read", "write"],
|
|
314
317
|
"entitlements": ["feature_1"],
|
|
318
|
+
"feature_flags": ["flag1", "flag2"],
|
|
315
319
|
}
|
|
316
320
|
|
|
317
321
|
with patch.object(Session, "unseal_data", return_value=mock_session), patch(
|
|
@@ -331,6 +335,7 @@ class TestSessionBase(SessionFixtures):
|
|
|
331
335
|
assert response.roles == ["admin", "member"]
|
|
332
336
|
assert response.permissions == ["read", "write"]
|
|
333
337
|
assert response.entitlements == ["feature_1"]
|
|
338
|
+
assert response.feature_flags == ["flag1", "flag2"]
|
|
334
339
|
assert response.user.id == session_constants["USER_ID"]
|
|
335
340
|
assert response.impersonator is None
|
|
336
341
|
|
|
@@ -410,6 +415,7 @@ class TestSession(SessionFixtures):
|
|
|
410
415
|
"roles": ["admin"],
|
|
411
416
|
"permissions": ["read"],
|
|
412
417
|
"entitlements": ["feature_1"],
|
|
418
|
+
"feature_flags": ["flag1", "flag2"],
|
|
413
419
|
},
|
|
414
420
|
):
|
|
415
421
|
response = session.refresh()
|
|
@@ -511,6 +517,7 @@ class TestAsyncSession(SessionFixtures):
|
|
|
511
517
|
"roles": ["admin"],
|
|
512
518
|
"permissions": ["read"],
|
|
513
519
|
"entitlements": ["feature_1"],
|
|
520
|
+
"feature_flags": ["flag1", "flag2"],
|
|
514
521
|
},
|
|
515
522
|
):
|
|
516
523
|
response = await session.refresh()
|
|
@@ -718,6 +718,37 @@ class TestUserManagement(UserManagementFixtures):
|
|
|
718
718
|
"grant_type": "authorization_code",
|
|
719
719
|
}
|
|
720
720
|
|
|
721
|
+
def test_authenticate_with_code_with_invitation_token(
|
|
722
|
+
self,
|
|
723
|
+
capture_and_mock_http_client_request,
|
|
724
|
+
mock_auth_response,
|
|
725
|
+
base_authentication_params,
|
|
726
|
+
):
|
|
727
|
+
params = {
|
|
728
|
+
"code": "test_code",
|
|
729
|
+
"code_verifier": "test_code_verifier",
|
|
730
|
+
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
|
|
731
|
+
"ip_address": "192.0.0.1",
|
|
732
|
+
"invitation_token": "invitation_token_12345",
|
|
733
|
+
}
|
|
734
|
+
request_kwargs = capture_and_mock_http_client_request(
|
|
735
|
+
self.http_client, mock_auth_response, 200
|
|
736
|
+
)
|
|
737
|
+
|
|
738
|
+
response = syncify(self.user_management.authenticate_with_code(**params))
|
|
739
|
+
|
|
740
|
+
assert request_kwargs["url"].endswith("user_management/authenticate")
|
|
741
|
+
assert request_kwargs["method"] == "post"
|
|
742
|
+
assert response.user.id == "user_01H7ZGXFP5C6BBQY6Z7277ZCT0"
|
|
743
|
+
assert response.organization_id == "org_12345"
|
|
744
|
+
assert response.access_token == "access_token_12345"
|
|
745
|
+
assert response.refresh_token == "refresh_token_12345"
|
|
746
|
+
assert request_kwargs["json"] == {
|
|
747
|
+
**params,
|
|
748
|
+
**base_authentication_params,
|
|
749
|
+
"grant_type": "authorization_code",
|
|
750
|
+
}
|
|
751
|
+
|
|
721
752
|
def test_authenticate_with_magic_auth(
|
|
722
753
|
self,
|
|
723
754
|
capture_and_mock_http_client_request,
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from typing import Union
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from tests.utils.list_resource import list_response_of
|
|
6
|
+
from tests.utils.syncify import syncify
|
|
7
|
+
from tests.types.test_auto_pagination_function import TestAutoPaginationFunction
|
|
8
|
+
from workos.user_management import AsyncUserManagement, UserManagement
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _mock_session(id: str):
|
|
12
|
+
now = "2025-07-23T14:00:00.000Z"
|
|
13
|
+
return {
|
|
14
|
+
"object": "session",
|
|
15
|
+
"id": id,
|
|
16
|
+
"user_id": "user_123",
|
|
17
|
+
"organization_id": "org_123",
|
|
18
|
+
"status": "active",
|
|
19
|
+
"auth_method": "password",
|
|
20
|
+
"impersonator": None,
|
|
21
|
+
"ip_address": "192.168.1.1",
|
|
22
|
+
"user_agent": "Mozilla/5.0",
|
|
23
|
+
"expires_at": "2025-07-23T15:00:00.000Z",
|
|
24
|
+
"ended_at": None,
|
|
25
|
+
"created_at": now,
|
|
26
|
+
"updated_at": now,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@pytest.mark.sync_and_async(UserManagement, AsyncUserManagement)
|
|
31
|
+
class TestUserManagementListSessions:
|
|
32
|
+
@pytest.fixture(autouse=True)
|
|
33
|
+
def setup(self, module_instance: Union[UserManagement, AsyncUserManagement]):
|
|
34
|
+
self.http_client = module_instance._http_client
|
|
35
|
+
self.user_management = module_instance
|
|
36
|
+
|
|
37
|
+
def test_list_sessions_query_and_parsing(
|
|
38
|
+
self, capture_and_mock_http_client_request
|
|
39
|
+
):
|
|
40
|
+
sessions = [_mock_session("session_1"), _mock_session("session_2")]
|
|
41
|
+
response = list_response_of(data=sessions)
|
|
42
|
+
request_kwargs = capture_and_mock_http_client_request(
|
|
43
|
+
self.http_client, response, 200
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
result = syncify(
|
|
47
|
+
self.user_management.list_sessions(
|
|
48
|
+
user_id="user_123", limit=10, before="before_id", order="desc"
|
|
49
|
+
)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
assert request_kwargs["url"].endswith("user_management/users/user_123/sessions")
|
|
53
|
+
assert request_kwargs["method"] == "get"
|
|
54
|
+
assert request_kwargs["params"]["limit"] == 10
|
|
55
|
+
assert request_kwargs["params"]["before"] == "before_id"
|
|
56
|
+
assert request_kwargs["params"]["order"] == "desc"
|
|
57
|
+
assert "after" not in request_kwargs["params"]
|
|
58
|
+
assert len(result.data) == 2
|
|
59
|
+
assert result.data[0].id == "session_1"
|
|
60
|
+
assert result.list_metadata.before is None
|
|
61
|
+
assert result.list_metadata.after is None
|
|
62
|
+
|
|
63
|
+
def test_list_sessions_auto_pagination(
|
|
64
|
+
self, test_auto_pagination: TestAutoPaginationFunction
|
|
65
|
+
):
|
|
66
|
+
data = [_mock_session(str(i)) for i in range(40)]
|
|
67
|
+
test_auto_pagination(
|
|
68
|
+
http_client=self.http_client,
|
|
69
|
+
list_function=self.user_management.list_sessions,
|
|
70
|
+
list_function_params={"user_id": "user_123"},
|
|
71
|
+
expected_all_page_data=data,
|
|
72
|
+
url_path_keys=["user_id"],
|
|
73
|
+
)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from typing import Union
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from tests.utils.syncify import syncify
|
|
6
|
+
from workos.user_management import AsyncUserManagement, UserManagement
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _mock_session(id: str):
|
|
10
|
+
now = "2025-07-23T14:00:00.000Z"
|
|
11
|
+
return {
|
|
12
|
+
"object": "session",
|
|
13
|
+
"id": id,
|
|
14
|
+
"user_id": "user_123",
|
|
15
|
+
"organization_id": "org_123",
|
|
16
|
+
"status": "revoked",
|
|
17
|
+
"auth_method": "password",
|
|
18
|
+
"ip_address": "192.168.1.1",
|
|
19
|
+
"user_agent": "Mozilla/5.0",
|
|
20
|
+
"expires_at": "2025-07-23T15:00:00.000Z",
|
|
21
|
+
"ended_at": now,
|
|
22
|
+
"created_at": now,
|
|
23
|
+
"updated_at": now,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@pytest.mark.sync_and_async(UserManagement, AsyncUserManagement)
|
|
28
|
+
class TestUserManagementRevokeSession:
|
|
29
|
+
@pytest.fixture(autouse=True)
|
|
30
|
+
def setup(self, module_instance: Union[UserManagement, AsyncUserManagement]):
|
|
31
|
+
self.http_client = module_instance._http_client
|
|
32
|
+
self.user_management = module_instance
|
|
33
|
+
|
|
34
|
+
def test_revoke_session(self, capture_and_mock_http_client_request):
|
|
35
|
+
mock = _mock_session("session_abc")
|
|
36
|
+
request_kwargs = capture_and_mock_http_client_request(
|
|
37
|
+
self.http_client, mock, 200
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
response = syncify(
|
|
41
|
+
self.user_management.revoke_session(session_id="session_abc")
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
assert request_kwargs["url"].endswith("user_management/sessions/revoke")
|
|
45
|
+
assert request_kwargs["method"] == "post"
|
|
46
|
+
assert request_kwargs["json"] == {"session_id": "session_abc"}
|
|
47
|
+
assert response.id == "session_abc"
|
|
@@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, List, Protocol
|
|
|
4
4
|
from functools import lru_cache
|
|
5
5
|
import json
|
|
6
6
|
from typing import Any, Dict, Optional, Union, cast
|
|
7
|
+
|
|
7
8
|
import jwt
|
|
8
9
|
from jwt import PyJWKClient
|
|
9
10
|
from cryptography.fernet import Fernet
|
|
@@ -107,6 +108,7 @@ class SessionModule(Protocol):
|
|
|
107
108
|
entitlements=decoded.get("entitlements", None),
|
|
108
109
|
user=session["user"],
|
|
109
110
|
impersonator=session.get("impersonator", None),
|
|
111
|
+
feature_flags=decoded.get("feature_flags", None),
|
|
110
112
|
)
|
|
111
113
|
|
|
112
114
|
def refresh(
|
|
@@ -235,6 +237,7 @@ class Session(SessionModule):
|
|
|
235
237
|
entitlements=decoded.get("entitlements", None),
|
|
236
238
|
user=auth_response.user,
|
|
237
239
|
impersonator=auth_response.impersonator,
|
|
240
|
+
feature_flags=decoded.get("feature_flags", None),
|
|
238
241
|
)
|
|
239
242
|
except Exception as e:
|
|
240
243
|
return RefreshWithSessionCookieErrorResponse(
|
|
@@ -326,6 +329,7 @@ class AsyncSession(SessionModule):
|
|
|
326
329
|
entitlements=decoded.get("entitlements", None),
|
|
327
330
|
user=auth_response.user,
|
|
328
331
|
impersonator=auth_response.impersonator,
|
|
332
|
+
feature_flags=decoded.get("feature_flags", None),
|
|
329
333
|
)
|
|
330
334
|
except Exception as e:
|
|
331
335
|
return RefreshWithSessionCookieErrorResponse(
|
|
@@ -34,6 +34,7 @@ from workos.types.mfa import AuthenticationFactor
|
|
|
34
34
|
from workos.types.organizations import Organization
|
|
35
35
|
from workos.types.sso import ConnectionWithDomains
|
|
36
36
|
from workos.types.user_management import Invitation, OrganizationMembership, User
|
|
37
|
+
from workos.types.user_management.session import Session as UserManagementSession
|
|
37
38
|
from workos.types.vault import ObjectDigest
|
|
38
39
|
from workos.types.workos_model import WorkOSModel
|
|
39
40
|
from workos.utils.request_helper import DEFAULT_LIST_RESPONSE_LIMIT
|
|
@@ -54,6 +55,7 @@ ListableResource = TypeVar(
|
|
|
54
55
|
AuthorizationResource,
|
|
55
56
|
AuthorizationResourceType,
|
|
56
57
|
User,
|
|
58
|
+
UserManagementSession,
|
|
57
59
|
ObjectDigest,
|
|
58
60
|
Warrant,
|
|
59
61
|
WarrantQueryResult,
|
|
@@ -19,6 +19,7 @@ class AuthenticateWithCodeParameters(AuthenticateWithBaseParameters):
|
|
|
19
19
|
code_verifier: Union[str, None]
|
|
20
20
|
grant_type: Literal["authorization_code"]
|
|
21
21
|
session: Union[SessionConfig, None]
|
|
22
|
+
invitation_token: Union[str, None]
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
class AuthenticateWithMagicAuthParameters(AuthenticateWithBaseParameters):
|
|
@@ -24,6 +24,7 @@ class AuthenticateWithSessionCookieSuccessResponse(WorkOSModel):
|
|
|
24
24
|
user: User
|
|
25
25
|
impersonator: Optional[Impersonator] = None
|
|
26
26
|
entitlements: Optional[Sequence[str]] = None
|
|
27
|
+
feature_flags: Optional[Sequence[str]] = None
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
class AuthenticateWithSessionCookieErrorResponse(WorkOSModel):
|
|
@@ -45,3 +46,34 @@ class RefreshWithSessionCookieErrorResponse(WorkOSModel):
|
|
|
45
46
|
class SessionConfig(TypedDict, total=False):
|
|
46
47
|
seal_session: bool
|
|
47
48
|
cookie_password: str
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
AuthMethodType = Literal[
|
|
52
|
+
"external_auth",
|
|
53
|
+
"impersonation",
|
|
54
|
+
"magic_code",
|
|
55
|
+
"migrated_session",
|
|
56
|
+
"oauth",
|
|
57
|
+
"passkey",
|
|
58
|
+
"password",
|
|
59
|
+
"sso",
|
|
60
|
+
"unknown",
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class Session(WorkOSModel):
|
|
65
|
+
"""Representation of a WorkOS User Management Session."""
|
|
66
|
+
|
|
67
|
+
object: Literal["session"]
|
|
68
|
+
id: str
|
|
69
|
+
user_id: str
|
|
70
|
+
organization_id: Optional[str] = None
|
|
71
|
+
status: str
|
|
72
|
+
auth_method: AuthMethodType
|
|
73
|
+
impersonator: Optional[Impersonator] = None
|
|
74
|
+
ip_address: Optional[str] = None
|
|
75
|
+
user_agent: Optional[str] = None
|
|
76
|
+
expires_at: str
|
|
77
|
+
ended_at: Optional[str] = None
|
|
78
|
+
created_at: str
|
|
79
|
+
updated_at: str
|
|
@@ -48,6 +48,7 @@ from workos.types.user_management.list_filters import (
|
|
|
48
48
|
from workos.types.user_management.password_hash_type import PasswordHashType
|
|
49
49
|
from workos.types.user_management.screen_hint import ScreenHintType
|
|
50
50
|
from workos.types.user_management.session import SessionConfig
|
|
51
|
+
from workos.types.user_management.session import Session as UserManagementSession
|
|
51
52
|
from workos.types.user_management.user_management_provider_type import (
|
|
52
53
|
UserManagementProviderType,
|
|
53
54
|
)
|
|
@@ -86,6 +87,8 @@ MAGIC_AUTH_DETAIL_PATH = "user_management/magic_auth/{0}"
|
|
|
86
87
|
MAGIC_AUTH_PATH = "user_management/magic_auth"
|
|
87
88
|
USER_SEND_MAGIC_AUTH_PATH = "user_management/magic_auth/send"
|
|
88
89
|
USER_AUTH_FACTORS_PATH = "user_management/users/{0}/auth_factors"
|
|
90
|
+
USER_SESSIONS_PATH = "user_management/users/{0}/sessions"
|
|
91
|
+
SESSIONS_REVOKE_PATH = "user_management/sessions/revoke"
|
|
89
92
|
EMAIL_VERIFICATION_DETAIL_PATH = "user_management/email_verification/{0}"
|
|
90
93
|
INVITATION_PATH = "user_management/invitations"
|
|
91
94
|
INVITATION_DETAIL_PATH = "user_management/invitations/{0}"
|
|
@@ -109,6 +112,12 @@ InvitationsListResource = WorkOSListResource[
|
|
|
109
112
|
Invitation, InvitationsListFilters, ListMetadata
|
|
110
113
|
]
|
|
111
114
|
|
|
115
|
+
from workos.types.user_management.list_filters import SessionsListFilters
|
|
116
|
+
|
|
117
|
+
SessionsListResource = WorkOSListResource[
|
|
118
|
+
UserManagementSession, SessionsListFilters, ListMetadata
|
|
119
|
+
]
|
|
120
|
+
|
|
112
121
|
|
|
113
122
|
class UserManagementModule(Protocol):
|
|
114
123
|
"""Offers methods for using the WorkOS User Management API."""
|
|
@@ -488,6 +497,7 @@ class UserManagementModule(Protocol):
|
|
|
488
497
|
code_verifier: Optional[str] = None,
|
|
489
498
|
ip_address: Optional[str] = None,
|
|
490
499
|
user_agent: Optional[str] = None,
|
|
500
|
+
invitation_token: Optional[str] = None,
|
|
491
501
|
) -> SyncOrAsync[AuthenticationResponse]:
|
|
492
502
|
"""Authenticates an OAuth user or a user that is logging in through SSO.
|
|
493
503
|
|
|
@@ -498,6 +508,7 @@ class UserManagementModule(Protocol):
|
|
|
498
508
|
url as part of the PKCE flow. This parameter is required when the client secret is not present. (Optional)
|
|
499
509
|
ip_address (str): The IP address of the request from the user who is attempting to authenticate. (Optional)
|
|
500
510
|
user_agent (str): The user agent of the request from the user who is attempting to authenticate. (Optional)
|
|
511
|
+
invitation_token (str): The token of an Invitation, if required. (Optional)
|
|
501
512
|
|
|
502
513
|
Returns:
|
|
503
514
|
AuthenticationResponse: Authentication response from WorkOS.
|
|
@@ -718,6 +729,20 @@ class UserManagementModule(Protocol):
|
|
|
718
729
|
"""
|
|
719
730
|
...
|
|
720
731
|
|
|
732
|
+
def list_sessions(
|
|
733
|
+
self,
|
|
734
|
+
*,
|
|
735
|
+
user_id: str,
|
|
736
|
+
limit: Optional[int] = None,
|
|
737
|
+
before: Optional[str] = None,
|
|
738
|
+
after: Optional[str] = None,
|
|
739
|
+
order: Optional[PaginationOrder] = "desc",
|
|
740
|
+
) -> SyncOrAsync["SessionsListResource"]: ...
|
|
741
|
+
|
|
742
|
+
def revoke_session(
|
|
743
|
+
self, *, session_id: str
|
|
744
|
+
) -> SyncOrAsync[UserManagementSession]: ...
|
|
745
|
+
|
|
721
746
|
def get_magic_auth(self, magic_auth_id: str) -> SyncOrAsync[MagicAuth]:
|
|
722
747
|
"""Get the details of a Magic Auth object.
|
|
723
748
|
|
|
@@ -1166,6 +1191,7 @@ class UserManagement(UserManagementModule):
|
|
|
1166
1191
|
code_verifier: Optional[str] = None,
|
|
1167
1192
|
ip_address: Optional[str] = None,
|
|
1168
1193
|
user_agent: Optional[str] = None,
|
|
1194
|
+
invitation_token: Optional[str] = None,
|
|
1169
1195
|
) -> AuthKitAuthenticationResponse:
|
|
1170
1196
|
if (
|
|
1171
1197
|
session is not None
|
|
@@ -1181,6 +1207,7 @@ class UserManagement(UserManagementModule):
|
|
|
1181
1207
|
"user_agent": user_agent,
|
|
1182
1208
|
"code_verifier": code_verifier,
|
|
1183
1209
|
"session": session,
|
|
1210
|
+
"invitation_token": invitation_token,
|
|
1184
1211
|
}
|
|
1185
1212
|
|
|
1186
1213
|
return self._authenticate_with(
|
|
@@ -1373,6 +1400,54 @@ class UserManagement(UserManagementModule):
|
|
|
1373
1400
|
|
|
1374
1401
|
return MagicAuth.model_validate(response)
|
|
1375
1402
|
|
|
1403
|
+
def list_sessions(
|
|
1404
|
+
self,
|
|
1405
|
+
*,
|
|
1406
|
+
user_id: str,
|
|
1407
|
+
limit: Optional[int] = DEFAULT_LIST_RESPONSE_LIMIT,
|
|
1408
|
+
before: Optional[str] = None,
|
|
1409
|
+
after: Optional[str] = None,
|
|
1410
|
+
order: Optional[PaginationOrder] = "desc",
|
|
1411
|
+
) -> "SessionsListResource":
|
|
1412
|
+
limit_value: int = limit if limit is not None else DEFAULT_LIST_RESPONSE_LIMIT
|
|
1413
|
+
|
|
1414
|
+
params: ListArgs = {
|
|
1415
|
+
"limit": limit_value,
|
|
1416
|
+
"before": before,
|
|
1417
|
+
"after": after,
|
|
1418
|
+
"order": order,
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
response = self._http_client.request(
|
|
1422
|
+
USER_SESSIONS_PATH.format(user_id),
|
|
1423
|
+
method=REQUEST_METHOD_GET,
|
|
1424
|
+
params=params,
|
|
1425
|
+
)
|
|
1426
|
+
|
|
1427
|
+
list_args: SessionsListFilters = {
|
|
1428
|
+
"limit": limit_value,
|
|
1429
|
+
"before": before,
|
|
1430
|
+
"after": after,
|
|
1431
|
+
"user_id": user_id,
|
|
1432
|
+
}
|
|
1433
|
+
if order is not None:
|
|
1434
|
+
list_args["order"] = order
|
|
1435
|
+
|
|
1436
|
+
return SessionsListResource(
|
|
1437
|
+
list_method=self.list_sessions,
|
|
1438
|
+
list_args=list_args,
|
|
1439
|
+
**ListPage[UserManagementSession](**response).model_dump(),
|
|
1440
|
+
)
|
|
1441
|
+
|
|
1442
|
+
def revoke_session(self, *, session_id: str) -> UserManagementSession:
|
|
1443
|
+
json = {"session_id": session_id}
|
|
1444
|
+
|
|
1445
|
+
response = self._http_client.request(
|
|
1446
|
+
SESSIONS_REVOKE_PATH, method=REQUEST_METHOD_POST, json=json
|
|
1447
|
+
)
|
|
1448
|
+
|
|
1449
|
+
return UserManagementSession.model_validate(response)
|
|
1450
|
+
|
|
1376
1451
|
def enroll_auth_factor(
|
|
1377
1452
|
self,
|
|
1378
1453
|
*,
|
|
@@ -1807,6 +1882,7 @@ class AsyncUserManagement(UserManagementModule):
|
|
|
1807
1882
|
code_verifier: Optional[str] = None,
|
|
1808
1883
|
ip_address: Optional[str] = None,
|
|
1809
1884
|
user_agent: Optional[str] = None,
|
|
1885
|
+
invitation_token: Optional[str] = None,
|
|
1810
1886
|
) -> AuthKitAuthenticationResponse:
|
|
1811
1887
|
if (
|
|
1812
1888
|
session is not None
|
|
@@ -1822,6 +1898,7 @@ class AsyncUserManagement(UserManagementModule):
|
|
|
1822
1898
|
"user_agent": user_agent,
|
|
1823
1899
|
"code_verifier": code_verifier,
|
|
1824
1900
|
"session": session,
|
|
1901
|
+
"invitation_token": invitation_token,
|
|
1825
1902
|
}
|
|
1826
1903
|
|
|
1827
1904
|
return await self._authenticate_with(
|
|
@@ -2027,6 +2104,54 @@ class AsyncUserManagement(UserManagementModule):
|
|
|
2027
2104
|
|
|
2028
2105
|
return MagicAuth.model_validate(response)
|
|
2029
2106
|
|
|
2107
|
+
async def list_sessions(
|
|
2108
|
+
self,
|
|
2109
|
+
*,
|
|
2110
|
+
user_id: str,
|
|
2111
|
+
limit: Optional[int] = DEFAULT_LIST_RESPONSE_LIMIT,
|
|
2112
|
+
before: Optional[str] = None,
|
|
2113
|
+
after: Optional[str] = None,
|
|
2114
|
+
order: Optional[PaginationOrder] = "desc",
|
|
2115
|
+
) -> "SessionsListResource":
|
|
2116
|
+
limit_value: int = limit if limit is not None else DEFAULT_LIST_RESPONSE_LIMIT
|
|
2117
|
+
|
|
2118
|
+
params: ListArgs = {
|
|
2119
|
+
"limit": limit_value,
|
|
2120
|
+
"before": before,
|
|
2121
|
+
"after": after,
|
|
2122
|
+
"order": order,
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2125
|
+
response = await self._http_client.request(
|
|
2126
|
+
USER_SESSIONS_PATH.format(user_id),
|
|
2127
|
+
method=REQUEST_METHOD_GET,
|
|
2128
|
+
params=params,
|
|
2129
|
+
)
|
|
2130
|
+
|
|
2131
|
+
list_args: SessionsListFilters = {
|
|
2132
|
+
"limit": limit_value,
|
|
2133
|
+
"before": before,
|
|
2134
|
+
"after": after,
|
|
2135
|
+
"user_id": user_id,
|
|
2136
|
+
}
|
|
2137
|
+
if order is not None:
|
|
2138
|
+
list_args["order"] = order
|
|
2139
|
+
|
|
2140
|
+
return SessionsListResource(
|
|
2141
|
+
list_method=self.list_sessions,
|
|
2142
|
+
list_args=list_args,
|
|
2143
|
+
**ListPage[UserManagementSession](**response).model_dump(),
|
|
2144
|
+
)
|
|
2145
|
+
|
|
2146
|
+
async def revoke_session(self, *, session_id: str) -> UserManagementSession:
|
|
2147
|
+
json = {"session_id": session_id}
|
|
2148
|
+
|
|
2149
|
+
response = await self._http_client.request(
|
|
2150
|
+
SESSIONS_REVOKE_PATH, method=REQUEST_METHOD_POST, json=json
|
|
2151
|
+
)
|
|
2152
|
+
|
|
2153
|
+
return UserManagementSession.model_validate(response)
|
|
2154
|
+
|
|
2030
2155
|
async def enroll_auth_factor(
|
|
2031
2156
|
self,
|
|
2032
2157
|
*,
|
|
@@ -16,6 +16,8 @@ tests/test_session.py
|
|
|
16
16
|
tests/test_sso.py
|
|
17
17
|
tests/test_sync_http_client.py
|
|
18
18
|
tests/test_user_management.py
|
|
19
|
+
tests/test_user_management_list_sessions.py
|
|
20
|
+
tests/test_user_management_revoke_session.py
|
|
19
21
|
tests/test_vault.py
|
|
20
22
|
tests/test_webhooks.py
|
|
21
23
|
tests/test_widgets.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{workos-5.29.0 → workos-5.31.0}/workos/types/events/connection_payload_with_legacy_fields.py
RENAMED
|
File without changes
|
|
File without changes
|
{workos-5.29.0 → workos-5.31.0}/workos/types/events/directory_group_with_previous_attributes.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{workos-5.29.0 → workos-5.31.0}/workos/types/events/directory_user_with_previous_attributes.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{workos-5.29.0 → workos-5.31.0}/workos/types/mfa/authentication_challenge_verification_response.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{workos-5.29.0 → workos-5.31.0}/workos/types/user_management/user_management_provider_type.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|