diff --git a/.changelog-pending/2026-05-26T13-24-07-b0eb6fb50f020df713d0233e344a6be05739f59e.md b/.changelog-pending/2026-05-26T13-24-07-b0eb6fb50f020df713d0233e344a6be05739f59e.md new file mode 100644 index 00000000..2916bb3d --- /dev/null +++ b/.changelog-pending/2026-05-26T13-24-07-b0eb6fb50f020df713d0233e344a6be05739f59e.md @@ -0,0 +1,72 @@ +* [#662](https://github.com/workos/workos-python/pull/662) feat(generated)!: regenerate from spec (10 changes) + + **⚠️ Breaking** + * **user_management:** Remove organization membership methods, move to new service + * Removed `list_organization_memberships`, `create_organization_membership`, `get_organization_membership`, `update_organization_membership`, `delete_organization_membership`, `deactivate_organization_membership`, and `reactivate_organization_membership` methods from UserManagement. + * Removed `RoleSingle` and `RoleMultiple` dataclasses from UserManagement. + * Organization membership management is now handled by the new `OrganizationMembershipService`. + * Client accessor renamed from `client.user_management_organization_membership_groups` to `client.organization_membership`. + * **organization_membership:** Add new OrganizationMembershipService with membership and group operations + * Created new `OrganizationMembershipService` with `list_organization_memberships`, `create_organization_membership`, `get_organization_membership`, `update_organization_membership`, `delete_organization_membership`, `deactivate_organization_membership`, `reactivate_organization_membership`, and `list_organization_membership_groups` methods. + * Added `RoleSingle` and `RoleMultiple` dataclasses to support role assignment. + * Added `AsyncOrganizationMembershipService` for async operations. + * **vault:** Replace hand-maintained Vault module with generated Vault service + * The old `workos.vault` module (`vault.py`) has been replaced by a generated `vault/_resource.py` service. Method renames: + * `read_object` → `get_kv` + * `read_object_by_name` → `get_name` + * `get_object_metadata` → removed (no direct equivalent) + * `list_objects` → `list_kv` + * `list_object_versions` → `list_kv_versions` + * `create_object` → `create_kv` + * `update_object` → `update_kv` + * `delete_object` → `delete_kv` + * `create_data_key(key_context=...)` → `create_data_key(context=...)` + * `decrypt_data_key` → `create_decrypt` + * Removed types: `DataKey`, `DataKeyPair`, `ObjectDigest`, `ObjectUpdateBy`. Replaced by new generated models (`CreateDataKeyResponse`, `DecryptResponse`, `ObjectMetadata`, `ObjectSummary`, `ObjectWithoutValue`, `VaultObject`, etc.). + * Added new methods: `create_rekey`, `list_kv_metadata`. + * Added `AsyncVault` for async operations. + * Client-side `encrypt`/`decrypt` (AES-GCM) methods are preserved with the same signatures. + * **connect:** `ConnectApplication` is now a discriminated union + * `ConnectApplication` was a single dataclass; it is now a discriminated union dispatcher based on `application_type`. + * All Connect methods (`list_applications`, `create_application`, `get_application`, `update_application`) now return `ConnectApplicationVariant` (a union of `ConnectApplicationM2M`, `ConnectApplicationOAuth`, or `ConnectApplicationUnknown`). + * Code using `isinstance(x, ConnectApplication)` or accessing type-specific fields without checking the variant will need updating. + * **radar:** Remove device_fingerprint and bot_score parameters from assess request + * Removed `device_fingerprint` and `bot_score` optional parameters from `Radar.create_attempt` and `AsyncRadar.create_attempt` methods. + * Removed these fields from `RadarStandaloneAssessRequest` model. + * **radar:** Rename radar list/action enums and remove enum values + * Renamed `RadarAction` to `RadarListAction` and `RadarType` to `RadarListType` (affects `add_list_entry` and `remove_list_entry` method signatures). + * `RadarStandaloneResponseBlocklistType` is now a lazy re-export alias of `RadarListType`. + * Removed `credential_stuffing` and `ip_sign_up_rate_limit` values from `RadarStandaloneResponseControl` enum. + * Removed `login`, `signup`, `sign_up`, and `sign_in` values from `RadarStandaloneAssessRequestAction` enum; only `sign-up` and `sign-in` remain. + * **authorization:** Remove search parameter and add resource/role filtering + * Removed `search` parameter from `Authorization.list_resources` and `AsyncAuthorization.list_resources`. + * Added `resource_id`, `resource_external_id`, `resource_type_slug` parameters to `list_role_assignments` method. + * Added `role_slug` parameter to `list_role_assignments_for_resource_by_external_id` and `list_role_assignments_for_resource` methods. + * **api_keys:** Add expires_at field to API key models + * Added `expires_at` optional field to `CreateOrganizationApiKey` model. + * Added `expires_at` optional field to `CreateUserApiKey` model. + * Added `expires_at` to organizational and user API key models (OrganizationApiKey, OrganizationApiKeyWithValue, UserApiKey, UserApiKeyWithValue). + * Added `expires_at` parameter to `create_organization_api_key` and `create_user_api_key` methods. + * **audit_logs:** Rename audit log models and update service references + * Renamed `AuditLogActionJson` to `AuditLogAction`. + * Renamed `AuditLogExportJson` to `AuditLogExport`. + * Renamed `AuditLogSchemaJson` to `AuditLogSchema`. + * Renamed `AuditLogSchemaJsonActor` to `AuditLogSchemaActorInput` and `AuditLogSchemaJsonTarget` to `AuditLogSchemaTargetInput`. + * Added new `AuditLogSchemaInput` model (used for schema creation payloads). + * Renamed `AuditLogsRetentionJson` to `AuditLogsRetention`. + * Updated all service methods to use new model names. + * **webhooks:** Rename WebhookEndpointJson to WebhookEndpoint + * Renamed `WebhookEndpointJson` model to `WebhookEndpoint`. + * Updated all service methods to use the new model name. + * Updated webhook endpoint status references. + + **Features** + * **common:** Add new models for pipes events and enhancements + * Added `Actor` model representing the user or API key that performed an action. + * Added `Error` model for error response bodies. + * Added `PipeConnectedAccount` model with state enumeration. + * Added pipe event models: `PipesConnectedAccountConnected`, `PipesConnectedAccountDisconnected`, `PipesConnectedAccountReauthorizationNeeded`. + * Added webhook event enum values for pipes connected account events. + * Renamed `AuditLogExportJsonState` to `AuditLogExportState`. + * Renamed `WebhookEndpointJsonStatus` to `WebhookEndpointStatus`. + * Updated `UserManagementAuthenticationScreenHint` to use `RadarStandaloneAssessRequestAction` type alias. diff --git a/.last-synced-sha b/.last-synced-sha index 047fc7ee..ad25d3d1 100644 --- a/.last-synced-sha +++ b/.last-synced-sha @@ -1 +1 @@ -a10d9ecb766d2dd996aecb19aa9c801d78bb7c26 +cb6857d51b453e3cbdb5bf3647d3ca229dd8af65 diff --git a/.oagen-manifest.json b/.oagen-manifest.json index 5232cb40..33a4fb50 100644 --- a/.oagen-manifest.json +++ b/.oagen-manifest.json @@ -1,7 +1,7 @@ { "version": 2, "language": "python", - "generatedAt": "2026-05-11T15:56:51.952Z", + "generatedAt": "2026-05-26T19:47:29.645Z", "files": [ "src/workos/_client.py", "src/workos/admin_portal/__init__.py", @@ -27,21 +27,21 @@ "src/workos/audit_logs/__init__.py", "src/workos/audit_logs/_resource.py", "src/workos/audit_logs/models/__init__.py", - "src/workos/audit_logs/models/audit_log_action_json.py", + "src/workos/audit_logs/models/audit_log_action.py", "src/workos/audit_logs/models/audit_log_event.py", "src/workos/audit_logs/models/audit_log_event_actor.py", "src/workos/audit_logs/models/audit_log_event_context.py", "src/workos/audit_logs/models/audit_log_event_create_response.py", "src/workos/audit_logs/models/audit_log_event_ingestion.py", "src/workos/audit_logs/models/audit_log_event_target.py", + "src/workos/audit_logs/models/audit_log_export.py", "src/workos/audit_logs/models/audit_log_export_creation.py", - "src/workos/audit_logs/models/audit_log_export_json.py", "src/workos/audit_logs/models/audit_log_schema.py", "src/workos/audit_logs/models/audit_log_schema_actor.py", - "src/workos/audit_logs/models/audit_log_schema_json.py", - "src/workos/audit_logs/models/audit_log_schema_json_actor.py", - "src/workos/audit_logs/models/audit_log_schema_json_target.py", + "src/workos/audit_logs/models/audit_log_schema_actor_input.py", + "src/workos/audit_logs/models/audit_log_schema_input.py", "src/workos/audit_logs/models/audit_log_schema_target.py", + "src/workos/audit_logs/models/audit_log_schema_target_input.py", "src/workos/authorization/__init__.py", "src/workos/authorization/_resource.py", "src/workos/authorization/models/__init__.py", @@ -71,6 +71,7 @@ "src/workos/common/models/action_authentication_denied_data.py", "src/workos/common/models/action_user_registration_denied.py", "src/workos/common/models/action_user_registration_denied_data.py", + "src/workos/common/models/actor.py", "src/workos/common/models/add_role_permission.py", "src/workos/common/models/api_key_created.py", "src/workos/common/models/api_key_created_data.py", @@ -81,7 +82,7 @@ "src/workos/common/models/audit_log_configuration_log_stream_state.py", "src/workos/common/models/audit_log_configuration_log_stream_type.py", "src/workos/common/models/audit_log_configuration_state.py", - "src/workos/common/models/audit_log_export_json_state.py", + "src/workos/common/models/audit_log_export_state.py", "src/workos/common/models/authenticate_response_authentication_method.py", "src/workos/common/models/authenticate_response_impersonator.py", "src/workos/common/models/authentication_challenge.py", @@ -143,6 +144,9 @@ "src/workos/common/models/authentication_sso_timed_out_data_sso.py", "src/workos/common/models/authorization_permission.py", "src/workos/common/models/connect_application.py", + "src/workos/common/models/connect_application_m2m.py", + "src/workos/common/models/connect_application_oauth.py", + "src/workos/common/models/connect_application_oauth_redirect_uris.py", "src/workos/common/models/connected_account_state.py", "src/workos/common/models/connection_activated.py", "src/workos/common/models/connection_activated_data.py", @@ -216,6 +220,7 @@ "src/workos/common/models/dsync_user_updated_data_state.py", "src/workos/common/models/email_verification_created.py", "src/workos/common/models/email_verification_created_data.py", + "src/workos/common/models/error_response.py", "src/workos/common/models/event_context.py", "src/workos/common/models/event_context_actor.py", "src/workos/common/models/event_context_actor_source.py", @@ -355,6 +360,11 @@ "src/workos/common/models/permission_deleted_data.py", "src/workos/common/models/permission_updated.py", "src/workos/common/models/permission_updated_data.py", + "src/workos/common/models/pipe_connected_account.py", + "src/workos/common/models/pipe_connected_account_state.py", + "src/workos/common/models/pipes_connected_account_connected.py", + "src/workos/common/models/pipes_connected_account_disconnected.py", + "src/workos/common/models/pipes_connected_account_reauthorization_needed.py", "src/workos/common/models/profile_connection_type.py", "src/workos/common/models/radar_standalone_assess_request_action.py", "src/workos/common/models/radar_standalone_assess_request_auth_method.py", @@ -435,7 +445,7 @@ "src/workos/common/models/waitlist_user_created.py", "src/workos/common/models/waitlist_user_denied.py", "src/workos/common/models/waitlist_user_state.py", - "src/workos/common/models/webhook_endpoint_json_status.py", + "src/workos/common/models/webhook_endpoint_status.py", "src/workos/common/models/widget_session_token_scopes.py", "src/workos/connect/__init__.py", "src/workos/connect/_resource.py", @@ -488,12 +498,20 @@ "src/workos/organization_domains/models/__init__.py", "src/workos/organization_domains/models/create_organization_domain.py", "src/workos/organization_domains/models/organization_domain_stand_alone.py", + "src/workos/organization_membership/__init__.py", + "src/workos/organization_membership/_resource.py", + "src/workos/organization_membership/models/__init__.py", + "src/workos/organization_membership/models/create_user_organization_membership.py", + "src/workos/organization_membership/models/organization_membership.py", + "src/workos/organization_membership/models/update_user_organization_membership.py", + "src/workos/organization_membership/models/user_management_organization_membership_statuses.py", + "src/workos/organization_membership/models/user_organization_membership.py", "src/workos/organizations/__init__.py", "src/workos/organizations/_resource.py", "src/workos/organizations/models/__init__.py", "src/workos/organizations/models/audit_log_configuration.py", "src/workos/organizations/models/audit_log_configuration_log_stream.py", - "src/workos/organizations/models/audit_logs_retention_json.py", + "src/workos/organizations/models/audit_logs_retention.py", "src/workos/organizations/models/organization.py", "src/workos/organizations/models/organization_domain_data.py", "src/workos/organizations/models/organization_input.py", @@ -514,14 +532,14 @@ "src/workos/radar/__init__.py", "src/workos/radar/_resource.py", "src/workos/radar/models/__init__.py", - "src/workos/radar/models/radar_action.py", + "src/workos/radar/models/radar_list_action.py", "src/workos/radar/models/radar_list_entry_already_present_response.py", + "src/workos/radar/models/radar_list_type.py", "src/workos/radar/models/radar_standalone_assess_request.py", "src/workos/radar/models/radar_standalone_delete_radar_list_entry_request.py", "src/workos/radar/models/radar_standalone_response.py", "src/workos/radar/models/radar_standalone_update_radar_attempt_request.py", "src/workos/radar/models/radar_standalone_update_radar_list_request.py", - "src/workos/radar/models/radar_type.py", "src/workos/sso/__init__.py", "src/workos/sso/_resource.py", "src/workos/sso/models/__init__.py", @@ -549,12 +567,13 @@ "src/workos/types/groups/__init__.py", "src/workos/types/multi_factor_auth/__init__.py", "src/workos/types/organization_domains/__init__.py", + "src/workos/types/organization_membership/__init__.py", "src/workos/types/organizations/__init__.py", "src/workos/types/pipes/__init__.py", "src/workos/types/radar/__init__.py", "src/workos/types/sso/__init__.py", "src/workos/types/user_management/__init__.py", - "src/workos/types/user_management_organization_membership_groups/__init__.py", + "src/workos/types/vault/__init__.py", "src/workos/types/webhooks/__init__.py", "src/workos/types/widgets/__init__.py", "src/workos/user_management/__init__.py", @@ -574,7 +593,6 @@ "src/workos/user_management/models/create_user.py", "src/workos/user_management/models/create_user_api_key.py", "src/workos/user_management/models/create_user_invite_options.py", - "src/workos/user_management/models/create_user_organization_membership.py", "src/workos/user_management/models/device_authorization_response.py", "src/workos/user_management/models/device_code_session_authenticate_request.py", "src/workos/user_management/models/email_change.py", @@ -589,7 +607,6 @@ "src/workos/user_management/models/magic_auth.py", "src/workos/user_management/models/magic_auth_code_session_authenticate_request.py", "src/workos/user_management/models/mfa_totp_session_authenticate_request.py", - "src/workos/user_management/models/organization_membership.py", "src/workos/user_management/models/organization_selection_session_authenticate_request.py", "src/workos/user_management/models/password_reset.py", "src/workos/user_management/models/password_session_authenticate_request.py", @@ -603,7 +620,6 @@ "src/workos/user_management/models/sso_device_authorization_request.py", "src/workos/user_management/models/update_jwt_template.py", "src/workos/user_management/models/update_user.py", - "src/workos/user_management/models/update_user_organization_membership.py", "src/workos/user_management/models/user_api_key.py", "src/workos/user_management/models/user_api_key_owner.py", "src/workos/user_management/models/user_api_key_with_value.py", @@ -612,19 +628,33 @@ "src/workos/user_management/models/user_invite.py", "src/workos/user_management/models/user_management_authentication_provider.py", "src/workos/user_management/models/user_management_authentication_screen_hint.py", - "src/workos/user_management/models/user_management_organization_membership_statuses.py", - "src/workos/user_management/models/user_organization_membership.py", "src/workos/user_management/models/verify_email_address.py", "src/workos/user_management/models/verify_email_response.py", - "src/workos/user_management_organization_membership_groups/__init__.py", - "src/workos/user_management_organization_membership_groups/_resource.py", - "src/workos/user_management_organization_membership_groups/models/__init__.py", + "src/workos/vault/__init__.py", + "src/workos/vault/_resource.py", + "src/workos/vault/models/__init__.py", + "src/workos/vault/models/create_data_key_request.py", + "src/workos/vault/models/create_data_key_response.py", + "src/workos/vault/models/create_object_request.py", + "src/workos/vault/models/decrypt_request.py", + "src/workos/vault/models/decrypt_response.py", + "src/workos/vault/models/delete_object_response.py", + "src/workos/vault/models/list_metadata.py", + "src/workos/vault/models/object_metadata.py", + "src/workos/vault/models/object_summary.py", + "src/workos/vault/models/object_version.py", + "src/workos/vault/models/object_without_value.py", + "src/workos/vault/models/rekey_request.py", + "src/workos/vault/models/update_object_request.py", + "src/workos/vault/models/vault_object.py", + "src/workos/vault/models/vault_order.py", + "src/workos/vault/models/version_list_response.py", "src/workos/webhooks/__init__.py", "src/workos/webhooks/_resource.py", "src/workos/webhooks/models/__init__.py", "src/workos/webhooks/models/create_webhook_endpoint.py", "src/workos/webhooks/models/update_webhook_endpoint.py", - "src/workos/webhooks/models/webhook_endpoint_json.py", + "src/workos/webhooks/models/webhook_endpoint.py", "src/workos/widgets/__init__.py", "src/workos/widgets/_resource.py", "src/workos/widgets/models/__init__.py", @@ -634,6 +664,7 @@ "tests/fixtures/action_authentication_denied_data.json", "tests/fixtures/action_user_registration_denied.json", "tests/fixtures/action_user_registration_denied_data.json", + "tests/fixtures/actor.json", "tests/fixtures/add_role_permission.json", "tests/fixtures/api_key.json", "tests/fixtures/api_key_created.json", @@ -646,7 +677,7 @@ "tests/fixtures/api_key_validation_response.json", "tests/fixtures/application_credentials_list_item.json", "tests/fixtures/assign_role.json", - "tests/fixtures/audit_log_action_json.json", + "tests/fixtures/audit_log_action.json", "tests/fixtures/audit_log_configuration.json", "tests/fixtures/audit_log_configuration_log_stream.json", "tests/fixtures/audit_log_event.json", @@ -655,15 +686,15 @@ "tests/fixtures/audit_log_event_create_response.json", "tests/fixtures/audit_log_event_ingestion.json", "tests/fixtures/audit_log_event_target.json", + "tests/fixtures/audit_log_export.json", "tests/fixtures/audit_log_export_creation.json", - "tests/fixtures/audit_log_export_json.json", "tests/fixtures/audit_log_schema.json", "tests/fixtures/audit_log_schema_actor.json", - "tests/fixtures/audit_log_schema_json.json", - "tests/fixtures/audit_log_schema_json_actor.json", - "tests/fixtures/audit_log_schema_json_target.json", + "tests/fixtures/audit_log_schema_actor_input.json", + "tests/fixtures/audit_log_schema_input.json", "tests/fixtures/audit_log_schema_target.json", - "tests/fixtures/audit_logs_retention_json.json", + "tests/fixtures/audit_log_schema_target_input.json", + "tests/fixtures/audit_logs_retention.json", "tests/fixtures/authenticate_response.json", "tests/fixtures/authenticate_response_impersonator.json", "tests/fixtures/authenticate_response_oauth_token.json", @@ -732,6 +763,9 @@ "tests/fixtures/check_authorization.json", "tests/fixtures/confirm_email_change.json", "tests/fixtures/connect_application.json", + "tests/fixtures/connect_application_m2m.json", + "tests/fixtures/connect_application_oauth.json", + "tests/fixtures/connect_application_oauth_redirect_uris.json", "tests/fixtures/connected_account.json", "tests/fixtures/connection.json", "tests/fixtures/connection_activated.json", @@ -756,11 +790,14 @@ "tests/fixtures/create_authorization_permission.json", "tests/fixtures/create_authorization_resource.json", "tests/fixtures/create_cors_origin.json", + "tests/fixtures/create_data_key_request.json", + "tests/fixtures/create_data_key_response.json", "tests/fixtures/create_group.json", "tests/fixtures/create_group_membership.json", "tests/fixtures/create_m2m_application.json", "tests/fixtures/create_magic_code_and_return.json", "tests/fixtures/create_oauth_application.json", + "tests/fixtures/create_object_request.json", "tests/fixtures/create_organization_api_key.json", "tests/fixtures/create_organization_domain.json", "tests/fixtures/create_organization_role.json", @@ -781,6 +818,9 @@ "tests/fixtures/data_integrations_list_response.json", "tests/fixtures/data_integrations_list_response_data.json", "tests/fixtures/data_integrations_list_response_data_connected_account.json", + "tests/fixtures/decrypt_request.json", + "tests/fixtures/decrypt_response.json", + "tests/fixtures/delete_object_response.json", "tests/fixtures/device_authorization_response.json", "tests/fixtures/device_code_session_authenticate_request.json", "tests/fixtures/directory.json", @@ -821,6 +861,7 @@ "tests/fixtures/email_verification_created.json", "tests/fixtures/email_verification_created_data.json", "tests/fixtures/enroll_user_authentication_factor.json", + "tests/fixtures/error_response.json", "tests/fixtures/event_context.json", "tests/fixtures/event_context_actor.json", "tests/fixtures/event_context_google_analytics_session.json", @@ -884,8 +925,8 @@ "tests/fixtures/jwks_response.json", "tests/fixtures/jwks_response_keys.json", "tests/fixtures/jwt_template_response.json", - "tests/fixtures/list_audit_log_action_json.json", - "tests/fixtures/list_audit_log_schema_json.json", + "tests/fixtures/list_audit_log_action.json", + "tests/fixtures/list_audit_log_schema.json", "tests/fixtures/list_authentication_factor.json", "tests/fixtures/list_authorization_permission.json", "tests/fixtures/list_authorization_resource.json", @@ -898,6 +939,8 @@ "tests/fixtures/list_event_schema.json", "tests/fixtures/list_flag.json", "tests/fixtures/list_group.json", + "tests/fixtures/list_metadata.json", + "tests/fixtures/list_object_summary.json", "tests/fixtures/list_organization.json", "tests/fixtures/list_organization_api_key.json", "tests/fixtures/list_user.json", @@ -907,13 +950,17 @@ "tests/fixtures/list_user_organization_membership_base_list_data.json", "tests/fixtures/list_user_role_assignment.json", "tests/fixtures/list_user_sessions_list_item.json", - "tests/fixtures/list_webhook_endpoint_json.json", + "tests/fixtures/list_webhook_endpoint.json", "tests/fixtures/magic_auth.json", "tests/fixtures/magic_auth_code_session_authenticate_request.json", "tests/fixtures/magic_auth_created.json", "tests/fixtures/magic_auth_created_data.json", "tests/fixtures/mfa_totp_session_authenticate_request.json", "tests/fixtures/new_connect_application_secret.json", + "tests/fixtures/object_metadata.json", + "tests/fixtures/object_summary.json", + "tests/fixtures/object_version.json", + "tests/fixtures/object_without_value.json", "tests/fixtures/organization.json", "tests/fixtures/organization_api_key.json", "tests/fixtures/organization_api_key_owner.json", @@ -970,6 +1017,10 @@ "tests/fixtures/permission_deleted_data.json", "tests/fixtures/permission_updated.json", "tests/fixtures/permission_updated_data.json", + "tests/fixtures/pipe_connected_account.json", + "tests/fixtures/pipes_connected_account_connected.json", + "tests/fixtures/pipes_connected_account_disconnected.json", + "tests/fixtures/pipes_connected_account_reauthorization_needed.json", "tests/fixtures/portal_link_response.json", "tests/fixtures/profile.json", "tests/fixtures/radar_list_entry_already_present_response.json", @@ -981,6 +1032,7 @@ "tests/fixtures/redirect_uri.json", "tests/fixtures/redirect_uri_input.json", "tests/fixtures/refresh_token_session_authenticate_request.json", + "tests/fixtures/rekey_request.json", "tests/fixtures/remove_role.json", "tests/fixtures/resend_user_invite_options.json", "tests/fixtures/reset_password_response.json", @@ -1017,6 +1069,7 @@ "tests/fixtures/update_group.json", "tests/fixtures/update_jwt_template.json", "tests/fixtures/update_oauth_application.json", + "tests/fixtures/update_object_request.json", "tests/fixtures/update_organization.json", "tests/fixtures/update_organization_role.json", "tests/fixtures/update_role.json", @@ -1069,13 +1122,15 @@ "tests/fixtures/vault_metadata_read_data.json", "tests/fixtures/vault_names_listed.json", "tests/fixtures/vault_names_listed_data.json", + "tests/fixtures/vault_object.json", "tests/fixtures/verify_email_address.json", "tests/fixtures/verify_email_response.json", + "tests/fixtures/version_list_response.json", "tests/fixtures/waitlist_user.json", "tests/fixtures/waitlist_user_approved.json", "tests/fixtures/waitlist_user_created.json", "tests/fixtures/waitlist_user_denied.json", - "tests/fixtures/webhook_endpoint_json.json", + "tests/fixtures/webhook_endpoint.json", "tests/fixtures/widget_session_token.json", "tests/fixtures/widget_session_token_response.json", "tests/test_admin_portal.py", @@ -1090,12 +1145,13 @@ "tests/test_models_round_trip.py", "tests/test_multi_factor_auth.py", "tests/test_organization_domains.py", + "tests/test_organization_membership.py", "tests/test_organizations.py", "tests/test_pipes.py", "tests/test_radar.py", "tests/test_sso.py", "tests/test_user_management.py", - "tests/test_user_management_organization_membership_groups.py", + "tests/test_vault.py", "tests/test_webhooks.py", "tests/test_widgets.py" ], @@ -1662,35 +1718,35 @@ }, "GET /user_management/organization_memberships": { "sdkMethod": "list_organization_memberships", - "service": "user_management" + "service": "organization_membership" }, "POST /user_management/organization_memberships": { "sdkMethod": "create_organization_membership", - "service": "user_management" + "service": "organization_membership" }, "GET /user_management/organization_memberships/{id}": { "sdkMethod": "get_organization_membership", - "service": "user_management" + "service": "organization_membership" }, "PUT /user_management/organization_memberships/{id}": { "sdkMethod": "update_organization_membership", - "service": "user_management" + "service": "organization_membership" }, "DELETE /user_management/organization_memberships/{id}": { "sdkMethod": "delete_organization_membership", - "service": "user_management" + "service": "organization_membership" }, "PUT /user_management/organization_memberships/{id}/deactivate": { "sdkMethod": "deactivate_organization_membership", - "service": "user_management" + "service": "organization_membership" }, "PUT /user_management/organization_memberships/{id}/reactivate": { "sdkMethod": "reactivate_organization_membership", - "service": "user_management" + "service": "organization_membership" }, "GET /user_management/organization_memberships/{omId}/groups": { "sdkMethod": "list_organization_membership_groups", - "service": "user_management_organization_membership_groups" + "service": "organization_membership" }, "POST /user_management/redirect_uris": { "sdkMethod": "create_redirect_uri", @@ -1728,6 +1784,50 @@ "sdkMethod": "create_user_auth_factor", "service": "multi_factor_auth" }, + "POST /vault/v1/keys/data-key": { + "sdkMethod": "create_data_key", + "service": "vault" + }, + "POST /vault/v1/keys/decrypt": { + "sdkMethod": "create_decrypt", + "service": "vault" + }, + "POST /vault/v1/keys/rekey": { + "sdkMethod": "create_rekey", + "service": "vault" + }, + "GET /vault/v1/kv": { + "sdkMethod": "list_kv", + "service": "vault" + }, + "POST /vault/v1/kv": { + "sdkMethod": "create_kv", + "service": "vault" + }, + "GET /vault/v1/kv/name/{name}": { + "sdkMethod": "get_name", + "service": "vault" + }, + "GET /vault/v1/kv/{id}": { + "sdkMethod": "get_kv", + "service": "vault" + }, + "PUT /vault/v1/kv/{id}": { + "sdkMethod": "update_kv", + "service": "vault" + }, + "DELETE /vault/v1/kv/{id}": { + "sdkMethod": "delete_kv", + "service": "vault" + }, + "GET /vault/v1/kv/{id}/metadata": { + "sdkMethod": "list_kv_metadata", + "service": "vault" + }, + "GET /vault/v1/kv/{id}/versions": { + "sdkMethod": "list_kv_versions", + "service": "vault" + }, "GET /webhook_endpoints": { "sdkMethod": "list_webhook_endpoints", "service": "webhooks" diff --git a/src/workos/_client.py b/src/workos/_client.py index baa25896..dc0543cb 100644 --- a/src/workos/_client.py +++ b/src/workos/_client.py @@ -26,15 +26,15 @@ from .admin_portal._resource import AdminPortal, AsyncAdminPortal from .radar._resource import Radar, AsyncRadar from .user_management._resource import UserManagement, AsyncUserManagement -from .user_management_organization_membership_groups._resource import ( - UserManagementOrganizationMembershipGroups, - AsyncUserManagementOrganizationMembershipGroups, +from .organization_membership._resource import ( + OrganizationMembershipService, + AsyncOrganizationMembershipService, ) +from .vault._resource import Vault, AsyncVault from .webhooks._resource import Webhooks, AsyncWebhooks from .widgets._resource import Widgets, AsyncWidgets from .audit_logs._resource import AuditLogs, AsyncAuditLogs from .passwordless import AsyncPasswordless, Passwordless -from .vault import AsyncVault, Vault from .actions import Actions, AsyncActions from .pkce import PKCE @@ -118,11 +118,14 @@ def user_management(self) -> UserManagement: return UserManagement(self) @functools.cached_property - def user_management_organization_membership_groups( - self, - ) -> UserManagementOrganizationMembershipGroups: - """User Management Organization Membership Groups API resources.""" - return UserManagementOrganizationMembershipGroups(self) + def organization_membership(self) -> OrganizationMembershipService: + """Organization Membership Service API resources.""" + return OrganizationMembershipService(self) + + @functools.cached_property + def vault(self) -> Vault: + """Vault API resources.""" + return Vault(self) @functools.cached_property def webhooks(self) -> Webhooks: @@ -151,11 +154,6 @@ def passwordless(self) -> Passwordless: """Passwordless authentication sessions.""" return Passwordless(self) - @functools.cached_property - def vault(self) -> Vault: - """Vault encryption, key management, and secret storage.""" - return Vault(self) - @functools.cached_property def actions(self) -> Actions: """Actions logging and audit trail.""" @@ -248,11 +246,14 @@ def user_management(self) -> AsyncUserManagement: return AsyncUserManagement(self) @functools.cached_property - def user_management_organization_membership_groups( - self, - ) -> AsyncUserManagementOrganizationMembershipGroups: - """User Management Organization Membership Groups API resources.""" - return AsyncUserManagementOrganizationMembershipGroups(self) + def organization_membership(self) -> AsyncOrganizationMembershipService: + """Organization Membership Service API resources.""" + return AsyncOrganizationMembershipService(self) + + @functools.cached_property + def vault(self) -> AsyncVault: + """Vault API resources.""" + return AsyncVault(self) @functools.cached_property def webhooks(self) -> AsyncWebhooks: @@ -281,11 +282,6 @@ def passwordless(self) -> AsyncPasswordless: """Passwordless authentication sessions.""" return AsyncPasswordless(self) - @functools.cached_property - def vault(self) -> AsyncVault: - """Vault encryption, key management, and secret storage.""" - return AsyncVault(self) - @functools.cached_property def actions(self) -> AsyncActions: """Actions logging and audit trail.""" @@ -297,7 +293,3 @@ def pkce(self) -> PKCE: return PKCE() # @oagen-ignore-end - - -# @oagen-ignore-start — non-spec service imports (hand-maintained) -# @oagen-ignore-end diff --git a/src/workos/api_keys/_resource.py b/src/workos/api_keys/_resource.py index b0598e73..36b76741 100644 --- a/src/workos/api_keys/_resource.py +++ b/src/workos/api_keys/_resource.py @@ -78,6 +78,7 @@ def create_organization_api_key( *, name: str, permissions: Optional[List[str]] = None, + expires_at: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> OrganizationApiKeyWithValue: """Create an API key for an organization @@ -88,6 +89,7 @@ def create_organization_api_key( organization_id: Unique identifier of the Organization. name: The name for the API key. permissions: The permission slugs to assign to the API key. + expires_at: The timestamp when the API key should expire. Must be a future timestamp. If omitted, the key does not expire. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: @@ -105,6 +107,7 @@ def create_organization_api_key( for k, v in { "name": name, "permissions": permissions, + "expires_at": expires_at, }.items() if v is not None } @@ -238,6 +241,7 @@ async def create_organization_api_key( *, name: str, permissions: Optional[List[str]] = None, + expires_at: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> OrganizationApiKeyWithValue: """Create an API key for an organization @@ -248,6 +252,7 @@ async def create_organization_api_key( organization_id: Unique identifier of the Organization. name: The name for the API key. permissions: The permission slugs to assign to the API key. + expires_at: The timestamp when the API key should expire. Must be a future timestamp. If omitted, the key does not expire. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: @@ -265,6 +270,7 @@ async def create_organization_api_key( for k, v in { "name": name, "permissions": permissions, + "expires_at": expires_at, }.items() if v is not None } diff --git a/src/workos/api_keys/models/api_key.py b/src/workos/api_keys/models/api_key.py index dcc59ed6..16789239 100644 --- a/src/workos/api_keys/models/api_key.py +++ b/src/workos/api_keys/models/api_key.py @@ -29,6 +29,8 @@ class ApiKey: """An obfuscated representation of the API Key value.""" last_used_at: Optional[datetime] """Timestamp of when the API Key was last used.""" + expires_at: Optional[datetime] + """Timestamp when the API Key expires. Null means the key does not expire.""" permissions: List[str] """The permission slugs assigned to the API Key.""" created_at: datetime @@ -62,6 +64,9 @@ def from_dict(cls, data: Dict[str, Any]) -> "ApiKey": last_used_at=_parse_datetime(_v_last_used_at) if (_v_last_used_at := data["last_used_at"]) is not None else None, + expires_at=_parse_datetime(_v_expires_at) + if (_v_expires_at := data["expires_at"]) is not None + else None, permissions=data["permissions"], created_at=_parse_datetime(data["created_at"]), updated_at=_parse_datetime(data["updated_at"]), @@ -81,6 +86,10 @@ def to_dict(self) -> Dict[str, Any]: result["last_used_at"] = _format_datetime(self.last_used_at) else: result["last_used_at"] = None + if self.expires_at is not None: + result["expires_at"] = _format_datetime(self.expires_at) + else: + result["expires_at"] = None result["permissions"] = self.permissions result["created_at"] = _format_datetime(self.created_at) result["updated_at"] = _format_datetime(self.updated_at) diff --git a/src/workos/api_keys/models/create_organization_api_key.py b/src/workos/api_keys/models/create_organization_api_key.py index 9e39ef6a..b9f53f66 100644 --- a/src/workos/api_keys/models/create_organization_api_key.py +++ b/src/workos/api_keys/models/create_organization_api_key.py @@ -3,8 +3,10 @@ from __future__ import annotations from dataclasses import dataclass +from datetime import datetime from typing import Any, Dict, List, Optional from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime @dataclass(slots=True) @@ -15,6 +17,8 @@ class CreateOrganizationApiKey: """The name for the API key.""" permissions: Optional[List[str]] = None """The permission slugs to assign to the API key.""" + expires_at: Optional[datetime] = None + """The timestamp when the API key should expire. Must be a future timestamp. If omitted, the key does not expire.""" @classmethod def from_dict(cls, data: Dict[str, Any]) -> "CreateOrganizationApiKey": @@ -23,6 +27,9 @@ def from_dict(cls, data: Dict[str, Any]) -> "CreateOrganizationApiKey": return cls( name=data["name"], permissions=data.get("permissions"), + expires_at=_parse_datetime(_v_expires_at) + if (_v_expires_at := data.get("expires_at")) is not None + else None, ) except (KeyError, ValueError) as e: _raise_deserialize_error("CreateOrganizationApiKey", e) @@ -33,4 +40,6 @@ def to_dict(self) -> Dict[str, Any]: result["name"] = self.name if self.permissions is not None: result["permissions"] = self.permissions + if self.expires_at is not None: + result["expires_at"] = _format_datetime(self.expires_at) return result diff --git a/src/workos/api_keys/models/organization_api_key.py b/src/workos/api_keys/models/organization_api_key.py index 493e26ce..2a3f3cc3 100644 --- a/src/workos/api_keys/models/organization_api_key.py +++ b/src/workos/api_keys/models/organization_api_key.py @@ -28,6 +28,8 @@ class OrganizationApiKey: """An obfuscated representation of the API Key value.""" last_used_at: Optional[datetime] """Timestamp of when the API Key was last used.""" + expires_at: Optional[datetime] + """Timestamp when the API Key expires. Null means the key does not expire.""" permissions: List[str] """The permission slugs assigned to the API Key.""" created_at: datetime @@ -50,6 +52,9 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationApiKey": last_used_at=_parse_datetime(_v_last_used_at) if (_v_last_used_at := data["last_used_at"]) is not None else None, + expires_at=_parse_datetime(_v_expires_at) + if (_v_expires_at := data["expires_at"]) is not None + else None, permissions=data["permissions"], created_at=_parse_datetime(data["created_at"]), updated_at=_parse_datetime(data["updated_at"]), @@ -69,6 +74,10 @@ def to_dict(self) -> Dict[str, Any]: result["last_used_at"] = _format_datetime(self.last_used_at) else: result["last_used_at"] = None + if self.expires_at is not None: + result["expires_at"] = _format_datetime(self.expires_at) + else: + result["expires_at"] = None result["permissions"] = self.permissions result["created_at"] = _format_datetime(self.created_at) result["updated_at"] = _format_datetime(self.updated_at) diff --git a/src/workos/api_keys/models/organization_api_key_with_value.py b/src/workos/api_keys/models/organization_api_key_with_value.py index acd75504..ad021809 100644 --- a/src/workos/api_keys/models/organization_api_key_with_value.py +++ b/src/workos/api_keys/models/organization_api_key_with_value.py @@ -28,6 +28,8 @@ class OrganizationApiKeyWithValue: """An obfuscated representation of the API Key value.""" last_used_at: Optional[datetime] """Timestamp of when the API Key was last used.""" + expires_at: Optional[datetime] + """Timestamp when the API Key expires. Null means the key does not expire.""" permissions: List[str] """The permission slugs assigned to the API Key.""" created_at: datetime @@ -52,6 +54,9 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationApiKeyWithValue": last_used_at=_parse_datetime(_v_last_used_at) if (_v_last_used_at := data["last_used_at"]) is not None else None, + expires_at=_parse_datetime(_v_expires_at) + if (_v_expires_at := data["expires_at"]) is not None + else None, permissions=data["permissions"], created_at=_parse_datetime(data["created_at"]), updated_at=_parse_datetime(data["updated_at"]), @@ -72,6 +77,10 @@ def to_dict(self) -> Dict[str, Any]: result["last_used_at"] = _format_datetime(self.last_used_at) else: result["last_used_at"] = None + if self.expires_at is not None: + result["expires_at"] = _format_datetime(self.expires_at) + else: + result["expires_at"] = None result["permissions"] = self.permissions result["created_at"] = _format_datetime(self.created_at) result["updated_at"] = _format_datetime(self.updated_at) diff --git a/src/workos/audit_logs/_resource.py b/src/workos/audit_logs/_resource.py index db5352b6..bd5a8caf 100644 --- a/src/workos/audit_logs/_resource.py +++ b/src/workos/audit_logs/_resource.py @@ -9,15 +9,15 @@ from .._types import RequestOptions, enum_value from .models import ( - AuditLogActionJson, + AuditLogAction, AuditLogEvent, AuditLogEventCreateResponse, - AuditLogExportJson, - AuditLogSchemaActor, - AuditLogSchemaJson, - AuditLogSchemaTarget, + AuditLogExport, + AuditLogSchema, + AuditLogSchemaActorInput, + AuditLogSchemaTargetInput, ) -from workos.organizations.models.audit_logs_retention_json import AuditLogsRetentionJson +from workos.organizations.models.audit_logs_retention import AuditLogsRetention from workos.common.models.pagination_order import PaginationOrder from .._pagination import AsyncPage, SyncPage @@ -33,7 +33,7 @@ def get_organization_audit_logs_retention( id: str, *, request_options: Optional[RequestOptions] = None, - ) -> AuditLogsRetentionJson: + ) -> AuditLogsRetention: """Get Retention Get the configured event retention period for the given Organization. @@ -43,7 +43,7 @@ def get_organization_audit_logs_retention( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - AuditLogsRetentionJson + AuditLogsRetention Raises: NotFoundError: If the resource is not found (404). @@ -54,7 +54,7 @@ def get_organization_audit_logs_retention( return self._client.request( method="get", path=("organizations", str(id), "audit_logs_retention"), - model=AuditLogsRetentionJson, + model=AuditLogsRetention, request_options=request_options, ) @@ -64,7 +64,7 @@ def update_organization_audit_logs_retention( *, retention_period_in_days: int, request_options: Optional[RequestOptions] = None, - ) -> AuditLogsRetentionJson: + ) -> AuditLogsRetention: """Set Retention Set the event retention period for the given Organization. @@ -75,7 +75,7 @@ def update_organization_audit_logs_retention( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - AuditLogsRetentionJson + AuditLogsRetention Raises: NotFoundError: If the resource is not found (404). @@ -91,7 +91,7 @@ def update_organization_audit_logs_retention( method="put", path=("organizations", str(id), "audit_logs_retention"), body=body, - model=AuditLogsRetentionJson, + model=AuditLogsRetention, request_options=request_options, ) @@ -103,7 +103,7 @@ def list_actions( after: Optional[str] = None, order: Optional[Union[PaginationOrder, str]] = "desc", request_options: Optional[RequestOptions] = None, - ) -> SyncPage[AuditLogActionJson]: + ) -> SyncPage[AuditLogAction]: """List Actions Get a list of all Audit Log actions in the current environment. @@ -116,7 +116,7 @@ def list_actions( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - SyncPage[AuditLogActionJson] + SyncPage[AuditLogAction] Raises: NotFoundError: If the resource is not found (404). @@ -138,7 +138,7 @@ def list_actions( return self._client.request_page( method="get", path=("audit_logs", "actions"), - model=AuditLogActionJson, + model=AuditLogAction, params=params, request_options=request_options, ) @@ -152,7 +152,7 @@ def list_action_schemas( after: Optional[str] = None, order: Optional[Union[PaginationOrder, str]] = "desc", request_options: Optional[RequestOptions] = None, - ) -> SyncPage[AuditLogSchemaJson]: + ) -> SyncPage[AuditLogSchema]: """List Schemas Get a list of all schemas for the Audit Logs action identified by `:name`. @@ -166,7 +166,7 @@ def list_action_schemas( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - SyncPage[AuditLogSchemaJson] + SyncPage[AuditLogSchema] Raises: NotFoundError: If the resource is not found (404). @@ -188,7 +188,7 @@ def list_action_schemas( return self._client.request_page( method="get", path=("audit_logs", "actions", str(action_name), "schemas"), - model=AuditLogSchemaJson, + model=AuditLogSchema, params=params, request_options=request_options, ) @@ -197,11 +197,11 @@ def create_schema( self, action_name: str, *, - targets: List[AuditLogSchemaTarget], - actor: Optional[AuditLogSchemaActor] = None, + targets: List[AuditLogSchemaTargetInput], + actor: Optional[AuditLogSchemaActorInput] = None, metadata: Optional[Dict[str, Any]] = None, request_options: Optional[RequestOptions] = None, - ) -> AuditLogSchemaJson: + ) -> AuditLogSchema: """Create Schema Creates a new Audit Log schema used to validate the payload of incoming Audit Log Events. If the `action` does not exist, it will also be created. @@ -214,7 +214,7 @@ def create_schema( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - AuditLogSchemaJson + AuditLogSchema Raises: UnprocessableEntityError: If the request data is unprocessable (422). @@ -235,7 +235,7 @@ def create_schema( method="post", path=("audit_logs", "actions", str(action_name), "schemas"), body=body, - model=AuditLogSchemaJson, + model=AuditLogSchema, request_options=request_options, ) @@ -299,7 +299,7 @@ def create_export( actor_ids: Optional[List[str]] = None, targets: Optional[List[str]] = None, request_options: Optional[RequestOptions] = None, - ) -> AuditLogExportJson: + ) -> AuditLogExport: """Create Export Create an Audit Log Export. Exports are scoped to a single organization within a specified date range. @@ -316,7 +316,7 @@ def create_export( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - AuditLogExportJson + AuditLogExport Raises: BadRequestError: If the request is malformed (400). @@ -342,7 +342,7 @@ def create_export( method="post", path=("audit_logs", "exports"), body=body, - model=AuditLogExportJson, + model=AuditLogExport, request_options=request_options, ) @@ -351,7 +351,7 @@ def get_export( audit_log_export_id: str, *, request_options: Optional[RequestOptions] = None, - ) -> AuditLogExportJson: + ) -> AuditLogExport: """Get Export Get an Audit Log Export. The URL will expire after 10 minutes. If the export is needed again at a later time, refetching the export will regenerate the URL. @@ -361,7 +361,7 @@ def get_export( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - AuditLogExportJson + AuditLogExport Raises: NotFoundError: If the resource is not found (404). @@ -372,7 +372,7 @@ def get_export( return self._client.request( method="get", path=("audit_logs", "exports", str(audit_log_export_id)), - model=AuditLogExportJson, + model=AuditLogExport, request_options=request_options, ) @@ -388,7 +388,7 @@ async def get_organization_audit_logs_retention( id: str, *, request_options: Optional[RequestOptions] = None, - ) -> AuditLogsRetentionJson: + ) -> AuditLogsRetention: """Get Retention Get the configured event retention period for the given Organization. @@ -398,7 +398,7 @@ async def get_organization_audit_logs_retention( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - AuditLogsRetentionJson + AuditLogsRetention Raises: NotFoundError: If the resource is not found (404). @@ -409,7 +409,7 @@ async def get_organization_audit_logs_retention( return await self._client.request( method="get", path=("organizations", str(id), "audit_logs_retention"), - model=AuditLogsRetentionJson, + model=AuditLogsRetention, request_options=request_options, ) @@ -419,7 +419,7 @@ async def update_organization_audit_logs_retention( *, retention_period_in_days: int, request_options: Optional[RequestOptions] = None, - ) -> AuditLogsRetentionJson: + ) -> AuditLogsRetention: """Set Retention Set the event retention period for the given Organization. @@ -430,7 +430,7 @@ async def update_organization_audit_logs_retention( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - AuditLogsRetentionJson + AuditLogsRetention Raises: NotFoundError: If the resource is not found (404). @@ -446,7 +446,7 @@ async def update_organization_audit_logs_retention( method="put", path=("organizations", str(id), "audit_logs_retention"), body=body, - model=AuditLogsRetentionJson, + model=AuditLogsRetention, request_options=request_options, ) @@ -458,7 +458,7 @@ async def list_actions( after: Optional[str] = None, order: Optional[Union[PaginationOrder, str]] = "desc", request_options: Optional[RequestOptions] = None, - ) -> AsyncPage[AuditLogActionJson]: + ) -> AsyncPage[AuditLogAction]: """List Actions Get a list of all Audit Log actions in the current environment. @@ -471,7 +471,7 @@ async def list_actions( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - AsyncPage[AuditLogActionJson] + AsyncPage[AuditLogAction] Raises: NotFoundError: If the resource is not found (404). @@ -493,7 +493,7 @@ async def list_actions( return await self._client.request_page( method="get", path=("audit_logs", "actions"), - model=AuditLogActionJson, + model=AuditLogAction, params=params, request_options=request_options, ) @@ -507,7 +507,7 @@ async def list_action_schemas( after: Optional[str] = None, order: Optional[Union[PaginationOrder, str]] = "desc", request_options: Optional[RequestOptions] = None, - ) -> AsyncPage[AuditLogSchemaJson]: + ) -> AsyncPage[AuditLogSchema]: """List Schemas Get a list of all schemas for the Audit Logs action identified by `:name`. @@ -521,7 +521,7 @@ async def list_action_schemas( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - AsyncPage[AuditLogSchemaJson] + AsyncPage[AuditLogSchema] Raises: NotFoundError: If the resource is not found (404). @@ -543,7 +543,7 @@ async def list_action_schemas( return await self._client.request_page( method="get", path=("audit_logs", "actions", str(action_name), "schemas"), - model=AuditLogSchemaJson, + model=AuditLogSchema, params=params, request_options=request_options, ) @@ -552,11 +552,11 @@ async def create_schema( self, action_name: str, *, - targets: List[AuditLogSchemaTarget], - actor: Optional[AuditLogSchemaActor] = None, + targets: List[AuditLogSchemaTargetInput], + actor: Optional[AuditLogSchemaActorInput] = None, metadata: Optional[Dict[str, Any]] = None, request_options: Optional[RequestOptions] = None, - ) -> AuditLogSchemaJson: + ) -> AuditLogSchema: """Create Schema Creates a new Audit Log schema used to validate the payload of incoming Audit Log Events. If the `action` does not exist, it will also be created. @@ -569,7 +569,7 @@ async def create_schema( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - AuditLogSchemaJson + AuditLogSchema Raises: UnprocessableEntityError: If the request data is unprocessable (422). @@ -590,7 +590,7 @@ async def create_schema( method="post", path=("audit_logs", "actions", str(action_name), "schemas"), body=body, - model=AuditLogSchemaJson, + model=AuditLogSchema, request_options=request_options, ) @@ -654,7 +654,7 @@ async def create_export( actor_ids: Optional[List[str]] = None, targets: Optional[List[str]] = None, request_options: Optional[RequestOptions] = None, - ) -> AuditLogExportJson: + ) -> AuditLogExport: """Create Export Create an Audit Log Export. Exports are scoped to a single organization within a specified date range. @@ -671,7 +671,7 @@ async def create_export( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - AuditLogExportJson + AuditLogExport Raises: BadRequestError: If the request is malformed (400). @@ -697,7 +697,7 @@ async def create_export( method="post", path=("audit_logs", "exports"), body=body, - model=AuditLogExportJson, + model=AuditLogExport, request_options=request_options, ) @@ -706,7 +706,7 @@ async def get_export( audit_log_export_id: str, *, request_options: Optional[RequestOptions] = None, - ) -> AuditLogExportJson: + ) -> AuditLogExport: """Get Export Get an Audit Log Export. The URL will expire after 10 minutes. If the export is needed again at a later time, refetching the export will regenerate the URL. @@ -716,7 +716,7 @@ async def get_export( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - AuditLogExportJson + AuditLogExport Raises: NotFoundError: If the resource is not found (404). @@ -727,6 +727,6 @@ async def get_export( return await self._client.request( method="get", path=("audit_logs", "exports", str(audit_log_export_id)), - model=AuditLogExportJson, + model=AuditLogExport, request_options=request_options, ) diff --git a/src/workos/audit_logs/models/__init__.py b/src/workos/audit_logs/models/__init__.py index 81483482..91e21b71 100644 --- a/src/workos/audit_logs/models/__init__.py +++ b/src/workos/audit_logs/models/__init__.py @@ -1,6 +1,6 @@ # This file is auto-generated by oagen. Do not edit. -from .audit_log_action_json import AuditLogActionJson as AuditLogActionJson +from .audit_log_action import AuditLogAction as AuditLogAction from .audit_log_event import AuditLogEvent as AuditLogEvent from .audit_log_event_actor import AuditLogEventActor as AuditLogEventActor from .audit_log_event_context import AuditLogEventContext as AuditLogEventContext @@ -9,15 +9,15 @@ ) from .audit_log_event_ingestion import AuditLogEventIngestion as AuditLogEventIngestion from .audit_log_event_target import AuditLogEventTarget as AuditLogEventTarget +from .audit_log_export import AuditLogExport as AuditLogExport from .audit_log_export_creation import AuditLogExportCreation as AuditLogExportCreation -from .audit_log_export_json import AuditLogExportJson as AuditLogExportJson from .audit_log_schema import AuditLogSchema as AuditLogSchema from .audit_log_schema_actor import AuditLogSchemaActor as AuditLogSchemaActor -from .audit_log_schema_json import AuditLogSchemaJson as AuditLogSchemaJson -from .audit_log_schema_json_actor import ( - AuditLogSchemaJsonActor as AuditLogSchemaJsonActor, -) -from .audit_log_schema_json_target import ( - AuditLogSchemaJsonTarget as AuditLogSchemaJsonTarget, +from .audit_log_schema_actor_input import ( + AuditLogSchemaActorInput as AuditLogSchemaActorInput, ) +from .audit_log_schema_input import AuditLogSchemaInput as AuditLogSchemaInput from .audit_log_schema_target import AuditLogSchemaTarget as AuditLogSchemaTarget +from .audit_log_schema_target_input import ( + AuditLogSchemaTargetInput as AuditLogSchemaTargetInput, +) diff --git a/src/workos/audit_logs/models/audit_log_action_json.py b/src/workos/audit_logs/models/audit_log_action.py similarity index 77% rename from src/workos/audit_logs/models/audit_log_action_json.py rename to src/workos/audit_logs/models/audit_log_action.py index 366f9bc0..1771c9b0 100644 --- a/src/workos/audit_logs/models/audit_log_action_json.py +++ b/src/workos/audit_logs/models/audit_log_action.py @@ -9,18 +9,18 @@ from workos._types import _raise_deserialize_error from workos._types import _format_datetime, _parse_datetime -from .audit_log_schema_json import AuditLogSchemaJson +from .audit_log_schema import AuditLogSchema @dataclass(slots=True) -class AuditLogActionJson: - """Audit Log Action Json model.""" +class AuditLogAction: + """Audit Log Action model.""" object: Literal["audit_log_action"] """Distinguishes the Audit Log Action object.""" name: str """Identifier of what action was taken.""" - schema: "AuditLogSchemaJson" + schema: "AuditLogSchema" """The schema associated with the action.""" created_at: datetime """An ISO 8601 timestamp.""" @@ -28,20 +28,18 @@ class AuditLogActionJson: """An ISO 8601 timestamp.""" @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "AuditLogActionJson": + def from_dict(cls, data: Dict[str, Any]) -> "AuditLogAction": """Deserialize from a dictionary.""" try: return cls( object=data.get("object", "audit_log_action"), name=data["name"], - schema=AuditLogSchemaJson.from_dict( - cast(Dict[str, Any], data["schema"]) - ), + schema=AuditLogSchema.from_dict(cast(Dict[str, Any], data["schema"])), created_at=_parse_datetime(data["created_at"]), updated_at=_parse_datetime(data["updated_at"]), ) except (KeyError, ValueError) as e: - _raise_deserialize_error("AuditLogActionJson", e) + _raise_deserialize_error("AuditLogAction", e) def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" diff --git a/src/workos/audit_logs/models/audit_log_export_json.py b/src/workos/audit_logs/models/audit_log_export.py similarity index 82% rename from src/workos/audit_logs/models/audit_log_export_json.py rename to src/workos/audit_logs/models/audit_log_export.py index 0c9c328b..381de12a 100644 --- a/src/workos/audit_logs/models/audit_log_export_json.py +++ b/src/workos/audit_logs/models/audit_log_export.py @@ -8,18 +8,18 @@ from typing import Any, Dict, Literal, Optional from workos._types import _raise_deserialize_error from workos._types import _format_datetime, _parse_datetime -from workos.common.models.audit_log_export_json_state import AuditLogExportJsonState +from workos.common.models.audit_log_export_state import AuditLogExportState @dataclass(slots=True) -class AuditLogExportJson: - """Audit Log Export Json model.""" +class AuditLogExport: + """Audit Log Export model.""" object: Literal["audit_log_export"] """Distinguishes the Audit Log Export object.""" id: str """The unique ID of the Audit Log Export.""" - state: "AuditLogExportJsonState" + state: "AuditLogExportState" """The state of the export. Possible values: pending, ready, error.""" created_at: datetime """An ISO 8601 timestamp.""" @@ -29,19 +29,19 @@ class AuditLogExportJson: """A URL to the CSV file. Only defined when the Audit Log Export is ready.""" @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "AuditLogExportJson": + def from_dict(cls, data: Dict[str, Any]) -> "AuditLogExport": """Deserialize from a dictionary.""" try: return cls( object=data.get("object", "audit_log_export"), id=data["id"], - state=AuditLogExportJsonState(data["state"]), + state=AuditLogExportState(data["state"]), created_at=_parse_datetime(data["created_at"]), updated_at=_parse_datetime(data["updated_at"]), url=data.get("url"), ) except (KeyError, ValueError) as e: - _raise_deserialize_error("AuditLogExportJson", e) + _raise_deserialize_error("AuditLogExport", e) def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" diff --git a/src/workos/audit_logs/models/audit_log_schema.py b/src/workos/audit_logs/models/audit_log_schema.py index 564f43e1..e0f0d74c 100644 --- a/src/workos/audit_logs/models/audit_log_schema.py +++ b/src/workos/audit_logs/models/audit_log_schema.py @@ -3,9 +3,11 @@ from __future__ import annotations from dataclasses import dataclass +from datetime import datetime from typing import cast -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List, Literal, Optional from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime from .audit_log_schema_actor import AuditLogSchemaActor from .audit_log_schema_target import AuditLogSchemaTarget @@ -15,22 +17,31 @@ class AuditLogSchema: """Audit Log Schema model.""" + object: Literal["audit_log_schema"] + """Distinguishes the Audit Log Schema object.""" + version: int + """The version of the schema.""" targets: List["AuditLogSchemaTarget"] """The list of targets for the schema.""" + created_at: datetime + """The timestamp when the Audit Log Schema was created.""" actor: Optional["AuditLogSchemaActor"] = None """The metadata schema for the actor.""" metadata: Optional[Dict[str, Any]] = None - """Optional JSON schema for event metadata.""" + """Additional data associated with the event or entity.""" @classmethod def from_dict(cls, data: Dict[str, Any]) -> "AuditLogSchema": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "audit_log_schema"), + version=data["version"], targets=[ AuditLogSchemaTarget.from_dict(cast(Dict[str, Any], item)) for item in cast(list[Any], data["targets"]) ], + created_at=_parse_datetime(data["created_at"]), actor=AuditLogSchemaActor.from_dict(cast(Dict[str, Any], _v_actor)) if (_v_actor := data.get("actor")) is not None else None, @@ -42,7 +53,10 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuditLogSchema": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object + result["version"] = self.version result["targets"] = [item.to_dict() for item in self.targets] + result["created_at"] = _format_datetime(self.created_at) if self.actor is not None: result["actor"] = self.actor.to_dict() if self.metadata is not None: diff --git a/src/workos/audit_logs/models/audit_log_schema_actor.py b/src/workos/audit_logs/models/audit_log_schema_actor.py index b6896963..b744ebb6 100644 --- a/src/workos/audit_logs/models/audit_log_schema_actor.py +++ b/src/workos/audit_logs/models/audit_log_schema_actor.py @@ -9,10 +9,10 @@ @dataclass(slots=True) class AuditLogSchemaActor: - """Audit Log Schema Actor model.""" + """The metadata schema for the actor.""" metadata: Dict[str, Any] - """JSON schema for actor metadata.""" + """The JSON Schema definition for actor metadata.""" @classmethod def from_dict(cls, data: Dict[str, Any]) -> "AuditLogSchemaActor": diff --git a/src/workos/audit_logs/models/audit_log_schema_json_actor.py b/src/workos/audit_logs/models/audit_log_schema_actor_input.py similarity index 70% rename from src/workos/audit_logs/models/audit_log_schema_json_actor.py rename to src/workos/audit_logs/models/audit_log_schema_actor_input.py index 2c9bfdb6..9ae3e8ac 100644 --- a/src/workos/audit_logs/models/audit_log_schema_json_actor.py +++ b/src/workos/audit_logs/models/audit_log_schema_actor_input.py @@ -3,4 +3,4 @@ from typing import TypeAlias from .audit_log_schema_actor import AuditLogSchemaActor -AuditLogSchemaJsonActor: TypeAlias = AuditLogSchemaActor +AuditLogSchemaActorInput: TypeAlias = AuditLogSchemaActor diff --git a/src/workos/audit_logs/models/audit_log_schema_input.py b/src/workos/audit_logs/models/audit_log_schema_input.py new file mode 100644 index 00000000..2036a51d --- /dev/null +++ b/src/workos/audit_logs/models/audit_log_schema_input.py @@ -0,0 +1,50 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import cast +from typing import Any, Dict, List, Optional +from workos._types import _raise_deserialize_error + +from .audit_log_schema_actor_input import AuditLogSchemaActorInput +from .audit_log_schema_target_input import AuditLogSchemaTargetInput + + +@dataclass(slots=True) +class AuditLogSchemaInput: + """Audit Log Schema Input model.""" + + targets: List["AuditLogSchemaTargetInput"] + """The list of targets for the schema.""" + actor: Optional["AuditLogSchemaActorInput"] = None + """The metadata schema for the actor.""" + metadata: Optional[Dict[str, Any]] = None + """Optional JSON schema for event metadata.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AuditLogSchemaInput": + """Deserialize from a dictionary.""" + try: + return cls( + targets=[ + AuditLogSchemaTargetInput.from_dict(cast(Dict[str, Any], item)) + for item in cast(list[Any], data["targets"]) + ], + actor=AuditLogSchemaActorInput.from_dict(cast(Dict[str, Any], _v_actor)) + if (_v_actor := data.get("actor")) is not None + else None, + metadata=data.get("metadata"), + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AuditLogSchemaInput", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["targets"] = [item.to_dict() for item in self.targets] + if self.actor is not None: + result["actor"] = self.actor.to_dict() + if self.metadata is not None: + result["metadata"] = self.metadata + return result diff --git a/src/workos/audit_logs/models/audit_log_schema_json.py b/src/workos/audit_logs/models/audit_log_schema_json.py deleted file mode 100644 index be52b803..00000000 --- a/src/workos/audit_logs/models/audit_log_schema_json.py +++ /dev/null @@ -1,64 +0,0 @@ -# This file is auto-generated by oagen. Do not edit. - -from __future__ import annotations - -from dataclasses import dataclass -from datetime import datetime -from typing import cast -from typing import Any, Dict, List, Literal, Optional -from workos._types import _raise_deserialize_error -from workos._types import _format_datetime, _parse_datetime - -from .audit_log_schema_json_actor import AuditLogSchemaJsonActor -from .audit_log_schema_json_target import AuditLogSchemaJsonTarget - - -@dataclass(slots=True) -class AuditLogSchemaJson: - """Audit Log Schema Json model.""" - - object: Literal["audit_log_schema"] - """Distinguishes the Audit Log Schema object.""" - version: int - """The version of the schema.""" - targets: List["AuditLogSchemaJsonTarget"] - """The list of targets for the schema.""" - created_at: datetime - """The timestamp when the Audit Log Schema was created.""" - actor: Optional["AuditLogSchemaJsonActor"] = None - """The metadata schema for the actor.""" - metadata: Optional[Dict[str, Any]] = None - """Additional data associated with the event or entity.""" - - @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "AuditLogSchemaJson": - """Deserialize from a dictionary.""" - try: - return cls( - object=data.get("object", "audit_log_schema"), - version=data["version"], - targets=[ - AuditLogSchemaJsonTarget.from_dict(cast(Dict[str, Any], item)) - for item in cast(list[Any], data["targets"]) - ], - created_at=_parse_datetime(data["created_at"]), - actor=AuditLogSchemaJsonActor.from_dict(cast(Dict[str, Any], _v_actor)) - if (_v_actor := data.get("actor")) is not None - else None, - metadata=data.get("metadata"), - ) - except (KeyError, ValueError) as e: - _raise_deserialize_error("AuditLogSchemaJson", e) - - def to_dict(self) -> Dict[str, Any]: - """Serialize to a dictionary.""" - result: Dict[str, Any] = {} - result["object"] = self.object - result["version"] = self.version - result["targets"] = [item.to_dict() for item in self.targets] - result["created_at"] = _format_datetime(self.created_at) - if self.actor is not None: - result["actor"] = self.actor.to_dict() - if self.metadata is not None: - result["metadata"] = self.metadata - return result diff --git a/src/workos/audit_logs/models/audit_log_schema_json_target.py b/src/workos/audit_logs/models/audit_log_schema_json_target.py deleted file mode 100644 index cccca9e0..00000000 --- a/src/workos/audit_logs/models/audit_log_schema_json_target.py +++ /dev/null @@ -1,36 +0,0 @@ -# This file is auto-generated by oagen. Do not edit. - -from __future__ import annotations - -from dataclasses import dataclass -from typing import Any, Dict, Optional -from workos._types import _raise_deserialize_error - - -@dataclass(slots=True) -class AuditLogSchemaJsonTarget: - """Audit Log Schema Json Target model.""" - - type: str - """The type of the target resource.""" - metadata: Optional[Dict[str, Any]] = None - """Additional data associated with the event or entity.""" - - @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "AuditLogSchemaJsonTarget": - """Deserialize from a dictionary.""" - try: - return cls( - type=data["type"], - metadata=data.get("metadata"), - ) - except (KeyError, ValueError) as e: - _raise_deserialize_error("AuditLogSchemaJsonTarget", e) - - def to_dict(self) -> Dict[str, Any]: - """Serialize to a dictionary.""" - result: Dict[str, Any] = {} - result["type"] = self.type - if self.metadata is not None: - result["metadata"] = self.metadata - return result diff --git a/src/workos/audit_logs/models/audit_log_schema_target.py b/src/workos/audit_logs/models/audit_log_schema_target.py index 052064be..3c7b813e 100644 --- a/src/workos/audit_logs/models/audit_log_schema_target.py +++ b/src/workos/audit_logs/models/audit_log_schema_target.py @@ -1,6 +1,36 @@ # This file is auto-generated by oagen. Do not edit. -from typing import TypeAlias -from .audit_log_schema_json_target import AuditLogSchemaJsonTarget +from __future__ import annotations -AuditLogSchemaTarget: TypeAlias = AuditLogSchemaJsonTarget +from dataclasses import dataclass +from typing import Any, Dict, Optional +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class AuditLogSchemaTarget: + """Audit Log Schema Target model.""" + + type: str + """The type of the target resource.""" + metadata: Optional[Dict[str, Any]] = None + """Additional data associated with the event or entity.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "AuditLogSchemaTarget": + """Deserialize from a dictionary.""" + try: + return cls( + type=data["type"], + metadata=data.get("metadata"), + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("AuditLogSchemaTarget", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["type"] = self.type + if self.metadata is not None: + result["metadata"] = self.metadata + return result diff --git a/src/workos/audit_logs/models/audit_log_schema_target_input.py b/src/workos/audit_logs/models/audit_log_schema_target_input.py new file mode 100644 index 00000000..756cd5b8 --- /dev/null +++ b/src/workos/audit_logs/models/audit_log_schema_target_input.py @@ -0,0 +1,6 @@ +# This file is auto-generated by oagen. Do not edit. + +from typing import TypeAlias +from .audit_log_schema_target import AuditLogSchemaTarget + +AuditLogSchemaTargetInput: TypeAlias = AuditLogSchemaTarget diff --git a/src/workos/authorization/_resource.py b/src/workos/authorization/_resource.py index cd7afcd8..7e2a1d40 100644 --- a/src/workos/authorization/_resource.py +++ b/src/workos/authorization/_resource.py @@ -331,6 +331,9 @@ def list_role_assignments( before: Optional[str] = None, after: Optional[str] = None, order: Optional[Union[PaginationOrder, str]] = "desc", + resource_id: Optional[str] = None, + resource_external_id: Optional[str] = None, + resource_type_slug: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> SyncPage[UserRoleAssignment]: """List role assignments @@ -343,6 +346,9 @@ def list_role_assignments( before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to descending. Defaults to `desc`. + resource_id: Filter assignments by the ID of the resource. + resource_external_id: Filter assignments by the external ID of the resource. + resource_type_slug: Filter assignments by the slug of the resource type. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: @@ -362,6 +368,9 @@ def list_role_assignments( "before": before, "after": after, "order": enum_value(order) if order is not None else None, + "resource_id": resource_id, + "resource_external_id": resource_external_id, + "resource_type_slug": resource_type_slug, }.items() if v is not None } @@ -1103,6 +1112,7 @@ def list_role_assignments_for_resource_by_external_id( before: Optional[str] = None, after: Optional[str] = None, order: Optional[Union[PaginationOrder, str]] = "desc", + role_slug: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> SyncPage[UserRoleAssignment]: """List role assignments for a resource by external ID @@ -1117,6 +1127,7 @@ def list_role_assignments_for_resource_by_external_id( before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to descending. Defaults to `desc`. + role_slug: Filter assignments by the slug of the role. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: @@ -1136,6 +1147,7 @@ def list_role_assignments_for_resource_by_external_id( "before": before, "after": after, "order": enum_value(order) if order is not None else None, + "role_slug": role_slug, }.items() if v is not None } @@ -1165,7 +1177,6 @@ def list_resources( organization_id: Optional[str] = None, resource_type_slug: Optional[str] = None, resource_external_id: Optional[str] = None, - search: Optional[str] = None, parent: Optional[Union[ParentById, ParentByExternalId]] = None, request_options: Optional[RequestOptions] = None, ) -> SyncPage[AuthorizationResource]: @@ -1181,7 +1192,6 @@ def list_resources( organization_id: Filter resources by organization ID. resource_type_slug: Filter resources by resource type slug. resource_external_id: Filter resources by external ID. - search: Search resources by name. parent: Identifies the parent. One of: ParentById, ParentByExternalId. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. @@ -1205,7 +1215,6 @@ def list_resources( "organization_id": organization_id, "resource_type_slug": resource_type_slug, "resource_external_id": resource_external_id, - "search": search, }.items() if v is not None } @@ -1496,6 +1505,7 @@ def list_role_assignments_for_resource( before: Optional[str] = None, after: Optional[str] = None, order: Optional[Union[PaginationOrder, str]] = "desc", + role_slug: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> SyncPage[UserRoleAssignment]: """List role assignments for a resource @@ -1508,6 +1518,7 @@ def list_role_assignments_for_resource( before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to descending. Defaults to `desc`. + role_slug: Filter assignments by the slug of the role. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: @@ -1527,6 +1538,7 @@ def list_role_assignments_for_resource( "before": before, "after": after, "order": enum_value(order) if order is not None else None, + "role_slug": role_slug, }.items() if v is not None } @@ -2229,6 +2241,9 @@ async def list_role_assignments( before: Optional[str] = None, after: Optional[str] = None, order: Optional[Union[PaginationOrder, str]] = "desc", + resource_id: Optional[str] = None, + resource_external_id: Optional[str] = None, + resource_type_slug: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> AsyncPage[UserRoleAssignment]: """List role assignments @@ -2241,6 +2256,9 @@ async def list_role_assignments( before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to descending. Defaults to `desc`. + resource_id: Filter assignments by the ID of the resource. + resource_external_id: Filter assignments by the external ID of the resource. + resource_type_slug: Filter assignments by the slug of the resource type. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: @@ -2260,6 +2278,9 @@ async def list_role_assignments( "before": before, "after": after, "order": enum_value(order) if order is not None else None, + "resource_id": resource_id, + "resource_external_id": resource_external_id, + "resource_type_slug": resource_type_slug, }.items() if v is not None } @@ -3001,6 +3022,7 @@ async def list_role_assignments_for_resource_by_external_id( before: Optional[str] = None, after: Optional[str] = None, order: Optional[Union[PaginationOrder, str]] = "desc", + role_slug: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> AsyncPage[UserRoleAssignment]: """List role assignments for a resource by external ID @@ -3015,6 +3037,7 @@ async def list_role_assignments_for_resource_by_external_id( before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to descending. Defaults to `desc`. + role_slug: Filter assignments by the slug of the role. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: @@ -3034,6 +3057,7 @@ async def list_role_assignments_for_resource_by_external_id( "before": before, "after": after, "order": enum_value(order) if order is not None else None, + "role_slug": role_slug, }.items() if v is not None } @@ -3063,7 +3087,6 @@ async def list_resources( organization_id: Optional[str] = None, resource_type_slug: Optional[str] = None, resource_external_id: Optional[str] = None, - search: Optional[str] = None, parent: Optional[Union[ParentById, ParentByExternalId]] = None, request_options: Optional[RequestOptions] = None, ) -> AsyncPage[AuthorizationResource]: @@ -3079,7 +3102,6 @@ async def list_resources( organization_id: Filter resources by organization ID. resource_type_slug: Filter resources by resource type slug. resource_external_id: Filter resources by external ID. - search: Search resources by name. parent: Identifies the parent. One of: ParentById, ParentByExternalId. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. @@ -3103,7 +3125,6 @@ async def list_resources( "organization_id": organization_id, "resource_type_slug": resource_type_slug, "resource_external_id": resource_external_id, - "search": search, }.items() if v is not None } @@ -3394,6 +3415,7 @@ async def list_role_assignments_for_resource( before: Optional[str] = None, after: Optional[str] = None, order: Optional[Union[PaginationOrder, str]] = "desc", + role_slug: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> AsyncPage[UserRoleAssignment]: """List role assignments for a resource @@ -3406,6 +3428,7 @@ async def list_role_assignments_for_resource( before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to descending. Defaults to `desc`. + role_slug: Filter assignments by the slug of the role. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: @@ -3425,6 +3448,7 @@ async def list_role_assignments_for_resource( "before": before, "after": after, "order": enum_value(order) if order is not None else None, + "role_slug": role_slug, }.items() if v is not None } diff --git a/src/workos/common/__init__.py b/src/workos/common/__init__.py index de763f73..93f6bd87 100644 --- a/src/workos/common/__init__.py +++ b/src/workos/common/__init__.py @@ -4,6 +4,7 @@ from .models import ActionAuthenticationDeniedData as ActionAuthenticationDeniedData from .models import ActionUserRegistrationDenied as ActionUserRegistrationDenied from .models import ActionUserRegistrationDeniedData as ActionUserRegistrationDeniedData +from .models import Actor as Actor from .models import AddRolePermission as AddRolePermission from .models import ApiKeyCreated as ApiKeyCreated from .models import ApiKeyCreatedData as ApiKeyCreatedData @@ -18,7 +19,7 @@ AuditLogConfigurationLogStreamType as AuditLogConfigurationLogStreamType, ) from .models import AuditLogConfigurationState as AuditLogConfigurationState -from .models import AuditLogExportJsonState as AuditLogExportJsonState +from .models import AuditLogExportState as AuditLogExportState from .models import ( AuthenticateResponseAuthenticationMethod as AuthenticateResponseAuthenticationMethod, ) @@ -115,6 +116,13 @@ from .models import AuthenticationSSOTimedOutDataSSO as AuthenticationSSOTimedOutDataSSO from .models import AuthorizationPermission as AuthorizationPermission from .models import ConnectApplication as ConnectApplication +from .models import ConnectApplicationM2M as ConnectApplicationM2M +from .models import ConnectApplicationOAuth as ConnectApplicationOAuth +from .models import ( + ConnectApplicationOAuthRedirectUris as ConnectApplicationOAuthRedirectUris, +) +from .models import ConnectApplicationUnknown as ConnectApplicationUnknown +from .models import ConnectApplicationVariant as ConnectApplicationVariant from .models import ConnectedAccountState as ConnectedAccountState from .models import ConnectionActivated as ConnectionActivated from .models import ConnectionActivatedData as ConnectionActivatedData @@ -190,6 +198,7 @@ from .models import DsyncUserUpdatedDataEmail as DsyncUserUpdatedDataEmail from .models import EmailVerificationCreated as EmailVerificationCreated from .models import EmailVerificationCreatedData as EmailVerificationCreatedData +from .models import ErrorResponse as ErrorResponse from .models import EventContext as EventContext from .models import EventContextActor as EventContextActor from .models import ( @@ -340,6 +349,14 @@ from .models import PermissionDeletedData as PermissionDeletedData from .models import PermissionUpdated as PermissionUpdated from .models import PermissionUpdatedData as PermissionUpdatedData +from .models import PipeConnectedAccount as PipeConnectedAccount +from .models import PipesConnectedAccountConnected as PipesConnectedAccountConnected +from .models import ( + PipesConnectedAccountDisconnected as PipesConnectedAccountDisconnected, +) +from .models import ( + PipesConnectedAccountReauthorizationNeeded as PipesConnectedAccountReauthorizationNeeded, +) from .models import ProfileConnectionType as ProfileConnectionType from .models import ( RadarStandaloneAssessRequestAction as RadarStandaloneAssessRequestAction, @@ -419,5 +436,5 @@ from .models import WaitlistUserApproved as WaitlistUserApproved from .models import WaitlistUserCreated as WaitlistUserCreated from .models import WaitlistUserDenied as WaitlistUserDenied -from .models import WebhookEndpointJsonStatus as WebhookEndpointJsonStatus +from .models import WebhookEndpointStatus as WebhookEndpointStatus from .models import WidgetSessionTokenScopes as WidgetSessionTokenScopes diff --git a/src/workos/common/models/__init__.py b/src/workos/common/models/__init__.py index b21bb204..0dee7492 100644 --- a/src/workos/common/models/__init__.py +++ b/src/workos/common/models/__init__.py @@ -12,6 +12,7 @@ from .action_user_registration_denied_data import ( ActionUserRegistrationDeniedData as ActionUserRegistrationDeniedData, ) +from .actor import Actor as Actor from .add_role_permission import AddRolePermission as AddRolePermission from .api_key_created import ApiKeyCreated as ApiKeyCreated from .api_key_created_data import ApiKeyCreatedData as ApiKeyCreatedData @@ -28,9 +29,7 @@ from .audit_log_configuration_state import ( AuditLogConfigurationState as AuditLogConfigurationState, ) -from .audit_log_export_json_state import ( - AuditLogExportJsonState as AuditLogExportJsonState, -) +from .audit_log_export_state import AuditLogExportState as AuditLogExportState from .authenticate_response_authentication_method import ( AuthenticateResponseAuthenticationMethod as AuthenticateResponseAuthenticationMethod, ) @@ -203,6 +202,15 @@ ) from .authorization_permission import AuthorizationPermission as AuthorizationPermission from .connect_application import ConnectApplication as ConnectApplication +from .connect_application_m2m import ConnectApplicationM2M as ConnectApplicationM2M +from .connect_application_oauth import ( + ConnectApplicationOAuth as ConnectApplicationOAuth, +) +from .connect_application_oauth_redirect_uris import ( + ConnectApplicationOAuthRedirectUris as ConnectApplicationOAuthRedirectUris, +) +from .connect_application import ConnectApplicationUnknown as ConnectApplicationUnknown +from .connect_application import ConnectApplicationVariant as ConnectApplicationVariant from .connected_account_state import ConnectedAccountState as ConnectedAccountState from .connection_activated import ConnectionActivated as ConnectionActivated from .connection_activated_data import ( @@ -310,6 +318,7 @@ from .email_verification_created_data import ( EmailVerificationCreatedData as EmailVerificationCreatedData, ) +from .error_response import ErrorResponse as ErrorResponse from .event_context import EventContext as EventContext from .event_context_actor import EventContextActor as EventContextActor from .event_context_google_analytics_session import ( @@ -526,6 +535,16 @@ from .permission_deleted_data import PermissionDeletedData as PermissionDeletedData from .permission_updated import PermissionUpdated as PermissionUpdated from .permission_updated_data import PermissionUpdatedData as PermissionUpdatedData +from .pipe_connected_account import PipeConnectedAccount as PipeConnectedAccount +from .pipes_connected_account_connected import ( + PipesConnectedAccountConnected as PipesConnectedAccountConnected, +) +from .pipes_connected_account_disconnected import ( + PipesConnectedAccountDisconnected as PipesConnectedAccountDisconnected, +) +from .pipes_connected_account_reauthorization_needed import ( + PipesConnectedAccountReauthorizationNeeded as PipesConnectedAccountReauthorizationNeeded, +) from .profile_connection_type import ProfileConnectionType as ProfileConnectionType from .radar_standalone_assess_request_action import ( RadarStandaloneAssessRequestAction as RadarStandaloneAssessRequestAction, @@ -633,9 +652,7 @@ from .waitlist_user_approved import WaitlistUserApproved as WaitlistUserApproved from .waitlist_user_created import WaitlistUserCreated as WaitlistUserCreated from .waitlist_user_denied import WaitlistUserDenied as WaitlistUserDenied -from .webhook_endpoint_json_status import ( - WebhookEndpointJsonStatus as WebhookEndpointJsonStatus, -) +from .webhook_endpoint_status import WebhookEndpointStatus as WebhookEndpointStatus from .widget_session_token_scopes import ( WidgetSessionTokenScopes as WidgetSessionTokenScopes, ) diff --git a/src/workos/common/models/action_authentication_denied.py b/src/workos/common/models/action_authentication_denied.py index cd01a8a2..163a3314 100644 --- a/src/workos/common/models/action_authentication_denied.py +++ b/src/workos/common/models/action_authentication_denied.py @@ -17,6 +17,8 @@ class ActionAuthenticationDenied: """Action Authentication Denied model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["action.authentication.denied"] @@ -24,8 +26,6 @@ class ActionAuthenticationDenied: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "ActionAuthenticationDenied": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "action.authentication.denied"), data=ActionAuthenticationDeniedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "ActionAuthenticationDenied": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/action_user_registration_denied.py b/src/workos/common/models/action_user_registration_denied.py index 66e8b01e..38b5318a 100644 --- a/src/workos/common/models/action_user_registration_denied.py +++ b/src/workos/common/models/action_user_registration_denied.py @@ -17,6 +17,8 @@ class ActionUserRegistrationDenied: """Action User Registration Denied model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["action.user_registration.denied"] @@ -24,8 +26,6 @@ class ActionUserRegistrationDenied: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "ActionUserRegistrationDenied": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "action.user_registration.denied"), data=ActionUserRegistrationDeniedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "ActionUserRegistrationDenied": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/actor.py b/src/workos/common/models/actor.py new file mode 100644 index 00000000..0edd4bed --- /dev/null +++ b/src/workos/common/models/actor.py @@ -0,0 +1,35 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class Actor: + """The user or API key that performed an action.""" + + id: str + """Unique identifier of the actor.""" + name: str + """Display name of the actor.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "Actor": + """Deserialize from a dictionary.""" + try: + return cls( + id=data["id"], + name=data["name"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("Actor", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["id"] = self.id + result["name"] = self.name + return result diff --git a/src/workos/common/models/api_key_created.py b/src/workos/common/models/api_key_created.py index e3d81e77..61dfc0fd 100644 --- a/src/workos/common/models/api_key_created.py +++ b/src/workos/common/models/api_key_created.py @@ -17,6 +17,8 @@ class ApiKeyCreated: """Api Key Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["api_key.created"] @@ -24,8 +26,6 @@ class ApiKeyCreated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "ApiKeyCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "api_key.created"), data=ApiKeyCreatedData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "ApiKeyCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/api_key_created_data.py b/src/workos/common/models/api_key_created_data.py index e075c098..764c5b19 100644 --- a/src/workos/common/models/api_key_created_data.py +++ b/src/workos/common/models/api_key_created_data.py @@ -3,9 +3,11 @@ from __future__ import annotations from dataclasses import dataclass +from datetime import datetime from typing import cast from typing import Any, Dict, List, Literal, Optional, Union from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime from .api_key_created_data_owner import ApiKeyCreatedDataOwner from .user_api_key_created_data_owner import UserApiKeyCreatedDataOwner @@ -33,6 +35,8 @@ class ApiKeyCreatedData: """The timestamp when the API key was created.""" updated_at: str """The timestamp when the API key was last updated.""" + expires_at: Optional[datetime] = None + """Timestamp when the API Key expires. Null means the key does not expire.""" @classmethod def from_dict(cls, data: Dict[str, Any]) -> "ApiKeyCreatedData": @@ -61,6 +65,9 @@ def from_dict(cls, data: Dict[str, Any]) -> "ApiKeyCreatedData": permissions=data["permissions"], created_at=data["created_at"], updated_at=data["updated_at"], + expires_at=_parse_datetime(_v_expires_at) + if (_v_expires_at := data.get("expires_at")) is not None + else None, ) except (KeyError, ValueError) as e: _raise_deserialize_error("ApiKeyCreatedData", e) @@ -80,4 +87,8 @@ def to_dict(self) -> Dict[str, Any]: result["permissions"] = self.permissions result["created_at"] = self.created_at result["updated_at"] = self.updated_at + if self.expires_at is not None: + result["expires_at"] = _format_datetime(self.expires_at) + else: + result["expires_at"] = None return result diff --git a/src/workos/common/models/api_key_revoked.py b/src/workos/common/models/api_key_revoked.py index 3e815a40..6bc18439 100644 --- a/src/workos/common/models/api_key_revoked.py +++ b/src/workos/common/models/api_key_revoked.py @@ -17,6 +17,8 @@ class ApiKeyRevoked: """Api Key Revoked model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["api_key.revoked"] @@ -24,8 +26,6 @@ class ApiKeyRevoked: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "ApiKeyRevoked": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "api_key.revoked"), data=ApiKeyRevokedData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "ApiKeyRevoked": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/audit_log_export_json_state.py b/src/workos/common/models/audit_log_export_state.py similarity index 68% rename from src/workos/common/models/audit_log_export_json_state.py rename to src/workos/common/models/audit_log_export_state.py index 07e1b027..f430a47b 100644 --- a/src/workos/common/models/audit_log_export_json_state.py +++ b/src/workos/common/models/audit_log_export_state.py @@ -1,6 +1,6 @@ # This file is auto-generated by oagen. Do not edit. -"""Enumeration of audit log export json state values.""" +"""Enumeration of audit log export state values.""" from __future__ import annotations @@ -9,15 +9,15 @@ from typing import Literal, TypeAlias -class AuditLogExportJsonState(str, Enum): - """Known values for AuditLogExportJsonState.""" +class AuditLogExportState(str, Enum): + """Known values for AuditLogExportState.""" PENDING = "pending" READY = "ready" ERROR = "error" @classmethod - def _missing_(cls, value: object) -> Optional["AuditLogExportJsonState"]: + def _missing_(cls, value: object) -> Optional["AuditLogExportState"]: if not isinstance(value, str): return None unknown = str.__new__(cls, value) @@ -26,4 +26,4 @@ def _missing_(cls, value: object) -> Optional["AuditLogExportJsonState"]: return unknown -AuditLogExportJsonStateLiteral: TypeAlias = Literal["pending", "ready", "error"] +AuditLogExportStateLiteral: TypeAlias = Literal["pending", "ready", "error"] diff --git a/src/workos/common/models/authentication_email_verification_failed.py b/src/workos/common/models/authentication_email_verification_failed.py index d1e2b354..42c87e15 100644 --- a/src/workos/common/models/authentication_email_verification_failed.py +++ b/src/workos/common/models/authentication_email_verification_failed.py @@ -19,6 +19,8 @@ class AuthenticationEmailVerificationFailed: """Authentication Email Verification Failed model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["authentication.email_verification_failed"] @@ -26,8 +28,6 @@ class AuthenticationEmailVerificationFailed: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -35,13 +35,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationEmailVerificationFail """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "authentication.email_verification_failed"), data=AuthenticationEmailVerificationFailedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -52,11 +52,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationEmailVerificationFail def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/authentication_email_verification_succeeded.py b/src/workos/common/models/authentication_email_verification_succeeded.py index f3a4a06b..78e55325 100644 --- a/src/workos/common/models/authentication_email_verification_succeeded.py +++ b/src/workos/common/models/authentication_email_verification_succeeded.py @@ -19,6 +19,8 @@ class AuthenticationEmailVerificationSucceeded: """Authentication Email Verification Succeeded model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["authentication.email_verification_succeeded"] @@ -26,8 +28,6 @@ class AuthenticationEmailVerificationSucceeded: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -37,13 +37,13 @@ def from_dict( """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "authentication.email_verification_succeeded"), data=AuthenticationEmailVerificationSucceededData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -54,11 +54,11 @@ def from_dict( def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/authentication_magic_auth_failed.py b/src/workos/common/models/authentication_magic_auth_failed.py index 678bb6c1..66729888 100644 --- a/src/workos/common/models/authentication_magic_auth_failed.py +++ b/src/workos/common/models/authentication_magic_auth_failed.py @@ -17,6 +17,8 @@ class AuthenticationMagicAuthFailed: """Authentication Magic Auth Failed model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["authentication.magic_auth_failed"] @@ -24,8 +26,6 @@ class AuthenticationMagicAuthFailed: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationMagicAuthFailed": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "authentication.magic_auth_failed"), data=AuthenticationMagicAuthFailedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationMagicAuthFailed": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/authentication_magic_auth_succeeded.py b/src/workos/common/models/authentication_magic_auth_succeeded.py index 9c1e15a8..e83f872d 100644 --- a/src/workos/common/models/authentication_magic_auth_succeeded.py +++ b/src/workos/common/models/authentication_magic_auth_succeeded.py @@ -19,6 +19,8 @@ class AuthenticationMagicAuthSucceeded: """Authentication Magic Auth Succeeded model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["authentication.magic_auth_succeeded"] @@ -26,8 +28,6 @@ class AuthenticationMagicAuthSucceeded: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -35,13 +35,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationMagicAuthSucceeded": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "authentication.magic_auth_succeeded"), data=AuthenticationMagicAuthSucceededData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -52,11 +52,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationMagicAuthSucceeded": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/authentication_mfa_failed.py b/src/workos/common/models/authentication_mfa_failed.py index 1f183c77..6f2a991d 100644 --- a/src/workos/common/models/authentication_mfa_failed.py +++ b/src/workos/common/models/authentication_mfa_failed.py @@ -17,6 +17,8 @@ class AuthenticationMFAFailed: """Authentication MFA Failed model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["authentication.mfa_failed"] @@ -24,8 +26,6 @@ class AuthenticationMFAFailed: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationMFAFailed": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "authentication.mfa_failed"), data=AuthenticationMFAFailedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationMFAFailed": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/authentication_mfa_succeeded.py b/src/workos/common/models/authentication_mfa_succeeded.py index 9c3ce842..633735c3 100644 --- a/src/workos/common/models/authentication_mfa_succeeded.py +++ b/src/workos/common/models/authentication_mfa_succeeded.py @@ -17,6 +17,8 @@ class AuthenticationMFASucceeded: """Authentication MFA Succeeded model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["authentication.mfa_succeeded"] @@ -24,8 +26,6 @@ class AuthenticationMFASucceeded: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationMFASucceeded": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "authentication.mfa_succeeded"), data=AuthenticationMFASucceededData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationMFASucceeded": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/authentication_oauth_failed.py b/src/workos/common/models/authentication_oauth_failed.py index a55ca8c6..a70b3b21 100644 --- a/src/workos/common/models/authentication_oauth_failed.py +++ b/src/workos/common/models/authentication_oauth_failed.py @@ -17,6 +17,8 @@ class AuthenticationOAuthFailed: """Authentication O Auth Failed model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["authentication.oauth_failed"] @@ -24,8 +26,6 @@ class AuthenticationOAuthFailed: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationOAuthFailed": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "authentication.oauth_failed"), data=AuthenticationOAuthFailedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationOAuthFailed": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/authentication_oauth_succeeded.py b/src/workos/common/models/authentication_oauth_succeeded.py index 8b5dbfbf..b0b82f3a 100644 --- a/src/workos/common/models/authentication_oauth_succeeded.py +++ b/src/workos/common/models/authentication_oauth_succeeded.py @@ -17,6 +17,8 @@ class AuthenticationOAuthSucceeded: """Authentication O Auth Succeeded model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["authentication.oauth_succeeded"] @@ -24,8 +26,6 @@ class AuthenticationOAuthSucceeded: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationOAuthSucceeded": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "authentication.oauth_succeeded"), data=AuthenticationOAuthSucceededData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationOAuthSucceeded": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/authentication_passkey_failed.py b/src/workos/common/models/authentication_passkey_failed.py index 9fdfaeb6..f5e23818 100644 --- a/src/workos/common/models/authentication_passkey_failed.py +++ b/src/workos/common/models/authentication_passkey_failed.py @@ -17,6 +17,8 @@ class AuthenticationPasskeyFailed: """Authentication Passkey Failed model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["authentication.passkey_failed"] @@ -24,8 +26,6 @@ class AuthenticationPasskeyFailed: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationPasskeyFailed": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "authentication.passkey_failed"), data=AuthenticationPasskeyFailedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationPasskeyFailed": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/authentication_passkey_succeeded.py b/src/workos/common/models/authentication_passkey_succeeded.py index e5a751f1..b6e677ef 100644 --- a/src/workos/common/models/authentication_passkey_succeeded.py +++ b/src/workos/common/models/authentication_passkey_succeeded.py @@ -17,6 +17,8 @@ class AuthenticationPasskeySucceeded: """Authentication Passkey Succeeded model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["authentication.passkey_succeeded"] @@ -24,8 +26,6 @@ class AuthenticationPasskeySucceeded: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationPasskeySucceeded": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "authentication.passkey_succeeded"), data=AuthenticationPasskeySucceededData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationPasskeySucceeded": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/authentication_password_failed.py b/src/workos/common/models/authentication_password_failed.py index a93becc3..3b9d57c4 100644 --- a/src/workos/common/models/authentication_password_failed.py +++ b/src/workos/common/models/authentication_password_failed.py @@ -17,6 +17,8 @@ class AuthenticationPasswordFailed: """Authentication Password Failed model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["authentication.password_failed"] @@ -24,8 +26,6 @@ class AuthenticationPasswordFailed: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationPasswordFailed": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "authentication.password_failed"), data=AuthenticationPasswordFailedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationPasswordFailed": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/authentication_password_succeeded.py b/src/workos/common/models/authentication_password_succeeded.py index 5e33bb50..f7e4a42e 100644 --- a/src/workos/common/models/authentication_password_succeeded.py +++ b/src/workos/common/models/authentication_password_succeeded.py @@ -17,6 +17,8 @@ class AuthenticationPasswordSucceeded: """Authentication Password Succeeded model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["authentication.password_succeeded"] @@ -24,8 +26,6 @@ class AuthenticationPasswordSucceeded: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationPasswordSucceeded": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "authentication.password_succeeded"), data=AuthenticationPasswordSucceededData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationPasswordSucceeded": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/authentication_radar_risk_detected.py b/src/workos/common/models/authentication_radar_risk_detected.py index 06a8904e..91de4531 100644 --- a/src/workos/common/models/authentication_radar_risk_detected.py +++ b/src/workos/common/models/authentication_radar_risk_detected.py @@ -17,6 +17,8 @@ class AuthenticationRadarRiskDetected: """Authentication Radar Risk Detected model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["authentication.radar_risk_detected"] @@ -24,8 +26,6 @@ class AuthenticationRadarRiskDetected: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationRadarRiskDetected": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "authentication.radar_risk_detected"), data=AuthenticationRadarRiskDetectedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationRadarRiskDetected": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/authentication_sso_failed.py b/src/workos/common/models/authentication_sso_failed.py index 0cc430e2..5f988302 100644 --- a/src/workos/common/models/authentication_sso_failed.py +++ b/src/workos/common/models/authentication_sso_failed.py @@ -17,6 +17,8 @@ class AuthenticationSSOFailed: """Authentication SSO Failed model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["authentication.sso_failed"] @@ -24,8 +26,6 @@ class AuthenticationSSOFailed: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationSSOFailed": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "authentication.sso_failed"), data=AuthenticationSSOFailedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationSSOFailed": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/authentication_sso_started.py b/src/workos/common/models/authentication_sso_started.py index 23ef78b5..0871ab16 100644 --- a/src/workos/common/models/authentication_sso_started.py +++ b/src/workos/common/models/authentication_sso_started.py @@ -17,6 +17,8 @@ class AuthenticationSSOStarted: """Authentication SSO Started model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["authentication.sso_started"] @@ -24,8 +26,6 @@ class AuthenticationSSOStarted: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationSSOStarted": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "authentication.sso_started"), data=AuthenticationSSOStartedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationSSOStarted": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/authentication_sso_succeeded.py b/src/workos/common/models/authentication_sso_succeeded.py index f84385cf..d7e574c4 100644 --- a/src/workos/common/models/authentication_sso_succeeded.py +++ b/src/workos/common/models/authentication_sso_succeeded.py @@ -17,6 +17,8 @@ class AuthenticationSSOSucceeded: """Authentication SSO Succeeded model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["authentication.sso_succeeded"] @@ -24,8 +26,6 @@ class AuthenticationSSOSucceeded: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationSSOSucceeded": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "authentication.sso_succeeded"), data=AuthenticationSSOSucceededData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationSSOSucceeded": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/authentication_sso_timed_out.py b/src/workos/common/models/authentication_sso_timed_out.py index 6e5d2e8c..49aab5e9 100644 --- a/src/workos/common/models/authentication_sso_timed_out.py +++ b/src/workos/common/models/authentication_sso_timed_out.py @@ -17,6 +17,8 @@ class AuthenticationSSOTimedOut: """Authentication SSO Timed Out model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["authentication.sso_timed_out"] @@ -24,8 +26,6 @@ class AuthenticationSSOTimedOut: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationSSOTimedOut": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "authentication.sso_timed_out"), data=AuthenticationSSOTimedOutData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "AuthenticationSSOTimedOut": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/connect_application.py b/src/workos/common/models/connect_application.py index 6bf7a2e7..79aaa4c7 100644 --- a/src/workos/common/models/connect_application.py +++ b/src/workos/common/models/connect_application.py @@ -3,72 +3,59 @@ from __future__ import annotations from dataclasses import dataclass -from datetime import datetime -from typing import Any, Dict, List, Literal, Optional +from typing import Any, ClassVar, Dict, Union, cast from workos._types import _raise_deserialize_error -from workos._types import _format_datetime, _parse_datetime + +from .connect_application_m2m import ConnectApplicationM2M +from .connect_application_oauth import ConnectApplicationOAuth @dataclass(slots=True) -class ConnectApplication: - """Connect Application model.""" +class ConnectApplicationUnknown: + """Unknown variant of ConnectApplication not yet recognized by this SDK version.""" - object: Literal["connect_application"] - """Distinguishes the connect application object.""" - id: str - """The unique ID of the connect application.""" - client_id: str - """The client ID of the connect application.""" - description: Optional[str] - """A description of the connect application.""" - name: str - """The name of the connect application.""" - scopes: List[str] - """The scopes available for this application.""" - created_at: datetime - """An ISO 8601 timestamp.""" - updated_at: datetime - """An ISO 8601 timestamp.""" - application_type: Optional[Literal["m2m"]] = None - """The type of the application.""" - organization_id: Optional[str] = None - """The ID of the organization the application belongs to.""" + raw_data: Dict[str, Any] + """The raw payload, preserved so callers can still inspect the data.""" @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "ConnectApplication": - """Deserialize from a dictionary.""" - try: - return cls( - object=data.get("object", "connect_application"), - id=data["id"], - client_id=data["client_id"], - description=data["description"], - name=data["name"], - scopes=data["scopes"], - created_at=_parse_datetime(data["created_at"]), - updated_at=_parse_datetime(data["updated_at"]), - application_type=data.get("application_type"), - organization_id=data.get("organization_id"), - ) - except (KeyError, ValueError) as e: - _raise_deserialize_error("ConnectApplication", e) + def from_dict(cls, data: Dict[str, Any]) -> "ConnectApplicationUnknown": + """Wrap raw data in an unknown variant.""" + return cls(raw_data=data) def to_dict(self) -> Dict[str, Any]: - """Serialize to a dictionary.""" - result: Dict[str, Any] = {} - result["object"] = self.object - result["id"] = self.id - result["client_id"] = self.client_id - if self.description is not None: - result["description"] = self.description - else: - result["description"] = None - result["name"] = self.name - result["scopes"] = self.scopes - result["created_at"] = _format_datetime(self.created_at) - result["updated_at"] = _format_datetime(self.updated_at) - if self.application_type is not None: - result["application_type"] = self.application_type - if self.organization_id is not None: - result["organization_id"] = self.organization_id - return result + """Return the original raw data.""" + return dict(self.raw_data) + + +ConnectApplicationVariant = Union[ + ConnectApplicationM2M, + ConnectApplicationOAuth, + ConnectApplicationUnknown, +] + + +class ConnectApplication: + """Discriminated union dispatcher (discriminated by 'application_type').""" + + _DISPATCH: ClassVar[Dict[str, type]] = { + "m2m": ConnectApplicationM2M, + "oauth": ConnectApplicationOAuth, + } + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "ConnectApplicationVariant": + """Deserialize from a dictionary, dispatching to the correct variant.""" + if "application_type" not in data: + _raise_deserialize_error( + "ConnectApplication", + ValueError("Missing required field 'application_type'"), + ) + disc_value = data["application_type"] + if disc_value is None: + _raise_deserialize_error( + "ConnectApplication", ValueError("application_type must not be None") + ) + dispatch_cls = cls._DISPATCH.get(disc_value) + if dispatch_cls is not None: + return cast("ConnectApplicationVariant", dispatch_cls.from_dict(data)) + return ConnectApplicationUnknown.from_dict(data) diff --git a/src/workos/common/models/connect_application_m2m.py b/src/workos/common/models/connect_application_m2m.py new file mode 100644 index 00000000..e8bea8b3 --- /dev/null +++ b/src/workos/common/models/connect_application_m2m.py @@ -0,0 +1,72 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import Any, Dict, List, Literal, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + + +@dataclass(slots=True) +class ConnectApplicationM2M: + """Connect Application M2M model.""" + + object: Literal["connect_application"] + """Distinguishes the connect application object.""" + id: str + """The unique ID of the connect application.""" + client_id: str + """The client ID of the connect application.""" + description: Optional[str] + """A description of the connect application.""" + name: str + """The name of the connect application.""" + scopes: List[str] + """The scopes available for this application.""" + created_at: datetime + """An ISO 8601 timestamp.""" + updated_at: datetime + """An ISO 8601 timestamp.""" + application_type: Literal["m2m"] + """The type of the application.""" + organization_id: str + """The ID of the organization the application belongs to.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "ConnectApplicationM2M": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "connect_application"), + id=data["id"], + client_id=data["client_id"], + description=data["description"], + name=data["name"], + scopes=data["scopes"], + created_at=_parse_datetime(data["created_at"]), + updated_at=_parse_datetime(data["updated_at"]), + application_type=data.get("application_type", "m2m"), + organization_id=data["organization_id"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("ConnectApplicationM2M", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["client_id"] = self.client_id + if self.description is not None: + result["description"] = self.description + else: + result["description"] = None + result["name"] = self.name + result["scopes"] = self.scopes + result["created_at"] = _format_datetime(self.created_at) + result["updated_at"] = _format_datetime(self.updated_at) + result["application_type"] = self.application_type + result["organization_id"] = self.organization_id + return result diff --git a/src/workos/common/models/connect_application_oauth.py b/src/workos/common/models/connect_application_oauth.py new file mode 100644 index 00000000..85b54664 --- /dev/null +++ b/src/workos/common/models/connect_application_oauth.py @@ -0,0 +1,98 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import cast +from typing import Any, Dict, List, Literal, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + +from .connect_application_oauth_redirect_uris import ConnectApplicationOAuthRedirectUris + + +@dataclass(slots=True) +class ConnectApplicationOAuth: + """Connect Application O Auth model.""" + + object: Literal["connect_application"] + """Distinguishes the connect application object.""" + id: str + """The unique ID of the connect application.""" + client_id: str + """The client ID of the connect application.""" + description: Optional[str] + """A description of the connect application.""" + name: str + """The name of the connect application.""" + scopes: List[str] + """The scopes available for this application.""" + created_at: datetime + """An ISO 8601 timestamp.""" + updated_at: datetime + """An ISO 8601 timestamp.""" + application_type: Literal["oauth"] + """The type of the application.""" + redirect_uris: List["ConnectApplicationOAuthRedirectUris"] + """The redirect URIs configured for this application.""" + uses_pkce: bool + """Whether the application uses PKCE for authorization.""" + is_first_party: bool + """Whether the application is a first-party application.""" + was_dynamically_registered: Optional[bool] = None + """Whether the application was dynamically registered.""" + organization_id: Optional[str] = None + """The ID of the organization the application belongs to.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "ConnectApplicationOAuth": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "connect_application"), + id=data["id"], + client_id=data["client_id"], + description=data["description"], + name=data["name"], + scopes=data["scopes"], + created_at=_parse_datetime(data["created_at"]), + updated_at=_parse_datetime(data["updated_at"]), + application_type=data.get("application_type", "oauth"), + redirect_uris=[ + ConnectApplicationOAuthRedirectUris.from_dict( + cast(Dict[str, Any], item) + ) + for item in cast(list[Any], data["redirect_uris"]) + ], + uses_pkce=data["uses_pkce"], + is_first_party=data["is_first_party"], + was_dynamically_registered=data.get("was_dynamically_registered"), + organization_id=data.get("organization_id"), + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("ConnectApplicationOAuth", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["client_id"] = self.client_id + if self.description is not None: + result["description"] = self.description + else: + result["description"] = None + result["name"] = self.name + result["scopes"] = self.scopes + result["created_at"] = _format_datetime(self.created_at) + result["updated_at"] = _format_datetime(self.updated_at) + result["application_type"] = self.application_type + result["redirect_uris"] = [item.to_dict() for item in self.redirect_uris] + result["uses_pkce"] = self.uses_pkce + result["is_first_party"] = self.is_first_party + if self.was_dynamically_registered is not None: + result["was_dynamically_registered"] = self.was_dynamically_registered + if self.organization_id is not None: + result["organization_id"] = self.organization_id + return result diff --git a/src/workos/common/models/connect_application_oauth_redirect_uris.py b/src/workos/common/models/connect_application_oauth_redirect_uris.py new file mode 100644 index 00000000..d1a4dd38 --- /dev/null +++ b/src/workos/common/models/connect_application_oauth_redirect_uris.py @@ -0,0 +1,35 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class ConnectApplicationOAuthRedirectUris: + """Connect Application O Auth Redirect Uris model.""" + + uri: str + """The redirect URI for the application.""" + default: bool + """Whether this is the default redirect URI.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "ConnectApplicationOAuthRedirectUris": + """Deserialize from a dictionary.""" + try: + return cls( + uri=data["uri"], + default=data["default"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("ConnectApplicationOAuthRedirectUris", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["uri"] = self.uri + result["default"] = self.default + return result diff --git a/src/workos/common/models/connection_activated.py b/src/workos/common/models/connection_activated.py index 516be577..c0f60117 100644 --- a/src/workos/common/models/connection_activated.py +++ b/src/workos/common/models/connection_activated.py @@ -17,6 +17,8 @@ class ConnectionActivated: """Connection Activated model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["connection.activated"] @@ -24,8 +26,6 @@ class ConnectionActivated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "ConnectionActivated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "connection.activated"), data=ConnectionActivatedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "ConnectionActivated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/connection_deactivated.py b/src/workos/common/models/connection_deactivated.py index f0b032e6..1e6ad18b 100644 --- a/src/workos/common/models/connection_deactivated.py +++ b/src/workos/common/models/connection_deactivated.py @@ -17,6 +17,8 @@ class ConnectionDeactivated: """Connection Deactivated model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["connection.deactivated"] @@ -24,8 +26,6 @@ class ConnectionDeactivated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "ConnectionDeactivated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "connection.deactivated"), data=ConnectionDeactivatedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "ConnectionDeactivated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/connection_deleted.py b/src/workos/common/models/connection_deleted.py index a6ff735e..fa8725ec 100644 --- a/src/workos/common/models/connection_deleted.py +++ b/src/workos/common/models/connection_deleted.py @@ -17,6 +17,8 @@ class ConnectionDeleted: """Connection Deleted model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["connection.deleted"] @@ -24,8 +26,6 @@ class ConnectionDeleted: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "ConnectionDeleted": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "connection.deleted"), data=ConnectionDeletedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "ConnectionDeleted": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/connection_saml_certificate_renewal_required.py b/src/workos/common/models/connection_saml_certificate_renewal_required.py index 23da83c1..2185ed68 100644 --- a/src/workos/common/models/connection_saml_certificate_renewal_required.py +++ b/src/workos/common/models/connection_saml_certificate_renewal_required.py @@ -19,6 +19,8 @@ class ConnectionSAMLCertificateRenewalRequired: """Connection SAML Certificate Renewal Required model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["connection.saml_certificate_renewal_required"] @@ -26,8 +28,6 @@ class ConnectionSAMLCertificateRenewalRequired: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -37,13 +37,13 @@ def from_dict( """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "connection.saml_certificate_renewal_required"), data=ConnectionSAMLCertificateRenewalRequiredData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -54,11 +54,11 @@ def from_dict( def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/connection_saml_certificate_renewed.py b/src/workos/common/models/connection_saml_certificate_renewed.py index 18ba4fb8..e212fddb 100644 --- a/src/workos/common/models/connection_saml_certificate_renewed.py +++ b/src/workos/common/models/connection_saml_certificate_renewed.py @@ -19,6 +19,8 @@ class ConnectionSAMLCertificateRenewed: """Connection SAML Certificate Renewed model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["connection.saml_certificate_renewed"] @@ -26,8 +28,6 @@ class ConnectionSAMLCertificateRenewed: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -35,13 +35,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "ConnectionSAMLCertificateRenewed": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "connection.saml_certificate_renewed"), data=ConnectionSAMLCertificateRenewedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -52,11 +52,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "ConnectionSAMLCertificateRenewed": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/create_webhook_endpoint_events.py b/src/workos/common/models/create_webhook_endpoint_events.py index eb393978..353c159c 100644 --- a/src/workos/common/models/create_webhook_endpoint_events.py +++ b/src/workos/common/models/create_webhook_endpoint_events.py @@ -88,6 +88,11 @@ class CreateWebhookEndpointEvents(str, Enum): PERMISSION_CREATED = "permission.created" PERMISSION_DELETED = "permission.deleted" PERMISSION_UPDATED = "permission.updated" + PIPES_CONNECTED_ACCOUNT_CONNECTED = "pipes.connected_account.connected" + PIPES_CONNECTED_ACCOUNT_DISCONNECTED = "pipes.connected_account.disconnected" + PIPES_CONNECTED_ACCOUNT_REAUTHORIZATION_NEEDED = ( + "pipes.connected_account.reauthorization_needed" + ) SESSION_CREATED = "session.created" SESSION_REVOKED = "session.revoked" WAITLIST_USER_APPROVED = "waitlist_user.approved" @@ -177,6 +182,9 @@ def _missing_(cls, value: object) -> Optional["CreateWebhookEndpointEvents"]: "permission.created", "permission.deleted", "permission.updated", + "pipes.connected_account.connected", + "pipes.connected_account.disconnected", + "pipes.connected_account.reauthorization_needed", "session.created", "session.revoked", "waitlist_user.approved", diff --git a/src/workos/common/models/dsync_activated.py b/src/workos/common/models/dsync_activated.py index aabce55b..86abc79e 100644 --- a/src/workos/common/models/dsync_activated.py +++ b/src/workos/common/models/dsync_activated.py @@ -17,6 +17,8 @@ class DsyncActivated: """Dsync Activated model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["dsync.activated"] @@ -24,8 +26,6 @@ class DsyncActivated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncActivated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "dsync.activated"), data=DsyncActivatedData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncActivated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/dsync_deactivated.py b/src/workos/common/models/dsync_deactivated.py index 87760a07..4ae6c6b8 100644 --- a/src/workos/common/models/dsync_deactivated.py +++ b/src/workos/common/models/dsync_deactivated.py @@ -17,6 +17,8 @@ class DsyncDeactivated: """Dsync Deactivated model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["dsync.deactivated"] @@ -24,8 +26,6 @@ class DsyncDeactivated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncDeactivated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "dsync.deactivated"), data=DsyncDeactivatedData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncDeactivated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/dsync_deleted.py b/src/workos/common/models/dsync_deleted.py index 5a5b22a2..b4a093b5 100644 --- a/src/workos/common/models/dsync_deleted.py +++ b/src/workos/common/models/dsync_deleted.py @@ -17,6 +17,8 @@ class DsyncDeleted: """Dsync Deleted model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["dsync.deleted"] @@ -24,8 +26,6 @@ class DsyncDeleted: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncDeleted": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "dsync.deleted"), data=DsyncDeletedData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncDeleted": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/dsync_group_created.py b/src/workos/common/models/dsync_group_created.py index e6d91496..95bbf6ad 100644 --- a/src/workos/common/models/dsync_group_created.py +++ b/src/workos/common/models/dsync_group_created.py @@ -17,6 +17,8 @@ class DsyncGroupCreated: """Dsync Group Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["dsync.group.created"] @@ -24,8 +26,6 @@ class DsyncGroupCreated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncGroupCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "dsync.group.created"), data=DirectoryGroup.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncGroupCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/dsync_group_deleted.py b/src/workos/common/models/dsync_group_deleted.py index fb835f01..69b6ffe2 100644 --- a/src/workos/common/models/dsync_group_deleted.py +++ b/src/workos/common/models/dsync_group_deleted.py @@ -17,6 +17,8 @@ class DsyncGroupDeleted: """Dsync Group Deleted model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["dsync.group.deleted"] @@ -24,8 +26,6 @@ class DsyncGroupDeleted: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncGroupDeleted": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "dsync.group.deleted"), data=DirectoryGroup.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncGroupDeleted": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/dsync_group_updated.py b/src/workos/common/models/dsync_group_updated.py index 1394ce4c..b89bcde3 100644 --- a/src/workos/common/models/dsync_group_updated.py +++ b/src/workos/common/models/dsync_group_updated.py @@ -17,6 +17,8 @@ class DsyncGroupUpdated: """Dsync Group Updated model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["dsync.group.updated"] @@ -24,8 +26,6 @@ class DsyncGroupUpdated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncGroupUpdated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "dsync.group.updated"), data=DsyncGroupUpdatedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncGroupUpdated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/dsync_group_user_added.py b/src/workos/common/models/dsync_group_user_added.py index 9388edfb..061acd81 100644 --- a/src/workos/common/models/dsync_group_user_added.py +++ b/src/workos/common/models/dsync_group_user_added.py @@ -17,6 +17,8 @@ class DsyncGroupUserAdded: """Dsync Group User Added model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["dsync.group.user_added"] @@ -24,8 +26,6 @@ class DsyncGroupUserAdded: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncGroupUserAdded": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "dsync.group.user_added"), data=DsyncGroupUserAddedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncGroupUserAdded": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/dsync_group_user_removed.py b/src/workos/common/models/dsync_group_user_removed.py index b1cb9698..93f8c225 100644 --- a/src/workos/common/models/dsync_group_user_removed.py +++ b/src/workos/common/models/dsync_group_user_removed.py @@ -17,6 +17,8 @@ class DsyncGroupUserRemoved: """Dsync Group User Removed model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["dsync.group.user_removed"] @@ -24,8 +26,6 @@ class DsyncGroupUserRemoved: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncGroupUserRemoved": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "dsync.group.user_removed"), data=DsyncGroupUserRemovedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncGroupUserRemoved": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/dsync_user_created.py b/src/workos/common/models/dsync_user_created.py index ec0e5527..3471b110 100644 --- a/src/workos/common/models/dsync_user_created.py +++ b/src/workos/common/models/dsync_user_created.py @@ -17,6 +17,8 @@ class DsyncUserCreated: """Dsync User Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["dsync.user.created"] @@ -24,8 +26,6 @@ class DsyncUserCreated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncUserCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "dsync.user.created"), data=DirectoryUser.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncUserCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/dsync_user_deleted.py b/src/workos/common/models/dsync_user_deleted.py index 3d3dd61c..be2c1139 100644 --- a/src/workos/common/models/dsync_user_deleted.py +++ b/src/workos/common/models/dsync_user_deleted.py @@ -17,6 +17,8 @@ class DsyncUserDeleted: """Dsync User Deleted model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["dsync.user.deleted"] @@ -24,8 +26,6 @@ class DsyncUserDeleted: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncUserDeleted": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "dsync.user.deleted"), data=DirectoryUser.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncUserDeleted": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/dsync_user_updated.py b/src/workos/common/models/dsync_user_updated.py index 7a01036d..1d528b1c 100644 --- a/src/workos/common/models/dsync_user_updated.py +++ b/src/workos/common/models/dsync_user_updated.py @@ -17,6 +17,8 @@ class DsyncUserUpdated: """Dsync User Updated model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["dsync.user.updated"] @@ -24,8 +26,6 @@ class DsyncUserUpdated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncUserUpdated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "dsync.user.updated"), data=DsyncUserUpdatedData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "DsyncUserUpdated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/email_verification_created.py b/src/workos/common/models/email_verification_created.py index 9f07ac02..0f38e7c8 100644 --- a/src/workos/common/models/email_verification_created.py +++ b/src/workos/common/models/email_verification_created.py @@ -17,6 +17,8 @@ class EmailVerificationCreated: """Email Verification Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["email_verification.created"] @@ -24,8 +26,6 @@ class EmailVerificationCreated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "EmailVerificationCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "email_verification.created"), data=EmailVerificationCreatedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "EmailVerificationCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/error_response.py b/src/workos/common/models/error_response.py new file mode 100644 index 00000000..514556dd --- /dev/null +++ b/src/workos/common/models/error_response.py @@ -0,0 +1,31 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class ErrorResponse: + """Error response body.""" + + error: str + """A human-readable description of the error.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "ErrorResponse": + """Deserialize from a dictionary.""" + try: + return cls( + error=data["error"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("ErrorResponse", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["error"] = self.error + return result diff --git a/src/workos/common/models/flag_created.py b/src/workos/common/models/flag_created.py index c90ba994..b316cd20 100644 --- a/src/workos/common/models/flag_created.py +++ b/src/workos/common/models/flag_created.py @@ -17,6 +17,8 @@ class FlagCreated: """Flag Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["flag.created"] @@ -26,14 +28,13 @@ class FlagCreated: """An ISO 8601 timestamp.""" context: "FlagCreatedContext" """Additional context about the event.""" - object: Literal["event"] - """Distinguishes the Event object.""" @classmethod def from_dict(cls, data: Dict[str, Any]) -> "FlagCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "flag.created"), data=FlagCreatedData.from_dict(cast(Dict[str, Any], data["data"])), @@ -41,7 +42,6 @@ def from_dict(cls, data: Dict[str, Any]) -> "FlagCreated": context=FlagCreatedContext.from_dict( cast(Dict[str, Any], data["context"]) ), - object=data.get("object", "event"), ) except (KeyError, ValueError) as e: _raise_deserialize_error("FlagCreated", e) @@ -49,10 +49,10 @@ def from_dict(cls, data: Dict[str, Any]) -> "FlagCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) result["context"] = self.context.to_dict() - result["object"] = self.object return result diff --git a/src/workos/common/models/flag_deleted.py b/src/workos/common/models/flag_deleted.py index e650aaf8..0594d67f 100644 --- a/src/workos/common/models/flag_deleted.py +++ b/src/workos/common/models/flag_deleted.py @@ -17,6 +17,8 @@ class FlagDeleted: """Flag Deleted model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["flag.deleted"] @@ -26,14 +28,13 @@ class FlagDeleted: """An ISO 8601 timestamp.""" context: "FlagDeletedContext" """Additional context about the event.""" - object: Literal["event"] - """Distinguishes the Event object.""" @classmethod def from_dict(cls, data: Dict[str, Any]) -> "FlagDeleted": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "flag.deleted"), data=FlagDeletedData.from_dict(cast(Dict[str, Any], data["data"])), @@ -41,7 +42,6 @@ def from_dict(cls, data: Dict[str, Any]) -> "FlagDeleted": context=FlagDeletedContext.from_dict( cast(Dict[str, Any], data["context"]) ), - object=data.get("object", "event"), ) except (KeyError, ValueError) as e: _raise_deserialize_error("FlagDeleted", e) @@ -49,10 +49,10 @@ def from_dict(cls, data: Dict[str, Any]) -> "FlagDeleted": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) result["context"] = self.context.to_dict() - result["object"] = self.object return result diff --git a/src/workos/common/models/flag_rule_updated.py b/src/workos/common/models/flag_rule_updated.py index a8e24484..d53a806e 100644 --- a/src/workos/common/models/flag_rule_updated.py +++ b/src/workos/common/models/flag_rule_updated.py @@ -17,6 +17,8 @@ class FlagRuleUpdated: """Flag Rule Updated model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["flag.rule_updated"] @@ -26,14 +28,13 @@ class FlagRuleUpdated: """An ISO 8601 timestamp.""" context: "FlagRuleUpdatedContext" """Additional context about the event.""" - object: Literal["event"] - """Distinguishes the Event object.""" @classmethod def from_dict(cls, data: Dict[str, Any]) -> "FlagRuleUpdated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "flag.rule_updated"), data=FlagRuleUpdatedData.from_dict(cast(Dict[str, Any], data["data"])), @@ -41,7 +42,6 @@ def from_dict(cls, data: Dict[str, Any]) -> "FlagRuleUpdated": context=FlagRuleUpdatedContext.from_dict( cast(Dict[str, Any], data["context"]) ), - object=data.get("object", "event"), ) except (KeyError, ValueError) as e: _raise_deserialize_error("FlagRuleUpdated", e) @@ -49,10 +49,10 @@ def from_dict(cls, data: Dict[str, Any]) -> "FlagRuleUpdated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) result["context"] = self.context.to_dict() - result["object"] = self.object return result diff --git a/src/workos/common/models/flag_rule_updated_context_configured_target_organization.py b/src/workos/common/models/flag_rule_updated_context_configured_target_organization.py index 00bfe656..a08ae2ed 100644 --- a/src/workos/common/models/flag_rule_updated_context_configured_target_organization.py +++ b/src/workos/common/models/flag_rule_updated_context_configured_target_organization.py @@ -1,39 +1,6 @@ # This file is auto-generated by oagen. Do not edit. -from __future__ import annotations +from typing import TypeAlias +from .actor import Actor -from dataclasses import dataclass -from typing import Any, Dict -from workos._types import _raise_deserialize_error - - -@dataclass(slots=True) -class FlagRuleUpdatedContextConfiguredTargetOrganization: - """Flag Rule Updated Context Configured Target Organization model.""" - - id: str - """The ID of the organization.""" - name: str - """The name of the organization.""" - - @classmethod - def from_dict( - cls, data: Dict[str, Any] - ) -> "FlagRuleUpdatedContextConfiguredTargetOrganization": - """Deserialize from a dictionary.""" - try: - return cls( - id=data["id"], - name=data["name"], - ) - except (KeyError, ValueError) as e: - _raise_deserialize_error( - "FlagRuleUpdatedContextConfiguredTargetOrganization", e - ) - - def to_dict(self) -> Dict[str, Any]: - """Serialize to a dictionary.""" - result: Dict[str, Any] = {} - result["id"] = self.id - result["name"] = self.name - return result +FlagRuleUpdatedContextConfiguredTargetOrganization: TypeAlias = Actor diff --git a/src/workos/common/models/flag_rule_updated_context_previous_attribute_context_configured_target_organization.py b/src/workos/common/models/flag_rule_updated_context_previous_attribute_context_configured_target_organization.py index 8161553b..fecfdfe0 100644 --- a/src/workos/common/models/flag_rule_updated_context_previous_attribute_context_configured_target_organization.py +++ b/src/workos/common/models/flag_rule_updated_context_previous_attribute_context_configured_target_organization.py @@ -1,8 +1,6 @@ # This file is auto-generated by oagen. Do not edit. from typing import TypeAlias -from .flag_rule_updated_context_configured_target_organization import ( - FlagRuleUpdatedContextConfiguredTargetOrganization, -) +from .actor import Actor -FlagRuleUpdatedContextPreviousAttributeContextConfiguredTargetOrganization: TypeAlias = FlagRuleUpdatedContextConfiguredTargetOrganization +FlagRuleUpdatedContextPreviousAttributeContextConfiguredTargetOrganization: TypeAlias = Actor diff --git a/src/workos/common/models/flag_updated.py b/src/workos/common/models/flag_updated.py index b2503187..a99c937e 100644 --- a/src/workos/common/models/flag_updated.py +++ b/src/workos/common/models/flag_updated.py @@ -17,6 +17,8 @@ class FlagUpdated: """Flag Updated model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["flag.updated"] @@ -26,14 +28,13 @@ class FlagUpdated: """An ISO 8601 timestamp.""" context: "FlagUpdatedContext" """Additional context about the event.""" - object: Literal["event"] - """Distinguishes the Event object.""" @classmethod def from_dict(cls, data: Dict[str, Any]) -> "FlagUpdated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "flag.updated"), data=FlagUpdatedData.from_dict(cast(Dict[str, Any], data["data"])), @@ -41,7 +42,6 @@ def from_dict(cls, data: Dict[str, Any]) -> "FlagUpdated": context=FlagUpdatedContext.from_dict( cast(Dict[str, Any], data["context"]) ), - object=data.get("object", "event"), ) except (KeyError, ValueError) as e: _raise_deserialize_error("FlagUpdated", e) @@ -49,10 +49,10 @@ def from_dict(cls, data: Dict[str, Any]) -> "FlagUpdated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) result["context"] = self.context.to_dict() - result["object"] = self.object return result diff --git a/src/workos/common/models/group_created.py b/src/workos/common/models/group_created.py index 86771890..3bf15f76 100644 --- a/src/workos/common/models/group_created.py +++ b/src/workos/common/models/group_created.py @@ -17,6 +17,8 @@ class GroupCreated: """Group Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["group.created"] @@ -24,8 +26,6 @@ class GroupCreated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "GroupCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "group.created"), data=Group.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "GroupCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/group_deleted.py b/src/workos/common/models/group_deleted.py index 51ded16a..1ffe31db 100644 --- a/src/workos/common/models/group_deleted.py +++ b/src/workos/common/models/group_deleted.py @@ -17,6 +17,8 @@ class GroupDeleted: """Group Deleted model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["group.deleted"] @@ -24,8 +26,6 @@ class GroupDeleted: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "GroupDeleted": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "group.deleted"), data=Group.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "GroupDeleted": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/group_member_added.py b/src/workos/common/models/group_member_added.py index 0177d915..431d3369 100644 --- a/src/workos/common/models/group_member_added.py +++ b/src/workos/common/models/group_member_added.py @@ -17,6 +17,8 @@ class GroupMemberAdded: """Group Member Added model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["group.member_added"] @@ -24,8 +26,6 @@ class GroupMemberAdded: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "GroupMemberAdded": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "group.member_added"), data=GroupMemberAddedData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "GroupMemberAdded": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/group_member_removed.py b/src/workos/common/models/group_member_removed.py index 3d145eb2..8cbbb7d3 100644 --- a/src/workos/common/models/group_member_removed.py +++ b/src/workos/common/models/group_member_removed.py @@ -17,6 +17,8 @@ class GroupMemberRemoved: """Group Member Removed model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["group.member_removed"] @@ -24,8 +26,6 @@ class GroupMemberRemoved: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "GroupMemberRemoved": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "group.member_removed"), data=GroupMemberRemovedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "GroupMemberRemoved": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/group_updated.py b/src/workos/common/models/group_updated.py index 966ac61d..8318de60 100644 --- a/src/workos/common/models/group_updated.py +++ b/src/workos/common/models/group_updated.py @@ -17,6 +17,8 @@ class GroupUpdated: """Group Updated model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["group.updated"] @@ -24,8 +26,6 @@ class GroupUpdated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "GroupUpdated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "group.updated"), data=Group.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "GroupUpdated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/invitation_accepted.py b/src/workos/common/models/invitation_accepted.py index 237f306a..5463dfce 100644 --- a/src/workos/common/models/invitation_accepted.py +++ b/src/workos/common/models/invitation_accepted.py @@ -17,6 +17,8 @@ class InvitationAccepted: """Invitation Accepted model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["invitation.accepted"] @@ -24,8 +26,6 @@ class InvitationAccepted: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "InvitationAccepted": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "invitation.accepted"), data=InvitationAcceptedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "InvitationAccepted": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/invitation_created.py b/src/workos/common/models/invitation_created.py index 891c3dc5..2d492f97 100644 --- a/src/workos/common/models/invitation_created.py +++ b/src/workos/common/models/invitation_created.py @@ -17,6 +17,8 @@ class InvitationCreated: """Invitation Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["invitation.created"] @@ -24,8 +26,6 @@ class InvitationCreated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "InvitationCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "invitation.created"), data=InvitationCreatedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "InvitationCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/invitation_resent.py b/src/workos/common/models/invitation_resent.py index f0e0408e..85f072e8 100644 --- a/src/workos/common/models/invitation_resent.py +++ b/src/workos/common/models/invitation_resent.py @@ -17,6 +17,8 @@ class InvitationResent: """Invitation Resent model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["invitation.resent"] @@ -24,8 +26,6 @@ class InvitationResent: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "InvitationResent": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "invitation.resent"), data=InvitationResentData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "InvitationResent": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/invitation_revoked.py b/src/workos/common/models/invitation_revoked.py index 014b849e..b67f791d 100644 --- a/src/workos/common/models/invitation_revoked.py +++ b/src/workos/common/models/invitation_revoked.py @@ -17,6 +17,8 @@ class InvitationRevoked: """Invitation Revoked model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["invitation.revoked"] @@ -24,8 +26,6 @@ class InvitationRevoked: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "InvitationRevoked": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "invitation.revoked"), data=InvitationRevokedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "InvitationRevoked": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/magic_auth_created.py b/src/workos/common/models/magic_auth_created.py index 5ba02c33..04e865b7 100644 --- a/src/workos/common/models/magic_auth_created.py +++ b/src/workos/common/models/magic_auth_created.py @@ -17,6 +17,8 @@ class MagicAuthCreated: """Magic Auth Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["magic_auth.created"] @@ -24,8 +26,6 @@ class MagicAuthCreated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "MagicAuthCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "magic_auth.created"), data=MagicAuthCreatedData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "MagicAuthCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/organization_created.py b/src/workos/common/models/organization_created.py index 1f0efa13..dced9181 100644 --- a/src/workos/common/models/organization_created.py +++ b/src/workos/common/models/organization_created.py @@ -17,6 +17,8 @@ class OrganizationCreated: """Organization Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["organization.created"] @@ -24,8 +26,6 @@ class OrganizationCreated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "organization.created"), data=OrganizationCreatedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/organization_deleted.py b/src/workos/common/models/organization_deleted.py index 0178bd65..14519fad 100644 --- a/src/workos/common/models/organization_deleted.py +++ b/src/workos/common/models/organization_deleted.py @@ -17,6 +17,8 @@ class OrganizationDeleted: """Organization Deleted model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["organization.deleted"] @@ -24,8 +26,6 @@ class OrganizationDeleted: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationDeleted": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "organization.deleted"), data=OrganizationDeletedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationDeleted": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/organization_domain_created.py b/src/workos/common/models/organization_domain_created.py index 1ed9c091..8f876f33 100644 --- a/src/workos/common/models/organization_domain_created.py +++ b/src/workos/common/models/organization_domain_created.py @@ -17,6 +17,8 @@ class OrganizationDomainCreated: """Organization Domain Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["organization_domain.created"] @@ -24,8 +26,6 @@ class OrganizationDomainCreated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationDomainCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "organization_domain.created"), data=OrganizationDomainCreatedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationDomainCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/organization_domain_deleted.py b/src/workos/common/models/organization_domain_deleted.py index 75574005..71226caf 100644 --- a/src/workos/common/models/organization_domain_deleted.py +++ b/src/workos/common/models/organization_domain_deleted.py @@ -17,6 +17,8 @@ class OrganizationDomainDeleted: """Organization Domain Deleted model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["organization_domain.deleted"] @@ -24,8 +26,6 @@ class OrganizationDomainDeleted: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationDomainDeleted": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "organization_domain.deleted"), data=OrganizationDomainDeletedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationDomainDeleted": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/organization_domain_updated.py b/src/workos/common/models/organization_domain_updated.py index a683845f..1c5cadb2 100644 --- a/src/workos/common/models/organization_domain_updated.py +++ b/src/workos/common/models/organization_domain_updated.py @@ -17,6 +17,8 @@ class OrganizationDomainUpdated: """Organization Domain Updated model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["organization_domain.updated"] @@ -24,8 +26,6 @@ class OrganizationDomainUpdated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationDomainUpdated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "organization_domain.updated"), data=OrganizationDomainUpdatedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationDomainUpdated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/organization_domain_verification_failed.py b/src/workos/common/models/organization_domain_verification_failed.py index 314e8e8f..b52bfdfc 100644 --- a/src/workos/common/models/organization_domain_verification_failed.py +++ b/src/workos/common/models/organization_domain_verification_failed.py @@ -19,6 +19,8 @@ class OrganizationDomainVerificationFailed: """Organization Domain Verification Failed model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["organization_domain.verification_failed"] @@ -26,8 +28,6 @@ class OrganizationDomainVerificationFailed: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -35,13 +35,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationDomainVerificationFaile """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "organization_domain.verification_failed"), data=OrganizationDomainVerificationFailedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -52,11 +52,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationDomainVerificationFaile def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/organization_domain_verified.py b/src/workos/common/models/organization_domain_verified.py index d55bb179..a8890f36 100644 --- a/src/workos/common/models/organization_domain_verified.py +++ b/src/workos/common/models/organization_domain_verified.py @@ -17,6 +17,8 @@ class OrganizationDomainVerified: """Organization Domain Verified model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["organization_domain.verified"] @@ -24,8 +26,6 @@ class OrganizationDomainVerified: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationDomainVerified": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "organization_domain.verified"), data=OrganizationDomainVerifiedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationDomainVerified": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/organization_membership_created.py b/src/workos/common/models/organization_membership_created.py index d9e8196d..92beced3 100644 --- a/src/workos/common/models/organization_membership_created.py +++ b/src/workos/common/models/organization_membership_created.py @@ -17,6 +17,8 @@ class OrganizationMembershipCreated: """Organization Membership Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["organization_membership.created"] @@ -24,8 +26,6 @@ class OrganizationMembershipCreated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationMembershipCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "organization_membership.created"), data=OrganizationMembershipCreatedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationMembershipCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/organization_membership_deleted.py b/src/workos/common/models/organization_membership_deleted.py index 2a8e1d9a..7c20c542 100644 --- a/src/workos/common/models/organization_membership_deleted.py +++ b/src/workos/common/models/organization_membership_deleted.py @@ -17,6 +17,8 @@ class OrganizationMembershipDeleted: """Organization Membership Deleted model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["organization_membership.deleted"] @@ -24,8 +26,6 @@ class OrganizationMembershipDeleted: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationMembershipDeleted": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "organization_membership.deleted"), data=OrganizationMembershipDeletedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationMembershipDeleted": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/organization_membership_updated.py b/src/workos/common/models/organization_membership_updated.py index 8b978b2b..a5a124b0 100644 --- a/src/workos/common/models/organization_membership_updated.py +++ b/src/workos/common/models/organization_membership_updated.py @@ -17,6 +17,8 @@ class OrganizationMembershipUpdated: """Organization Membership Updated model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["organization_membership.updated"] @@ -24,8 +26,6 @@ class OrganizationMembershipUpdated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationMembershipUpdated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "organization_membership.updated"), data=OrganizationMembershipUpdatedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationMembershipUpdated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/organization_role_created.py b/src/workos/common/models/organization_role_created.py index 1217f010..3eac8508 100644 --- a/src/workos/common/models/organization_role_created.py +++ b/src/workos/common/models/organization_role_created.py @@ -17,6 +17,8 @@ class OrganizationRoleCreated: """Organization Role Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["organization_role.created"] @@ -24,8 +26,6 @@ class OrganizationRoleCreated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationRoleCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "organization_role.created"), data=OrganizationRoleCreatedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationRoleCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/organization_role_deleted.py b/src/workos/common/models/organization_role_deleted.py index fc191ef4..943bee1c 100644 --- a/src/workos/common/models/organization_role_deleted.py +++ b/src/workos/common/models/organization_role_deleted.py @@ -17,6 +17,8 @@ class OrganizationRoleDeleted: """Organization Role Deleted model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["organization_role.deleted"] @@ -24,8 +26,6 @@ class OrganizationRoleDeleted: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationRoleDeleted": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "organization_role.deleted"), data=OrganizationRoleDeletedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationRoleDeleted": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/organization_role_updated.py b/src/workos/common/models/organization_role_updated.py index dcbd7510..31499846 100644 --- a/src/workos/common/models/organization_role_updated.py +++ b/src/workos/common/models/organization_role_updated.py @@ -17,6 +17,8 @@ class OrganizationRoleUpdated: """Organization Role Updated model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["organization_role.updated"] @@ -24,8 +26,6 @@ class OrganizationRoleUpdated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationRoleUpdated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "organization_role.updated"), data=OrganizationRoleUpdatedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationRoleUpdated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/organization_updated.py b/src/workos/common/models/organization_updated.py index d63297f1..f1a30e81 100644 --- a/src/workos/common/models/organization_updated.py +++ b/src/workos/common/models/organization_updated.py @@ -17,6 +17,8 @@ class OrganizationUpdated: """Organization Updated model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["organization.updated"] @@ -24,8 +26,6 @@ class OrganizationUpdated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationUpdated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "organization.updated"), data=OrganizationUpdatedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "OrganizationUpdated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/password_reset_created.py b/src/workos/common/models/password_reset_created.py index 4ba9d1b5..fa243571 100644 --- a/src/workos/common/models/password_reset_created.py +++ b/src/workos/common/models/password_reset_created.py @@ -17,6 +17,8 @@ class PasswordResetCreated: """Password Reset Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["password_reset.created"] @@ -24,8 +26,6 @@ class PasswordResetCreated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "PasswordResetCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "password_reset.created"), data=PasswordResetCreatedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "PasswordResetCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/password_reset_succeeded.py b/src/workos/common/models/password_reset_succeeded.py index 428e7b1a..d6074f23 100644 --- a/src/workos/common/models/password_reset_succeeded.py +++ b/src/workos/common/models/password_reset_succeeded.py @@ -17,6 +17,8 @@ class PasswordResetSucceeded: """Password Reset Succeeded model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["password_reset.succeeded"] @@ -24,8 +26,6 @@ class PasswordResetSucceeded: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "PasswordResetSucceeded": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "password_reset.succeeded"), data=PasswordResetSucceededData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "PasswordResetSucceeded": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/permission_created.py b/src/workos/common/models/permission_created.py index 3a10d60a..86795636 100644 --- a/src/workos/common/models/permission_created.py +++ b/src/workos/common/models/permission_created.py @@ -17,6 +17,8 @@ class PermissionCreated: """Permission Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["permission.created"] @@ -24,8 +26,6 @@ class PermissionCreated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "PermissionCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "permission.created"), data=PermissionCreatedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "PermissionCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/permission_deleted.py b/src/workos/common/models/permission_deleted.py index 1d5b99aa..b1b73f43 100644 --- a/src/workos/common/models/permission_deleted.py +++ b/src/workos/common/models/permission_deleted.py @@ -17,6 +17,8 @@ class PermissionDeleted: """Permission Deleted model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["permission.deleted"] @@ -24,8 +26,6 @@ class PermissionDeleted: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "PermissionDeleted": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "permission.deleted"), data=PermissionDeletedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "PermissionDeleted": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/permission_updated.py b/src/workos/common/models/permission_updated.py index d2de7fe6..72612eaf 100644 --- a/src/workos/common/models/permission_updated.py +++ b/src/workos/common/models/permission_updated.py @@ -17,6 +17,8 @@ class PermissionUpdated: """Permission Updated model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["permission.updated"] @@ -24,8 +26,6 @@ class PermissionUpdated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "PermissionUpdated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "permission.updated"), data=PermissionUpdatedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "PermissionUpdated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/pipe_connected_account.py b/src/workos/common/models/pipe_connected_account.py new file mode 100644 index 00000000..14673ec4 --- /dev/null +++ b/src/workos/common/models/pipe_connected_account.py @@ -0,0 +1,79 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Any, Dict, List, Literal, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime +from .pipe_connected_account_state import PipeConnectedAccountState + + +@dataclass(slots=True) +class PipeConnectedAccount: + """Pipe Connected Account model.""" + + object: Literal["connected_account"] + """The connected account object.""" + id: str + """The unique ID of the connected account.""" + data_integration_id: str + """The unique ID of the data integration.""" + provider_slug: str + """The provider slug for this connected account.""" + user_id: Optional[str] + """The ID of the User the connected account belongs to.""" + organization_id: Optional[str] + """The ID of the Organization the connected account belongs to.""" + scopes: List[str] + """The OAuth scopes granted for this connected account.""" + state: "PipeConnectedAccountState" + """The state of the connected account.""" + created_at: datetime + """An ISO 8601 timestamp.""" + updated_at: datetime + """An ISO 8601 timestamp.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "PipeConnectedAccount": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "connected_account"), + id=data["id"], + data_integration_id=data["data_integration_id"], + provider_slug=data["provider_slug"], + user_id=data["user_id"], + organization_id=data["organization_id"], + scopes=data["scopes"], + state=PipeConnectedAccountState(data["state"]), + created_at=_parse_datetime(data["created_at"]), + updated_at=_parse_datetime(data["updated_at"]), + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("PipeConnectedAccount", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["data_integration_id"] = self.data_integration_id + result["provider_slug"] = self.provider_slug + if self.user_id is not None: + result["user_id"] = self.user_id + else: + result["user_id"] = None + if self.organization_id is not None: + result["organization_id"] = self.organization_id + else: + result["organization_id"] = None + result["scopes"] = self.scopes + result["state"] = ( + self.state.value if isinstance(self.state, Enum) else self.state + ) + result["created_at"] = _format_datetime(self.created_at) + result["updated_at"] = _format_datetime(self.updated_at) + return result diff --git a/src/workos/common/models/pipe_connected_account_state.py b/src/workos/common/models/pipe_connected_account_state.py new file mode 100644 index 00000000..7a91ca62 --- /dev/null +++ b/src/workos/common/models/pipe_connected_account_state.py @@ -0,0 +1,30 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Enumeration of pipe connected account state values.""" + +from __future__ import annotations + +from enum import Enum +from typing import Optional +from typing import Literal, TypeAlias + + +class PipeConnectedAccountState(str, Enum): + """Known values for PipeConnectedAccountState.""" + + CONNECTED = "connected" + NEEDS_REAUTHORIZATION = "needs_reauthorization" + + @classmethod + def _missing_(cls, value: object) -> Optional["PipeConnectedAccountState"]: + if not isinstance(value, str): + return None + unknown = str.__new__(cls, value) + unknown._name_ = value.upper() + unknown._value_ = value + return unknown + + +PipeConnectedAccountStateLiteral: TypeAlias = Literal[ + "connected", "needs_reauthorization" +] diff --git a/src/workos/common/models/pipes_connected_account_connected.py b/src/workos/common/models/pipes_connected_account_connected.py new file mode 100644 index 00000000..04e53e97 --- /dev/null +++ b/src/workos/common/models/pipes_connected_account_connected.py @@ -0,0 +1,58 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import cast +from typing import Any, Dict, Literal, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + +from .event_context import EventContext +from .pipe_connected_account import PipeConnectedAccount + + +@dataclass(slots=True) +class PipesConnectedAccountConnected: + """Pipes Connected Account Connected model.""" + + object: Literal["event"] + """Distinguishes the Event object.""" + id: str + """Unique identifier for the event.""" + event: Literal["pipes.connected_account.connected"] + data: "PipeConnectedAccount" + """The event payload.""" + created_at: datetime + """An ISO 8601 timestamp.""" + context: Optional["EventContext"] = None + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "PipesConnectedAccountConnected": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "event"), + id=data["id"], + event=data.get("event", "pipes.connected_account.connected"), + data=PipeConnectedAccount.from_dict(cast(Dict[str, Any], data["data"])), + created_at=_parse_datetime(data["created_at"]), + context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) + if (_v_context := data.get("context")) is not None + else None, + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("PipesConnectedAccountConnected", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["event"] = self.event + result["data"] = self.data.to_dict() + result["created_at"] = _format_datetime(self.created_at) + if self.context is not None: + result["context"] = self.context.to_dict() + return result diff --git a/src/workos/common/models/pipes_connected_account_disconnected.py b/src/workos/common/models/pipes_connected_account_disconnected.py new file mode 100644 index 00000000..9694ae1c --- /dev/null +++ b/src/workos/common/models/pipes_connected_account_disconnected.py @@ -0,0 +1,58 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import cast +from typing import Any, Dict, Literal, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + +from .event_context import EventContext +from .pipe_connected_account import PipeConnectedAccount + + +@dataclass(slots=True) +class PipesConnectedAccountDisconnected: + """Pipes Connected Account Disconnected model.""" + + object: Literal["event"] + """Distinguishes the Event object.""" + id: str + """Unique identifier for the event.""" + event: Literal["pipes.connected_account.disconnected"] + data: "PipeConnectedAccount" + """The event payload.""" + created_at: datetime + """An ISO 8601 timestamp.""" + context: Optional["EventContext"] = None + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "PipesConnectedAccountDisconnected": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "event"), + id=data["id"], + event=data.get("event", "pipes.connected_account.disconnected"), + data=PipeConnectedAccount.from_dict(cast(Dict[str, Any], data["data"])), + created_at=_parse_datetime(data["created_at"]), + context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) + if (_v_context := data.get("context")) is not None + else None, + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("PipesConnectedAccountDisconnected", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["event"] = self.event + result["data"] = self.data.to_dict() + result["created_at"] = _format_datetime(self.created_at) + if self.context is not None: + result["context"] = self.context.to_dict() + return result diff --git a/src/workos/common/models/pipes_connected_account_reauthorization_needed.py b/src/workos/common/models/pipes_connected_account_reauthorization_needed.py new file mode 100644 index 00000000..5d981c1f --- /dev/null +++ b/src/workos/common/models/pipes_connected_account_reauthorization_needed.py @@ -0,0 +1,62 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import cast +from typing import Any, Dict, Literal, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + +from .event_context import EventContext +from .pipe_connected_account import PipeConnectedAccount + + +@dataclass(slots=True) +class PipesConnectedAccountReauthorizationNeeded: + """Pipes Connected Account Reauthorization Needed model.""" + + object: Literal["event"] + """Distinguishes the Event object.""" + id: str + """Unique identifier for the event.""" + event: Literal["pipes.connected_account.reauthorization_needed"] + data: "PipeConnectedAccount" + """The event payload.""" + created_at: datetime + """An ISO 8601 timestamp.""" + context: Optional["EventContext"] = None + + @classmethod + def from_dict( + cls, data: Dict[str, Any] + ) -> "PipesConnectedAccountReauthorizationNeeded": + """Deserialize from a dictionary.""" + try: + return cls( + object=data.get("object", "event"), + id=data["id"], + event=data.get( + "event", "pipes.connected_account.reauthorization_needed" + ), + data=PipeConnectedAccount.from_dict(cast(Dict[str, Any], data["data"])), + created_at=_parse_datetime(data["created_at"]), + context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) + if (_v_context := data.get("context")) is not None + else None, + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("PipesConnectedAccountReauthorizationNeeded", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["object"] = self.object + result["id"] = self.id + result["event"] = self.event + result["data"] = self.data.to_dict() + result["created_at"] = _format_datetime(self.created_at) + if self.context is not None: + result["context"] = self.context.to_dict() + return result diff --git a/src/workos/common/models/radar_standalone_assess_request_action.py b/src/workos/common/models/radar_standalone_assess_request_action.py index 44cd1da3..1f59209e 100644 --- a/src/workos/common/models/radar_standalone_assess_request_action.py +++ b/src/workos/common/models/radar_standalone_assess_request_action.py @@ -12,14 +12,8 @@ class RadarStandaloneAssessRequestAction(str, Enum): """Known values for RadarStandaloneAssessRequestAction.""" - LOGIN = "login" - SIGNUP = "signup" SIGN_UP = "sign-up" SIGN_IN = "sign-in" - SIGN_UP_2 = "sign_up" - SIGN_IN_2 = "sign_in" - SIGN_IN_3 = "sign in" - SIGN_UP_3 = "sign up" @classmethod def _missing_(cls, value: object) -> Optional["RadarStandaloneAssessRequestAction"]: @@ -31,6 +25,4 @@ def _missing_(cls, value: object) -> Optional["RadarStandaloneAssessRequestActio return unknown -RadarStandaloneAssessRequestActionLiteral: TypeAlias = Literal[ - "login", "signup", "sign-up", "sign-in", "sign_up", "sign_in", "sign in", "sign up" -] +RadarStandaloneAssessRequestActionLiteral: TypeAlias = Literal["sign-up", "sign-in"] diff --git a/src/workos/common/models/radar_standalone_response_blocklist_type.py b/src/workos/common/models/radar_standalone_response_blocklist_type.py index ca45b4dd..cb1762c2 100644 --- a/src/workos/common/models/radar_standalone_response_blocklist_type.py +++ b/src/workos/common/models/radar_standalone_response_blocklist_type.py @@ -1,43 +1,19 @@ # This file is auto-generated by oagen. Do not edit. -"""Enumeration of radar standalone response blocklist type values.""" +from typing import TYPE_CHECKING -from __future__ import annotations +if TYPE_CHECKING: + from workos.radar.models.radar_list_type import ( + RadarListType as RadarStandaloneResponseBlocklistType, + ) +else: -from enum import Enum -from typing import Optional -from typing import Literal, TypeAlias + def __getattr__(name: str): + if name == "RadarStandaloneResponseBlocklistType": + from workos.radar.models.radar_list_type import RadarListType + return RadarListType + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") -class RadarStandaloneResponseBlocklistType(str, Enum): - """Known values for RadarStandaloneResponseBlocklistType.""" - IP_ADDRESS = "ip_address" - DOMAIN = "domain" - EMAIL = "email" - DEVICE = "device" - USER_AGENT = "user_agent" - DEVICE_FINGERPRINT = "device_fingerprint" - COUNTRY = "country" - - @classmethod - def _missing_( - cls, value: object - ) -> Optional["RadarStandaloneResponseBlocklistType"]: - if not isinstance(value, str): - return None - unknown = str.__new__(cls, value) - unknown._name_ = value.upper() - unknown._value_ = value - return unknown - - -RadarStandaloneResponseBlocklistTypeLiteral: TypeAlias = Literal[ - "ip_address", - "domain", - "email", - "device", - "user_agent", - "device_fingerprint", - "country", -] +__all__ = ["RadarStandaloneResponseBlocklistType"] diff --git a/src/workos/common/models/radar_standalone_response_control.py b/src/workos/common/models/radar_standalone_response_control.py index 2e599da7..94c2383b 100644 --- a/src/workos/common/models/radar_standalone_response_control.py +++ b/src/workos/common/models/radar_standalone_response_control.py @@ -14,9 +14,7 @@ class RadarStandaloneResponseControl(str, Enum): BOT_DETECTION = "bot_detection" BRUTE_FORCE_ATTACK = "brute_force_attack" - CREDENTIAL_STUFFING = "credential_stuffing" DOMAIN_SIGN_UP_RATE_LIMIT = "domain_sign_up_rate_limit" - IP_SIGN_UP_RATE_LIMIT = "ip_sign_up_rate_limit" IMPOSSIBLE_TRAVEL = "impossible_travel" REPEAT_SIGN_UP = "repeat_sign_up" STALE_ACCOUNT = "stale_account" @@ -36,9 +34,7 @@ def _missing_(cls, value: object) -> Optional["RadarStandaloneResponseControl"]: RadarStandaloneResponseControlLiteral: TypeAlias = Literal[ "bot_detection", "brute_force_attack", - "credential_stuffing", "domain_sign_up_rate_limit", - "ip_sign_up_rate_limit", "impossible_travel", "repeat_sign_up", "stale_account", diff --git a/src/workos/common/models/role_created.py b/src/workos/common/models/role_created.py index 5f284bac..8532139f 100644 --- a/src/workos/common/models/role_created.py +++ b/src/workos/common/models/role_created.py @@ -17,6 +17,8 @@ class RoleCreated: """Role Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["role.created"] @@ -24,8 +26,6 @@ class RoleCreated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "RoleCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "role.created"), data=RoleCreatedData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "RoleCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/role_deleted.py b/src/workos/common/models/role_deleted.py index 65928fdb..14576121 100644 --- a/src/workos/common/models/role_deleted.py +++ b/src/workos/common/models/role_deleted.py @@ -17,6 +17,8 @@ class RoleDeleted: """Role Deleted model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["role.deleted"] @@ -24,8 +26,6 @@ class RoleDeleted: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "RoleDeleted": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "role.deleted"), data=RoleDeletedData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "RoleDeleted": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/role_updated.py b/src/workos/common/models/role_updated.py index 6c057c4a..9c100c67 100644 --- a/src/workos/common/models/role_updated.py +++ b/src/workos/common/models/role_updated.py @@ -17,6 +17,8 @@ class RoleUpdated: """Role Updated model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["role.updated"] @@ -24,8 +26,6 @@ class RoleUpdated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "RoleUpdated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "role.updated"), data=RoleUpdatedData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "RoleUpdated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/session_created.py b/src/workos/common/models/session_created.py index a92bab98..a3d2fbc1 100644 --- a/src/workos/common/models/session_created.py +++ b/src/workos/common/models/session_created.py @@ -17,6 +17,8 @@ class SessionCreated: """Session Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["session.created"] @@ -24,8 +26,6 @@ class SessionCreated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "SessionCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "session.created"), data=SessionCreatedData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "SessionCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/session_revoked.py b/src/workos/common/models/session_revoked.py index 14266e54..0e0c3a5f 100644 --- a/src/workos/common/models/session_revoked.py +++ b/src/workos/common/models/session_revoked.py @@ -17,6 +17,8 @@ class SessionRevoked: """Session Revoked model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["session.revoked"] @@ -24,8 +26,6 @@ class SessionRevoked: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "SessionRevoked": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "session.revoked"), data=SessionRevokedData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "SessionRevoked": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/user_created.py b/src/workos/common/models/user_created.py index 9024de22..5bfc6410 100644 --- a/src/workos/common/models/user_created.py +++ b/src/workos/common/models/user_created.py @@ -17,6 +17,8 @@ class UserCreated: """User Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["user.created"] @@ -24,8 +26,6 @@ class UserCreated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "UserCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "user.created"), data=User.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "UserCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/user_deleted.py b/src/workos/common/models/user_deleted.py index 8b1538e1..97bf84ec 100644 --- a/src/workos/common/models/user_deleted.py +++ b/src/workos/common/models/user_deleted.py @@ -17,6 +17,8 @@ class UserDeleted: """User Deleted model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["user.deleted"] @@ -24,8 +26,6 @@ class UserDeleted: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "UserDeleted": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "user.deleted"), data=User.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "UserDeleted": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/user_updated.py b/src/workos/common/models/user_updated.py index b4a18398..e3159d50 100644 --- a/src/workos/common/models/user_updated.py +++ b/src/workos/common/models/user_updated.py @@ -17,6 +17,8 @@ class UserUpdated: """User Updated model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["user.updated"] @@ -24,8 +26,6 @@ class UserUpdated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "UserUpdated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "user.updated"), data=User.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "UserUpdated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/vault_byok_key_deleted.py b/src/workos/common/models/vault_byok_key_deleted.py index 6cc0012e..a1ddac72 100644 --- a/src/workos/common/models/vault_byok_key_deleted.py +++ b/src/workos/common/models/vault_byok_key_deleted.py @@ -17,6 +17,8 @@ class VaultByokKeyDeleted: """Vault Byok Key Deleted model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["vault.byok_key.deleted"] @@ -24,8 +26,6 @@ class VaultByokKeyDeleted: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultByokKeyDeleted": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "vault.byok_key.deleted"), data=VaultByokKeyDeletedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultByokKeyDeleted": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/vault_byok_key_verification_completed.py b/src/workos/common/models/vault_byok_key_verification_completed.py index d74fe80b..a8f735bf 100644 --- a/src/workos/common/models/vault_byok_key_verification_completed.py +++ b/src/workos/common/models/vault_byok_key_verification_completed.py @@ -19,6 +19,8 @@ class VaultByokKeyVerificationCompleted: """Vault Byok Key Verification Completed model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["vault.byok_key.verification_completed"] @@ -26,8 +28,6 @@ class VaultByokKeyVerificationCompleted: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -35,13 +35,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultByokKeyVerificationCompleted": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "vault.byok_key.verification_completed"), data=VaultByokKeyVerificationCompletedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -52,11 +52,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultByokKeyVerificationCompleted": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/vault_data_created.py b/src/workos/common/models/vault_data_created.py index 92784a88..33ed01d9 100644 --- a/src/workos/common/models/vault_data_created.py +++ b/src/workos/common/models/vault_data_created.py @@ -17,6 +17,8 @@ class VaultDataCreated: """Vault Data Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["vault.data.created"] @@ -24,8 +26,6 @@ class VaultDataCreated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultDataCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "vault.data.created"), data=VaultDataCreatedData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultDataCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/vault_data_deleted.py b/src/workos/common/models/vault_data_deleted.py index 6fbb6c79..1a273802 100644 --- a/src/workos/common/models/vault_data_deleted.py +++ b/src/workos/common/models/vault_data_deleted.py @@ -17,6 +17,8 @@ class VaultDataDeleted: """Vault Data Deleted model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["vault.data.deleted"] @@ -24,8 +26,6 @@ class VaultDataDeleted: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultDataDeleted": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "vault.data.deleted"), data=VaultDataDeletedData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultDataDeleted": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/vault_data_read.py b/src/workos/common/models/vault_data_read.py index 160b5911..1fed88f6 100644 --- a/src/workos/common/models/vault_data_read.py +++ b/src/workos/common/models/vault_data_read.py @@ -17,6 +17,8 @@ class VaultDataRead: """Vault Data Read model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["vault.data.read"] @@ -24,8 +26,6 @@ class VaultDataRead: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultDataRead": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "vault.data.read"), data=VaultDataReadData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultDataRead": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/vault_data_updated.py b/src/workos/common/models/vault_data_updated.py index e7a99d51..791be53f 100644 --- a/src/workos/common/models/vault_data_updated.py +++ b/src/workos/common/models/vault_data_updated.py @@ -17,6 +17,8 @@ class VaultDataUpdated: """Vault Data Updated model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["vault.data.updated"] @@ -24,8 +26,6 @@ class VaultDataUpdated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultDataUpdated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "vault.data.updated"), data=VaultDataUpdatedData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultDataUpdated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/vault_dek_decrypted.py b/src/workos/common/models/vault_dek_decrypted.py index b571926b..ed7d7fb3 100644 --- a/src/workos/common/models/vault_dek_decrypted.py +++ b/src/workos/common/models/vault_dek_decrypted.py @@ -17,6 +17,8 @@ class VaultDekDecrypted: """Vault Dek Decrypted model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["vault.dek.decrypted"] @@ -24,8 +26,6 @@ class VaultDekDecrypted: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultDekDecrypted": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "vault.dek.decrypted"), data=VaultDekDecryptedData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultDekDecrypted": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/vault_dek_read.py b/src/workos/common/models/vault_dek_read.py index bac9c4c4..382af324 100644 --- a/src/workos/common/models/vault_dek_read.py +++ b/src/workos/common/models/vault_dek_read.py @@ -17,6 +17,8 @@ class VaultDekRead: """Vault Dek Read model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["vault.dek.read"] @@ -24,8 +26,6 @@ class VaultDekRead: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultDekRead": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "vault.dek.read"), data=VaultDekReadData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultDekRead": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/vault_kek_created.py b/src/workos/common/models/vault_kek_created.py index f739a0f8..3fe21141 100644 --- a/src/workos/common/models/vault_kek_created.py +++ b/src/workos/common/models/vault_kek_created.py @@ -17,6 +17,8 @@ class VaultKekCreated: """Vault Kek Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["vault.kek.created"] @@ -24,8 +26,6 @@ class VaultKekCreated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultKekCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "vault.kek.created"), data=VaultKekCreatedData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultKekCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/vault_metadata_read.py b/src/workos/common/models/vault_metadata_read.py index f21ffa81..23dede63 100644 --- a/src/workos/common/models/vault_metadata_read.py +++ b/src/workos/common/models/vault_metadata_read.py @@ -17,6 +17,8 @@ class VaultMetadataRead: """Vault Metadata Read model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["vault.metadata.read"] @@ -24,8 +26,6 @@ class VaultMetadataRead: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,13 +33,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultMetadataRead": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "vault.metadata.read"), data=VaultMetadataReadData.from_dict( cast(Dict[str, Any], data["data"]) ), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -50,11 +50,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultMetadataRead": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/vault_names_listed.py b/src/workos/common/models/vault_names_listed.py index 583e8b05..86fe0aa0 100644 --- a/src/workos/common/models/vault_names_listed.py +++ b/src/workos/common/models/vault_names_listed.py @@ -17,6 +17,8 @@ class VaultNamesListed: """Vault Names Listed model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["vault.names.listed"] @@ -24,8 +26,6 @@ class VaultNamesListed: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultNamesListed": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "vault.names.listed"), data=VaultNamesListedData.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "VaultNamesListed": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/waitlist_user_approved.py b/src/workos/common/models/waitlist_user_approved.py index 74cc7dbe..08e0802c 100644 --- a/src/workos/common/models/waitlist_user_approved.py +++ b/src/workos/common/models/waitlist_user_approved.py @@ -17,6 +17,8 @@ class WaitlistUserApproved: """Waitlist User Approved model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["waitlist_user.approved"] @@ -24,8 +26,6 @@ class WaitlistUserApproved: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "WaitlistUserApproved": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "waitlist_user.approved"), data=WaitlistUser.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "WaitlistUserApproved": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/waitlist_user_created.py b/src/workos/common/models/waitlist_user_created.py index 89abe09c..f02037cc 100644 --- a/src/workos/common/models/waitlist_user_created.py +++ b/src/workos/common/models/waitlist_user_created.py @@ -17,6 +17,8 @@ class WaitlistUserCreated: """Waitlist User Created model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["waitlist_user.created"] @@ -24,8 +26,6 @@ class WaitlistUserCreated: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "WaitlistUserCreated": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "waitlist_user.created"), data=WaitlistUser.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "WaitlistUserCreated": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/waitlist_user_denied.py b/src/workos/common/models/waitlist_user_denied.py index afd30abc..deb30ed5 100644 --- a/src/workos/common/models/waitlist_user_denied.py +++ b/src/workos/common/models/waitlist_user_denied.py @@ -17,6 +17,8 @@ class WaitlistUserDenied: """Waitlist User Denied model.""" + object: Literal["event"] + """Distinguishes the Event object.""" id: str """Unique identifier for the event.""" event: Literal["waitlist_user.denied"] @@ -24,8 +26,6 @@ class WaitlistUserDenied: """The event payload.""" created_at: datetime """An ISO 8601 timestamp.""" - object: Literal["event"] - """Distinguishes the Event object.""" context: Optional["EventContext"] = None @classmethod @@ -33,11 +33,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "WaitlistUserDenied": """Deserialize from a dictionary.""" try: return cls( + object=data.get("object", "event"), id=data["id"], event=data.get("event", "waitlist_user.denied"), data=WaitlistUser.from_dict(cast(Dict[str, Any], data["data"])), created_at=_parse_datetime(data["created_at"]), - object=data.get("object", "event"), context=EventContext.from_dict(cast(Dict[str, Any], _v_context)) if (_v_context := data.get("context")) is not None else None, @@ -48,11 +48,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "WaitlistUserDenied": def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" result: Dict[str, Any] = {} + result["object"] = self.object result["id"] = self.id result["event"] = self.event result["data"] = self.data.to_dict() result["created_at"] = _format_datetime(self.created_at) - result["object"] = self.object if self.context is not None: result["context"] = self.context.to_dict() return result diff --git a/src/workos/common/models/webhook_endpoint_json_status.py b/src/workos/common/models/webhook_endpoint_status.py similarity index 59% rename from src/workos/common/models/webhook_endpoint_json_status.py rename to src/workos/common/models/webhook_endpoint_status.py index e6739d4c..77c53020 100644 --- a/src/workos/common/models/webhook_endpoint_json_status.py +++ b/src/workos/common/models/webhook_endpoint_status.py @@ -3,5 +3,5 @@ from typing import TypeAlias from .update_webhook_endpoint_status import UpdateWebhookEndpointStatus -WebhookEndpointJsonStatus: TypeAlias = UpdateWebhookEndpointStatus -__all__ = ["WebhookEndpointJsonStatus"] +WebhookEndpointStatus: TypeAlias = UpdateWebhookEndpointStatus +__all__ = ["WebhookEndpointStatus"] diff --git a/src/workos/connect/_resource.py b/src/workos/connect/_resource.py index 0e41ab7d..8b53d8e4 100644 --- a/src/workos/connect/_resource.py +++ b/src/workos/connect/_resource.py @@ -19,6 +19,7 @@ UserObject, ) from workos.common.models.connect_application import ConnectApplication +from workos.common.models.connect_application import ConnectApplicationVariant from workos.common.models.pagination_order import PaginationOrder from .._pagination import AsyncPage, SyncPage @@ -97,7 +98,7 @@ def list_applications( order: Optional[Union[PaginationOrder, str]] = "desc", organization_id: Optional[str] = None, request_options: Optional[RequestOptions] = None, - ) -> SyncPage[ConnectApplication]: + ) -> SyncPage[ConnectApplicationVariant]: """List Connect Applications List all Connect Applications in the current environment with optional filtering. @@ -111,7 +112,7 @@ def list_applications( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - SyncPage[ConnectApplication] + SyncPage[ConnectApplicationVariant] Raises: UnprocessableEntityError: If the request data is unprocessable (422). @@ -130,12 +131,15 @@ def list_applications( }.items() if v is not None } - return self._client.request_page( - method="get", - path=("connect", "applications"), - model=ConnectApplication, - params=params, - request_options=request_options, + return cast( + SyncPage[ConnectApplicationVariant], + self._client.request_page( + method="get", + path=("connect", "applications"), + model=ConnectApplication, # type: ignore[arg-type] # dispatcher; pagination only calls from_dict + params=params, + request_options=request_options, + ), ) def create_application( @@ -143,7 +147,7 @@ def create_application( *, body: Union[CreateOAuthApplication, CreateM2MApplication, Dict[str, Any]], request_options: Optional[RequestOptions] = None, - ) -> ConnectApplication: + ) -> ConnectApplicationVariant: """Create a Connect Application Create a new Connect Application. Supports both OAuth and Machine-to-Machine (M2M) application types. @@ -153,7 +157,7 @@ def create_application( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - ConnectApplication + ConnectApplicationVariant Raises: NotFoundError: If the resource is not found (404). @@ -163,12 +167,15 @@ def create_application( ServerError: If the server returns a 5xx error. """ _body: Dict[str, Any] = body if isinstance(body, dict) else body.to_dict() - return self._client.request( - method="post", - path=("connect", "applications"), - body=_body, - model=ConnectApplication, - request_options=request_options, + return cast( + ConnectApplicationVariant, + self._client.request( + method="post", + path=("connect", "applications"), + body=_body, + model=ConnectApplication, # type: ignore[arg-type] # dispatcher; request only calls from_dict + request_options=request_options, + ), ) def create_oauth_application( @@ -182,7 +189,7 @@ def create_oauth_application( uses_pkce: Optional[bool] = None, organization_id: Optional[str] = None, request_options: Optional[RequestOptions] = None, - ) -> ConnectApplication: + ) -> ConnectApplicationVariant: """Create oauth application.""" body: Dict[str, Any] = { "application_type": "oauth", @@ -200,12 +207,15 @@ def create_oauth_application( if organization_id is not None: body["organization_id"] = organization_id - return self._client.request( - method="POST", - path=("connect", "applications"), - body=body, - model=ConnectApplication, - request_options=request_options, + return cast( + ConnectApplicationVariant, + self._client.request( + method="POST", + path=("connect", "applications"), + body=body, + model=ConnectApplication, # type: ignore[arg-type] # dispatcher; request only calls from_dict + request_options=request_options, + ), ) def create_m2m_application( @@ -216,7 +226,7 @@ def create_m2m_application( description: Optional[str] = None, scopes: Optional[List[str]] = None, request_options: Optional[RequestOptions] = None, - ) -> ConnectApplication: + ) -> ConnectApplicationVariant: """Create m2m application.""" body: Dict[str, Any] = { "application_type": "m2m", @@ -228,12 +238,15 @@ def create_m2m_application( if scopes is not None: body["scopes"] = scopes - return self._client.request( - method="POST", - path=("connect", "applications"), - body=body, - model=ConnectApplication, - request_options=request_options, + return cast( + ConnectApplicationVariant, + self._client.request( + method="POST", + path=("connect", "applications"), + body=body, + model=ConnectApplication, # type: ignore[arg-type] # dispatcher; request only calls from_dict + request_options=request_options, + ), ) def get_application( @@ -241,7 +254,7 @@ def get_application( id: str, *, request_options: Optional[RequestOptions] = None, - ) -> ConnectApplication: + ) -> ConnectApplicationVariant: """Get a Connect Application Retrieve details for a specific Connect Application by ID or client ID. @@ -251,7 +264,7 @@ def get_application( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - ConnectApplication + ConnectApplicationVariant Raises: NotFoundError: If the resource is not found (404). @@ -259,11 +272,14 @@ def get_application( RateLimitExceededError: If rate limited (429). ServerError: If the server returns a 5xx error. """ - return self._client.request( - method="get", - path=("connect", "applications", str(id)), - model=ConnectApplication, - request_options=request_options, + return cast( + ConnectApplicationVariant, + self._client.request( + method="get", + path=("connect", "applications", str(id)), + model=ConnectApplication, # type: ignore[arg-type] # dispatcher; request only calls from_dict + request_options=request_options, + ), ) def update_application( @@ -275,7 +291,7 @@ def update_application( scopes: Optional[List[str]] = None, redirect_uris: Optional[List[RedirectUriInput]] = None, request_options: Optional[RequestOptions] = None, - ) -> ConnectApplication: + ) -> ConnectApplicationVariant: """Update a Connect Application Update an existing Connect Application. For OAuth applications, you can update redirect URIs. For all applications, you can update the name, description, and scopes. @@ -289,7 +305,7 @@ def update_application( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - ConnectApplication + ConnectApplicationVariant Raises: NotFoundError: If the resource is not found (404). @@ -310,12 +326,15 @@ def update_application( }.items() if v is not None } - return self._client.request( - method="put", - path=("connect", "applications", str(id)), - body=body, - model=ConnectApplication, - request_options=request_options, + return cast( + ConnectApplicationVariant, + self._client.request( + method="put", + path=("connect", "applications", str(id)), + body=body, + model=ConnectApplication, # type: ignore[arg-type] # dispatcher; request only calls from_dict + request_options=request_options, + ), ) def delete_application( @@ -511,7 +530,7 @@ async def list_applications( order: Optional[Union[PaginationOrder, str]] = "desc", organization_id: Optional[str] = None, request_options: Optional[RequestOptions] = None, - ) -> AsyncPage[ConnectApplication]: + ) -> AsyncPage[ConnectApplicationVariant]: """List Connect Applications List all Connect Applications in the current environment with optional filtering. @@ -525,7 +544,7 @@ async def list_applications( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - AsyncPage[ConnectApplication] + AsyncPage[ConnectApplicationVariant] Raises: UnprocessableEntityError: If the request data is unprocessable (422). @@ -544,12 +563,15 @@ async def list_applications( }.items() if v is not None } - return await self._client.request_page( - method="get", - path=("connect", "applications"), - model=ConnectApplication, - params=params, - request_options=request_options, + return cast( + AsyncPage[ConnectApplicationVariant], + await self._client.request_page( + method="get", + path=("connect", "applications"), + model=ConnectApplication, # type: ignore[arg-type] # dispatcher; pagination only calls from_dict + params=params, + request_options=request_options, + ), ) async def create_application( @@ -557,7 +579,7 @@ async def create_application( *, body: Union[CreateOAuthApplication, CreateM2MApplication, Dict[str, Any]], request_options: Optional[RequestOptions] = None, - ) -> ConnectApplication: + ) -> ConnectApplicationVariant: """Create a Connect Application Create a new Connect Application. Supports both OAuth and Machine-to-Machine (M2M) application types. @@ -567,7 +589,7 @@ async def create_application( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - ConnectApplication + ConnectApplicationVariant Raises: NotFoundError: If the resource is not found (404). @@ -577,12 +599,15 @@ async def create_application( ServerError: If the server returns a 5xx error. """ _body: Dict[str, Any] = body if isinstance(body, dict) else body.to_dict() - return await self._client.request( - method="post", - path=("connect", "applications"), - body=_body, - model=ConnectApplication, - request_options=request_options, + return cast( + ConnectApplicationVariant, + await self._client.request( + method="post", + path=("connect", "applications"), + body=_body, + model=ConnectApplication, # type: ignore[arg-type] # dispatcher; request only calls from_dict + request_options=request_options, + ), ) async def create_oauth_application( @@ -596,7 +621,7 @@ async def create_oauth_application( uses_pkce: Optional[bool] = None, organization_id: Optional[str] = None, request_options: Optional[RequestOptions] = None, - ) -> ConnectApplication: + ) -> ConnectApplicationVariant: """Create oauth application.""" body: Dict[str, Any] = { "application_type": "oauth", @@ -614,12 +639,15 @@ async def create_oauth_application( if organization_id is not None: body["organization_id"] = organization_id - return await self._client.request( - method="POST", - path=("connect", "applications"), - body=body, - model=ConnectApplication, - request_options=request_options, + return cast( + ConnectApplicationVariant, + await self._client.request( + method="POST", + path=("connect", "applications"), + body=body, + model=ConnectApplication, # type: ignore[arg-type] # dispatcher; request only calls from_dict + request_options=request_options, + ), ) async def create_m2m_application( @@ -630,7 +658,7 @@ async def create_m2m_application( description: Optional[str] = None, scopes: Optional[List[str]] = None, request_options: Optional[RequestOptions] = None, - ) -> ConnectApplication: + ) -> ConnectApplicationVariant: """Create m2m application.""" body: Dict[str, Any] = { "application_type": "m2m", @@ -642,12 +670,15 @@ async def create_m2m_application( if scopes is not None: body["scopes"] = scopes - return await self._client.request( - method="POST", - path=("connect", "applications"), - body=body, - model=ConnectApplication, - request_options=request_options, + return cast( + ConnectApplicationVariant, + await self._client.request( + method="POST", + path=("connect", "applications"), + body=body, + model=ConnectApplication, # type: ignore[arg-type] # dispatcher; request only calls from_dict + request_options=request_options, + ), ) async def get_application( @@ -655,7 +686,7 @@ async def get_application( id: str, *, request_options: Optional[RequestOptions] = None, - ) -> ConnectApplication: + ) -> ConnectApplicationVariant: """Get a Connect Application Retrieve details for a specific Connect Application by ID or client ID. @@ -665,7 +696,7 @@ async def get_application( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - ConnectApplication + ConnectApplicationVariant Raises: NotFoundError: If the resource is not found (404). @@ -673,11 +704,14 @@ async def get_application( RateLimitExceededError: If rate limited (429). ServerError: If the server returns a 5xx error. """ - return await self._client.request( - method="get", - path=("connect", "applications", str(id)), - model=ConnectApplication, - request_options=request_options, + return cast( + ConnectApplicationVariant, + await self._client.request( + method="get", + path=("connect", "applications", str(id)), + model=ConnectApplication, # type: ignore[arg-type] # dispatcher; request only calls from_dict + request_options=request_options, + ), ) async def update_application( @@ -689,7 +723,7 @@ async def update_application( scopes: Optional[List[str]] = None, redirect_uris: Optional[List[RedirectUriInput]] = None, request_options: Optional[RequestOptions] = None, - ) -> ConnectApplication: + ) -> ConnectApplicationVariant: """Update a Connect Application Update an existing Connect Application. For OAuth applications, you can update redirect URIs. For all applications, you can update the name, description, and scopes. @@ -703,7 +737,7 @@ async def update_application( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - ConnectApplication + ConnectApplicationVariant Raises: NotFoundError: If the resource is not found (404). @@ -724,12 +758,15 @@ async def update_application( }.items() if v is not None } - return await self._client.request( - method="put", - path=("connect", "applications", str(id)), - body=body, - model=ConnectApplication, - request_options=request_options, + return cast( + ConnectApplicationVariant, + await self._client.request( + method="put", + path=("connect", "applications", str(id)), + body=body, + model=ConnectApplication, # type: ignore[arg-type] # dispatcher; request only calls from_dict + request_options=request_options, + ), ) async def delete_application( diff --git a/src/workos/connect/models/__init__.py b/src/workos/connect/models/__init__.py index 5c4d76ec..46445679 100644 --- a/src/workos/connect/models/__init__.py +++ b/src/workos/connect/models/__init__.py @@ -6,6 +6,12 @@ from workos.common.models.connect_application import ( ConnectApplication as ConnectApplication, ) +from workos.common.models.connect_application import ( + ConnectApplicationUnknown as ConnectApplicationUnknown, +) +from workos.common.models.connect_application import ( + ConnectApplicationVariant as ConnectApplicationVariant, +) from .create_application_secret import ( CreateApplicationSecret as CreateApplicationSecret, ) diff --git a/src/workos/connect/models/application_credentials_list_item.py b/src/workos/connect/models/application_credentials_list_item.py index 8fea31c3..f3569fd2 100644 --- a/src/workos/connect/models/application_credentials_list_item.py +++ b/src/workos/connect/models/application_credentials_list_item.py @@ -19,7 +19,7 @@ class ApplicationCredentialsListItem: """The unique ID of the client secret.""" secret_hint: str """A hint showing the last few characters of the secret value.""" - last_used_at: Optional[str] + last_used_at: Optional[datetime] """The timestamp when the client secret was last used, or null if never used.""" created_at: datetime """An ISO 8601 timestamp.""" @@ -34,7 +34,9 @@ def from_dict(cls, data: Dict[str, Any]) -> "ApplicationCredentialsListItem": object=data.get("object", "connect_application_secret"), id=data["id"], secret_hint=data["secret_hint"], - last_used_at=data["last_used_at"], + last_used_at=_parse_datetime(_v_last_used_at) + if (_v_last_used_at := data["last_used_at"]) is not None + else None, created_at=_parse_datetime(data["created_at"]), updated_at=_parse_datetime(data["updated_at"]), ) @@ -48,7 +50,7 @@ def to_dict(self) -> Dict[str, Any]: result["id"] = self.id result["secret_hint"] = self.secret_hint if self.last_used_at is not None: - result["last_used_at"] = self.last_used_at + result["last_used_at"] = _format_datetime(self.last_used_at) else: result["last_used_at"] = None result["created_at"] = _format_datetime(self.created_at) diff --git a/src/workos/connect/models/new_connect_application_secret.py b/src/workos/connect/models/new_connect_application_secret.py index 2413c07d..4efe0840 100644 --- a/src/workos/connect/models/new_connect_application_secret.py +++ b/src/workos/connect/models/new_connect_application_secret.py @@ -19,7 +19,7 @@ class NewConnectApplicationSecret: """The unique ID of the client secret.""" secret_hint: str """A hint showing the last few characters of the secret value.""" - last_used_at: Optional[str] + last_used_at: Optional[datetime] """The timestamp when the client secret was last used, or null if never used.""" created_at: datetime """An ISO 8601 timestamp.""" @@ -36,7 +36,9 @@ def from_dict(cls, data: Dict[str, Any]) -> "NewConnectApplicationSecret": object=data.get("object", "connect_application_secret"), id=data["id"], secret_hint=data["secret_hint"], - last_used_at=data["last_used_at"], + last_used_at=_parse_datetime(_v_last_used_at) + if (_v_last_used_at := data["last_used_at"]) is not None + else None, created_at=_parse_datetime(data["created_at"]), updated_at=_parse_datetime(data["updated_at"]), secret=data["secret"], @@ -51,7 +53,7 @@ def to_dict(self) -> Dict[str, Any]: result["id"] = self.id result["secret_hint"] = self.secret_hint if self.last_used_at is not None: - result["last_used_at"] = self.last_used_at + result["last_used_at"] = _format_datetime(self.last_used_at) else: result["last_used_at"] = None result["created_at"] = _format_datetime(self.created_at) diff --git a/src/workos/events/models/event_schema.py b/src/workos/events/models/event_schema.py index 25fa0079..3bdd75ec 100644 --- a/src/workos/events/models/event_schema.py +++ b/src/workos/events/models/event_schema.py @@ -111,6 +111,15 @@ from workos.common.models.permission_created import PermissionCreated from workos.common.models.permission_deleted import PermissionDeleted from workos.common.models.permission_updated import PermissionUpdated +from workos.common.models.pipes_connected_account_connected import ( + PipesConnectedAccountConnected, +) +from workos.common.models.pipes_connected_account_disconnected import ( + PipesConnectedAccountDisconnected, +) +from workos.common.models.pipes_connected_account_reauthorization_needed import ( + PipesConnectedAccountReauthorizationNeeded, +) from workos.common.models.role_created import RoleCreated from workos.common.models.role_deleted import RoleDeleted from workos.common.models.role_updated import RoleUpdated @@ -226,6 +235,9 @@ def to_dict(self) -> Dict[str, Any]: PermissionCreated, PermissionDeleted, PermissionUpdated, + PipesConnectedAccountConnected, + PipesConnectedAccountDisconnected, + PipesConnectedAccountReauthorizationNeeded, RoleCreated, RoleDeleted, RoleUpdated, @@ -327,6 +339,9 @@ class EventSchema: "permission.created": PermissionCreated, "permission.deleted": PermissionDeleted, "permission.updated": PermissionUpdated, + "pipes.connected_account.connected": PipesConnectedAccountConnected, + "pipes.connected_account.disconnected": PipesConnectedAccountDisconnected, + "pipes.connected_account.reauthorization_needed": PipesConnectedAccountReauthorizationNeeded, "role.created": RoleCreated, "role.deleted": RoleDeleted, "role.updated": RoleUpdated, diff --git a/src/workos/groups/_resource.py b/src/workos/groups/_resource.py index cb86fd26..cfa5c456 100644 --- a/src/workos/groups/_resource.py +++ b/src/workos/groups/_resource.py @@ -308,6 +308,7 @@ def create_group_organization_membership( Group Raises: + BadRequestError: If the request is malformed (400). AuthorizationError: If the request is forbidden (403). NotFoundError: If the resource is not found (404). UnprocessableEntityError: If the request data is unprocessable (422). @@ -663,6 +664,7 @@ async def create_group_organization_membership( Group Raises: + BadRequestError: If the request is malformed (400). AuthorizationError: If the request is forbidden (403). NotFoundError: If the resource is not found (404). UnprocessableEntityError: If the request data is unprocessable (422). diff --git a/src/workos/organization_membership/__init__.py b/src/workos/organization_membership/__init__.py new file mode 100644 index 00000000..92ec1ac9 --- /dev/null +++ b/src/workos/organization_membership/__init__.py @@ -0,0 +1,9 @@ +# This file is auto-generated by oagen. Do not edit. + +from ._resource import ( + OrganizationMembershipService as OrganizationMembershipService, + AsyncOrganizationMembershipService as AsyncOrganizationMembershipService, + RoleSingle as RoleSingle, + RoleMultiple as RoleMultiple, +) +from .models import * diff --git a/src/workos/organization_membership/_resource.py b/src/workos/organization_membership/_resource.py new file mode 100644 index 00000000..b989561f --- /dev/null +++ b/src/workos/organization_membership/_resource.py @@ -0,0 +1,702 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union + +if TYPE_CHECKING: + from .._client import AsyncWorkOSClient, WorkOSClient + +from .._types import RequestOptions, enum_value +from .models import OrganizationMembership, UserOrganizationMembership +from workos.common.models.group import Group +from .models import UserManagementOrganizationMembershipStatuses +from workos.common.models.pagination_order import PaginationOrder +from .._pagination import AsyncPage, SyncPage +from dataclasses import dataclass + + +@dataclass +class RoleSingle: + """Identify role single.""" + + role_slug: str + + +@dataclass +class RoleMultiple: + """Identify role multiple.""" + + role_slugs: List[str] + + +class OrganizationMembershipService: + """Organization Membership Service API resources.""" + + def __init__(self, client: "WorkOSClient") -> None: + self._client = client + + def list_organization_memberships( + self, + *, + limit: Optional[int] = None, + before: Optional[str] = None, + after: Optional[str] = None, + order: Optional[Union[PaginationOrder, str]] = "desc", + organization_id: Optional[str] = None, + statuses: Optional[ + List[Union[UserManagementOrganizationMembershipStatuses, str]] + ] = None, + user_id: Optional[str] = None, + request_options: Optional[RequestOptions] = None, + ) -> SyncPage[UserOrganizationMembership]: + """List organization memberships + + Get a list of all organization memberships matching the criteria specified. At least one of `user_id` or `organization_id` must be provided. By default only active memberships are returned. Use the `statuses` parameter to filter by other statuses. + + Args: + limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`. + before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. + after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. + order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to descending. Defaults to `desc`. + organization_id: The ID of the [organization](https://workos.com/docs/reference/organization) which the user belongs to. + statuses: Filter by the status of the organization membership. Array including any of `active`, `inactive`, or `pending`. + user_id: The ID of the [user](https://workos.com/docs/reference/authkit/user). + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + SyncPage[UserOrganizationMembership] + + Raises: + BadRequestError: If the request is malformed (400). + NotFoundError: If the resource is not found (404). + UnprocessableEntityError: If the request data is unprocessable (422). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + params = { + k: v + for k, v in { + "limit": limit, + "before": before, + "after": after, + "order": enum_value(order) if order is not None else None, + "organization_id": organization_id, + "statuses": ",".join(str(v) for v in statuses) + if statuses is not None + else None, + "user_id": user_id, + }.items() + if v is not None + } + return self._client.request_page( + method="get", + path=("user_management", "organization_memberships"), + model=UserOrganizationMembership, + params=params, + request_options=request_options, + ) + + def create_organization_membership( + self, + *, + user_id: str, + organization_id: str, + role: Optional[Union[RoleSingle, RoleMultiple]] = None, + request_options: Optional[RequestOptions] = None, + ) -> OrganizationMembership: + """Create an organization membership + + Creates a new `active` organization membership for the given organization and user. + + Calling this API with an organization and user that match an `inactive` organization membership will activate the membership with the specified role(s). + + Args: + user_id: The ID of the [user](https://workos.com/docs/reference/authkit/user). + organization_id: The ID of the [organization](https://workos.com/docs/reference/organization) which the user belongs to. + role: Identifies the role. One of: RoleSingle, RoleMultiple. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + OrganizationMembership + + Raises: + BadRequestError: If the request is malformed (400). + NotFoundError: If the resource is not found (404). + UnprocessableEntityError: If the request data is unprocessable (422). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + body: Dict[str, Any] = { + "user_id": user_id, + "organization_id": organization_id, + } + if role is not None: + if isinstance(role, RoleSingle): + body["role_slug"] = role.role_slug + elif isinstance(role, RoleMultiple): + body["role_slugs"] = role.role_slugs + return self._client.request( + method="post", + path=("user_management", "organization_memberships"), + body=body, + model=OrganizationMembership, + request_options=request_options, + ) + + def get_organization_membership( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> UserOrganizationMembership: + """Get an organization membership + + Get the details of an existing organization membership. + + Args: + id: The unique ID of the organization membership. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + UserOrganizationMembership + + Raises: + NotFoundError: If the resource is not found (404). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + return self._client.request( + method="get", + path=("user_management", "organization_memberships", str(id)), + model=UserOrganizationMembership, + request_options=request_options, + ) + + def update_organization_membership( + self, + id: str, + *, + role: Optional[Union[RoleSingle, RoleMultiple]] = None, + request_options: Optional[RequestOptions] = None, + ) -> UserOrganizationMembership: + """Update an organization membership + + Update the details of an existing organization membership. + + Args: + id: The unique ID of the organization membership. + role: Identifies the role. One of: RoleSingle, RoleMultiple. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + UserOrganizationMembership + + Raises: + NotFoundError: If the resource is not found (404). + UnprocessableEntityError: If the request data is unprocessable (422). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + body: Dict[str, Any] = {} + if role is not None: + if isinstance(role, RoleSingle): + body["role_slug"] = role.role_slug + elif isinstance(role, RoleMultiple): + body["role_slugs"] = role.role_slugs + return self._client.request( + method="put", + path=("user_management", "organization_memberships", str(id)), + body=body, + model=UserOrganizationMembership, + request_options=request_options, + ) + + def delete_organization_membership( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> None: + """Delete an organization membership + + Permanently deletes an existing organization membership. It cannot be undone. + + Args: + id: The unique ID of the organization membership. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Raises: + NotFoundError: If the resource is not found (404). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + self._client.request( + method="delete", + path=("user_management", "organization_memberships", str(id)), + request_options=request_options, + ) + + def deactivate_organization_membership( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> OrganizationMembership: + """Deactivate an organization membership + + Deactivates an `active` organization membership. Emits an [organization_membership.updated](https://workos.com/docs/events/organization-membership) event upon successful deactivation. + + - Deactivating an `inactive` membership is a no-op and does not emit an event. + - Deactivating a `pending` membership returns an error. This membership should be [deleted](https://workos.com/docs/reference/authkit/organization-membership/delete) instead. + + See the [membership management documentation](https://workos.com/docs/authkit/users-organizations/organizations/membership-management) for additional details. + + Args: + id: The unique ID of the organization membership. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + OrganizationMembership + + Raises: + BadRequestError: If the request is malformed (400). + NotFoundError: If the resource is not found (404). + UnprocessableEntityError: If the request data is unprocessable (422). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + return self._client.request( + method="put", + path=("user_management", "organization_memberships", str(id), "deactivate"), + model=OrganizationMembership, + request_options=request_options, + ) + + def reactivate_organization_membership( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> UserOrganizationMembership: + """Reactivate an organization membership + + Reactivates an `inactive` organization membership, retaining the pre-existing role(s). Emits an [organization_membership.updated](https://workos.com/docs/events/organization-membership) event upon successful reactivation. + + - Reactivating an `active` membership is a no-op and does not emit an event. + - Reactivating a `pending` membership returns an error. The user needs to [accept the invitation](https://workos.com/docs/authkit/invitations) instead. + + See the [membership management documentation](https://workos.com/docs/authkit/users-organizations/organizations/membership-management) for additional details. + + Args: + id: The unique ID of the organization membership. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + UserOrganizationMembership + + Raises: + BadRequestError: If the request is malformed (400). + NotFoundError: If the resource is not found (404). + UnprocessableEntityError: If the request data is unprocessable (422). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + return self._client.request( + method="put", + path=("user_management", "organization_memberships", str(id), "reactivate"), + model=UserOrganizationMembership, + request_options=request_options, + ) + + def list_organization_membership_groups( + self, + om_id: str, + *, + limit: Optional[int] = None, + before: Optional[str] = None, + after: Optional[str] = None, + order: Optional[Union[PaginationOrder, str]] = "desc", + request_options: Optional[RequestOptions] = None, + ) -> SyncPage[Group]: + """List groups + + Get a list of groups that an organization membership belongs to. + + Args: + om_id: Unique identifier of the Organization Membership. + limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`. + before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. + after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. + order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to descending. Defaults to `desc`. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + SyncPage[Group] + + Raises: + NotFoundError: If the resource is not found (404). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + params = { + k: v + for k, v in { + "limit": limit, + "before": before, + "after": after, + "order": enum_value(order) if order is not None else None, + }.items() + if v is not None + } + return self._client.request_page( + method="get", + path=("user_management", "organization_memberships", str(om_id), "groups"), + model=Group, + params=params, + request_options=request_options, + ) + + +class AsyncOrganizationMembershipService: + """Organization Membership Service API resources (async).""" + + def __init__(self, client: "AsyncWorkOSClient") -> None: + self._client = client + + async def list_organization_memberships( + self, + *, + limit: Optional[int] = None, + before: Optional[str] = None, + after: Optional[str] = None, + order: Optional[Union[PaginationOrder, str]] = "desc", + organization_id: Optional[str] = None, + statuses: Optional[ + List[Union[UserManagementOrganizationMembershipStatuses, str]] + ] = None, + user_id: Optional[str] = None, + request_options: Optional[RequestOptions] = None, + ) -> AsyncPage[UserOrganizationMembership]: + """List organization memberships + + Get a list of all organization memberships matching the criteria specified. At least one of `user_id` or `organization_id` must be provided. By default only active memberships are returned. Use the `statuses` parameter to filter by other statuses. + + Args: + limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`. + before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. + after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. + order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to descending. Defaults to `desc`. + organization_id: The ID of the [organization](https://workos.com/docs/reference/organization) which the user belongs to. + statuses: Filter by the status of the organization membership. Array including any of `active`, `inactive`, or `pending`. + user_id: The ID of the [user](https://workos.com/docs/reference/authkit/user). + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + AsyncPage[UserOrganizationMembership] + + Raises: + BadRequestError: If the request is malformed (400). + NotFoundError: If the resource is not found (404). + UnprocessableEntityError: If the request data is unprocessable (422). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + params = { + k: v + for k, v in { + "limit": limit, + "before": before, + "after": after, + "order": enum_value(order) if order is not None else None, + "organization_id": organization_id, + "statuses": ",".join(str(v) for v in statuses) + if statuses is not None + else None, + "user_id": user_id, + }.items() + if v is not None + } + return await self._client.request_page( + method="get", + path=("user_management", "organization_memberships"), + model=UserOrganizationMembership, + params=params, + request_options=request_options, + ) + + async def create_organization_membership( + self, + *, + user_id: str, + organization_id: str, + role: Optional[Union[RoleSingle, RoleMultiple]] = None, + request_options: Optional[RequestOptions] = None, + ) -> OrganizationMembership: + """Create an organization membership + + Creates a new `active` organization membership for the given organization and user. + + Calling this API with an organization and user that match an `inactive` organization membership will activate the membership with the specified role(s). + + Args: + user_id: The ID of the [user](https://workos.com/docs/reference/authkit/user). + organization_id: The ID of the [organization](https://workos.com/docs/reference/organization) which the user belongs to. + role: Identifies the role. One of: RoleSingle, RoleMultiple. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + OrganizationMembership + + Raises: + BadRequestError: If the request is malformed (400). + NotFoundError: If the resource is not found (404). + UnprocessableEntityError: If the request data is unprocessable (422). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + body: Dict[str, Any] = { + "user_id": user_id, + "organization_id": organization_id, + } + if role is not None: + if isinstance(role, RoleSingle): + body["role_slug"] = role.role_slug + elif isinstance(role, RoleMultiple): + body["role_slugs"] = role.role_slugs + return await self._client.request( + method="post", + path=("user_management", "organization_memberships"), + body=body, + model=OrganizationMembership, + request_options=request_options, + ) + + async def get_organization_membership( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> UserOrganizationMembership: + """Get an organization membership + + Get the details of an existing organization membership. + + Args: + id: The unique ID of the organization membership. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + UserOrganizationMembership + + Raises: + NotFoundError: If the resource is not found (404). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + return await self._client.request( + method="get", + path=("user_management", "organization_memberships", str(id)), + model=UserOrganizationMembership, + request_options=request_options, + ) + + async def update_organization_membership( + self, + id: str, + *, + role: Optional[Union[RoleSingle, RoleMultiple]] = None, + request_options: Optional[RequestOptions] = None, + ) -> UserOrganizationMembership: + """Update an organization membership + + Update the details of an existing organization membership. + + Args: + id: The unique ID of the organization membership. + role: Identifies the role. One of: RoleSingle, RoleMultiple. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + UserOrganizationMembership + + Raises: + NotFoundError: If the resource is not found (404). + UnprocessableEntityError: If the request data is unprocessable (422). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + body: Dict[str, Any] = {} + if role is not None: + if isinstance(role, RoleSingle): + body["role_slug"] = role.role_slug + elif isinstance(role, RoleMultiple): + body["role_slugs"] = role.role_slugs + return await self._client.request( + method="put", + path=("user_management", "organization_memberships", str(id)), + body=body, + model=UserOrganizationMembership, + request_options=request_options, + ) + + async def delete_organization_membership( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> None: + """Delete an organization membership + + Permanently deletes an existing organization membership. It cannot be undone. + + Args: + id: The unique ID of the organization membership. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Raises: + NotFoundError: If the resource is not found (404). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + await self._client.request( + method="delete", + path=("user_management", "organization_memberships", str(id)), + request_options=request_options, + ) + + async def deactivate_organization_membership( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> OrganizationMembership: + """Deactivate an organization membership + + Deactivates an `active` organization membership. Emits an [organization_membership.updated](https://workos.com/docs/events/organization-membership) event upon successful deactivation. + + - Deactivating an `inactive` membership is a no-op and does not emit an event. + - Deactivating a `pending` membership returns an error. This membership should be [deleted](https://workos.com/docs/reference/authkit/organization-membership/delete) instead. + + See the [membership management documentation](https://workos.com/docs/authkit/users-organizations/organizations/membership-management) for additional details. + + Args: + id: The unique ID of the organization membership. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + OrganizationMembership + + Raises: + BadRequestError: If the request is malformed (400). + NotFoundError: If the resource is not found (404). + UnprocessableEntityError: If the request data is unprocessable (422). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + return await self._client.request( + method="put", + path=("user_management", "organization_memberships", str(id), "deactivate"), + model=OrganizationMembership, + request_options=request_options, + ) + + async def reactivate_organization_membership( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> UserOrganizationMembership: + """Reactivate an organization membership + + Reactivates an `inactive` organization membership, retaining the pre-existing role(s). Emits an [organization_membership.updated](https://workos.com/docs/events/organization-membership) event upon successful reactivation. + + - Reactivating an `active` membership is a no-op and does not emit an event. + - Reactivating a `pending` membership returns an error. The user needs to [accept the invitation](https://workos.com/docs/authkit/invitations) instead. + + See the [membership management documentation](https://workos.com/docs/authkit/users-organizations/organizations/membership-management) for additional details. + + Args: + id: The unique ID of the organization membership. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + UserOrganizationMembership + + Raises: + BadRequestError: If the request is malformed (400). + NotFoundError: If the resource is not found (404). + UnprocessableEntityError: If the request data is unprocessable (422). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + return await self._client.request( + method="put", + path=("user_management", "organization_memberships", str(id), "reactivate"), + model=UserOrganizationMembership, + request_options=request_options, + ) + + async def list_organization_membership_groups( + self, + om_id: str, + *, + limit: Optional[int] = None, + before: Optional[str] = None, + after: Optional[str] = None, + order: Optional[Union[PaginationOrder, str]] = "desc", + request_options: Optional[RequestOptions] = None, + ) -> AsyncPage[Group]: + """List groups + + Get a list of groups that an organization membership belongs to. + + Args: + om_id: Unique identifier of the Organization Membership. + limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`. + before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. + after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. + order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to descending. Defaults to `desc`. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + AsyncPage[Group] + + Raises: + NotFoundError: If the resource is not found (404). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + params = { + k: v + for k, v in { + "limit": limit, + "before": before, + "after": after, + "order": enum_value(order) if order is not None else None, + }.items() + if v is not None + } + return await self._client.request_page( + method="get", + path=("user_management", "organization_memberships", str(om_id), "groups"), + model=Group, + params=params, + request_options=request_options, + ) diff --git a/src/workos/organization_membership/models/__init__.py b/src/workos/organization_membership/models/__init__.py new file mode 100644 index 00000000..ba0a66cb --- /dev/null +++ b/src/workos/organization_membership/models/__init__.py @@ -0,0 +1,15 @@ +# This file is auto-generated by oagen. Do not edit. + +from .create_user_organization_membership import ( + CreateUserOrganizationMembership as CreateUserOrganizationMembership, +) +from .organization_membership import OrganizationMembership as OrganizationMembership +from .update_user_organization_membership import ( + UpdateUserOrganizationMembership as UpdateUserOrganizationMembership, +) +from .user_management_organization_membership_statuses import ( + UserManagementOrganizationMembershipStatuses as UserManagementOrganizationMembershipStatuses, +) +from .user_organization_membership import ( + UserOrganizationMembership as UserOrganizationMembership, +) diff --git a/src/workos/user_management/models/create_user_organization_membership.py b/src/workos/organization_membership/models/create_user_organization_membership.py similarity index 100% rename from src/workos/user_management/models/create_user_organization_membership.py rename to src/workos/organization_membership/models/create_user_organization_membership.py diff --git a/src/workos/user_management/models/organization_membership.py b/src/workos/organization_membership/models/organization_membership.py similarity index 100% rename from src/workos/user_management/models/organization_membership.py rename to src/workos/organization_membership/models/organization_membership.py diff --git a/src/workos/user_management/models/update_user_organization_membership.py b/src/workos/organization_membership/models/update_user_organization_membership.py similarity index 100% rename from src/workos/user_management/models/update_user_organization_membership.py rename to src/workos/organization_membership/models/update_user_organization_membership.py diff --git a/src/workos/organization_membership/models/user_management_organization_membership_statuses.py b/src/workos/organization_membership/models/user_management_organization_membership_statuses.py new file mode 100644 index 00000000..d56e50e8 --- /dev/null +++ b/src/workos/organization_membership/models/user_management_organization_membership_statuses.py @@ -0,0 +1,21 @@ +# This file is auto-generated by oagen. Do not edit. + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from workos.common.models.organization_membership_created_data_status import ( + OrganizationMembershipCreatedDataStatus as UserManagementOrganizationMembershipStatuses, + ) +else: + + def __getattr__(name: str): + if name == "UserManagementOrganizationMembershipStatuses": + from workos.common.models.organization_membership_created_data_status import ( + OrganizationMembershipCreatedDataStatus, + ) + + return OrganizationMembershipCreatedDataStatus + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + + +__all__ = ["UserManagementOrganizationMembershipStatuses"] diff --git a/src/workos/user_management/models/user_organization_membership.py b/src/workos/organization_membership/models/user_organization_membership.py similarity index 100% rename from src/workos/user_management/models/user_organization_membership.py rename to src/workos/organization_membership/models/user_organization_membership.py diff --git a/src/workos/organizations/models/__init__.py b/src/workos/organizations/models/__init__.py index e9809cbd..5cf3c16b 100644 --- a/src/workos/organizations/models/__init__.py +++ b/src/workos/organizations/models/__init__.py @@ -4,7 +4,7 @@ from .audit_log_configuration_log_stream import ( AuditLogConfigurationLogStream as AuditLogConfigurationLogStream, ) -from .audit_logs_retention_json import AuditLogsRetentionJson as AuditLogsRetentionJson +from .audit_logs_retention import AuditLogsRetention as AuditLogsRetention from .organization import Organization as Organization from .organization_domain_data import OrganizationDomainData as OrganizationDomainData from .organization_input import OrganizationInput as OrganizationInput diff --git a/src/workos/organizations/models/audit_logs_retention_json.py b/src/workos/organizations/models/audit_logs_retention.py similarity index 87% rename from src/workos/organizations/models/audit_logs_retention_json.py rename to src/workos/organizations/models/audit_logs_retention.py index 1e7fdf4b..a08db5cd 100644 --- a/src/workos/organizations/models/audit_logs_retention_json.py +++ b/src/workos/organizations/models/audit_logs_retention.py @@ -8,21 +8,21 @@ @dataclass(slots=True) -class AuditLogsRetentionJson: - """Audit Logs Retention Json model.""" +class AuditLogsRetention: + """Audit Logs Retention model.""" retention_period_in_days: Optional[int] """The number of days Audit Log events will be retained before being permanently deleted. Valid values are 30 and 365.""" @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "AuditLogsRetentionJson": + def from_dict(cls, data: Dict[str, Any]) -> "AuditLogsRetention": """Deserialize from a dictionary.""" try: return cls( retention_period_in_days=data["retention_period_in_days"], ) except (KeyError, ValueError) as e: - _raise_deserialize_error("AuditLogsRetentionJson", e) + _raise_deserialize_error("AuditLogsRetention", e) def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" diff --git a/src/workos/radar/_resource.py b/src/workos/radar/_resource.py index 45c16a58..c5a85559 100644 --- a/src/workos/radar/_resource.py +++ b/src/workos/radar/_resource.py @@ -9,7 +9,7 @@ from .._types import RequestOptions, enum_value from .models import RadarListEntryAlreadyPresentResponse, RadarStandaloneResponse -from .models import RadarAction, RadarType +from .models import RadarListAction, RadarListType from workos.common.models.radar_standalone_assess_request_action import ( RadarStandaloneAssessRequestAction, ) @@ -32,8 +32,6 @@ def create_attempt( email: str, auth_method: Union[RadarStandaloneAssessRequestAuthMethod, str], action: Union[RadarStandaloneAssessRequestAction, str], - device_fingerprint: Optional[str] = None, - bot_score: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> RadarStandaloneResponse: """Create an attempt @@ -46,8 +44,6 @@ def create_attempt( email: The email address of the user making the request. auth_method: The authentication method being used. action: The action being performed. - device_fingerprint: An optional device fingerprint for the request. - bot_score: An optional bot detection score for the request. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: @@ -60,17 +56,11 @@ def create_attempt( ServerError: If the server returns a 5xx error. """ body: Dict[str, Any] = { - k: v - for k, v in { - "ip_address": ip_address, - "user_agent": user_agent, - "email": email, - "auth_method": enum_value(auth_method), - "action": enum_value(action), - "device_fingerprint": device_fingerprint, - "bot_score": bot_score, - }.items() - if v is not None + "ip_address": ip_address, + "user_agent": user_agent, + "email": email, + "auth_method": enum_value(auth_method), + "action": enum_value(action), } return self._client.request( method="post", @@ -122,8 +112,8 @@ def update_attempt( def add_list_entry( self, - type: Union[RadarType, str], - action: Union[RadarAction, str], + type: Union[RadarListType, str], + action: Union[RadarListAction, str], *, entry: str, request_options: Optional[RequestOptions] = None, @@ -160,8 +150,8 @@ def add_list_entry( def remove_list_entry( self, - type: Union[RadarType, str], - action: Union[RadarAction, str], + type: Union[RadarListType, str], + action: Union[RadarListAction, str], *, entry: str, request_options: Optional[RequestOptions] = None, @@ -208,8 +198,6 @@ async def create_attempt( email: str, auth_method: Union[RadarStandaloneAssessRequestAuthMethod, str], action: Union[RadarStandaloneAssessRequestAction, str], - device_fingerprint: Optional[str] = None, - bot_score: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> RadarStandaloneResponse: """Create an attempt @@ -222,8 +210,6 @@ async def create_attempt( email: The email address of the user making the request. auth_method: The authentication method being used. action: The action being performed. - device_fingerprint: An optional device fingerprint for the request. - bot_score: An optional bot detection score for the request. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: @@ -236,17 +222,11 @@ async def create_attempt( ServerError: If the server returns a 5xx error. """ body: Dict[str, Any] = { - k: v - for k, v in { - "ip_address": ip_address, - "user_agent": user_agent, - "email": email, - "auth_method": enum_value(auth_method), - "action": enum_value(action), - "device_fingerprint": device_fingerprint, - "bot_score": bot_score, - }.items() - if v is not None + "ip_address": ip_address, + "user_agent": user_agent, + "email": email, + "auth_method": enum_value(auth_method), + "action": enum_value(action), } return await self._client.request( method="post", @@ -298,8 +278,8 @@ async def update_attempt( async def add_list_entry( self, - type: Union[RadarType, str], - action: Union[RadarAction, str], + type: Union[RadarListType, str], + action: Union[RadarListAction, str], *, entry: str, request_options: Optional[RequestOptions] = None, @@ -336,8 +316,8 @@ async def add_list_entry( async def remove_list_entry( self, - type: Union[RadarType, str], - action: Union[RadarAction, str], + type: Union[RadarListType, str], + action: Union[RadarListAction, str], *, entry: str, request_options: Optional[RequestOptions] = None, diff --git a/src/workos/radar/models/__init__.py b/src/workos/radar/models/__init__.py index afcc8cec..01ff5194 100644 --- a/src/workos/radar/models/__init__.py +++ b/src/workos/radar/models/__init__.py @@ -1,9 +1,10 @@ # This file is auto-generated by oagen. Do not edit. -from .radar_action import RadarAction as RadarAction +from .radar_list_action import RadarListAction as RadarListAction from .radar_list_entry_already_present_response import ( RadarListEntryAlreadyPresentResponse as RadarListEntryAlreadyPresentResponse, ) +from .radar_list_type import RadarListType as RadarListType from .radar_standalone_assess_request import ( RadarStandaloneAssessRequest as RadarStandaloneAssessRequest, ) @@ -19,4 +20,3 @@ from .radar_standalone_update_radar_list_request import ( RadarStandaloneUpdateRadarListRequest as RadarStandaloneUpdateRadarListRequest, ) -from .radar_type import RadarType as RadarType diff --git a/src/workos/radar/models/radar_action.py b/src/workos/radar/models/radar_list_action.py similarity index 63% rename from src/workos/radar/models/radar_action.py rename to src/workos/radar/models/radar_list_action.py index 7167dd11..52332c82 100644 --- a/src/workos/radar/models/radar_action.py +++ b/src/workos/radar/models/radar_list_action.py @@ -1,6 +1,6 @@ # This file is auto-generated by oagen. Do not edit. -"""Enumeration of radar action values.""" +"""Enumeration of radar list action values.""" from __future__ import annotations @@ -9,14 +9,14 @@ from typing import Literal, TypeAlias -class RadarAction(str, Enum): - """Known values for RadarAction.""" +class RadarListAction(str, Enum): + """Known values for RadarListAction.""" BLOCK = "block" ALLOW = "allow" @classmethod - def _missing_(cls, value: object) -> Optional["RadarAction"]: + def _missing_(cls, value: object) -> Optional["RadarListAction"]: if not isinstance(value, str): return None unknown = str.__new__(cls, value) @@ -25,4 +25,4 @@ def _missing_(cls, value: object) -> Optional["RadarAction"]: return unknown -RadarActionLiteral: TypeAlias = Literal["block", "allow"] +RadarListActionLiteral: TypeAlias = Literal["block", "allow"] diff --git a/src/workos/radar/models/radar_list_type.py b/src/workos/radar/models/radar_list_type.py new file mode 100644 index 00000000..65ec2d76 --- /dev/null +++ b/src/workos/radar/models/radar_list_type.py @@ -0,0 +1,41 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Enumeration of radar list type values.""" + +from __future__ import annotations + +from enum import Enum +from typing import Optional +from typing import Literal, TypeAlias + + +class RadarListType(str, Enum): + """Known values for RadarListType.""" + + IP_ADDRESS = "ip_address" + DOMAIN = "domain" + EMAIL = "email" + DEVICE = "device" + USER_AGENT = "user_agent" + DEVICE_FINGERPRINT = "device_fingerprint" + COUNTRY = "country" + + @classmethod + def _missing_(cls, value: object) -> Optional["RadarListType"]: + if not isinstance(value, str): + return None + unknown = str.__new__(cls, value) + unknown._name_ = value.upper() + unknown._value_ = value + return unknown + + +RadarListTypeLiteral: TypeAlias = Literal[ + "ip_address", + "domain", + "email", + "device", + "user_agent", + "device_fingerprint", + "country", +] diff --git a/src/workos/radar/models/radar_standalone_assess_request.py b/src/workos/radar/models/radar_standalone_assess_request.py index 52d65fe2..5a772920 100644 --- a/src/workos/radar/models/radar_standalone_assess_request.py +++ b/src/workos/radar/models/radar_standalone_assess_request.py @@ -4,7 +4,7 @@ from dataclasses import dataclass from enum import Enum -from typing import Any, Dict, Optional +from typing import Any, Dict from workos._types import _raise_deserialize_error from workos.common.models.radar_standalone_assess_request_action import ( RadarStandaloneAssessRequestAction, @@ -28,10 +28,6 @@ class RadarStandaloneAssessRequest: """The authentication method being used.""" action: "RadarStandaloneAssessRequestAction" """The action being performed.""" - device_fingerprint: Optional[str] = None - """An optional device fingerprint for the request.""" - bot_score: Optional[str] = None - """An optional bot detection score for the request.""" @classmethod def from_dict(cls, data: Dict[str, Any]) -> "RadarStandaloneAssessRequest": @@ -43,8 +39,6 @@ def from_dict(cls, data: Dict[str, Any]) -> "RadarStandaloneAssessRequest": email=data["email"], auth_method=RadarStandaloneAssessRequestAuthMethod(data["auth_method"]), action=RadarStandaloneAssessRequestAction(data["action"]), - device_fingerprint=data.get("device_fingerprint"), - bot_score=data.get("bot_score"), ) except (KeyError, ValueError) as e: _raise_deserialize_error("RadarStandaloneAssessRequest", e) @@ -63,8 +57,4 @@ def to_dict(self) -> Dict[str, Any]: result["action"] = ( self.action.value if isinstance(self.action, Enum) else self.action ) - if self.device_fingerprint is not None: - result["device_fingerprint"] = self.device_fingerprint - if self.bot_score is not None: - result["bot_score"] = self.bot_score return result diff --git a/src/workos/radar/models/radar_type.py b/src/workos/radar/models/radar_type.py deleted file mode 100644 index 01d0df82..00000000 --- a/src/workos/radar/models/radar_type.py +++ /dev/null @@ -1,9 +0,0 @@ -# This file is auto-generated by oagen. Do not edit. - -from typing import TypeAlias -from workos.common.models.radar_standalone_response_blocklist_type import ( - RadarStandaloneResponseBlocklistType, -) - -RadarType: TypeAlias = RadarStandaloneResponseBlocklistType -__all__ = ["RadarType"] diff --git a/src/workos/sso/_resource.py b/src/workos/sso/_resource.py index c088011a..00b110c3 100644 --- a/src/workos/sso/_resource.py +++ b/src/workos/sso/_resource.py @@ -172,7 +172,7 @@ def get_authorization_url( organization: Used to initiate SSO for an organization. The value should be a WorkOS organization ID. You can persist the WorkOS organization ID with application user or team identifiers. WorkOS will use the organization ID to determine the appropriate connection and the IdP to direct the user to for authentication. domain_hint: Can be used to pre-fill the domain field when initiating authentication with Microsoft OAuth or with a Google SAML connection type. - login_hint: Can be used to pre-fill the username/email address field of the IdP sign-in page for the user, if you know their username ahead of time. Currently supported for OAuth, OpenID Connect, Okta, and Entra ID connections. + login_hint: Can be used to pre-fill the username/email address field of the IdP sign-in page for the user, if you know their username ahead of time. Currently supported for OAuth, OpenID Connect, Okta, Entra ID, and custom SAML connections. nonce: A random string generated by the client that is used to mitigate replay attacks. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. @@ -589,7 +589,7 @@ def get_authorization_url( organization: Used to initiate SSO for an organization. The value should be a WorkOS organization ID. You can persist the WorkOS organization ID with application user or team identifiers. WorkOS will use the organization ID to determine the appropriate connection and the IdP to direct the user to for authentication. domain_hint: Can be used to pre-fill the domain field when initiating authentication with Microsoft OAuth or with a Google SAML connection type. - login_hint: Can be used to pre-fill the username/email address field of the IdP sign-in page for the user, if you know their username ahead of time. Currently supported for OAuth, OpenID Connect, Okta, and Entra ID connections. + login_hint: Can be used to pre-fill the username/email address field of the IdP sign-in page for the user, if you know their username ahead of time. Currently supported for OAuth, OpenID Connect, Okta, Entra ID, and custom SAML connections. nonce: A random string generated by the client that is used to mitigate replay attacks. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. diff --git a/src/workos/types/organization_membership/__init__.py b/src/workos/types/organization_membership/__init__.py new file mode 100644 index 00000000..38dbe2aa --- /dev/null +++ b/src/workos/types/organization_membership/__init__.py @@ -0,0 +1,3 @@ +# This file is auto-generated by oagen. Do not edit. + +from workos.organization_membership.models import * # noqa: F401,F403 diff --git a/src/workos/types/user_management_organization_membership_groups/__init__.py b/src/workos/types/user_management_organization_membership_groups/__init__.py deleted file mode 100644 index 08efae58..00000000 --- a/src/workos/types/user_management_organization_membership_groups/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# This file is auto-generated by oagen. Do not edit. - -from workos.user_management_organization_membership_groups.models import * # noqa: F401,F403 diff --git a/src/workos/user_management_organization_membership_groups/models/__init__.py b/src/workos/types/vault/__init__.py similarity index 50% rename from src/workos/user_management_organization_membership_groups/models/__init__.py rename to src/workos/types/vault/__init__.py index 33e9c7b7..7dda52ee 100644 --- a/src/workos/user_management_organization_membership_groups/models/__init__.py +++ b/src/workos/types/vault/__init__.py @@ -1,2 +1,3 @@ # This file is auto-generated by oagen. Do not edit. +from workos.vault.models import * # noqa: F401,F403 diff --git a/src/workos/user_management/__init__.py b/src/workos/user_management/__init__.py index 9d50739d..c90dd5a2 100644 --- a/src/workos/user_management/__init__.py +++ b/src/workos/user_management/__init__.py @@ -5,7 +5,5 @@ AsyncUserManagement as AsyncUserManagement, PasswordPlaintext as PasswordPlaintext, PasswordHashed as PasswordHashed, - RoleSingle as RoleSingle, - RoleMultiple as RoleMultiple, ) from .models import * diff --git a/src/workos/user_management/_resource.py b/src/workos/user_management/_resource.py index c9fbd8fb..56067646 100644 --- a/src/workos/user_management/_resource.py +++ b/src/workos/user_management/_resource.py @@ -21,7 +21,6 @@ JWTTemplateResponse, JwksResponse, MagicAuth, - OrganizationMembership, PasswordReset, PasswordSessionAuthenticateRequest, RedirectUri, @@ -37,7 +36,6 @@ UserApiKeyWithValue, UserIdentitiesGetItem, UserInvite, - UserOrganizationMembership, VerifyEmailResponse, ) from workos.common.models.user import User @@ -45,7 +43,6 @@ from .models import ( UserManagementAuthenticationProvider, UserManagementAuthenticationScreenHint, - UserManagementOrganizationMembershipStatuses, ) from workos.common.models.create_user_invite_options_locale import ( CreateUserInviteOptionsLocale, @@ -82,20 +79,6 @@ class PasswordHashed: password_hash_type: Union[CreateUserPasswordHashType, str] -@dataclass -class RoleSingle: - """Identify role single.""" - - role_slug: str - - -@dataclass -class RoleMultiple: - """Identify role multiple.""" - - role_slugs: List[str] - - class UserManagement: """User Management API resources.""" @@ -1725,286 +1708,6 @@ def get_magic_auth( request_options=request_options, ) - def list_organization_memberships( - self, - *, - limit: Optional[int] = None, - before: Optional[str] = None, - after: Optional[str] = None, - order: Optional[Union[PaginationOrder, str]] = "desc", - organization_id: Optional[str] = None, - statuses: Optional[ - List[Union[UserManagementOrganizationMembershipStatuses, str]] - ] = None, - user_id: Optional[str] = None, - request_options: Optional[RequestOptions] = None, - ) -> SyncPage[UserOrganizationMembership]: - """List organization memberships - - Get a list of all organization memberships matching the criteria specified. At least one of `user_id` or `organization_id` must be provided. By default only active memberships are returned. Use the `statuses` parameter to filter by other statuses. - - Args: - limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`. - before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. - after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. - order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to descending. Defaults to `desc`. - organization_id: The ID of the [organization](https://workos.com/docs/reference/organization) which the user belongs to. - statuses: Filter by the status of the organization membership. Array including any of `active`, `inactive`, or `pending`. - user_id: The ID of the [user](https://workos.com/docs/reference/authkit/user). - request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. - - Returns: - SyncPage[UserOrganizationMembership] - - Raises: - BadRequestError: If the request is malformed (400). - NotFoundError: If the resource is not found (404). - UnprocessableEntityError: If the request data is unprocessable (422). - AuthenticationError: If the API key is invalid (401). - RateLimitExceededError: If rate limited (429). - ServerError: If the server returns a 5xx error. - """ - params = { - k: v - for k, v in { - "limit": limit, - "before": before, - "after": after, - "order": enum_value(order) if order is not None else None, - "organization_id": organization_id, - "statuses": ",".join(str(v) for v in statuses) - if statuses is not None - else None, - "user_id": user_id, - }.items() - if v is not None - } - return self._client.request_page( - method="get", - path=("user_management", "organization_memberships"), - model=UserOrganizationMembership, - params=params, - request_options=request_options, - ) - - def create_organization_membership( - self, - *, - user_id: str, - organization_id: str, - role: Optional[Union[RoleSingle, RoleMultiple]] = None, - request_options: Optional[RequestOptions] = None, - ) -> OrganizationMembership: - """Create an organization membership - - Creates a new `active` organization membership for the given organization and user. - - Calling this API with an organization and user that match an `inactive` organization membership will activate the membership with the specified role(s). - - Args: - user_id: The ID of the [user](https://workos.com/docs/reference/authkit/user). - organization_id: The ID of the [organization](https://workos.com/docs/reference/organization) which the user belongs to. - role: Identifies the role. One of: RoleSingle, RoleMultiple. - request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. - - Returns: - OrganizationMembership - - Raises: - BadRequestError: If the request is malformed (400). - NotFoundError: If the resource is not found (404). - UnprocessableEntityError: If the request data is unprocessable (422). - AuthenticationError: If the API key is invalid (401). - RateLimitExceededError: If rate limited (429). - ServerError: If the server returns a 5xx error. - """ - body: Dict[str, Any] = { - "user_id": user_id, - "organization_id": organization_id, - } - if role is not None: - if isinstance(role, RoleSingle): - body["role_slug"] = role.role_slug - elif isinstance(role, RoleMultiple): - body["role_slugs"] = role.role_slugs - return self._client.request( - method="post", - path=("user_management", "organization_memberships"), - body=body, - model=OrganizationMembership, - request_options=request_options, - ) - - def get_organization_membership( - self, - id: str, - *, - request_options: Optional[RequestOptions] = None, - ) -> UserOrganizationMembership: - """Get an organization membership - - Get the details of an existing organization membership. - - Args: - id: The unique ID of the organization membership. - request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. - - Returns: - UserOrganizationMembership - - Raises: - NotFoundError: If the resource is not found (404). - AuthenticationError: If the API key is invalid (401). - RateLimitExceededError: If rate limited (429). - ServerError: If the server returns a 5xx error. - """ - return self._client.request( - method="get", - path=("user_management", "organization_memberships", str(id)), - model=UserOrganizationMembership, - request_options=request_options, - ) - - def update_organization_membership( - self, - id: str, - *, - role: Optional[Union[RoleSingle, RoleMultiple]] = None, - request_options: Optional[RequestOptions] = None, - ) -> UserOrganizationMembership: - """Update an organization membership - - Update the details of an existing organization membership. - - Args: - id: The unique ID of the organization membership. - role: Identifies the role. One of: RoleSingle, RoleMultiple. - request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. - - Returns: - UserOrganizationMembership - - Raises: - NotFoundError: If the resource is not found (404). - UnprocessableEntityError: If the request data is unprocessable (422). - AuthenticationError: If the API key is invalid (401). - RateLimitExceededError: If rate limited (429). - ServerError: If the server returns a 5xx error. - """ - body: Dict[str, Any] = {} - if role is not None: - if isinstance(role, RoleSingle): - body["role_slug"] = role.role_slug - elif isinstance(role, RoleMultiple): - body["role_slugs"] = role.role_slugs - return self._client.request( - method="put", - path=("user_management", "organization_memberships", str(id)), - body=body, - model=UserOrganizationMembership, - request_options=request_options, - ) - - def delete_organization_membership( - self, - id: str, - *, - request_options: Optional[RequestOptions] = None, - ) -> None: - """Delete an organization membership - - Permanently deletes an existing organization membership. It cannot be undone. - - Args: - id: The unique ID of the organization membership. - request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. - - Raises: - NotFoundError: If the resource is not found (404). - AuthenticationError: If the API key is invalid (401). - RateLimitExceededError: If rate limited (429). - ServerError: If the server returns a 5xx error. - """ - self._client.request( - method="delete", - path=("user_management", "organization_memberships", str(id)), - request_options=request_options, - ) - - def deactivate_organization_membership( - self, - id: str, - *, - request_options: Optional[RequestOptions] = None, - ) -> OrganizationMembership: - """Deactivate an organization membership - - Deactivates an `active` organization membership. Emits an [organization_membership.updated](https://workos.com/docs/events/organization-membership) event upon successful deactivation. - - - Deactivating an `inactive` membership is a no-op and does not emit an event. - - Deactivating a `pending` membership returns an error. This membership should be [deleted](https://workos.com/docs/reference/authkit/organization-membership/delete) instead. - - See the [membership management documentation](https://workos.com/docs/authkit/users-organizations/organizations/membership-management) for additional details. - - Args: - id: The unique ID of the organization membership. - request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. - - Returns: - OrganizationMembership - - Raises: - BadRequestError: If the request is malformed (400). - NotFoundError: If the resource is not found (404). - UnprocessableEntityError: If the request data is unprocessable (422). - AuthenticationError: If the API key is invalid (401). - RateLimitExceededError: If rate limited (429). - ServerError: If the server returns a 5xx error. - """ - return self._client.request( - method="put", - path=("user_management", "organization_memberships", str(id), "deactivate"), - model=OrganizationMembership, - request_options=request_options, - ) - - def reactivate_organization_membership( - self, - id: str, - *, - request_options: Optional[RequestOptions] = None, - ) -> UserOrganizationMembership: - """Reactivate an organization membership - - Reactivates an `inactive` organization membership, retaining the pre-existing role(s). Emits an [organization_membership.updated](https://workos.com/docs/events/organization-membership) event upon successful reactivation. - - - Reactivating an `active` membership is a no-op and does not emit an event. - - Reactivating a `pending` membership returns an error. The user needs to [accept the invitation](https://workos.com/docs/authkit/invitations) instead. - - See the [membership management documentation](https://workos.com/docs/authkit/users-organizations/organizations/membership-management) for additional details. - - Args: - id: The unique ID of the organization membership. - request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. - - Returns: - UserOrganizationMembership - - Raises: - BadRequestError: If the request is malformed (400). - NotFoundError: If the resource is not found (404). - UnprocessableEntityError: If the request data is unprocessable (422). - AuthenticationError: If the API key is invalid (401). - RateLimitExceededError: If rate limited (429). - ServerError: If the server returns a 5xx error. - """ - return self._client.request( - method="put", - path=("user_management", "organization_memberships", str(id), "reactivate"), - model=UserOrganizationMembership, - request_options=request_options, - ) - def create_redirect_uri( self, *, @@ -2183,6 +1886,7 @@ def create_user_api_key( name: str, organization_id: str, permissions: Optional[List[str]] = None, + expires_at: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> UserApiKeyWithValue: """Create an API key for a user @@ -2194,6 +1898,7 @@ def create_user_api_key( name: A descriptive name for the API key. organization_id: The ID of the organization the user API key is associated with. The user must have an active membership in this organization. permissions: The permission slugs to assign to the API key. Each permission must be enabled for user API keys. + expires_at: The timestamp when the API key should expire. Must be a future timestamp. If omitted, the key does not expire. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: @@ -2213,6 +1918,7 @@ def create_user_api_key( "name": name, "organization_id": organization_id, "permissions": permissions, + "expires_at": expires_at, }.items() if v is not None } @@ -4039,286 +3745,6 @@ async def get_magic_auth( request_options=request_options, ) - async def list_organization_memberships( - self, - *, - limit: Optional[int] = None, - before: Optional[str] = None, - after: Optional[str] = None, - order: Optional[Union[PaginationOrder, str]] = "desc", - organization_id: Optional[str] = None, - statuses: Optional[ - List[Union[UserManagementOrganizationMembershipStatuses, str]] - ] = None, - user_id: Optional[str] = None, - request_options: Optional[RequestOptions] = None, - ) -> AsyncPage[UserOrganizationMembership]: - """List organization memberships - - Get a list of all organization memberships matching the criteria specified. At least one of `user_id` or `organization_id` must be provided. By default only active memberships are returned. Use the `statuses` parameter to filter by other statuses. - - Args: - limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`. - before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. - after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. - order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to descending. Defaults to `desc`. - organization_id: The ID of the [organization](https://workos.com/docs/reference/organization) which the user belongs to. - statuses: Filter by the status of the organization membership. Array including any of `active`, `inactive`, or `pending`. - user_id: The ID of the [user](https://workos.com/docs/reference/authkit/user). - request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. - - Returns: - AsyncPage[UserOrganizationMembership] - - Raises: - BadRequestError: If the request is malformed (400). - NotFoundError: If the resource is not found (404). - UnprocessableEntityError: If the request data is unprocessable (422). - AuthenticationError: If the API key is invalid (401). - RateLimitExceededError: If rate limited (429). - ServerError: If the server returns a 5xx error. - """ - params = { - k: v - for k, v in { - "limit": limit, - "before": before, - "after": after, - "order": enum_value(order) if order is not None else None, - "organization_id": organization_id, - "statuses": ",".join(str(v) for v in statuses) - if statuses is not None - else None, - "user_id": user_id, - }.items() - if v is not None - } - return await self._client.request_page( - method="get", - path=("user_management", "organization_memberships"), - model=UserOrganizationMembership, - params=params, - request_options=request_options, - ) - - async def create_organization_membership( - self, - *, - user_id: str, - organization_id: str, - role: Optional[Union[RoleSingle, RoleMultiple]] = None, - request_options: Optional[RequestOptions] = None, - ) -> OrganizationMembership: - """Create an organization membership - - Creates a new `active` organization membership for the given organization and user. - - Calling this API with an organization and user that match an `inactive` organization membership will activate the membership with the specified role(s). - - Args: - user_id: The ID of the [user](https://workos.com/docs/reference/authkit/user). - organization_id: The ID of the [organization](https://workos.com/docs/reference/organization) which the user belongs to. - role: Identifies the role. One of: RoleSingle, RoleMultiple. - request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. - - Returns: - OrganizationMembership - - Raises: - BadRequestError: If the request is malformed (400). - NotFoundError: If the resource is not found (404). - UnprocessableEntityError: If the request data is unprocessable (422). - AuthenticationError: If the API key is invalid (401). - RateLimitExceededError: If rate limited (429). - ServerError: If the server returns a 5xx error. - """ - body: Dict[str, Any] = { - "user_id": user_id, - "organization_id": organization_id, - } - if role is not None: - if isinstance(role, RoleSingle): - body["role_slug"] = role.role_slug - elif isinstance(role, RoleMultiple): - body["role_slugs"] = role.role_slugs - return await self._client.request( - method="post", - path=("user_management", "organization_memberships"), - body=body, - model=OrganizationMembership, - request_options=request_options, - ) - - async def get_organization_membership( - self, - id: str, - *, - request_options: Optional[RequestOptions] = None, - ) -> UserOrganizationMembership: - """Get an organization membership - - Get the details of an existing organization membership. - - Args: - id: The unique ID of the organization membership. - request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. - - Returns: - UserOrganizationMembership - - Raises: - NotFoundError: If the resource is not found (404). - AuthenticationError: If the API key is invalid (401). - RateLimitExceededError: If rate limited (429). - ServerError: If the server returns a 5xx error. - """ - return await self._client.request( - method="get", - path=("user_management", "organization_memberships", str(id)), - model=UserOrganizationMembership, - request_options=request_options, - ) - - async def update_organization_membership( - self, - id: str, - *, - role: Optional[Union[RoleSingle, RoleMultiple]] = None, - request_options: Optional[RequestOptions] = None, - ) -> UserOrganizationMembership: - """Update an organization membership - - Update the details of an existing organization membership. - - Args: - id: The unique ID of the organization membership. - role: Identifies the role. One of: RoleSingle, RoleMultiple. - request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. - - Returns: - UserOrganizationMembership - - Raises: - NotFoundError: If the resource is not found (404). - UnprocessableEntityError: If the request data is unprocessable (422). - AuthenticationError: If the API key is invalid (401). - RateLimitExceededError: If rate limited (429). - ServerError: If the server returns a 5xx error. - """ - body: Dict[str, Any] = {} - if role is not None: - if isinstance(role, RoleSingle): - body["role_slug"] = role.role_slug - elif isinstance(role, RoleMultiple): - body["role_slugs"] = role.role_slugs - return await self._client.request( - method="put", - path=("user_management", "organization_memberships", str(id)), - body=body, - model=UserOrganizationMembership, - request_options=request_options, - ) - - async def delete_organization_membership( - self, - id: str, - *, - request_options: Optional[RequestOptions] = None, - ) -> None: - """Delete an organization membership - - Permanently deletes an existing organization membership. It cannot be undone. - - Args: - id: The unique ID of the organization membership. - request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. - - Raises: - NotFoundError: If the resource is not found (404). - AuthenticationError: If the API key is invalid (401). - RateLimitExceededError: If rate limited (429). - ServerError: If the server returns a 5xx error. - """ - await self._client.request( - method="delete", - path=("user_management", "organization_memberships", str(id)), - request_options=request_options, - ) - - async def deactivate_organization_membership( - self, - id: str, - *, - request_options: Optional[RequestOptions] = None, - ) -> OrganizationMembership: - """Deactivate an organization membership - - Deactivates an `active` organization membership. Emits an [organization_membership.updated](https://workos.com/docs/events/organization-membership) event upon successful deactivation. - - - Deactivating an `inactive` membership is a no-op and does not emit an event. - - Deactivating a `pending` membership returns an error. This membership should be [deleted](https://workos.com/docs/reference/authkit/organization-membership/delete) instead. - - See the [membership management documentation](https://workos.com/docs/authkit/users-organizations/organizations/membership-management) for additional details. - - Args: - id: The unique ID of the organization membership. - request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. - - Returns: - OrganizationMembership - - Raises: - BadRequestError: If the request is malformed (400). - NotFoundError: If the resource is not found (404). - UnprocessableEntityError: If the request data is unprocessable (422). - AuthenticationError: If the API key is invalid (401). - RateLimitExceededError: If rate limited (429). - ServerError: If the server returns a 5xx error. - """ - return await self._client.request( - method="put", - path=("user_management", "organization_memberships", str(id), "deactivate"), - model=OrganizationMembership, - request_options=request_options, - ) - - async def reactivate_organization_membership( - self, - id: str, - *, - request_options: Optional[RequestOptions] = None, - ) -> UserOrganizationMembership: - """Reactivate an organization membership - - Reactivates an `inactive` organization membership, retaining the pre-existing role(s). Emits an [organization_membership.updated](https://workos.com/docs/events/organization-membership) event upon successful reactivation. - - - Reactivating an `active` membership is a no-op and does not emit an event. - - Reactivating a `pending` membership returns an error. The user needs to [accept the invitation](https://workos.com/docs/authkit/invitations) instead. - - See the [membership management documentation](https://workos.com/docs/authkit/users-organizations/organizations/membership-management) for additional details. - - Args: - id: The unique ID of the organization membership. - request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. - - Returns: - UserOrganizationMembership - - Raises: - BadRequestError: If the request is malformed (400). - NotFoundError: If the resource is not found (404). - UnprocessableEntityError: If the request data is unprocessable (422). - AuthenticationError: If the API key is invalid (401). - RateLimitExceededError: If rate limited (429). - ServerError: If the server returns a 5xx error. - """ - return await self._client.request( - method="put", - path=("user_management", "organization_memberships", str(id), "reactivate"), - model=UserOrganizationMembership, - request_options=request_options, - ) - async def create_redirect_uri( self, *, @@ -4497,6 +3923,7 @@ async def create_user_api_key( name: str, organization_id: str, permissions: Optional[List[str]] = None, + expires_at: Optional[str] = None, request_options: Optional[RequestOptions] = None, ) -> UserApiKeyWithValue: """Create an API key for a user @@ -4508,6 +3935,7 @@ async def create_user_api_key( name: A descriptive name for the API key. organization_id: The ID of the organization the user API key is associated with. The user must have an active membership in this organization. permissions: The permission slugs to assign to the API key. Each permission must be enabled for user API keys. + expires_at: The timestamp when the API key should expire. Must be a future timestamp. If omitted, the key does not expire. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: @@ -4527,6 +3955,7 @@ async def create_user_api_key( "name": name, "organization_id": organization_id, "permissions": permissions, + "expires_at": expires_at, }.items() if v is not None } diff --git a/src/workos/user_management/models/__init__.py b/src/workos/user_management/models/__init__.py index d36fa02d..894c261c 100644 --- a/src/workos/user_management/models/__init__.py +++ b/src/workos/user_management/models/__init__.py @@ -29,9 +29,6 @@ from .create_user_invite_options import ( CreateUserInviteOptions as CreateUserInviteOptions, ) -from .create_user_organization_membership import ( - CreateUserOrganizationMembership as CreateUserOrganizationMembership, -) from .device_authorization_response import ( DeviceAuthorizationResponse as DeviceAuthorizationResponse, ) @@ -48,7 +45,6 @@ from .jwks_response_keys import JwksResponseKeys as JwksResponseKeys from .jwt_template_response import JWTTemplateResponse as JWTTemplateResponse from .magic_auth import MagicAuth as MagicAuth -from .organization_membership import OrganizationMembership as OrganizationMembership from .password_reset import PasswordReset as PasswordReset from .password_session_authenticate_request import ( PasswordSessionAuthenticateRequest as PasswordSessionAuthenticateRequest, @@ -71,9 +67,6 @@ ) from .update_jwt_template import UpdateJWTTemplate as UpdateJWTTemplate from .update_user import UpdateUser as UpdateUser -from .update_user_organization_membership import ( - UpdateUserOrganizationMembership as UpdateUserOrganizationMembership, -) from .device_code_session_authenticate_request import ( DeviceCodeSessionAuthenticateRequest as DeviceCodeSessionAuthenticateRequest, ) @@ -104,12 +97,6 @@ from .user_management_authentication_screen_hint import ( UserManagementAuthenticationScreenHint as UserManagementAuthenticationScreenHint, ) -from .user_management_organization_membership_statuses import ( - UserManagementOrganizationMembershipStatuses as UserManagementOrganizationMembershipStatuses, -) -from .user_organization_membership import ( - UserOrganizationMembership as UserOrganizationMembership, -) from workos.common.models.user_sessions_impersonator import ( UserSessionsImpersonator as UserSessionsImpersonator, ) diff --git a/src/workos/user_management/models/authorized_connect_application_list_data.py b/src/workos/user_management/models/authorized_connect_application_list_data.py index e6c4e35c..bfb44d31 100644 --- a/src/workos/user_management/models/authorized_connect_application_list_data.py +++ b/src/workos/user_management/models/authorized_connect_application_list_data.py @@ -7,7 +7,10 @@ from typing import Any, Dict, List, Literal, Optional from workos._types import _raise_deserialize_error -from workos.common.models.connect_application import ConnectApplication +from workos.common.models.connect_application import ( + ConnectApplication, + ConnectApplicationVariant, +) @dataclass(slots=True) @@ -20,7 +23,7 @@ class AuthorizedConnectApplicationListData: """The unique ID of the authorized connect application.""" granted_scopes: List[str] """The scopes granted by the user to the application.""" - application: "ConnectApplication" + application: "ConnectApplicationVariant" oauth_resource: Optional[str] = None """The OAuth resource associated with the authorized connect application, if one was requested.""" diff --git a/src/workos/user_management/models/create_user_api_key.py b/src/workos/user_management/models/create_user_api_key.py index 1dfcb28d..6cecf59a 100644 --- a/src/workos/user_management/models/create_user_api_key.py +++ b/src/workos/user_management/models/create_user_api_key.py @@ -3,8 +3,10 @@ from __future__ import annotations from dataclasses import dataclass +from datetime import datetime from typing import Any, Dict, List, Optional from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime @dataclass(slots=True) @@ -17,6 +19,8 @@ class CreateUserApiKey: """The ID of the organization the user API key is associated with. The user must have an active membership in this organization.""" permissions: Optional[List[str]] = None """The permission slugs to assign to the API key. Each permission must be enabled for user API keys.""" + expires_at: Optional[datetime] = None + """The timestamp when the API key should expire. Must be a future timestamp. If omitted, the key does not expire.""" @classmethod def from_dict(cls, data: Dict[str, Any]) -> "CreateUserApiKey": @@ -26,6 +30,9 @@ def from_dict(cls, data: Dict[str, Any]) -> "CreateUserApiKey": name=data["name"], organization_id=data["organization_id"], permissions=data.get("permissions"), + expires_at=_parse_datetime(_v_expires_at) + if (_v_expires_at := data.get("expires_at")) is not None + else None, ) except (KeyError, ValueError) as e: _raise_deserialize_error("CreateUserApiKey", e) @@ -37,4 +44,6 @@ def to_dict(self) -> Dict[str, Any]: result["organization_id"] = self.organization_id if self.permissions is not None: result["permissions"] = self.permissions + if self.expires_at is not None: + result["expires_at"] = _format_datetime(self.expires_at) return result diff --git a/src/workos/user_management/models/user_api_key.py b/src/workos/user_management/models/user_api_key.py index a3fd779a..39308148 100644 --- a/src/workos/user_management/models/user_api_key.py +++ b/src/workos/user_management/models/user_api_key.py @@ -28,6 +28,8 @@ class UserApiKey: """An obfuscated representation of the API Key value.""" last_used_at: Optional[datetime] """Timestamp of when the API Key was last used.""" + expires_at: Optional[datetime] + """Timestamp when the API Key expires. Null means the key does not expire.""" permissions: List[str] """The permission slugs assigned to the API Key.""" created_at: datetime @@ -48,6 +50,9 @@ def from_dict(cls, data: Dict[str, Any]) -> "UserApiKey": last_used_at=_parse_datetime(_v_last_used_at) if (_v_last_used_at := data["last_used_at"]) is not None else None, + expires_at=_parse_datetime(_v_expires_at) + if (_v_expires_at := data["expires_at"]) is not None + else None, permissions=data["permissions"], created_at=_parse_datetime(data["created_at"]), updated_at=_parse_datetime(data["updated_at"]), @@ -67,6 +72,10 @@ def to_dict(self) -> Dict[str, Any]: result["last_used_at"] = _format_datetime(self.last_used_at) else: result["last_used_at"] = None + if self.expires_at is not None: + result["expires_at"] = _format_datetime(self.expires_at) + else: + result["expires_at"] = None result["permissions"] = self.permissions result["created_at"] = _format_datetime(self.created_at) result["updated_at"] = _format_datetime(self.updated_at) diff --git a/src/workos/user_management/models/user_api_key_with_value.py b/src/workos/user_management/models/user_api_key_with_value.py index be464c3c..f565bfda 100644 --- a/src/workos/user_management/models/user_api_key_with_value.py +++ b/src/workos/user_management/models/user_api_key_with_value.py @@ -28,6 +28,8 @@ class UserApiKeyWithValue: """An obfuscated representation of the API Key value.""" last_used_at: Optional[datetime] """Timestamp of when the API Key was last used.""" + expires_at: Optional[datetime] + """Timestamp when the API Key expires. Null means the key does not expire.""" permissions: List[str] """The permission slugs assigned to the API Key.""" created_at: datetime @@ -52,6 +54,9 @@ def from_dict(cls, data: Dict[str, Any]) -> "UserApiKeyWithValue": last_used_at=_parse_datetime(_v_last_used_at) if (_v_last_used_at := data["last_used_at"]) is not None else None, + expires_at=_parse_datetime(_v_expires_at) + if (_v_expires_at := data["expires_at"]) is not None + else None, permissions=data["permissions"], created_at=_parse_datetime(data["created_at"]), updated_at=_parse_datetime(data["updated_at"]), @@ -72,6 +77,10 @@ def to_dict(self) -> Dict[str, Any]: result["last_used_at"] = _format_datetime(self.last_used_at) else: result["last_used_at"] = None + if self.expires_at is not None: + result["expires_at"] = _format_datetime(self.expires_at) + else: + result["expires_at"] = None result["permissions"] = self.permissions result["created_at"] = _format_datetime(self.created_at) result["updated_at"] = _format_datetime(self.updated_at) diff --git a/src/workos/user_management/models/user_management_authentication_screen_hint.py b/src/workos/user_management/models/user_management_authentication_screen_hint.py index 857f793a..4a0663b5 100644 --- a/src/workos/user_management/models/user_management_authentication_screen_hint.py +++ b/src/workos/user_management/models/user_management_authentication_screen_hint.py @@ -1,30 +1,21 @@ # This file is auto-generated by oagen. Do not edit. -"""Enumeration of user management authentication screen hint values.""" +from typing import TYPE_CHECKING -from __future__ import annotations +if TYPE_CHECKING: + from workos.common.models.radar_standalone_assess_request_action import ( + RadarStandaloneAssessRequestAction as UserManagementAuthenticationScreenHint, + ) +else: -from enum import Enum -from typing import Optional -from typing import Literal, TypeAlias + def __getattr__(name: str): + if name == "UserManagementAuthenticationScreenHint": + from workos.common.models.radar_standalone_assess_request_action import ( + RadarStandaloneAssessRequestAction, + ) + return RadarStandaloneAssessRequestAction + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") -class UserManagementAuthenticationScreenHint(str, Enum): - """Known values for UserManagementAuthenticationScreenHint.""" - SIGN_UP = "sign-up" - SIGN_IN = "sign-in" - - @classmethod - def _missing_( - cls, value: object - ) -> Optional["UserManagementAuthenticationScreenHint"]: - if not isinstance(value, str): - return None - unknown = str.__new__(cls, value) - unknown._name_ = value.upper() - unknown._value_ = value - return unknown - - -UserManagementAuthenticationScreenHintLiteral: TypeAlias = Literal["sign-up", "sign-in"] +__all__ = ["UserManagementAuthenticationScreenHint"] diff --git a/src/workos/user_management/models/user_management_organization_membership_statuses.py b/src/workos/user_management/models/user_management_organization_membership_statuses.py deleted file mode 100644 index 96e35b1f..00000000 --- a/src/workos/user_management/models/user_management_organization_membership_statuses.py +++ /dev/null @@ -1,11 +0,0 @@ -# This file is auto-generated by oagen. Do not edit. - -from typing import TypeAlias -from workos.common.models.organization_membership_created_data_status import ( - OrganizationMembershipCreatedDataStatus, -) - -UserManagementOrganizationMembershipStatuses: TypeAlias = ( - OrganizationMembershipCreatedDataStatus -) -__all__ = ["UserManagementOrganizationMembershipStatuses"] diff --git a/src/workos/user_management_organization_membership_groups/__init__.py b/src/workos/user_management_organization_membership_groups/__init__.py deleted file mode 100644 index b7bef0e9..00000000 --- a/src/workos/user_management_organization_membership_groups/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# This file is auto-generated by oagen. Do not edit. - -from ._resource import ( - UserManagementOrganizationMembershipGroups as UserManagementOrganizationMembershipGroups, - AsyncUserManagementOrganizationMembershipGroups as AsyncUserManagementOrganizationMembershipGroups, -) -from .models import * diff --git a/src/workos/user_management_organization_membership_groups/_resource.py b/src/workos/user_management_organization_membership_groups/_resource.py deleted file mode 100644 index 48fd4159..00000000 --- a/src/workos/user_management_organization_membership_groups/_resource.py +++ /dev/null @@ -1,125 +0,0 @@ -# This file is auto-generated by oagen. Do not edit. - -from __future__ import annotations - -from typing import TYPE_CHECKING, Optional, Union - -if TYPE_CHECKING: - from .._client import AsyncWorkOSClient, WorkOSClient - -from .._types import RequestOptions, enum_value -from workos.common.models.group import Group -from workos.common.models.pagination_order import PaginationOrder -from .._pagination import AsyncPage, SyncPage - - -class UserManagementOrganizationMembershipGroups: - """User Management Organization Membership Groups API resources.""" - - def __init__(self, client: "WorkOSClient") -> None: - self._client = client - - def list_organization_membership_groups( - self, - om_id: str, - *, - limit: Optional[int] = None, - before: Optional[str] = None, - after: Optional[str] = None, - order: Optional[Union[PaginationOrder, str]] = "desc", - request_options: Optional[RequestOptions] = None, - ) -> SyncPage[Group]: - """List groups - - Get a list of groups that an organization membership belongs to. - - Args: - om_id: Unique identifier of the Organization Membership. - limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`. - before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. - after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. - order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to descending. Defaults to `desc`. - request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. - - Returns: - SyncPage[Group] - - Raises: - NotFoundError: If the resource is not found (404). - AuthenticationError: If the API key is invalid (401). - RateLimitExceededError: If rate limited (429). - ServerError: If the server returns a 5xx error. - """ - params = { - k: v - for k, v in { - "limit": limit, - "before": before, - "after": after, - "order": enum_value(order) if order is not None else None, - }.items() - if v is not None - } - return self._client.request_page( - method="get", - path=("user_management", "organization_memberships", str(om_id), "groups"), - model=Group, - params=params, - request_options=request_options, - ) - - -class AsyncUserManagementOrganizationMembershipGroups: - """User Management Organization Membership Groups API resources (async).""" - - def __init__(self, client: "AsyncWorkOSClient") -> None: - self._client = client - - async def list_organization_membership_groups( - self, - om_id: str, - *, - limit: Optional[int] = None, - before: Optional[str] = None, - after: Optional[str] = None, - order: Optional[Union[PaginationOrder, str]] = "desc", - request_options: Optional[RequestOptions] = None, - ) -> AsyncPage[Group]: - """List groups - - Get a list of groups that an organization membership belongs to. - - Args: - om_id: Unique identifier of the Organization Membership. - limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`. - before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. - after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. - order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to descending. Defaults to `desc`. - request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. - - Returns: - AsyncPage[Group] - - Raises: - NotFoundError: If the resource is not found (404). - AuthenticationError: If the API key is invalid (401). - RateLimitExceededError: If rate limited (429). - ServerError: If the server returns a 5xx error. - """ - params = { - k: v - for k, v in { - "limit": limit, - "before": before, - "after": after, - "order": enum_value(order) if order is not None else None, - }.items() - if v is not None - } - return await self._client.request_page( - method="get", - path=("user_management", "organization_memberships", str(om_id), "groups"), - model=Group, - params=params, - request_options=request_options, - ) diff --git a/src/workos/vault.py b/src/workos/vault.py deleted file mode 100644 index 77f4058f..00000000 --- a/src/workos/vault.py +++ /dev/null @@ -1,682 +0,0 @@ -# @oagen-ignore-file -# This file is hand-maintained. The vault API endpoints are not yet in the -# OpenAPI spec, so this module provides the functionality until they are. -# The encrypt/decrypt methods use client-side AES-GCM and will always be -# hand-maintained regardless of spec coverage. - -from __future__ import annotations - -import base64 -import os -from dataclasses import dataclass -from typing import ( - TYPE_CHECKING, - Any, - Dict, - List, - Optional, - Sequence, - Tuple, -) - -from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes -from cryptography.hazmat.backends import default_backend - -if TYPE_CHECKING: - from ._client import AsyncWorkOSClient, WorkOSClient - -# --------------------------------------------------------------------------- -# Types -# --------------------------------------------------------------------------- - -KeyContext = Dict[str, str] - - -@dataclass(slots=True) -class DataKey: - """A plaintext data key used for local encryption operations.""" - - id: str - """The unique identifier for this data key.""" - key: str - """The base64-encoded plaintext key material.""" - - @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "DataKey": - return cls(id=data["id"], key=data["key"]) - - def to_dict(self) -> Dict[str, Any]: - return {"id": self.id, "key": self.key} - - -@dataclass(slots=True) -class DataKeyPair: - """A data key pair containing both the plaintext key and its encrypted form.""" - - context: KeyContext - """The key context used to generate this key pair.""" - data_key: DataKey - """The plaintext data key for local encryption.""" - encrypted_keys: str - """The encrypted form of the data key, for storage alongside ciphertext.""" - - @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "DataKeyPair": - return cls( - context=data["context"], - data_key=DataKey.from_dict(data["data_key"]), - encrypted_keys=data["encrypted_keys"], - ) - - def to_dict(self) -> Dict[str, Any]: - return { - "context": self.context, - "data_key": self.data_key.to_dict(), - "encrypted_keys": self.encrypted_keys, - } - - -@dataclass(slots=True) -class DecodedKeys: - """Decoded components of an encrypted payload.""" - - iv: bytes - """The initialization vector for AES-GCM decryption.""" - tag: bytes - """The authentication tag for AES-GCM verification.""" - keys: str - """Base64-encoded encrypted key material.""" - ciphertext: bytes - """The encrypted data.""" - - -@dataclass(slots=True) -class ObjectUpdateBy: - """The user or system that last updated a Vault object.""" - - id: str - """The unique identifier of the updater.""" - name: str - """The display name of the updater.""" - - @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "ObjectUpdateBy": - return cls(id=data["id"], name=data["name"]) - - def to_dict(self) -> Dict[str, Any]: - return {"id": self.id, "name": self.name} - - -@dataclass(slots=True) -class ObjectMetadata: - """Metadata for a Vault encrypted object, returned after create or update.""" - - context: KeyContext - """The key context associated with this object.""" - environment_id: str - """The WorkOS environment ID.""" - id: str - """The unique identifier of the Vault object.""" - key_id: str - """The encryption key ID used for this object.""" - updated_at: str - """ISO 8601 timestamp of the last update.""" - updated_by: ObjectUpdateBy - """The user or system that last updated this object.""" - version_id: str - """The version identifier for this object revision.""" - - @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "ObjectMetadata": - return cls( - context=data["context"], - environment_id=data["environment_id"], - id=data["id"], - key_id=data["key_id"], - updated_at=data["updated_at"], - updated_by=ObjectUpdateBy.from_dict(data["updated_by"]), - version_id=data["version_id"], - ) - - def to_dict(self) -> Dict[str, Any]: - return { - "context": self.context, - "environment_id": self.environment_id, - "id": self.id, - "key_id": self.key_id, - "updated_at": self.updated_at, - "updated_by": self.updated_by.to_dict(), - "version_id": self.version_id, - } - - -@dataclass(slots=True) -class VaultObject: - """A Vault encrypted object with its metadata and optionally decrypted value.""" - - id: str - """The unique identifier of the Vault object.""" - metadata: ObjectMetadata - """The object's metadata including key context and version info.""" - name: str - """The name of the Vault object.""" - value: Optional[str] = None - """The decrypted value, present only when explicitly requested.""" - - @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "VaultObject": - return cls( - id=data["id"], - metadata=ObjectMetadata.from_dict(data["metadata"]), - name=data["name"], - value=data.get("value"), - ) - - def to_dict(self) -> Dict[str, Any]: - result: Dict[str, Any] = { - "id": self.id, - "metadata": self.metadata.to_dict(), - "name": self.name, - } - if self.value is not None: - result["value"] = self.value - return result - - -@dataclass(slots=True) -class ObjectDigest: - """A summary of a Vault object returned in list operations.""" - - id: str - """The unique identifier of the Vault object.""" - name: str - """The name of the Vault object.""" - updated_at: str - """ISO 8601 timestamp of the last update.""" - - @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "ObjectDigest": - return cls(id=data["id"], name=data["name"], updated_at=data["updated_at"]) - - def to_dict(self) -> Dict[str, Any]: - return {"id": self.id, "name": self.name, "updated_at": self.updated_at} - - -@dataclass(slots=True) -class ObjectVersion: - """A version entry for a Vault object.""" - - created_at: str - """ISO 8601 timestamp when this version was created.""" - current_version: bool - """Whether this is the current (latest) version.""" - id: str - """The unique identifier of this version.""" - - @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "ObjectVersion": - return cls( - created_at=data["created_at"], - current_version=data["current_version"], - id=data["id"], - ) - - def to_dict(self) -> Dict[str, Any]: - return { - "created_at": self.created_at, - "current_version": self.current_version, - "id": self.id, - } - - -# --------------------------------------------------------------------------- -# Crypto helpers (AES-GCM, LEB128) -# --------------------------------------------------------------------------- - - -def _aes_gcm_encrypt( - plaintext: bytes, key: bytes, iv: bytes, aad: Optional[bytes] -) -> Dict[str, bytes]: - encryptor = Cipher( - algorithms.AES(key), modes.GCM(iv), backend=default_backend() - ).encryptor() - if aad: - encryptor.authenticate_additional_data(aad) - ciphertext = encryptor.update(plaintext) + encryptor.finalize() - return {"ciphertext": ciphertext, "iv": iv, "tag": encryptor.tag} - - -def _aes_gcm_decrypt( - ciphertext: bytes, - key: bytes, - iv: bytes, - tag: bytes, - aad: Optional[bytes] = None, -) -> bytes: - decryptor = Cipher( - algorithms.AES(key), modes.GCM(iv, tag), backend=default_backend() - ).decryptor() - if aad: - decryptor.authenticate_additional_data(aad) - return decryptor.update(ciphertext) + decryptor.finalize() - - -def _encode_u32_leb128(value: int) -> bytes: - """Encode a 32-bit unsigned integer as LEB128.""" - if value < 0 or value > 0xFFFFFFFF: - raise ValueError("Value must be a 32-bit unsigned integer") - encoded = bytearray() - while True: - byte = value & 0x7F - value >>= 7 - if value != 0: - byte |= 0x80 - encoded.append(byte) - if value == 0: - break - return bytes(encoded) - - -def _decode_u32_leb128(buf: bytes) -> Tuple[int, int]: - """Decode an unsigned LEB128-encoded 32-bit integer. Returns (value, bytes_consumed).""" - res = 0 - bit = 0 - for i, b in enumerate(buf): - if i >= 4 and (b & 0x80) != 0: - raise ValueError("LEB128 integer overflow (was more than 4 bytes)") - res |= (b & 0x7F) << (7 * bit) - if (b & 0x80) == 0: - if res > 0xFFFFFFFF: - raise ValueError("LEB128 integer overflow (exceeds 32 bits)") - return res, i + 1 - bit += 1 - raise ValueError("LEB128 integer not found") - - -def _decode_encrypted_payload(encrypted_data_b64: str) -> DecodedKeys: - """Extract IV, tag, keyBlobLength, keyBlob, and ciphertext from a base64 payload. - - Format: [IV:12b][TAG:16b][LEB128 Length][keyBlob][ciphertext] - """ - try: - payload = base64.b64decode(encrypted_data_b64) - except Exception as e: - raise ValueError("Base64 decoding failed") from e - - iv = payload[0:12] - tag = payload[12:28] - key_len, leb_len = _decode_u32_leb128(payload[28:]) - keys_index = 28 + leb_len - keys_end = keys_index + key_len - keys_slice = payload[keys_index:keys_end] - keys = base64.b64encode(keys_slice).decode("utf-8") - ciphertext = payload[keys_end:] - return DecodedKeys(iv=iv, tag=tag, keys=keys, ciphertext=ciphertext) - - -DEFAULT_RESPONSE_LIMIT = 10 - - -# --------------------------------------------------------------------------- -# Sync Vault -# --------------------------------------------------------------------------- - - -class Vault: - """WorkOS Vault service — encryption, key management, and secret storage.""" - - def __init__(self, client: "WorkOSClient") -> None: - self._client = client - - # -- KV operations -- - - def read_object(self, *, object_id: str) -> VaultObject: - """Get a Vault object with the value decrypted.""" - response = self._client.request( - method="get", - path=("vault", "v1", "kv", str(object_id)), - model=VaultObject, - ) - return response - - def read_object_by_name(self, *, name: str) -> VaultObject: - """Get a Vault object by name with the value decrypted.""" - response = self._client.request( - method="get", - path=("vault", "v1", "kv", "name", str(name)), - model=VaultObject, - ) - return response - - def get_object_metadata(self, *, object_id: str) -> VaultObject: - """Get a Vault object's metadata without decrypting the value.""" - response = self._client.request( - method="get", - path=("vault", "v1", "kv", str(object_id), "metadata"), - model=VaultObject, - ) - return response - - def list_objects( - self, - *, - limit: int = DEFAULT_RESPONSE_LIMIT, - before: Optional[str] = None, - after: Optional[str] = None, - ) -> Sequence[ObjectDigest]: - """Gets a list of encrypted Vault objects.""" - params: Dict[str, Any] = {"limit": limit} - if before is not None: - params["before"] = before - if after is not None: - params["after"] = after - - response = self._client.request_raw( - method="get", - path=("vault", "v1", "kv"), - params=params, - ) - data: List[Dict[str, Any]] = response.get("data", []) - return [ObjectDigest.from_dict(item) for item in data] - - def list_object_versions(self, *, object_id: str) -> Sequence[ObjectVersion]: - """Gets a list of versions for a specific Vault object.""" - response = self._client.request_raw( - method="get", - path=("vault", "v1", "kv", str(object_id), "versions"), - ) - data: List[Dict[str, Any]] = response.get("data", []) - return [ObjectVersion.from_dict(v) for v in data] - - def create_object( - self, - *, - name: str, - value: str, - key_context: KeyContext, - ) -> ObjectMetadata: - """Create a new Vault encrypted object.""" - response = self._client.request( - method="post", - path=("vault", "v1", "kv"), - body={"name": name, "value": value, "key_context": key_context}, - model=ObjectMetadata, - ) - return response - - def update_object( - self, - *, - object_id: str, - value: str, - version_check: Optional[str] = None, - ) -> VaultObject: - """Update an existing Vault object.""" - body: Dict[str, Any] = {"value": value} - if version_check is not None: - body["version_check"] = version_check - - response = self._client.request( - method="put", - path=("vault", "v1", "kv", str(object_id)), - body=body, - model=VaultObject, - ) - return response - - def delete_object(self, *, object_id: str) -> None: - """Permanently delete a Vault encrypted object.""" - self._client.request( - method="delete", - path=("vault", "v1", "kv", str(object_id)), - ) - - # -- Key operations -- - - def create_data_key(self, *, key_context: KeyContext) -> DataKeyPair: - """Generate a data key for local encryption.""" - response = self._client.request_raw( - method="post", - path=("vault", "v1", "keys", "data-key"), - body={"context": key_context}, - ) - return DataKeyPair( - context=response["context"], - data_key=DataKey(id=response["id"], key=response["data_key"]), - encrypted_keys=response["encrypted_keys"], - ) - - def decrypt_data_key(self, *, keys: str) -> DataKey: - """Decrypt encrypted data keys previously generated by create_data_key.""" - response = self._client.request_raw( - method="post", - path=("vault", "v1", "keys", "decrypt"), - body={"keys": keys}, - ) - return DataKey(id=response["id"], key=response["data_key"]) - - # -- Client-side encryption -- - - def encrypt( - self, - *, - data: str, - key_context: KeyContext, - associated_data: Optional[str] = None, - ) -> str: - """Encrypt data locally using AES-GCM with a data key derived from the context.""" - key_pair = self.create_data_key(key_context=key_context) - - key = base64.b64decode(key_pair.data_key.key) - key_blob = base64.b64decode(key_pair.encrypted_keys) - prefix_len_buffer = _encode_u32_leb128(len(key_blob)) - aad_buffer = associated_data.encode("utf-8") if associated_data else None - iv = os.urandom(12) - - result = _aes_gcm_encrypt(data.encode("utf-8"), key, iv, aad_buffer) - - combined = ( - result["iv"] - + result["tag"] - + prefix_len_buffer - + key_blob - + result["ciphertext"] - ) - return base64.b64encode(combined).decode("utf-8") - - def decrypt( - self, *, encrypted_data: str, associated_data: Optional[str] = None - ) -> str: - """Decrypt data that was previously encrypted using the encrypt method.""" - decoded = _decode_encrypted_payload(encrypted_data) - data_key = self.decrypt_data_key(keys=decoded.keys) - - key = base64.b64decode(data_key.key) - aad_buffer = associated_data.encode("utf-8") if associated_data else None - - decrypted_bytes = _aes_gcm_decrypt( - ciphertext=decoded.ciphertext, - key=key, - iv=decoded.iv, - tag=decoded.tag, - aad=aad_buffer, - ) - return decrypted_bytes.decode("utf-8") - - -# --------------------------------------------------------------------------- -# Async Vault -# --------------------------------------------------------------------------- - - -class AsyncVault: - """Async WorkOS Vault service.""" - - def __init__(self, client: "AsyncWorkOSClient") -> None: - self._client = client - - async def read_object(self, *, object_id: str) -> VaultObject: - """Get a Vault object with the value decrypted.""" - response = await self._client.request( - method="get", - path=("vault", "v1", "kv", str(object_id)), - model=VaultObject, - ) - return response - - async def read_object_by_name(self, *, name: str) -> VaultObject: - """Get a Vault object by name with the value decrypted.""" - response = await self._client.request( - method="get", - path=("vault", "v1", "kv", "name", str(name)), - model=VaultObject, - ) - return response - - async def get_object_metadata(self, *, object_id: str) -> VaultObject: - """Get a Vault object's metadata without decrypting the value.""" - response = await self._client.request( - method="get", - path=("vault", "v1", "kv", str(object_id), "metadata"), - model=VaultObject, - ) - return response - - async def list_objects( - self, - *, - limit: int = DEFAULT_RESPONSE_LIMIT, - before: Optional[str] = None, - after: Optional[str] = None, - ) -> Sequence[ObjectDigest]: - """Gets a list of encrypted Vault objects.""" - params: Dict[str, Any] = {"limit": limit} - if before is not None: - params["before"] = before - if after is not None: - params["after"] = after - response = await self._client.request_raw( - method="get", - path=("vault", "v1", "kv"), - params=params, - ) - data: List[Dict[str, Any]] = response.get("data", []) - return [ObjectDigest.from_dict(item) for item in data] - - async def list_object_versions(self, *, object_id: str) -> Sequence[ObjectVersion]: - """Gets a list of versions for a specific Vault object.""" - response = await self._client.request_raw( - method="get", - path=("vault", "v1", "kv", str(object_id), "versions"), - ) - data: List[Dict[str, Any]] = response.get("data", []) - return [ObjectVersion.from_dict(v) for v in data] - - async def create_object( - self, - *, - name: str, - value: str, - key_context: KeyContext, - ) -> ObjectMetadata: - """Create a new Vault encrypted object.""" - response = await self._client.request( - method="post", - path=("vault", "v1", "kv"), - body={"name": name, "value": value, "key_context": key_context}, - model=ObjectMetadata, - ) - return response - - async def update_object( - self, - *, - object_id: str, - value: str, - version_check: Optional[str] = None, - ) -> VaultObject: - """Update an existing Vault object.""" - body: Dict[str, Any] = {"value": value} - if version_check is not None: - body["version_check"] = version_check - response = await self._client.request( - method="put", - path=("vault", "v1", "kv", str(object_id)), - body=body, - model=VaultObject, - ) - return response - - async def delete_object(self, *, object_id: str) -> None: - """Permanently delete a Vault encrypted object.""" - await self._client.request( - method="delete", - path=("vault", "v1", "kv", str(object_id)), - ) - - async def create_data_key(self, *, key_context: KeyContext) -> DataKeyPair: - """Generate a data key for local encryption.""" - response = await self._client.request_raw( - method="post", - path=("vault", "v1", "keys", "data-key"), - body={"context": key_context}, - ) - return DataKeyPair( - context=response["context"], - data_key=DataKey(id=response["id"], key=response["data_key"]), - encrypted_keys=response["encrypted_keys"], - ) - - async def decrypt_data_key(self, *, keys: str) -> DataKey: - """Decrypt encrypted data keys previously generated by create_data_key.""" - response = await self._client.request_raw( - method="post", - path=("vault", "v1", "keys", "decrypt"), - body={"keys": keys}, - ) - return DataKey(id=response["id"], key=response["data_key"]) - - async def encrypt( - self, - *, - data: str, - key_context: KeyContext, - associated_data: Optional[str] = None, - ) -> str: - """Encrypt data locally using AES-GCM with a data key derived from the context.""" - key_pair = await self.create_data_key(key_context=key_context) - - key = base64.b64decode(key_pair.data_key.key) - key_blob = base64.b64decode(key_pair.encrypted_keys) - prefix_len_buffer = _encode_u32_leb128(len(key_blob)) - aad_buffer = associated_data.encode("utf-8") if associated_data else None - iv = os.urandom(12) - - result = _aes_gcm_encrypt(data.encode("utf-8"), key, iv, aad_buffer) - combined = ( - result["iv"] - + result["tag"] - + prefix_len_buffer - + key_blob - + result["ciphertext"] - ) - return base64.b64encode(combined).decode("utf-8") - - async def decrypt( - self, *, encrypted_data: str, associated_data: Optional[str] = None - ) -> str: - """Decrypt data that was previously encrypted using the encrypt method.""" - decoded = _decode_encrypted_payload(encrypted_data) - data_key = await self.decrypt_data_key(keys=decoded.keys) - - key = base64.b64decode(data_key.key) - aad_buffer = associated_data.encode("utf-8") if associated_data else None - - decrypted_bytes = _aes_gcm_decrypt( - ciphertext=decoded.ciphertext, - key=key, - iv=decoded.iv, - tag=decoded.tag, - aad=aad_buffer, - ) - return decrypted_bytes.decode("utf-8") diff --git a/src/workos/vault/__init__.py b/src/workos/vault/__init__.py new file mode 100644 index 00000000..0b4b579c --- /dev/null +++ b/src/workos/vault/__init__.py @@ -0,0 +1,4 @@ +# This file is auto-generated by oagen. Do not edit. + +from ._resource import Vault as Vault, AsyncVault as AsyncVault +from .models import * diff --git a/src/workos/vault/_resource.py b/src/workos/vault/_resource.py new file mode 100644 index 00000000..2c47d589 --- /dev/null +++ b/src/workos/vault/_resource.py @@ -0,0 +1,1043 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, Optional, Union + +if TYPE_CHECKING: + from .._client import AsyncWorkOSClient, WorkOSClient + +from .._types import RequestOptions, enum_value +from .models import ( + CreateDataKeyResponse, + DecryptResponse, + ObjectMetadata, + ObjectSummary, + ObjectWithoutValue, + VaultObject, + VersionListResponse, +) +from .models import VaultOrder +from .._pagination import AsyncPage, SyncPage + +# @oagen-ignore-start — client-side AES-GCM imports (hand-maintained) +import base64 +import os +from dataclasses import dataclass +from typing import Tuple + +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from cryptography.hazmat.backends import default_backend +# @oagen-ignore-end + +# @oagen-ignore-start — client-side AES-GCM helpers (hand-maintained) + + +@dataclass(slots=True) +class DecodedKeys: + iv: bytes + tag: bytes + keys: str + ciphertext: bytes + + +def _aes_gcm_encrypt( + plaintext: bytes, key: bytes, iv: bytes, aad: Optional[bytes] +) -> Dict[str, bytes]: + encryptor = Cipher( + algorithms.AES(key), modes.GCM(iv), backend=default_backend() + ).encryptor() + if aad: + encryptor.authenticate_additional_data(aad) + ciphertext = encryptor.update(plaintext) + encryptor.finalize() + return {"ciphertext": ciphertext, "iv": iv, "tag": encryptor.tag} + + +def _aes_gcm_decrypt( + ciphertext: bytes, + key: bytes, + iv: bytes, + tag: bytes, + aad: Optional[bytes] = None, +) -> bytes: + decryptor = Cipher( + algorithms.AES(key), modes.GCM(iv, tag), backend=default_backend() + ).decryptor() + if aad: + decryptor.authenticate_additional_data(aad) + return decryptor.update(ciphertext) + decryptor.finalize() + + +def _encode_u32_leb128(value: int) -> bytes: + if value < 0 or value > 0xFFFFFFFF: + raise ValueError("Value must be a 32-bit unsigned integer") + encoded = bytearray() + while True: + byte = value & 0x7F + value >>= 7 + if value != 0: + byte |= 0x80 + encoded.append(byte) + if value == 0: + break + return bytes(encoded) + + +def _decode_u32_leb128(buf: bytes) -> Tuple[int, int]: + res = 0 + bit = 0 + for i, b in enumerate(buf): + if i >= 4 and (b & 0x80) != 0: + raise ValueError("LEB128 integer overflow (was more than 4 bytes)") + res |= (b & 0x7F) << (7 * bit) + if (b & 0x80) == 0: + if res > 0xFFFFFFFF: + raise ValueError("LEB128 integer overflow (exceeds 32 bits)") + return res, i + 1 + bit += 1 + raise ValueError("LEB128 integer not found") + + +def _decode_encrypted_payload(encrypted_data_b64: str) -> DecodedKeys: + try: + payload = base64.b64decode(encrypted_data_b64) + except Exception as e: + raise ValueError("Base64 decoding failed") from e + + iv = payload[0:12] + tag = payload[12:28] + key_len, leb_len = _decode_u32_leb128(payload[28:]) + keys_index = 28 + leb_len + keys_end = keys_index + key_len + keys_slice = payload[keys_index:keys_end] + keys = base64.b64encode(keys_slice).decode("utf-8") + ciphertext = payload[keys_end:] + return DecodedKeys(iv=iv, tag=tag, keys=keys, ciphertext=ciphertext) + + +# @oagen-ignore-end +class Vault: + """Vault API resources.""" + + def __init__(self, client: "WorkOSClient") -> None: + self._client = client + + def create_data_key( + self, + *, + context: Dict[str, str], + request_options: Optional[RequestOptions] = None, + ) -> CreateDataKeyResponse: + """Create a data key + + Generate an isolated encryption key for local encryption operations. + + Args: + context: Map of values used to determine the encryption key. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + CreateDataKeyResponse + + Raises: + BadRequestError: If the request is malformed (400). + UnprocessableEntityError: If the request data is unprocessable (422). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + body: Dict[str, Any] = { + "context": context, + } + return self._client.request( + method="post", + path=("vault", "v1", "keys", "data-key"), + body=body, + model=CreateDataKeyResponse, + request_options=request_options, + ) + + def create_decrypt( + self, + *, + keys: str, + request_options: Optional[RequestOptions] = None, + ) -> DecryptResponse: + """Decrypt a data key + + Decrypt a previously encrypted data key from WorkOS Vault. + + Args: + keys: Base64-encoded encrypted data key to decrypt. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + DecryptResponse + + Raises: + BadRequestError: If the request is malformed (400). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + body: Dict[str, Any] = { + "keys": keys, + } + return self._client.request( + method="post", + path=("vault", "v1", "keys", "decrypt"), + body=body, + model=DecryptResponse, + request_options=request_options, + ) + + def create_rekey( + self, + *, + context: Dict[str, str], + encrypted_keys: str, + request_options: Optional[RequestOptions] = None, + ) -> CreateDataKeyResponse: + """Re-encrypt a data key + + Decrypt an existing data key and re-encrypt it under a new key context. + + Args: + context: Map of values used to determine the new encryption key. + encrypted_keys: Base64-encoded encrypted data key blob to re-encrypt. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + CreateDataKeyResponse + + Raises: + BadRequestError: If the request is malformed (400). + UnprocessableEntityError: If the request data is unprocessable (422). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + body: Dict[str, Any] = { + "context": context, + "encrypted_keys": encrypted_keys, + } + return self._client.request( + method="post", + path=("vault", "v1", "keys", "rekey"), + body=body, + model=CreateDataKeyResponse, + request_options=request_options, + ) + + def list_kv( + self, + *, + limit: Optional[int] = None, + before: Optional[str] = None, + after: Optional[str] = None, + order: Optional[Union[VaultOrder, str]] = None, + search: Optional[str] = None, + updated_after: Optional[str] = None, + request_options: Optional[RequestOptions] = None, + ) -> SyncPage[ObjectSummary]: + """List objects + + List all encrypted objects with cursor-based pagination. + + Args: + limit: Upper limit on the number of objects to return. Defaults to `10`. + before: Cursor for the previous page of results. + after: Cursor for the next page of results. + order: Sort direction for results. + search: Filter results by name or structured search JSON. + updated_after: ISO 8601 timestamp to filter by last modified time. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + SyncPage[ObjectSummary] + + Raises: + BadRequestError: If the request is malformed (400). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + params = { + k: v + for k, v in { + "limit": limit, + "before": before, + "after": after, + "order": enum_value(order) if order is not None else None, + "search": search, + "updatedAfter": updated_after, + }.items() + if v is not None + } + return self._client.request_page( + method="get", + path=("vault", "v1", "kv"), + model=ObjectSummary, + params=params, + request_options=request_options, + ) + + def create_kv( + self, + *, + key_context: Dict[str, str], + name: str, + value: str, + request_options: Optional[RequestOptions] = None, + ) -> ObjectMetadata: + """Create an object + + Encrypt and store a new key-value object. + + Args: + key_context: Map of values used to determine the encryption key. + name: Unique name for the object. + value: Plaintext data to encrypt and store. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + ObjectMetadata + + Raises: + BadRequestError: If the request is malformed (400). + ConflictError: If a conflict occurs (409). + UnprocessableEntityError: If the request data is unprocessable (422). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + body: Dict[str, Any] = { + "key_context": key_context, + "name": name, + "value": value, + } + return self._client.request( + method="post", + path=("vault", "v1", "kv"), + body=body, + model=ObjectMetadata, + request_options=request_options, + ) + + def get_name( + self, + name: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> VaultObject: + """Read an object by name + + Fetch and decrypt an object by its unique name. + + Args: + name: Unique name of the object. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + VaultObject + + Raises: + BadRequestError: If the request is malformed (400). + NotFoundError: If the resource is not found (404). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + return self._client.request( + method="get", + path=("vault", "v1", "kv", "name", str(name)), + model=VaultObject, + request_options=request_options, + ) + + def get_kv( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> VaultObject: + """Read an object by ID + + Fetch and decrypt an object by its unique identifier. + + Args: + id: Unique identifier of the object. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + VaultObject + + Raises: + BadRequestError: If the request is malformed (400). + NotFoundError: If the resource is not found (404). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + return self._client.request( + method="get", + path=("vault", "v1", "kv", str(id)), + model=VaultObject, + request_options=request_options, + ) + + def update_kv( + self, + id: str, + *, + value: str, + version_check: Optional[str] = None, + request_options: Optional[RequestOptions] = None, + ) -> ObjectWithoutValue: + """Update an object + + Update the value of an existing encrypted object. + + Args: + id: Unique identifier of the object. + value: New plaintext value. + version_check: ID of the expected current version for optimistic locking. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + ObjectWithoutValue + + Raises: + BadRequestError: If the request is malformed (400). + ConflictError: If a conflict occurs (409). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + body: Dict[str, Any] = { + k: v + for k, v in { + "value": value, + "version_check": version_check, + }.items() + if v is not None + } + return self._client.request( + method="put", + path=("vault", "v1", "kv", str(id)), + body=body, + model=ObjectWithoutValue, + request_options=request_options, + ) + + def delete_kv( + self, + id: str, + *, + version_check: Optional[str] = None, + request_options: Optional[RequestOptions] = None, + ) -> None: + """Delete an object + + Delete an encrypted object. + + Args: + id: Unique identifier of the object. + version_check: Expected current version for optimistic locking. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Raises: + NotFoundError: If the resource is not found (404). + ConflictError: If a conflict occurs (409). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + params: Dict[str, Any] = { + k: v + for k, v in { + "version_check": version_check, + }.items() + if v is not None + } + self._client.request( + method="delete", + path=("vault", "v1", "kv", str(id)), + params=params, + request_options=request_options, + ) + + def list_kv_metadata( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> ObjectWithoutValue: + """Describe an object + + Fetch metadata for an object without decrypting it. + + Args: + id: Unique identifier of the object. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + ObjectWithoutValue + + Raises: + BadRequestError: If the request is malformed (400). + NotFoundError: If the resource is not found (404). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + return self._client.request( + method="get", + path=("vault", "v1", "kv", str(id), "metadata"), + model=ObjectWithoutValue, + request_options=request_options, + ) + + def list_kv_versions( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> VersionListResponse: + """List object versions + + Retrieve all versions for a specific object. + + Args: + id: Unique identifier of the object. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + VersionListResponse + + Raises: + BadRequestError: If the request is malformed (400). + NotFoundError: If the resource is not found (404). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + return self._client.request( + method="get", + path=("vault", "v1", "kv", str(id), "versions"), + model=VersionListResponse, + request_options=request_options, + ) + + # @oagen-ignore-start — client-side AES-GCM encrypt/decrypt (hand-maintained) + + def encrypt( + self, + *, + data: str, + key_context: Dict[str, str], + associated_data: Optional[str] = None, + ) -> str: + """Encrypt data locally using AES-GCM with a data key derived from the context.""" + key_pair = self.create_data_key(context=key_context) + + key = base64.b64decode(key_pair.data_key) + key_blob = base64.b64decode(key_pair.encrypted_keys) + prefix_len_buffer = _encode_u32_leb128(len(key_blob)) + aad_buffer = associated_data.encode("utf-8") if associated_data else None + iv = os.urandom(12) + + result = _aes_gcm_encrypt(data.encode("utf-8"), key, iv, aad_buffer) + + combined = ( + result["iv"] + + result["tag"] + + prefix_len_buffer + + key_blob + + result["ciphertext"] + ) + return base64.b64encode(combined).decode("utf-8") + + def decrypt( + self, *, encrypted_data: str, associated_data: Optional[str] = None + ) -> str: + """Decrypt data that was previously encrypted using the encrypt method.""" + decoded = _decode_encrypted_payload(encrypted_data) + data_key = self.create_decrypt(keys=decoded.keys) + + key = base64.b64decode(data_key.data_key) + aad_buffer = associated_data.encode("utf-8") if associated_data else None + + decrypted_bytes = _aes_gcm_decrypt( + ciphertext=decoded.ciphertext, + key=key, + iv=decoded.iv, + tag=decoded.tag, + aad=aad_buffer, + ) + return decrypted_bytes.decode("utf-8") + + # @oagen-ignore-end + + +class AsyncVault: + """Vault API resources (async).""" + + def __init__(self, client: "AsyncWorkOSClient") -> None: + self._client = client + + async def create_data_key( + self, + *, + context: Dict[str, str], + request_options: Optional[RequestOptions] = None, + ) -> CreateDataKeyResponse: + """Create a data key + + Generate an isolated encryption key for local encryption operations. + + Args: + context: Map of values used to determine the encryption key. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + CreateDataKeyResponse + + Raises: + BadRequestError: If the request is malformed (400). + UnprocessableEntityError: If the request data is unprocessable (422). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + body: Dict[str, Any] = { + "context": context, + } + return await self._client.request( + method="post", + path=("vault", "v1", "keys", "data-key"), + body=body, + model=CreateDataKeyResponse, + request_options=request_options, + ) + + async def create_decrypt( + self, + *, + keys: str, + request_options: Optional[RequestOptions] = None, + ) -> DecryptResponse: + """Decrypt a data key + + Decrypt a previously encrypted data key from WorkOS Vault. + + Args: + keys: Base64-encoded encrypted data key to decrypt. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + DecryptResponse + + Raises: + BadRequestError: If the request is malformed (400). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + body: Dict[str, Any] = { + "keys": keys, + } + return await self._client.request( + method="post", + path=("vault", "v1", "keys", "decrypt"), + body=body, + model=DecryptResponse, + request_options=request_options, + ) + + async def create_rekey( + self, + *, + context: Dict[str, str], + encrypted_keys: str, + request_options: Optional[RequestOptions] = None, + ) -> CreateDataKeyResponse: + """Re-encrypt a data key + + Decrypt an existing data key and re-encrypt it under a new key context. + + Args: + context: Map of values used to determine the new encryption key. + encrypted_keys: Base64-encoded encrypted data key blob to re-encrypt. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + CreateDataKeyResponse + + Raises: + BadRequestError: If the request is malformed (400). + UnprocessableEntityError: If the request data is unprocessable (422). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + body: Dict[str, Any] = { + "context": context, + "encrypted_keys": encrypted_keys, + } + return await self._client.request( + method="post", + path=("vault", "v1", "keys", "rekey"), + body=body, + model=CreateDataKeyResponse, + request_options=request_options, + ) + + async def list_kv( + self, + *, + limit: Optional[int] = None, + before: Optional[str] = None, + after: Optional[str] = None, + order: Optional[Union[VaultOrder, str]] = None, + search: Optional[str] = None, + updated_after: Optional[str] = None, + request_options: Optional[RequestOptions] = None, + ) -> AsyncPage[ObjectSummary]: + """List objects + + List all encrypted objects with cursor-based pagination. + + Args: + limit: Upper limit on the number of objects to return. Defaults to `10`. + before: Cursor for the previous page of results. + after: Cursor for the next page of results. + order: Sort direction for results. + search: Filter results by name or structured search JSON. + updated_after: ISO 8601 timestamp to filter by last modified time. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + AsyncPage[ObjectSummary] + + Raises: + BadRequestError: If the request is malformed (400). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + params = { + k: v + for k, v in { + "limit": limit, + "before": before, + "after": after, + "order": enum_value(order) if order is not None else None, + "search": search, + "updatedAfter": updated_after, + }.items() + if v is not None + } + return await self._client.request_page( + method="get", + path=("vault", "v1", "kv"), + model=ObjectSummary, + params=params, + request_options=request_options, + ) + + async def create_kv( + self, + *, + key_context: Dict[str, str], + name: str, + value: str, + request_options: Optional[RequestOptions] = None, + ) -> ObjectMetadata: + """Create an object + + Encrypt and store a new key-value object. + + Args: + key_context: Map of values used to determine the encryption key. + name: Unique name for the object. + value: Plaintext data to encrypt and store. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + ObjectMetadata + + Raises: + BadRequestError: If the request is malformed (400). + ConflictError: If a conflict occurs (409). + UnprocessableEntityError: If the request data is unprocessable (422). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + body: Dict[str, Any] = { + "key_context": key_context, + "name": name, + "value": value, + } + return await self._client.request( + method="post", + path=("vault", "v1", "kv"), + body=body, + model=ObjectMetadata, + request_options=request_options, + ) + + async def get_name( + self, + name: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> VaultObject: + """Read an object by name + + Fetch and decrypt an object by its unique name. + + Args: + name: Unique name of the object. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + VaultObject + + Raises: + BadRequestError: If the request is malformed (400). + NotFoundError: If the resource is not found (404). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + return await self._client.request( + method="get", + path=("vault", "v1", "kv", "name", str(name)), + model=VaultObject, + request_options=request_options, + ) + + async def get_kv( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> VaultObject: + """Read an object by ID + + Fetch and decrypt an object by its unique identifier. + + Args: + id: Unique identifier of the object. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + VaultObject + + Raises: + BadRequestError: If the request is malformed (400). + NotFoundError: If the resource is not found (404). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + return await self._client.request( + method="get", + path=("vault", "v1", "kv", str(id)), + model=VaultObject, + request_options=request_options, + ) + + async def update_kv( + self, + id: str, + *, + value: str, + version_check: Optional[str] = None, + request_options: Optional[RequestOptions] = None, + ) -> ObjectWithoutValue: + """Update an object + + Update the value of an existing encrypted object. + + Args: + id: Unique identifier of the object. + value: New plaintext value. + version_check: ID of the expected current version for optimistic locking. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + ObjectWithoutValue + + Raises: + BadRequestError: If the request is malformed (400). + ConflictError: If a conflict occurs (409). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + body: Dict[str, Any] = { + k: v + for k, v in { + "value": value, + "version_check": version_check, + }.items() + if v is not None + } + return await self._client.request( + method="put", + path=("vault", "v1", "kv", str(id)), + body=body, + model=ObjectWithoutValue, + request_options=request_options, + ) + + async def delete_kv( + self, + id: str, + *, + version_check: Optional[str] = None, + request_options: Optional[RequestOptions] = None, + ) -> None: + """Delete an object + + Delete an encrypted object. + + Args: + id: Unique identifier of the object. + version_check: Expected current version for optimistic locking. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Raises: + NotFoundError: If the resource is not found (404). + ConflictError: If a conflict occurs (409). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + params: Dict[str, Any] = { + k: v + for k, v in { + "version_check": version_check, + }.items() + if v is not None + } + await self._client.request( + method="delete", + path=("vault", "v1", "kv", str(id)), + params=params, + request_options=request_options, + ) + + async def list_kv_metadata( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> ObjectWithoutValue: + """Describe an object + + Fetch metadata for an object without decrypting it. + + Args: + id: Unique identifier of the object. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + ObjectWithoutValue + + Raises: + BadRequestError: If the request is malformed (400). + NotFoundError: If the resource is not found (404). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + return await self._client.request( + method="get", + path=("vault", "v1", "kv", str(id), "metadata"), + model=ObjectWithoutValue, + request_options=request_options, + ) + + async def list_kv_versions( + self, + id: str, + *, + request_options: Optional[RequestOptions] = None, + ) -> VersionListResponse: + """List object versions + + Retrieve all versions for a specific object. + + Args: + id: Unique identifier of the object. + request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. + + Returns: + VersionListResponse + + Raises: + BadRequestError: If the request is malformed (400). + NotFoundError: If the resource is not found (404). + AuthenticationError: If the API key is invalid (401). + RateLimitExceededError: If rate limited (429). + ServerError: If the server returns a 5xx error. + """ + return await self._client.request( + method="get", + path=("vault", "v1", "kv", str(id), "versions"), + model=VersionListResponse, + request_options=request_options, + ) + + # @oagen-ignore-start — client-side AES-GCM encrypt/decrypt (hand-maintained) + + async def encrypt( + self, + *, + data: str, + key_context: Dict[str, str], + associated_data: Optional[str] = None, + ) -> str: + """Encrypt data locally using AES-GCM with a data key derived from the context.""" + key_pair = await self.create_data_key(context=key_context) + + key = base64.b64decode(key_pair.data_key) + key_blob = base64.b64decode(key_pair.encrypted_keys) + prefix_len_buffer = _encode_u32_leb128(len(key_blob)) + aad_buffer = associated_data.encode("utf-8") if associated_data else None + iv = os.urandom(12) + + result = _aes_gcm_encrypt(data.encode("utf-8"), key, iv, aad_buffer) + combined = ( + result["iv"] + + result["tag"] + + prefix_len_buffer + + key_blob + + result["ciphertext"] + ) + return base64.b64encode(combined).decode("utf-8") + + async def decrypt( + self, *, encrypted_data: str, associated_data: Optional[str] = None + ) -> str: + """Decrypt data that was previously encrypted using the encrypt method.""" + decoded = _decode_encrypted_payload(encrypted_data) + data_key = await self.create_decrypt(keys=decoded.keys) + + key = base64.b64decode(data_key.data_key) + aad_buffer = associated_data.encode("utf-8") if associated_data else None + + decrypted_bytes = _aes_gcm_decrypt( + ciphertext=decoded.ciphertext, + key=key, + iv=decoded.iv, + tag=decoded.tag, + aad=aad_buffer, + ) + return decrypted_bytes.decode("utf-8") + + # @oagen-ignore-end diff --git a/src/workos/vault/models/__init__.py b/src/workos/vault/models/__init__.py new file mode 100644 index 00000000..13aefaee --- /dev/null +++ b/src/workos/vault/models/__init__.py @@ -0,0 +1,19 @@ +# This file is auto-generated by oagen. Do not edit. + +from workos.common.models.actor import Actor as Actor +from .create_data_key_request import CreateDataKeyRequest as CreateDataKeyRequest +from .create_data_key_response import CreateDataKeyResponse as CreateDataKeyResponse +from .create_object_request import CreateObjectRequest as CreateObjectRequest +from .decrypt_request import DecryptRequest as DecryptRequest +from .decrypt_response import DecryptResponse as DecryptResponse +from .delete_object_response import DeleteObjectResponse as DeleteObjectResponse +from .list_metadata import ListMetadata as ListMetadata +from .object_metadata import ObjectMetadata as ObjectMetadata +from .object_summary import ObjectSummary as ObjectSummary +from .object_version import ObjectVersion as ObjectVersion +from .object_without_value import ObjectWithoutValue as ObjectWithoutValue +from .rekey_request import RekeyRequest as RekeyRequest +from .update_object_request import UpdateObjectRequest as UpdateObjectRequest +from .vault_object import VaultObject as VaultObject +from .vault_order import VaultOrder as VaultOrder +from .version_list_response import VersionListResponse as VersionListResponse diff --git a/src/workos/vault/models/create_data_key_request.py b/src/workos/vault/models/create_data_key_request.py new file mode 100644 index 00000000..0a078f29 --- /dev/null +++ b/src/workos/vault/models/create_data_key_request.py @@ -0,0 +1,31 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class CreateDataKeyRequest: + """Create Data Key Request model.""" + + context: Dict[str, str] + """Map of values used to determine the encryption key.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "CreateDataKeyRequest": + """Deserialize from a dictionary.""" + try: + return cls( + context=data["context"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("CreateDataKeyRequest", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["context"] = self.context + return result diff --git a/src/workos/vault/models/create_data_key_response.py b/src/workos/vault/models/create_data_key_response.py new file mode 100644 index 00000000..8039a077 --- /dev/null +++ b/src/workos/vault/models/create_data_key_response.py @@ -0,0 +1,43 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class CreateDataKeyResponse: + """Create Data Key Response model.""" + + context: Dict[str, str] + """Map of values used to determine the encryption key.""" + data_key: str + """Base64-encoded data encryption key.""" + encrypted_keys: str + """Base64-encoded encrypted data key blob.""" + id: str + """Unique identifier for the generated data key.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "CreateDataKeyResponse": + """Deserialize from a dictionary.""" + try: + return cls( + context=data["context"], + data_key=data["data_key"], + encrypted_keys=data["encrypted_keys"], + id=data["id"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("CreateDataKeyResponse", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["context"] = self.context + result["data_key"] = self.data_key + result["encrypted_keys"] = self.encrypted_keys + result["id"] = self.id + return result diff --git a/src/workos/vault/models/create_object_request.py b/src/workos/vault/models/create_object_request.py new file mode 100644 index 00000000..8af0a4ce --- /dev/null +++ b/src/workos/vault/models/create_object_request.py @@ -0,0 +1,39 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class CreateObjectRequest: + """Create Object Request model.""" + + key_context: Dict[str, str] + """Map of values used to determine the encryption key.""" + name: str + """Unique name for the object.""" + value: str + """Plaintext data to encrypt and store.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "CreateObjectRequest": + """Deserialize from a dictionary.""" + try: + return cls( + key_context=data["key_context"], + name=data["name"], + value=data["value"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("CreateObjectRequest", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["key_context"] = self.key_context + result["name"] = self.name + result["value"] = self.value + return result diff --git a/src/workos/vault/models/decrypt_request.py b/src/workos/vault/models/decrypt_request.py new file mode 100644 index 00000000..90e22b22 --- /dev/null +++ b/src/workos/vault/models/decrypt_request.py @@ -0,0 +1,31 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class DecryptRequest: + """Decrypt Request model.""" + + keys: str + """Base64-encoded encrypted data key to decrypt.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "DecryptRequest": + """Deserialize from a dictionary.""" + try: + return cls( + keys=data["keys"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("DecryptRequest", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["keys"] = self.keys + return result diff --git a/src/workos/vault/models/decrypt_response.py b/src/workos/vault/models/decrypt_response.py new file mode 100644 index 00000000..d6f15a43 --- /dev/null +++ b/src/workos/vault/models/decrypt_response.py @@ -0,0 +1,35 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class DecryptResponse: + """Decrypt Response model.""" + + data_key: str + """Base64-encoded decrypted data key.""" + id: str + """Unique identifier of the decrypted data key.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "DecryptResponse": + """Deserialize from a dictionary.""" + try: + return cls( + data_key=data["data_key"], + id=data["id"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("DecryptResponse", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["data_key"] = self.data_key + result["id"] = self.id + return result diff --git a/src/workos/vault/models/delete_object_response.py b/src/workos/vault/models/delete_object_response.py new file mode 100644 index 00000000..62364458 --- /dev/null +++ b/src/workos/vault/models/delete_object_response.py @@ -0,0 +1,35 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class DeleteObjectResponse: + """Delete Object Response model.""" + + name: str + """Name of the deleted object.""" + success: bool + """Whether the deletion succeeded.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "DeleteObjectResponse": + """Deserialize from a dictionary.""" + try: + return cls( + name=data["name"], + success=data["success"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("DeleteObjectResponse", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["name"] = self.name + result["success"] = self.success + return result diff --git a/src/workos/vault/models/list_metadata.py b/src/workos/vault/models/list_metadata.py new file mode 100644 index 00000000..d3ec885e --- /dev/null +++ b/src/workos/vault/models/list_metadata.py @@ -0,0 +1,41 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict, Optional +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class ListMetadata: + """Cursor-based pagination metadata.""" + + after: Optional[str] = None + """Cursor for the next page of results.""" + before: Optional[str] = None + """Cursor for the previous page of results.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "ListMetadata": + """Deserialize from a dictionary.""" + try: + return cls( + after=data.get("after"), + before=data.get("before"), + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("ListMetadata", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + if self.after is not None: + result["after"] = self.after + else: + result["after"] = None + if self.before is not None: + result["before"] = self.before + else: + result["before"] = None + return result diff --git a/src/workos/vault/models/object_metadata.py b/src/workos/vault/models/object_metadata.py new file mode 100644 index 00000000..13de4f35 --- /dev/null +++ b/src/workos/vault/models/object_metadata.py @@ -0,0 +1,62 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import cast +from typing import Any, Dict, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + +from workos.common.models.actor import Actor + + +@dataclass(slots=True) +class ObjectMetadata: + """Metadata for a stored encrypted object.""" + + context: Dict[str, str] + """Map of values used to determine the encryption key.""" + environment_id: str + """Environment the object belongs to.""" + id: str + """Unique identifier of the object.""" + key_id: str + """Encryption key identifier.""" + updated_at: datetime + """Timestamp of the last update.""" + updated_by: "Actor" + version_id: Optional[str] = None + """Current version identifier of the object.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "ObjectMetadata": + """Deserialize from a dictionary.""" + try: + return cls( + context=data["context"], + environment_id=data["environment_id"], + id=data["id"], + key_id=data["key_id"], + updated_at=_parse_datetime(data["updated_at"]), + updated_by=Actor.from_dict(cast(Dict[str, Any], data["updated_by"])), + version_id=data.get("version_id"), + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("ObjectMetadata", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["context"] = self.context + result["environment_id"] = self.environment_id + result["id"] = self.id + result["key_id"] = self.key_id + result["updated_at"] = _format_datetime(self.updated_at) + result["updated_by"] = self.updated_by.to_dict() + if self.version_id is not None: + result["version_id"] = self.version_id + else: + result["version_id"] = None + return result diff --git a/src/workos/vault/models/object_summary.py b/src/workos/vault/models/object_summary.py new file mode 100644 index 00000000..4ab8ba51 --- /dev/null +++ b/src/workos/vault/models/object_summary.py @@ -0,0 +1,46 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import Any, Dict, Optional +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + + +@dataclass(slots=True) +class ObjectSummary: + """Summary of an encrypted object returned in list responses.""" + + id: str + """Unique identifier of the object.""" + name: str + """Unique name of the object.""" + updated_at: Optional[datetime] = None + """Timestamp of the last update.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "ObjectSummary": + """Deserialize from a dictionary.""" + try: + return cls( + id=data["id"], + name=data["name"], + updated_at=_parse_datetime(_v_updated_at) + if (_v_updated_at := data.get("updated_at")) is not None + else None, + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("ObjectSummary", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["id"] = self.id + result["name"] = self.name + if self.updated_at is not None: + result["updated_at"] = _format_datetime(self.updated_at) + else: + result["updated_at"] = None + return result diff --git a/src/workos/vault/models/object_version.py b/src/workos/vault/models/object_version.py new file mode 100644 index 00000000..ebb0576d --- /dev/null +++ b/src/workos/vault/models/object_version.py @@ -0,0 +1,49 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import Any, Dict +from workos._types import _raise_deserialize_error +from workos._types import _format_datetime, _parse_datetime + + +@dataclass(slots=True) +class ObjectVersion: + """A static snapshot of an encrypted object.""" + + created_at: datetime + """Timestamp when the version was created.""" + current_version: bool + """Whether this is the active version.""" + etag: str + """Hash of the object value.""" + id: str + """Unique identifier of the version.""" + size: int + """Number of bytes of stored data.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "ObjectVersion": + """Deserialize from a dictionary.""" + try: + return cls( + created_at=_parse_datetime(data["created_at"]), + current_version=data["current_version"], + etag=data["etag"], + id=data["id"], + size=data["size"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("ObjectVersion", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["created_at"] = _format_datetime(self.created_at) + result["current_version"] = self.current_version + result["etag"] = self.etag + result["id"] = self.id + result["size"] = self.size + return result diff --git a/src/workos/vault/models/object_without_value.py b/src/workos/vault/models/object_without_value.py new file mode 100644 index 00000000..85787a9e --- /dev/null +++ b/src/workos/vault/models/object_without_value.py @@ -0,0 +1,43 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import cast +from typing import Any, Dict +from workos._types import _raise_deserialize_error + +from .object_metadata import ObjectMetadata + + +@dataclass(slots=True) +class ObjectWithoutValue: + """An encrypted object's metadata (value excluded).""" + + id: str + """Unique identifier of the object.""" + metadata: "ObjectMetadata" + name: str + """Unique name of the object.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "ObjectWithoutValue": + """Deserialize from a dictionary.""" + try: + return cls( + id=data["id"], + metadata=ObjectMetadata.from_dict( + cast(Dict[str, Any], data["metadata"]) + ), + name=data["name"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("ObjectWithoutValue", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["id"] = self.id + result["metadata"] = self.metadata.to_dict() + result["name"] = self.name + return result diff --git a/src/workos/vault/models/rekey_request.py b/src/workos/vault/models/rekey_request.py new file mode 100644 index 00000000..f10de48a --- /dev/null +++ b/src/workos/vault/models/rekey_request.py @@ -0,0 +1,35 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class RekeyRequest: + """Rekey Request model.""" + + context: Dict[str, str] + """Map of values used to determine the new encryption key.""" + encrypted_keys: str + """Base64-encoded encrypted data key blob to re-encrypt.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "RekeyRequest": + """Deserialize from a dictionary.""" + try: + return cls( + context=data["context"], + encrypted_keys=data["encrypted_keys"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("RekeyRequest", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["context"] = self.context + result["encrypted_keys"] = self.encrypted_keys + return result diff --git a/src/workos/vault/models/update_object_request.py b/src/workos/vault/models/update_object_request.py new file mode 100644 index 00000000..c20b02c7 --- /dev/null +++ b/src/workos/vault/models/update_object_request.py @@ -0,0 +1,38 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict, Optional +from workos._types import _raise_deserialize_error + + +@dataclass(slots=True) +class UpdateObjectRequest: + """Update Object Request model.""" + + value: str + """New plaintext value.""" + version_check: Optional[str] = None + """ID of the expected current version for optimistic locking.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "UpdateObjectRequest": + """Deserialize from a dictionary.""" + try: + return cls( + value=data["value"], + version_check=data.get("version_check"), + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("UpdateObjectRequest", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["value"] = self.value + if self.version_check is not None: + result["version_check"] = self.version_check + else: + result["version_check"] = None + return result diff --git a/src/workos/vault/models/vault_object.py b/src/workos/vault/models/vault_object.py new file mode 100644 index 00000000..5e80994f --- /dev/null +++ b/src/workos/vault/models/vault_object.py @@ -0,0 +1,47 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import cast +from typing import Any, Dict +from workos._types import _raise_deserialize_error + +from .object_metadata import ObjectMetadata + + +@dataclass(slots=True) +class VaultObject: + """An encrypted object with its decrypted value and metadata.""" + + id: str + """Unique identifier of the object.""" + metadata: "ObjectMetadata" + name: str + """Unique name of the object.""" + value: str + """Decrypted plaintext value.""" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "VaultObject": + """Deserialize from a dictionary.""" + try: + return cls( + id=data["id"], + metadata=ObjectMetadata.from_dict( + cast(Dict[str, Any], data["metadata"]) + ), + name=data["name"], + value=data["value"], + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("VaultObject", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["id"] = self.id + result["metadata"] = self.metadata.to_dict() + result["name"] = self.name + result["value"] = self.value + return result diff --git a/src/workos/vault/models/vault_order.py b/src/workos/vault/models/vault_order.py new file mode 100644 index 00000000..2a023174 --- /dev/null +++ b/src/workos/vault/models/vault_order.py @@ -0,0 +1,28 @@ +# This file is auto-generated by oagen. Do not edit. + +"""Enumeration of vault order values.""" + +from __future__ import annotations + +from enum import Enum +from typing import Optional +from typing import Literal, TypeAlias + + +class VaultOrder(str, Enum): + """Known values for VaultOrder.""" + + ASC = "asc" + DESC = "desc" + + @classmethod + def _missing_(cls, value: object) -> Optional["VaultOrder"]: + if not isinstance(value, str): + return None + unknown = str.__new__(cls, value) + unknown._name_ = value.upper() + unknown._value_ = value + return unknown + + +VaultOrderLiteral: TypeAlias = Literal["asc", "desc"] diff --git a/src/workos/vault/models/version_list_response.py b/src/workos/vault/models/version_list_response.py new file mode 100644 index 00000000..88beae50 --- /dev/null +++ b/src/workos/vault/models/version_list_response.py @@ -0,0 +1,43 @@ +# This file is auto-generated by oagen. Do not edit. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import cast +from typing import Any, Dict, List +from workos._types import _raise_deserialize_error + +from .list_metadata import ListMetadata +from .object_version import ObjectVersion + + +@dataclass(slots=True) +class VersionListResponse: + """Version List Response model.""" + + data: List["ObjectVersion"] + """List of object versions.""" + list_metadata: "ListMetadata" + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> "VersionListResponse": + """Deserialize from a dictionary.""" + try: + return cls( + data=[ + ObjectVersion.from_dict(cast(Dict[str, Any], item)) + for item in cast(list[Any], data["data"]) + ], + list_metadata=ListMetadata.from_dict( + cast(Dict[str, Any], data["list_metadata"]) + ), + ) + except (KeyError, ValueError) as e: + _raise_deserialize_error("VersionListResponse", e) + + def to_dict(self) -> Dict[str, Any]: + """Serialize to a dictionary.""" + result: Dict[str, Any] = {} + result["data"] = [item.to_dict() for item in self.data] + result["list_metadata"] = self.list_metadata.to_dict() + return result diff --git a/src/workos/webhooks/_resource.py b/src/workos/webhooks/_resource.py index 652f051e..d429d091 100644 --- a/src/workos/webhooks/_resource.py +++ b/src/workos/webhooks/_resource.py @@ -8,7 +8,7 @@ from .._client import AsyncWorkOSClient, WorkOSClient from .._types import RequestOptions, enum_value -from .models import WebhookEndpointJson +from .models import WebhookEndpoint from workos.common.models.create_webhook_endpoint_events import ( CreateWebhookEndpointEvents, ) @@ -25,6 +25,11 @@ import json import time +# @oagen-ignore-start +if TYPE_CHECKING: + from workos.events.models import EventSchemaVariant + # @oagen-ignore-end + class Webhooks: """Webhooks API resources.""" @@ -40,7 +45,7 @@ def list_webhook_endpoints( after: Optional[str] = None, order: Optional[Union[PaginationOrder, str]] = "desc", request_options: Optional[RequestOptions] = None, - ) -> SyncPage[WebhookEndpointJson]: + ) -> SyncPage[WebhookEndpoint]: """List Webhook Endpoints Get a list of all of your existing webhook endpoints. @@ -53,7 +58,7 @@ def list_webhook_endpoints( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - SyncPage[WebhookEndpointJson] + SyncPage[WebhookEndpoint] Raises: AuthenticationError: If the API key is invalid (401). @@ -73,7 +78,7 @@ def list_webhook_endpoints( return self._client.request_page( method="get", path=("webhook_endpoints",), - model=WebhookEndpointJson, + model=WebhookEndpoint, params=params, request_options=request_options, ) @@ -84,7 +89,7 @@ def create_webhook_endpoint( endpoint_url: str, events: List[Union[CreateWebhookEndpointEvents, str]], request_options: Optional[RequestOptions] = None, - ) -> WebhookEndpointJson: + ) -> WebhookEndpoint: """Create a Webhook Endpoint Create a new webhook endpoint to receive event notifications. @@ -95,7 +100,7 @@ def create_webhook_endpoint( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - WebhookEndpointJson + WebhookEndpoint Raises: ConflictError: If a conflict occurs (409). @@ -112,7 +117,7 @@ def create_webhook_endpoint( method="post", path=("webhook_endpoints",), body=body, - model=WebhookEndpointJson, + model=WebhookEndpoint, request_options=request_options, ) @@ -124,7 +129,7 @@ def update_webhook_endpoint( status: Optional[Union[UpdateWebhookEndpointStatus, str]] = None, events: Optional[List[Union[UpdateWebhookEndpointEvents, str]]] = None, request_options: Optional[RequestOptions] = None, - ) -> WebhookEndpointJson: + ) -> WebhookEndpoint: """Update a Webhook Endpoint Update the properties of an existing webhook endpoint. @@ -137,7 +142,7 @@ def update_webhook_endpoint( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - WebhookEndpointJson + WebhookEndpoint Raises: NotFoundError: If the resource is not found (404). @@ -160,7 +165,7 @@ def update_webhook_endpoint( method="patch", path=("webhook_endpoints", str(id)), body=body, - model=WebhookEndpointJson, + model=WebhookEndpoint, request_options=request_options, ) @@ -297,7 +302,7 @@ async def list_webhook_endpoints( after: Optional[str] = None, order: Optional[Union[PaginationOrder, str]] = "desc", request_options: Optional[RequestOptions] = None, - ) -> AsyncPage[WebhookEndpointJson]: + ) -> AsyncPage[WebhookEndpoint]: """List Webhook Endpoints Get a list of all of your existing webhook endpoints. @@ -310,7 +315,7 @@ async def list_webhook_endpoints( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - AsyncPage[WebhookEndpointJson] + AsyncPage[WebhookEndpoint] Raises: AuthenticationError: If the API key is invalid (401). @@ -330,7 +335,7 @@ async def list_webhook_endpoints( return await self._client.request_page( method="get", path=("webhook_endpoints",), - model=WebhookEndpointJson, + model=WebhookEndpoint, params=params, request_options=request_options, ) @@ -341,7 +346,7 @@ async def create_webhook_endpoint( endpoint_url: str, events: List[Union[CreateWebhookEndpointEvents, str]], request_options: Optional[RequestOptions] = None, - ) -> WebhookEndpointJson: + ) -> WebhookEndpoint: """Create a Webhook Endpoint Create a new webhook endpoint to receive event notifications. @@ -352,7 +357,7 @@ async def create_webhook_endpoint( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - WebhookEndpointJson + WebhookEndpoint Raises: ConflictError: If a conflict occurs (409). @@ -369,7 +374,7 @@ async def create_webhook_endpoint( method="post", path=("webhook_endpoints",), body=body, - model=WebhookEndpointJson, + model=WebhookEndpoint, request_options=request_options, ) @@ -381,7 +386,7 @@ async def update_webhook_endpoint( status: Optional[Union[UpdateWebhookEndpointStatus, str]] = None, events: Optional[List[Union[UpdateWebhookEndpointEvents, str]]] = None, request_options: Optional[RequestOptions] = None, - ) -> WebhookEndpointJson: + ) -> WebhookEndpoint: """Update a Webhook Endpoint Update the properties of an existing webhook endpoint. @@ -394,7 +399,7 @@ async def update_webhook_endpoint( request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: - WebhookEndpointJson + WebhookEndpoint Raises: NotFoundError: If the resource is not found (404). @@ -417,7 +422,7 @@ async def update_webhook_endpoint( method="patch", path=("webhook_endpoints", str(id)), body=body, - model=WebhookEndpointJson, + model=WebhookEndpoint, request_options=request_options, ) @@ -538,9 +543,3 @@ def verify_header( ) # @oagen-ignore-end - - -# @oagen-ignore-start -if TYPE_CHECKING: - from workos.events.models import EventSchemaVariant -# @oagen-ignore-end diff --git a/src/workos/webhooks/models/__init__.py b/src/workos/webhooks/models/__init__.py index 71fea740..4b50e3b7 100644 --- a/src/workos/webhooks/models/__init__.py +++ b/src/workos/webhooks/models/__init__.py @@ -2,4 +2,4 @@ from .create_webhook_endpoint import CreateWebhookEndpoint as CreateWebhookEndpoint from .update_webhook_endpoint import UpdateWebhookEndpoint as UpdateWebhookEndpoint -from .webhook_endpoint_json import WebhookEndpointJson as WebhookEndpointJson +from .webhook_endpoint import WebhookEndpoint as WebhookEndpoint diff --git a/src/workos/webhooks/models/webhook_endpoint_json.py b/src/workos/webhooks/models/webhook_endpoint.py similarity index 86% rename from src/workos/webhooks/models/webhook_endpoint_json.py rename to src/workos/webhooks/models/webhook_endpoint.py index 1a8441b6..a40c60ca 100644 --- a/src/workos/webhooks/models/webhook_endpoint_json.py +++ b/src/workos/webhooks/models/webhook_endpoint.py @@ -8,12 +8,12 @@ from typing import Any, Dict, List, Literal from workos._types import _raise_deserialize_error from workos._types import _format_datetime, _parse_datetime -from workos.common.models.webhook_endpoint_json_status import WebhookEndpointJsonStatus +from workos.common.models.webhook_endpoint_status import WebhookEndpointStatus @dataclass(slots=True) -class WebhookEndpointJson: - """Webhook Endpoint Json model.""" +class WebhookEndpoint: + """Webhook Endpoint model.""" object: Literal["webhook_endpoint"] """Distinguishes the Webhook Endpoint object.""" @@ -23,7 +23,7 @@ class WebhookEndpointJson: """The URL to which webhooks are sent.""" secret: str """The secret used to sign webhook payloads.""" - status: "WebhookEndpointJsonStatus" + status: "WebhookEndpointStatus" """Whether the Webhook Endpoint is enabled or disabled.""" events: List[str] """The events that the Webhook Endpoint is subscribed to.""" @@ -33,7 +33,7 @@ class WebhookEndpointJson: """An ISO 8601 timestamp.""" @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "WebhookEndpointJson": + def from_dict(cls, data: Dict[str, Any]) -> "WebhookEndpoint": """Deserialize from a dictionary.""" try: return cls( @@ -41,13 +41,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "WebhookEndpointJson": id=data["id"], endpoint_url=data["endpoint_url"], secret=data["secret"], - status=WebhookEndpointJsonStatus(data["status"]), + status=WebhookEndpointStatus(data["status"]), events=data["events"], created_at=_parse_datetime(data["created_at"]), updated_at=_parse_datetime(data["updated_at"]), ) except (KeyError, ValueError) as e: - _raise_deserialize_error("WebhookEndpointJson", e) + _raise_deserialize_error("WebhookEndpoint", e) def to_dict(self) -> Dict[str, Any]: """Serialize to a dictionary.""" diff --git a/tests/fixtures/action_authentication_denied.json b/tests/fixtures/action_authentication_denied.json index 51af3e3d..18fcd735 100644 --- a/tests/fixtures/action_authentication_denied.json +++ b/tests/fixtures/action_authentication_denied.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "action.authentication.denied", "data": { @@ -12,6 +13,7 @@ "ip_address": "203.0.113.1", "user_agent": "Mozilla/5.0" }, + "created_at": "2026-01-15T12:00:00.000Z", "context": { "google_analytics_client_id": "GA1.2.1234567890.1234567890", "google_analytics_sessions": [ @@ -31,7 +33,5 @@ "previous_attributes": { "key": {} } - }, - "created_at": "2026-01-15T12:00:00.000Z", - "object": "event" + } } diff --git a/tests/fixtures/action_user_registration_denied.json b/tests/fixtures/action_user_registration_denied.json index bb52ecbb..5f6a8bd0 100644 --- a/tests/fixtures/action_user_registration_denied.json +++ b/tests/fixtures/action_user_registration_denied.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "action.user_registration.denied", "data": { @@ -11,6 +12,7 @@ "ip_address": "203.0.113.1", "user_agent": "Mozilla/5.0" }, + "created_at": "2026-01-15T12:00:00.000Z", "context": { "google_analytics_client_id": "GA1.2.1234567890.1234567890", "google_analytics_sessions": [ @@ -30,7 +32,5 @@ "previous_attributes": { "key": {} } - }, - "created_at": "2026-01-15T12:00:00.000Z", - "object": "event" + } } diff --git a/tests/fixtures/actor.json b/tests/fixtures/actor.json new file mode 100644 index 00000000..51e70159 --- /dev/null +++ b/tests/fixtures/actor.json @@ -0,0 +1,4 @@ +{ + "id": "key_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "name": "My API Key" +} diff --git a/tests/fixtures/api_key.json b/tests/fixtures/api_key.json index e05b1db2..c0223734 100644 --- a/tests/fixtures/api_key.json +++ b/tests/fixtures/api_key.json @@ -8,6 +8,7 @@ "name": "Production API Key", "obfuscated_value": "sk_...3456", "last_used_at": null, + "expires_at": null, "permissions": [ "posts:read", "posts:write" diff --git a/tests/fixtures/api_key_created.json b/tests/fixtures/api_key_created.json index f98c97d6..d1d79f7f 100644 --- a/tests/fixtures/api_key_created.json +++ b/tests/fixtures/api_key_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "api_key.created", "data": { @@ -11,6 +12,7 @@ "name": "My API Key", "obfuscated_value": "sk_test_...1234", "last_used_at": "2026-01-15T12:00:00.000Z", + "expires_at": null, "permissions": [ "users:read", "users:write" @@ -38,6 +40,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/api_key_created_data.json b/tests/fixtures/api_key_created_data.json index 1f0a1945..486815fe 100644 --- a/tests/fixtures/api_key_created_data.json +++ b/tests/fixtures/api_key_created_data.json @@ -8,6 +8,7 @@ "name": "My API Key", "obfuscated_value": "sk_test_...1234", "last_used_at": "2026-01-15T12:00:00.000Z", + "expires_at": null, "permissions": [ "users:read", "users:write" diff --git a/tests/fixtures/api_key_revoked.json b/tests/fixtures/api_key_revoked.json index 859ccb36..eea6afd2 100644 --- a/tests/fixtures/api_key_revoked.json +++ b/tests/fixtures/api_key_revoked.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "api_key.revoked", "data": { @@ -11,6 +12,7 @@ "name": "My API Key", "obfuscated_value": "sk_test_...1234", "last_used_at": "2026-01-15T12:00:00.000Z", + "expires_at": null, "permissions": [ "users:read", "users:write" @@ -38,6 +40,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/api_key_revoked_data.json b/tests/fixtures/api_key_revoked_data.json index 1f0a1945..486815fe 100644 --- a/tests/fixtures/api_key_revoked_data.json +++ b/tests/fixtures/api_key_revoked_data.json @@ -8,6 +8,7 @@ "name": "My API Key", "obfuscated_value": "sk_test_...1234", "last_used_at": "2026-01-15T12:00:00.000Z", + "expires_at": null, "permissions": [ "users:read", "users:write" diff --git a/tests/fixtures/api_key_validation_response.json b/tests/fixtures/api_key_validation_response.json index 1e77554f..77549bf9 100644 --- a/tests/fixtures/api_key_validation_response.json +++ b/tests/fixtures/api_key_validation_response.json @@ -9,6 +9,7 @@ "name": "Production API Key", "obfuscated_value": "sk_...3456", "last_used_at": null, + "expires_at": null, "permissions": [ "posts:read", "posts:write" diff --git a/tests/fixtures/audit_log_action.json b/tests/fixtures/audit_log_action.json new file mode 100644 index 00000000..a7212b6c --- /dev/null +++ b/tests/fixtures/audit_log_action.json @@ -0,0 +1,42 @@ +{ + "object": "audit_log_action", + "name": "user.viewed_invoice", + "schema": { + "object": "audit_log_schema", + "version": 1, + "actor": { + "metadata": { + "type": "object", + "properties": { + "role": { + "type": "string" + } + } + } + }, + "targets": [ + { + "type": "invoice", + "metadata": { + "type": "object", + "properties": { + "cost": { + "type": "number" + } + } + } + } + ], + "metadata": { + "type": "object", + "properties": { + "transactionId": { + "type": "string" + } + } + }, + "created_at": "2026-01-15T12:00:00.000Z" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z" +} diff --git a/tests/fixtures/audit_log_event.json b/tests/fixtures/audit_log_event.json index ab6e39e7..ef2ffdb2 100644 --- a/tests/fixtures/audit_log_event.json +++ b/tests/fixtures/audit_log_event.json @@ -1,6 +1,6 @@ { "action": "user.signed_in", - "occurred_at": "2026-02-02T16:35:39.317Z", + "occurred_at": "2026-02-02T16:35:39.000Z", "actor": { "id": "user_TF4C5938", "type": "user", diff --git a/tests/fixtures/audit_log_event_ingestion.json b/tests/fixtures/audit_log_event_ingestion.json index 09c9f490..268fa05c 100644 --- a/tests/fixtures/audit_log_event_ingestion.json +++ b/tests/fixtures/audit_log_event_ingestion.json @@ -2,7 +2,7 @@ "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", "event": { "action": "user.signed_in", - "occurred_at": "2026-02-02T16:35:39.317Z", + "occurred_at": "2026-02-02T16:35:39.000Z", "actor": { "id": "user_TF4C5938", "type": "user", diff --git a/tests/fixtures/audit_log_export.json b/tests/fixtures/audit_log_export.json new file mode 100644 index 00000000..e076643f --- /dev/null +++ b/tests/fixtures/audit_log_export.json @@ -0,0 +1,8 @@ +{ + "object": "audit_log_export", + "id": "audit_log_export_01GBZK5MP7TD1YCFQHFR22180V", + "state": "ready", + "url": "https://exports.audit-logs.com/audit-log-exports/export.csv", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z" +} diff --git a/tests/fixtures/audit_log_schema.json b/tests/fixtures/audit_log_schema.json index 773d6b72..cdf6f075 100644 --- a/tests/fixtures/audit_log_schema.json +++ b/tests/fixtures/audit_log_schema.json @@ -1,4 +1,6 @@ { + "object": "audit_log_schema", + "version": 1, "actor": { "metadata": { "type": "object", @@ -29,5 +31,6 @@ "type": "string" } } - } + }, + "created_at": "2026-01-15T12:00:00.000Z" } diff --git a/tests/fixtures/audit_log_schema_actor.json b/tests/fixtures/audit_log_schema_actor.json index cea87599..319068e7 100644 --- a/tests/fixtures/audit_log_schema_actor.json +++ b/tests/fixtures/audit_log_schema_actor.json @@ -1,10 +1,5 @@ { "metadata": { - "type": "object", - "properties": { - "role": { - "type": "string" - } - } + "key": {} } } diff --git a/tests/fixtures/audit_log_schema_actor_input.json b/tests/fixtures/audit_log_schema_actor_input.json new file mode 100644 index 00000000..cea87599 --- /dev/null +++ b/tests/fixtures/audit_log_schema_actor_input.json @@ -0,0 +1,10 @@ +{ + "metadata": { + "type": "object", + "properties": { + "role": { + "type": "string" + } + } + } +} diff --git a/tests/fixtures/audit_log_schema_dto.json b/tests/fixtures/audit_log_schema_dto.json new file mode 100644 index 00000000..773d6b72 --- /dev/null +++ b/tests/fixtures/audit_log_schema_dto.json @@ -0,0 +1,33 @@ +{ + "actor": { + "metadata": { + "type": "object", + "properties": { + "role": { + "type": "string" + } + } + } + }, + "targets": [ + { + "type": "invoice", + "metadata": { + "type": "object", + "properties": { + "cost": { + "type": "number" + } + } + } + } + ], + "metadata": { + "type": "object", + "properties": { + "transactionId": { + "type": "string" + } + } + } +} diff --git a/tests/fixtures/audit_log_schema_input.json b/tests/fixtures/audit_log_schema_input.json new file mode 100644 index 00000000..773d6b72 --- /dev/null +++ b/tests/fixtures/audit_log_schema_input.json @@ -0,0 +1,33 @@ +{ + "actor": { + "metadata": { + "type": "object", + "properties": { + "role": { + "type": "string" + } + } + } + }, + "targets": [ + { + "type": "invoice", + "metadata": { + "type": "object", + "properties": { + "cost": { + "type": "number" + } + } + } + } + ], + "metadata": { + "type": "object", + "properties": { + "transactionId": { + "type": "string" + } + } + } +} diff --git a/tests/fixtures/audit_log_schema_target_input.json b/tests/fixtures/audit_log_schema_target_input.json new file mode 100644 index 00000000..328b5256 --- /dev/null +++ b/tests/fixtures/audit_log_schema_target_input.json @@ -0,0 +1,11 @@ +{ + "type": "invoice", + "metadata": { + "type": "object", + "properties": { + "cost": { + "type": "number" + } + } + } +} diff --git a/tests/fixtures/audit_logs_retention.json b/tests/fixtures/audit_logs_retention.json new file mode 100644 index 00000000..0720427e --- /dev/null +++ b/tests/fixtures/audit_logs_retention.json @@ -0,0 +1,3 @@ +{ + "retention_period_in_days": 30 +} diff --git a/tests/fixtures/authenticate_response.json b/tests/fixtures/authenticate_response.json index 5127ae3f..52a4cb8d 100644 --- a/tests/fixtures/authenticate_response.json +++ b/tests/fixtures/authenticate_response.json @@ -11,7 +11,7 @@ "metadata": { "timezone": "America/New_York" }, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" diff --git a/tests/fixtures/authentication_email_verification_failed.json b/tests/fixtures/authentication_email_verification_failed.json index 9115ce3b..d2943750 100644 --- a/tests/fixtures/authentication_email_verification_failed.json +++ b/tests/fixtures/authentication_email_verification_failed.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.email_verification_failed", "data": { @@ -33,6 +34,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/authentication_email_verification_succeeded.json b/tests/fixtures/authentication_email_verification_succeeded.json index 91e1484e..e41a17cd 100644 --- a/tests/fixtures/authentication_email_verification_succeeded.json +++ b/tests/fixtures/authentication_email_verification_succeeded.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.email_verification_succeeded", "data": { @@ -29,6 +30,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/authentication_magic_auth_failed.json b/tests/fixtures/authentication_magic_auth_failed.json index 20bb715f..dae55e92 100644 --- a/tests/fixtures/authentication_magic_auth_failed.json +++ b/tests/fixtures/authentication_magic_auth_failed.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.magic_auth_failed", "data": { @@ -33,6 +34,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/authentication_magic_auth_succeeded.json b/tests/fixtures/authentication_magic_auth_succeeded.json index 9d6aa527..a808f029 100644 --- a/tests/fixtures/authentication_magic_auth_succeeded.json +++ b/tests/fixtures/authentication_magic_auth_succeeded.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.magic_auth_succeeded", "data": { @@ -29,6 +30,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/authentication_mfa_failed.json b/tests/fixtures/authentication_mfa_failed.json index 624ebfca..1aca1447 100644 --- a/tests/fixtures/authentication_mfa_failed.json +++ b/tests/fixtures/authentication_mfa_failed.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.mfa_failed", "data": { @@ -33,6 +34,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/authentication_mfa_succeeded.json b/tests/fixtures/authentication_mfa_succeeded.json index ed151de8..c3eaac26 100644 --- a/tests/fixtures/authentication_mfa_succeeded.json +++ b/tests/fixtures/authentication_mfa_succeeded.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.mfa_succeeded", "data": { @@ -29,6 +30,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/authentication_oauth_failed.json b/tests/fixtures/authentication_oauth_failed.json index b2aa1291..d79d92bf 100644 --- a/tests/fixtures/authentication_oauth_failed.json +++ b/tests/fixtures/authentication_oauth_failed.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.oauth_failed", "data": { @@ -33,6 +34,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/authentication_oauth_succeeded.json b/tests/fixtures/authentication_oauth_succeeded.json index 8b69d6e4..9002eb8d 100644 --- a/tests/fixtures/authentication_oauth_succeeded.json +++ b/tests/fixtures/authentication_oauth_succeeded.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.oauth_succeeded", "data": { @@ -29,6 +30,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/authentication_passkey_failed.json b/tests/fixtures/authentication_passkey_failed.json index 26dd3e3d..f1937fe2 100644 --- a/tests/fixtures/authentication_passkey_failed.json +++ b/tests/fixtures/authentication_passkey_failed.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.passkey_failed", "data": { @@ -33,6 +34,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/authentication_passkey_succeeded.json b/tests/fixtures/authentication_passkey_succeeded.json index d9ad38f8..ed961f25 100644 --- a/tests/fixtures/authentication_passkey_succeeded.json +++ b/tests/fixtures/authentication_passkey_succeeded.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.passkey_succeeded", "data": { @@ -29,6 +30,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/authentication_password_failed.json b/tests/fixtures/authentication_password_failed.json index 9904b2a0..cdff4d0d 100644 --- a/tests/fixtures/authentication_password_failed.json +++ b/tests/fixtures/authentication_password_failed.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.password_failed", "data": { @@ -33,6 +34,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/authentication_password_succeeded.json b/tests/fixtures/authentication_password_succeeded.json index f4b02f54..f6c72c64 100644 --- a/tests/fixtures/authentication_password_succeeded.json +++ b/tests/fixtures/authentication_password_succeeded.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.password_succeeded", "data": { @@ -29,6 +30,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/authentication_radar_risk_detected.json b/tests/fixtures/authentication_radar_risk_detected.json index 52ebf529..919306e8 100644 --- a/tests/fixtures/authentication_radar_risk_detected.json +++ b/tests/fixtures/authentication_radar_risk_detected.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.radar_risk_detected", "data": { @@ -31,6 +32,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/authentication_sso_failed.json b/tests/fixtures/authentication_sso_failed.json index f5ff78cd..a77c6c59 100644 --- a/tests/fixtures/authentication_sso_failed.json +++ b/tests/fixtures/authentication_sso_failed.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.sso_failed", "data": { @@ -38,6 +39,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/authentication_sso_started.json b/tests/fixtures/authentication_sso_started.json index 2dd8bb81..12b2978f 100644 --- a/tests/fixtures/authentication_sso_started.json +++ b/tests/fixtures/authentication_sso_started.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.sso_started", "data": { @@ -34,6 +35,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/authentication_sso_succeeded.json b/tests/fixtures/authentication_sso_succeeded.json index f467dbce..1f2e7771 100644 --- a/tests/fixtures/authentication_sso_succeeded.json +++ b/tests/fixtures/authentication_sso_succeeded.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.sso_succeeded", "data": { @@ -34,6 +35,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/authentication_sso_timed_out.json b/tests/fixtures/authentication_sso_timed_out.json index f4d9061a..11f48ea3 100644 --- a/tests/fixtures/authentication_sso_timed_out.json +++ b/tests/fixtures/authentication_sso_timed_out.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.sso_timed_out", "data": { @@ -38,6 +39,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/authorized_connect_application_list_data.json b/tests/fixtures/authorized_connect_application_list_data.json index f08dc56e..0c2e4576 100644 --- a/tests/fixtures/authorized_connect_application_list_data.json +++ b/tests/fixtures/authorized_connect_application_list_data.json @@ -20,7 +20,16 @@ ], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", - "application_type": "m2m", + "application_type": "oauth", + "redirect_uris": [ + { + "uri": "https://example.com/callback", + "default": true + } + ], + "uses_pkce": true, + "is_first_party": true, + "was_dynamically_registered": true, "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT" } } diff --git a/tests/fixtures/connect_application.json b/tests/fixtures/connect_application.json index 2498d8fd..51420d65 100644 --- a/tests/fixtures/connect_application.json +++ b/tests/fixtures/connect_application.json @@ -11,6 +11,15 @@ ], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", - "application_type": "m2m", + "application_type": "oauth", + "redirect_uris": [ + { + "uri": "https://example.com/callback", + "default": true + } + ], + "uses_pkce": true, + "is_first_party": true, + "was_dynamically_registered": true, "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT" } diff --git a/tests/fixtures/connect_application_m2m.json b/tests/fixtures/connect_application_m2m.json new file mode 100644 index 00000000..2498d8fd --- /dev/null +++ b/tests/fixtures/connect_application_m2m.json @@ -0,0 +1,16 @@ +{ + "object": "connect_application", + "id": "conn_app_01HXYZ123456789ABCDEFGHIJ", + "client_id": "client_01HXYZ123456789ABCDEFGHIJ", + "description": "An application for managing user access", + "name": "My Application", + "scopes": [ + "openid", + "profile", + "email" + ], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "application_type": "m2m", + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT" +} diff --git a/tests/fixtures/connect_application_oauth.json b/tests/fixtures/connect_application_oauth.json new file mode 100644 index 00000000..51420d65 --- /dev/null +++ b/tests/fixtures/connect_application_oauth.json @@ -0,0 +1,25 @@ +{ + "object": "connect_application", + "id": "conn_app_01HXYZ123456789ABCDEFGHIJ", + "client_id": "client_01HXYZ123456789ABCDEFGHIJ", + "description": "An application for managing user access", + "name": "My Application", + "scopes": [ + "openid", + "profile", + "email" + ], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "application_type": "oauth", + "redirect_uris": [ + { + "uri": "https://example.com/callback", + "default": true + } + ], + "uses_pkce": true, + "is_first_party": true, + "was_dynamically_registered": true, + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT" +} diff --git a/tests/fixtures/connect_application_oauth_redirect_uris.json b/tests/fixtures/connect_application_oauth_redirect_uris.json new file mode 100644 index 00000000..083dd6a8 --- /dev/null +++ b/tests/fixtures/connect_application_oauth_redirect_uris.json @@ -0,0 +1,4 @@ +{ + "uri": "https://example.com/callback", + "default": true +} diff --git a/tests/fixtures/connection_activated.json b/tests/fixtures/connection_activated.json index e83a62a5..4cfd0d94 100644 --- a/tests/fixtures/connection_activated.json +++ b/tests/fixtures/connection_activated.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "connection.activated", "data": { @@ -40,6 +41,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/connection_deactivated.json b/tests/fixtures/connection_deactivated.json index 0636e74c..c852e344 100644 --- a/tests/fixtures/connection_deactivated.json +++ b/tests/fixtures/connection_deactivated.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "connection.deactivated", "data": { @@ -40,6 +41,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/connection_deleted.json b/tests/fixtures/connection_deleted.json index 104f9d58..7ff48d23 100644 --- a/tests/fixtures/connection_deleted.json +++ b/tests/fixtures/connection_deleted.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "connection.deleted", "data": { @@ -31,6 +32,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/connection_saml_certificate_renewal_required.json b/tests/fixtures/connection_saml_certificate_renewal_required.json index 30ed8794..bd5b15bc 100644 --- a/tests/fixtures/connection_saml_certificate_renewal_required.json +++ b/tests/fixtures/connection_saml_certificate_renewal_required.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "connection.saml_certificate_renewal_required", "data": { @@ -33,6 +34,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/connection_saml_certificate_renewed.json b/tests/fixtures/connection_saml_certificate_renewed.json index eabcb9bc..ca71c05f 100644 --- a/tests/fixtures/connection_saml_certificate_renewed.json +++ b/tests/fixtures/connection_saml_certificate_renewed.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "connection.saml_certificate_renewed", "data": { @@ -32,6 +33,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/create_data_key_request.json b/tests/fixtures/create_data_key_request.json new file mode 100644 index 00000000..b3a13312 --- /dev/null +++ b/tests/fixtures/create_data_key_request.json @@ -0,0 +1,5 @@ +{ + "context": { + "organization_id": "org_01K8ZYT4AWJ6XP0E0S8CTBHE3P" + } +} diff --git a/tests/fixtures/create_data_key_response.json b/tests/fixtures/create_data_key_response.json new file mode 100644 index 00000000..f5e6f427 --- /dev/null +++ b/tests/fixtures/create_data_key_response.json @@ -0,0 +1,8 @@ +{ + "context": { + "organization_id": "org_01K8ZYT4AWJ6XP0E0S8CTBHE3P" + }, + "data_key": "DR9idtey9MpMrA1VRFrz30HB1yNgL2PoHZyjAkFeWgg=", + "encrypted_keys": "V09TLkVLTS52MQBiZjUxY2NlYy03OGI0LTUyMDAtYjM4My0zNTczMGU3MWVmNjEBATEBJGJmNjVlMzI2LTQzYTAtNGIyMC04OGM0LTA3ZmYzZGU1NDM0YwF0YmY2NWUzMjYtNDNhMC00YjIwLTg4YzQtMDdmZjNkZTU0MzRj", + "id": "bf51ccec-78b4-5200-b383-35730e71ef61" +} diff --git a/tests/fixtures/create_object_request.json b/tests/fixtures/create_object_request.json new file mode 100644 index 00000000..aa54cb01 --- /dev/null +++ b/tests/fixtures/create_object_request.json @@ -0,0 +1,7 @@ +{ + "key_context": { + "organization_id": "org_01K8ZYT4AWJ6XP0E0S8CTBHE3P" + }, + "name": "my-secret", + "value": "s3cr3t-v4lu3" +} diff --git a/tests/fixtures/create_organization_api_key.json b/tests/fixtures/create_organization_api_key.json index d2791c16..852dc28f 100644 --- a/tests/fixtures/create_organization_api_key.json +++ b/tests/fixtures/create_organization_api_key.json @@ -3,5 +3,6 @@ "permissions": [ "posts:read", "posts:write" - ] + ], + "expires_at": "2030-01-01T00:00:00.000Z" } diff --git a/tests/fixtures/create_user_api_key.json b/tests/fixtures/create_user_api_key.json index 4bdce131..1a78e34f 100644 --- a/tests/fixtures/create_user_api_key.json +++ b/tests/fixtures/create_user_api_key.json @@ -4,5 +4,6 @@ "permissions": [ "posts:read", "posts:write" - ] + ], + "expires_at": "2030-01-01T00:00:00.000Z" } diff --git a/tests/fixtures/decrypt_request.json b/tests/fixtures/decrypt_request.json new file mode 100644 index 00000000..150ec560 --- /dev/null +++ b/tests/fixtures/decrypt_request.json @@ -0,0 +1,3 @@ +{ + "keys": "V09TLkVLTS52MQBiZjUxY2NlYy03OGI0LTUyMDAtYjM4My0zNTczMGU3MWVmNjEBATEBJGJmNjVlMzI2LTQzYTAtNGIyMC04OGM0LTA3ZmYzZGU1NDM0YwF0YmY2NWUzMjYtNDNhMC00YjIwLTg4YzQtMDdmZjNkZTU0MzRj" +} diff --git a/tests/fixtures/decrypt_response.json b/tests/fixtures/decrypt_response.json new file mode 100644 index 00000000..aab0d7f8 --- /dev/null +++ b/tests/fixtures/decrypt_response.json @@ -0,0 +1,4 @@ +{ + "data_key": "DR9idtey9MpMrA1VRFrz30HB1yNgL2PoHZyjAkFeWgg=", + "id": "bf51ccec-78b4-5200-b383-35730e71ef61" +} diff --git a/tests/fixtures/delete_object_response.json b/tests/fixtures/delete_object_response.json new file mode 100644 index 00000000..495662db --- /dev/null +++ b/tests/fixtures/delete_object_response.json @@ -0,0 +1,4 @@ +{ + "name": "my-secret", + "success": true +} diff --git a/tests/fixtures/dsync_activated.json b/tests/fixtures/dsync_activated.json index ee578f1a..b21c7fe6 100644 --- a/tests/fixtures/dsync_activated.json +++ b/tests/fixtures/dsync_activated.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.activated", "data": { @@ -39,6 +40,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/dsync_deactivated.json b/tests/fixtures/dsync_deactivated.json index 52780238..de8b82cb 100644 --- a/tests/fixtures/dsync_deactivated.json +++ b/tests/fixtures/dsync_deactivated.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.deactivated", "data": { @@ -39,6 +40,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/dsync_deleted.json b/tests/fixtures/dsync_deleted.json index 3933e2e0..cd34be8b 100644 --- a/tests/fixtures/dsync_deleted.json +++ b/tests/fixtures/dsync_deleted.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.deleted", "data": { @@ -31,6 +32,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/dsync_group_created.json b/tests/fixtures/dsync_group_created.json index 24ff886f..ae7342e2 100644 --- a/tests/fixtures/dsync_group_created.json +++ b/tests/fixtures/dsync_group_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.group.created", "data": { @@ -34,6 +35,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/dsync_group_deleted.json b/tests/fixtures/dsync_group_deleted.json index 4cd5be17..eb59c000 100644 --- a/tests/fixtures/dsync_group_deleted.json +++ b/tests/fixtures/dsync_group_deleted.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.group.deleted", "data": { @@ -34,6 +35,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/dsync_group_updated.json b/tests/fixtures/dsync_group_updated.json index e3b4376b..f4e32ecd 100644 --- a/tests/fixtures/dsync_group_updated.json +++ b/tests/fixtures/dsync_group_updated.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.group.updated", "data": { @@ -37,6 +38,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/dsync_group_user_added.json b/tests/fixtures/dsync_group_user_added.json index 50e7ed56..865a328b 100644 --- a/tests/fixtures/dsync_group_user_added.json +++ b/tests/fixtures/dsync_group_user_added.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.group.user_added", "data": { @@ -75,6 +76,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/dsync_group_user_removed.json b/tests/fixtures/dsync_group_user_removed.json index 4f5b9dff..8e6a4c75 100644 --- a/tests/fixtures/dsync_group_user_removed.json +++ b/tests/fixtures/dsync_group_user_removed.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.group.user_removed", "data": { @@ -75,6 +76,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/dsync_user_created.json b/tests/fixtures/dsync_user_created.json index 87059515..edc074bb 100644 --- a/tests/fixtures/dsync_user_created.json +++ b/tests/fixtures/dsync_user_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.user.created", "data": { @@ -59,6 +60,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/dsync_user_deleted.json b/tests/fixtures/dsync_user_deleted.json index f18a02dc..9aec13d3 100644 --- a/tests/fixtures/dsync_user_deleted.json +++ b/tests/fixtures/dsync_user_deleted.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.user.deleted", "data": { @@ -59,6 +60,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/dsync_user_updated.json b/tests/fixtures/dsync_user_updated.json index 143dfefb..a7802f7b 100644 --- a/tests/fixtures/dsync_user_updated.json +++ b/tests/fixtures/dsync_user_updated.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.user.updated", "data": { @@ -62,6 +63,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/email_change.json b/tests/fixtures/email_change.json index 41982624..2c7c4478 100644 --- a/tests/fixtures/email_change.json +++ b/tests/fixtures/email_change.json @@ -12,7 +12,7 @@ "metadata": { "timezone": "America/New_York" }, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" diff --git a/tests/fixtures/email_change_confirmation.json b/tests/fixtures/email_change_confirmation.json index 5da108ff..0709db84 100644 --- a/tests/fixtures/email_change_confirmation.json +++ b/tests/fixtures/email_change_confirmation.json @@ -12,7 +12,7 @@ "metadata": { "timezone": "America/New_York" }, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" diff --git a/tests/fixtures/email_change_confirmation_user.json b/tests/fixtures/email_change_confirmation_user.json index dcd50576..0870d3b2 100644 --- a/tests/fixtures/email_change_confirmation_user.json +++ b/tests/fixtures/email_change_confirmation_user.json @@ -10,7 +10,7 @@ "metadata": { "timezone": "America/New_York" }, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" diff --git a/tests/fixtures/email_verification_created.json b/tests/fixtures/email_verification_created.json index 07569ee6..d27ac34b 100644 --- a/tests/fixtures/email_verification_created.json +++ b/tests/fixtures/email_verification_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "email_verification.created", "data": { @@ -30,6 +31,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/error.json b/tests/fixtures/error.json new file mode 100644 index 00000000..ac5c385b --- /dev/null +++ b/tests/fixtures/error.json @@ -0,0 +1,3 @@ +{ + "error": "Invalid request parameters." +} diff --git a/tests/fixtures/error_response.json b/tests/fixtures/error_response.json new file mode 100644 index 00000000..ac5c385b --- /dev/null +++ b/tests/fixtures/error_response.json @@ -0,0 +1,3 @@ +{ + "error": "Invalid request parameters." +} diff --git a/tests/fixtures/event_schema.json b/tests/fixtures/event_schema.json index f3c3b571..18fcd735 100644 --- a/tests/fixtures/event_schema.json +++ b/tests/fixtures/event_schema.json @@ -1,32 +1,37 @@ { "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", - "event": "dsync.user.created", + "event": "action.authentication.denied", "data": { - "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", - "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", - "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", - "state": "active", - "email": "veda@foo-corp.com", - "emails": [ - { - "primary": true, - "type": "work", - "value": "veda@foo-corp.com" - } - ], - "idp_id": "2836", - "object": "directory_user", - "username": "veda@foo-corp.com", - "last_name": "Torp", - "first_name": "Veda", - "raw_attributes": {}, - "custom_attributes": {}, - "created_at": "2021-06-25T19:07:33.155Z", - "updated_at": "2021-06-25T19:07:33.155Z" + "action_endpoint_id": "action_endpoint_01EHWNCE74X7JSDV0X3SZ3KJNY", + "action_execution_id": "action_execution_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "authentication", + "verdict": "Deny", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "email": "user@example.com", + "ip_address": "203.0.113.1", + "user_agent": "Mozilla/5.0" }, "created_at": "2026-01-15T12:00:00.000Z", "context": { - "key": {} + "google_analytics_client_id": "GA1.2.1234567890.1234567890", + "google_analytics_sessions": [ + { + "containerId": "GTM-ABCDEF", + "sessionId": "1234567890", + "sessionNumber": "1" + } + ], + "ajs_anonymous_id": "ajs_anon_01EHWNCE74X7JSDV0X3SZ3KJNY", + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe" + }, + "previous_attributes": { + "key": {} + } } } diff --git a/tests/fixtures/flag_created.json b/tests/fixtures/flag_created.json index 871f9b16..94bb3cea 100644 --- a/tests/fixtures/flag_created.json +++ b/tests/fixtures/flag_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "flag.created", "data": { @@ -29,6 +30,5 @@ "source": "api", "name": "Jane Doe" } - }, - "object": "event" + } } diff --git a/tests/fixtures/flag_deleted.json b/tests/fixtures/flag_deleted.json index b9d6adda..fef918d2 100644 --- a/tests/fixtures/flag_deleted.json +++ b/tests/fixtures/flag_deleted.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "flag.deleted", "data": { @@ -29,6 +30,5 @@ "source": "api", "name": "Jane Doe" } - }, - "object": "event" + } } diff --git a/tests/fixtures/flag_rule_updated.json b/tests/fixtures/flag_rule_updated.json index 6f9e5b8c..716db0ec 100644 --- a/tests/fixtures/flag_rule_updated.json +++ b/tests/fixtures/flag_rule_updated.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "flag.rule_updated", "data": { @@ -67,6 +68,5 @@ } } } - }, - "object": "event" + } } diff --git a/tests/fixtures/flag_updated.json b/tests/fixtures/flag_updated.json index 313b85e7..1d76b24b 100644 --- a/tests/fixtures/flag_updated.json +++ b/tests/fixtures/flag_updated.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "flag.updated", "data": { @@ -41,6 +42,5 @@ "default_value": false } } - }, - "object": "event" + } } diff --git a/tests/fixtures/group_created.json b/tests/fixtures/group_created.json index 720d927c..1a310a1c 100644 --- a/tests/fixtures/group_created.json +++ b/tests/fixtures/group_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "group.created", "data": { @@ -30,6 +31,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/group_deleted.json b/tests/fixtures/group_deleted.json index b5bbcebb..179f0756 100644 --- a/tests/fixtures/group_deleted.json +++ b/tests/fixtures/group_deleted.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "group.deleted", "data": { @@ -30,6 +31,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/group_member_added.json b/tests/fixtures/group_member_added.json index b0aa3084..6b0489b1 100644 --- a/tests/fixtures/group_member_added.json +++ b/tests/fixtures/group_member_added.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "group.member_added", "data": { @@ -25,6 +26,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/group_member_removed.json b/tests/fixtures/group_member_removed.json index 6cc3112b..d6be3f61 100644 --- a/tests/fixtures/group_member_removed.json +++ b/tests/fixtures/group_member_removed.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "group.member_removed", "data": { @@ -25,6 +26,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/group_updated.json b/tests/fixtures/group_updated.json index 0e44f438..42b317e0 100644 --- a/tests/fixtures/group_updated.json +++ b/tests/fixtures/group_updated.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "group.updated", "data": { @@ -30,6 +31,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/invitation_accepted.json b/tests/fixtures/invitation_accepted.json index a1460b3c..5c0317bb 100644 --- a/tests/fixtures/invitation_accepted.json +++ b/tests/fixtures/invitation_accepted.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "invitation.accepted", "data": { @@ -36,6 +37,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/invitation_created.json b/tests/fixtures/invitation_created.json index 19039528..10d4a5ce 100644 --- a/tests/fixtures/invitation_created.json +++ b/tests/fixtures/invitation_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "invitation.created", "data": { @@ -36,6 +37,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/invitation_resent.json b/tests/fixtures/invitation_resent.json index 39f240fb..19f6fb85 100644 --- a/tests/fixtures/invitation_resent.json +++ b/tests/fixtures/invitation_resent.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "invitation.resent", "data": { @@ -36,6 +37,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/invitation_revoked.json b/tests/fixtures/invitation_revoked.json index 5b2fdfac..ef33bc3d 100644 --- a/tests/fixtures/invitation_revoked.json +++ b/tests/fixtures/invitation_revoked.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "invitation.revoked", "data": { @@ -36,6 +37,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/list_audit_log_action.json b/tests/fixtures/list_audit_log_action.json new file mode 100644 index 00000000..f36c55df --- /dev/null +++ b/tests/fixtures/list_audit_log_action.json @@ -0,0 +1,50 @@ +{ + "data": [ + { + "object": "audit_log_action", + "name": "user.viewed_invoice", + "schema": { + "object": "audit_log_schema", + "version": 1, + "actor": { + "metadata": { + "type": "object", + "properties": { + "role": { + "type": "string" + } + } + } + }, + "targets": [ + { + "type": "invoice", + "metadata": { + "type": "object", + "properties": { + "cost": { + "type": "number" + } + } + } + } + ], + "metadata": { + "type": "object", + "properties": { + "transactionId": { + "type": "string" + } + } + }, + "created_at": "2026-01-15T12:00:00.000Z" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z" + } + ], + "list_metadata": { + "before": null, + "after": null + } +} diff --git a/tests/fixtures/list_audit_log_schema.json b/tests/fixtures/list_audit_log_schema.json new file mode 100644 index 00000000..97bd6f5b --- /dev/null +++ b/tests/fixtures/list_audit_log_schema.json @@ -0,0 +1,44 @@ +{ + "data": [ + { + "object": "audit_log_schema", + "version": 1, + "actor": { + "metadata": { + "type": "object", + "properties": { + "role": { + "type": "string" + } + } + } + }, + "targets": [ + { + "type": "invoice", + "metadata": { + "type": "object", + "properties": { + "cost": { + "type": "number" + } + } + } + } + ], + "metadata": { + "type": "object", + "properties": { + "transactionId": { + "type": "string" + } + } + }, + "created_at": "2026-01-15T12:00:00.000Z" + } + ], + "list_metadata": { + "before": null, + "after": null + } +} diff --git a/tests/fixtures/list_authorized_connect_application_list_data.json b/tests/fixtures/list_authorized_connect_application_list_data.json index 147009ab..3adf896d 100644 --- a/tests/fixtures/list_authorized_connect_application_list_data.json +++ b/tests/fixtures/list_authorized_connect_application_list_data.json @@ -22,7 +22,16 @@ ], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", - "application_type": "m2m", + "application_type": "oauth", + "redirect_uris": [ + { + "uri": "https://example.com/callback", + "default": true + } + ], + "uses_pkce": true, + "is_first_party": true, + "was_dynamically_registered": true, "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT" } } diff --git a/tests/fixtures/list_connect_application.json b/tests/fixtures/list_connect_application.json index bc421436..6b961692 100644 --- a/tests/fixtures/list_connect_application.json +++ b/tests/fixtures/list_connect_application.json @@ -13,7 +13,16 @@ ], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", - "application_type": "m2m", + "application_type": "oauth", + "redirect_uris": [ + { + "uri": "https://example.com/callback", + "default": true + } + ], + "uses_pkce": true, + "is_first_party": true, + "was_dynamically_registered": true, "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT" } ], diff --git a/tests/fixtures/list_event_schema.json b/tests/fixtures/list_event_schema.json index cd8e9bb3..0a6a4aa4 100644 --- a/tests/fixtures/list_event_schema.json +++ b/tests/fixtures/list_event_schema.json @@ -3,33 +3,38 @@ { "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", - "event": "dsync.user.created", + "event": "action.authentication.denied", "data": { - "id": "directory_user_01E1JG7J09H96KYP8HM9B0G5SJ", - "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74", - "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y", - "state": "active", - "email": "veda@foo-corp.com", - "emails": [ - { - "primary": true, - "type": "work", - "value": "veda@foo-corp.com" - } - ], - "idp_id": "2836", - "object": "directory_user", - "username": "veda@foo-corp.com", - "last_name": "Torp", - "first_name": "Veda", - "raw_attributes": {}, - "custom_attributes": {}, - "created_at": "2021-06-25T19:07:33.155Z", - "updated_at": "2021-06-25T19:07:33.155Z" + "action_endpoint_id": "action_endpoint_01EHWNCE74X7JSDV0X3SZ3KJNY", + "action_execution_id": "action_execution_01EHWNCE74X7JSDV0X3SZ3KJNY", + "type": "authentication", + "verdict": "Deny", + "user_id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "email": "user@example.com", + "ip_address": "203.0.113.1", + "user_agent": "Mozilla/5.0" }, "created_at": "2026-01-15T12:00:00.000Z", "context": { - "key": {} + "google_analytics_client_id": "GA1.2.1234567890.1234567890", + "google_analytics_sessions": [ + { + "containerId": "GTM-ABCDEF", + "sessionId": "1234567890", + "sessionNumber": "1" + } + ], + "ajs_anonymous_id": "ajs_anon_01EHWNCE74X7JSDV0X3SZ3KJNY", + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe" + }, + "previous_attributes": { + "key": {} + } } } ], diff --git a/tests/fixtures/list_metadata.json b/tests/fixtures/list_metadata.json new file mode 100644 index 00000000..c558b90c --- /dev/null +++ b/tests/fixtures/list_metadata.json @@ -0,0 +1,4 @@ +{ + "after": "b21f3a8c-7e4d-4b1a-9c5e-2d8f6a7b3c4e", + "before": "a10e2b7d-6c3f-4a2b-8d1e-3f9a5b8c7d6e" +} diff --git a/tests/fixtures/list_object_summary.json b/tests/fixtures/list_object_summary.json new file mode 100644 index 00000000..5e2cc6cc --- /dev/null +++ b/tests/fixtures/list_object_summary.json @@ -0,0 +1,13 @@ +{ + "data": [ + { + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "name": "my-secret", + "updated_at": "2024-06-15T10:30:00.000Z" + } + ], + "list_metadata": { + "before": null, + "after": null + } +} diff --git a/tests/fixtures/list_organization_api_key.json b/tests/fixtures/list_organization_api_key.json index f6b9c99c..c989f9ae 100644 --- a/tests/fixtures/list_organization_api_key.json +++ b/tests/fixtures/list_organization_api_key.json @@ -10,6 +10,7 @@ "name": "Production API Key", "obfuscated_value": "sk_...3456", "last_used_at": null, + "expires_at": null, "permissions": [ "posts:read", "posts:write" diff --git a/tests/fixtures/list_user.json b/tests/fixtures/list_user.json index 390c74f9..2fb148db 100644 --- a/tests/fixtures/list_user.json +++ b/tests/fixtures/list_user.json @@ -12,7 +12,7 @@ "metadata": { "timezone": "America/New_York" }, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" diff --git a/tests/fixtures/list_user_api_key.json b/tests/fixtures/list_user_api_key.json index a6409aaa..6e277f1a 100644 --- a/tests/fixtures/list_user_api_key.json +++ b/tests/fixtures/list_user_api_key.json @@ -11,6 +11,7 @@ "name": "Production API Key", "obfuscated_value": "sk_...3456", "last_used_at": null, + "expires_at": null, "permissions": [ "posts:read", "posts:write" diff --git a/tests/fixtures/list_user_organization_membership.json b/tests/fixtures/list_user_organization_membership.json index b0764c60..b148e627 100644 --- a/tests/fixtures/list_user_organization_membership.json +++ b/tests/fixtures/list_user_organization_membership.json @@ -30,7 +30,7 @@ "metadata": { "timezone": "America/New_York" }, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" diff --git a/tests/fixtures/list_user_organization_membership_base_list_data.json b/tests/fixtures/list_user_organization_membership_base_list_data.json index f6dc992a..d58934c3 100644 --- a/tests/fixtures/list_user_organization_membership_base_list_data.json +++ b/tests/fixtures/list_user_organization_membership_base_list_data.json @@ -27,7 +27,7 @@ "metadata": { "timezone": "America/New_York" }, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" diff --git a/tests/fixtures/list_webhook_endpoint.json b/tests/fixtures/list_webhook_endpoint.json new file mode 100644 index 00000000..52f8410b --- /dev/null +++ b/tests/fixtures/list_webhook_endpoint.json @@ -0,0 +1,21 @@ +{ + "data": [ + { + "object": "webhook_endpoint", + "id": "we_0123456789", + "endpoint_url": "https://example.com/webhooks", + "secret": "whsec_0FWAiVGkEfGBqqsJH4aNAGBJ4", + "status": "enabled", + "events": [ + "user.created", + "dsync.user.created" + ], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z" + } + ], + "list_metadata": { + "before": null, + "after": null + } +} diff --git a/tests/fixtures/magic_auth_created.json b/tests/fixtures/magic_auth_created.json index 145aaef4..129c8b44 100644 --- a/tests/fixtures/magic_auth_created.json +++ b/tests/fixtures/magic_auth_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "magic_auth.created", "data": { @@ -30,6 +31,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/object.json b/tests/fixtures/object.json new file mode 100644 index 00000000..eee443ed --- /dev/null +++ b/tests/fixtures/object.json @@ -0,0 +1,19 @@ +{ + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "metadata": { + "context": { + "organization_id": "org_01K8ZYT4AWJ6XP0E0S8CTBHE3P" + }, + "environment_id": "environment_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "key_id": "bf65e326-43a0-4b20-88c4-07ff3de5434c", + "updated_at": "2024-06-15T10:30:00Z", + "updated_by": { + "id": "key_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "name": "My API Key" + }, + "version_id": "c3d4e5f6-7890-abcd-ef12-34567890abcd" + }, + "name": "my-secret", + "value": "s3cr3t-v4lu3" +} diff --git a/tests/fixtures/object_metadata.json b/tests/fixtures/object_metadata.json new file mode 100644 index 00000000..3496b0e9 --- /dev/null +++ b/tests/fixtures/object_metadata.json @@ -0,0 +1,14 @@ +{ + "context": { + "organization_id": "org_01K8ZYT4AWJ6XP0E0S8CTBHE3P" + }, + "environment_id": "environment_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "key_id": "bf65e326-43a0-4b20-88c4-07ff3de5434c", + "updated_at": "2024-06-15T10:30:00.000Z", + "updated_by": { + "id": "key_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "name": "My API Key" + }, + "version_id": "c3d4e5f6-7890-abcd-ef12-34567890abcd" +} diff --git a/tests/fixtures/object_summary.json b/tests/fixtures/object_summary.json new file mode 100644 index 00000000..ea3e1dcf --- /dev/null +++ b/tests/fixtures/object_summary.json @@ -0,0 +1,5 @@ +{ + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "name": "my-secret", + "updated_at": "2024-06-15T10:30:00.000Z" +} diff --git a/tests/fixtures/object_version.json b/tests/fixtures/object_version.json new file mode 100644 index 00000000..757d6690 --- /dev/null +++ b/tests/fixtures/object_version.json @@ -0,0 +1,7 @@ +{ + "created_at": "2024-06-15T10:30:00.000Z", + "current_version": true, + "etag": "d41d8cd98f00b204e9800998ecf8427e", + "id": "c3d4e5f6-7890-abcd-ef12-34567890abcd", + "size": 256 +} diff --git a/tests/fixtures/object_without_value.json b/tests/fixtures/object_without_value.json new file mode 100644 index 00000000..42a5f4ae --- /dev/null +++ b/tests/fixtures/object_without_value.json @@ -0,0 +1,18 @@ +{ + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "metadata": { + "context": { + "organization_id": "org_01K8ZYT4AWJ6XP0E0S8CTBHE3P" + }, + "environment_id": "environment_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "key_id": "bf65e326-43a0-4b20-88c4-07ff3de5434c", + "updated_at": "2024-06-15T10:30:00.000Z", + "updated_by": { + "id": "key_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "name": "My API Key" + }, + "version_id": "c3d4e5f6-7890-abcd-ef12-34567890abcd" + }, + "name": "my-secret" +} diff --git a/tests/fixtures/organization_api_key.json b/tests/fixtures/organization_api_key.json index e05b1db2..c0223734 100644 --- a/tests/fixtures/organization_api_key.json +++ b/tests/fixtures/organization_api_key.json @@ -8,6 +8,7 @@ "name": "Production API Key", "obfuscated_value": "sk_...3456", "last_used_at": null, + "expires_at": null, "permissions": [ "posts:read", "posts:write" diff --git a/tests/fixtures/organization_api_key_with_value.json b/tests/fixtures/organization_api_key_with_value.json index 9c85f194..080e38cd 100644 --- a/tests/fixtures/organization_api_key_with_value.json +++ b/tests/fixtures/organization_api_key_with_value.json @@ -8,6 +8,7 @@ "name": "Production API Key", "obfuscated_value": "sk_...3456", "last_used_at": null, + "expires_at": "2030-01-01T00:00:00.000Z", "permissions": [ "posts:read", "posts:write" diff --git a/tests/fixtures/organization_created.json b/tests/fixtures/organization_created.json index 0bd57d10..30af67f7 100644 --- a/tests/fixtures/organization_created.json +++ b/tests/fixtures/organization_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization.created", "data": { @@ -47,6 +48,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/organization_deleted.json b/tests/fixtures/organization_deleted.json index 3d76fa68..df318299 100644 --- a/tests/fixtures/organization_deleted.json +++ b/tests/fixtures/organization_deleted.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization.deleted", "data": { @@ -47,6 +48,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/organization_domain_created.json b/tests/fixtures/organization_domain_created.json index 579580b8..30817ed5 100644 --- a/tests/fixtures/organization_domain_created.json +++ b/tests/fixtures/organization_domain_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_domain.created", "data": { @@ -33,6 +34,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/organization_domain_deleted.json b/tests/fixtures/organization_domain_deleted.json index 1e7e7476..d425773f 100644 --- a/tests/fixtures/organization_domain_deleted.json +++ b/tests/fixtures/organization_domain_deleted.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_domain.deleted", "data": { @@ -33,6 +34,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/organization_domain_updated.json b/tests/fixtures/organization_domain_updated.json index a4851a97..ff3a7555 100644 --- a/tests/fixtures/organization_domain_updated.json +++ b/tests/fixtures/organization_domain_updated.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_domain.updated", "data": { @@ -33,6 +34,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/organization_domain_verification_failed.json b/tests/fixtures/organization_domain_verification_failed.json index fe89780d..8300d386 100644 --- a/tests/fixtures/organization_domain_verification_failed.json +++ b/tests/fixtures/organization_domain_verification_failed.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_domain.verification_failed", "data": { @@ -36,6 +37,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/organization_domain_verified.json b/tests/fixtures/organization_domain_verified.json index ec60b317..95455036 100644 --- a/tests/fixtures/organization_domain_verified.json +++ b/tests/fixtures/organization_domain_verified.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_domain.verified", "data": { @@ -33,6 +34,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/organization_membership.json b/tests/fixtures/organization_membership.json index efba3046..a514b321 100644 --- a/tests/fixtures/organization_membership.json +++ b/tests/fixtures/organization_membership.json @@ -28,7 +28,7 @@ "metadata": { "timezone": "America/New_York" }, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" diff --git a/tests/fixtures/organization_membership_created.json b/tests/fixtures/organization_membership_created.json index 28ebf83c..fd0ebd49 100644 --- a/tests/fixtures/organization_membership_created.json +++ b/tests/fixtures/organization_membership_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_membership.created", "data": { @@ -42,6 +43,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/organization_membership_deleted.json b/tests/fixtures/organization_membership_deleted.json index c729e1c9..8a5c448b 100644 --- a/tests/fixtures/organization_membership_deleted.json +++ b/tests/fixtures/organization_membership_deleted.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_membership.deleted", "data": { @@ -42,6 +43,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/organization_membership_updated.json b/tests/fixtures/organization_membership_updated.json index 2baa8c1f..36e85455 100644 --- a/tests/fixtures/organization_membership_updated.json +++ b/tests/fixtures/organization_membership_updated.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_membership.updated", "data": { @@ -42,6 +43,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/organization_role_created.json b/tests/fixtures/organization_role_created.json index babf5d79..e8234311 100644 --- a/tests/fixtures/organization_role_created.json +++ b/tests/fixtures/organization_role_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_role.created", "data": { @@ -35,6 +36,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/organization_role_deleted.json b/tests/fixtures/organization_role_deleted.json index 77a218a1..cd35a60a 100644 --- a/tests/fixtures/organization_role_deleted.json +++ b/tests/fixtures/organization_role_deleted.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_role.deleted", "data": { @@ -35,6 +36,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/organization_role_updated.json b/tests/fixtures/organization_role_updated.json index 3a42722e..c0c3024c 100644 --- a/tests/fixtures/organization_role_updated.json +++ b/tests/fixtures/organization_role_updated.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_role.updated", "data": { @@ -35,6 +36,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/organization_updated.json b/tests/fixtures/organization_updated.json index 5c5cf506..c7030187 100644 --- a/tests/fixtures/organization_updated.json +++ b/tests/fixtures/organization_updated.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization.updated", "data": { @@ -47,6 +48,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/password_reset_created.json b/tests/fixtures/password_reset_created.json index ebf89e30..0964d5f0 100644 --- a/tests/fixtures/password_reset_created.json +++ b/tests/fixtures/password_reset_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "password_reset.created", "data": { @@ -29,6 +30,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/password_reset_succeeded.json b/tests/fixtures/password_reset_succeeded.json index 93154db4..16ee3716 100644 --- a/tests/fixtures/password_reset_succeeded.json +++ b/tests/fixtures/password_reset_succeeded.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "password_reset.succeeded", "data": { @@ -29,6 +30,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/permission_created.json b/tests/fixtures/permission_created.json index d3b7d142..f991b655 100644 --- a/tests/fixtures/permission_created.json +++ b/tests/fixtures/permission_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "permission.created", "data": { @@ -31,6 +32,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/permission_deleted.json b/tests/fixtures/permission_deleted.json index 89956adc..ee636f8e 100644 --- a/tests/fixtures/permission_deleted.json +++ b/tests/fixtures/permission_deleted.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "permission.deleted", "data": { @@ -31,6 +32,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/permission_updated.json b/tests/fixtures/permission_updated.json index 4b5fa285..17ddb1d5 100644 --- a/tests/fixtures/permission_updated.json +++ b/tests/fixtures/permission_updated.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "permission.updated", "data": { @@ -31,6 +32,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/pipe_connected_account.json b/tests/fixtures/pipe_connected_account.json new file mode 100644 index 00000000..cb474498 --- /dev/null +++ b/tests/fixtures/pipe_connected_account.json @@ -0,0 +1,15 @@ +{ + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "scopes": [ + "repo", + "user:email" + ], + "state": "connected", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z" +} diff --git a/tests/fixtures/pipes_connected_account_connected.json b/tests/fixtures/pipes_connected_account_connected.json new file mode 100644 index 00000000..c72f06a2 --- /dev/null +++ b/tests/fixtures/pipes_connected_account_connected.json @@ -0,0 +1,41 @@ +{ + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "pipes.connected_account.connected", + "data": { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "scopes": [ + "repo", + "user:email" + ], + "state": "connected", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "context": { + "google_analytics_client_id": "GA1.2.1234567890.1234567890", + "google_analytics_sessions": [ + { + "containerId": "GTM-ABCDEF", + "sessionId": "1234567890", + "sessionNumber": "1" + } + ], + "ajs_anonymous_id": "ajs_anon_01EHWNCE74X7JSDV0X3SZ3KJNY", + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe" + }, + "previous_attributes": { + "key": {} + } + } +} diff --git a/tests/fixtures/pipes_connected_account_disconnected.json b/tests/fixtures/pipes_connected_account_disconnected.json new file mode 100644 index 00000000..e66fab99 --- /dev/null +++ b/tests/fixtures/pipes_connected_account_disconnected.json @@ -0,0 +1,41 @@ +{ + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "pipes.connected_account.disconnected", + "data": { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "scopes": [ + "repo", + "user:email" + ], + "state": "connected", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "context": { + "google_analytics_client_id": "GA1.2.1234567890.1234567890", + "google_analytics_sessions": [ + { + "containerId": "GTM-ABCDEF", + "sessionId": "1234567890", + "sessionNumber": "1" + } + ], + "ajs_anonymous_id": "ajs_anon_01EHWNCE74X7JSDV0X3SZ3KJNY", + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe" + }, + "previous_attributes": { + "key": {} + } + } +} diff --git a/tests/fixtures/pipes_connected_account_reauthorization_needed.json b/tests/fixtures/pipes_connected_account_reauthorization_needed.json new file mode 100644 index 00000000..2aa23471 --- /dev/null +++ b/tests/fixtures/pipes_connected_account_reauthorization_needed.json @@ -0,0 +1,41 @@ +{ + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "pipes.connected_account.reauthorization_needed", + "data": { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "scopes": [ + "repo", + "user:email" + ], + "state": "connected", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z" + }, + "created_at": "2026-01-15T12:00:00.000Z", + "context": { + "google_analytics_client_id": "GA1.2.1234567890.1234567890", + "google_analytics_sessions": [ + { + "containerId": "GTM-ABCDEF", + "sessionId": "1234567890", + "sessionNumber": "1" + } + ], + "ajs_anonymous_id": "ajs_anon_01EHWNCE74X7JSDV0X3SZ3KJNY", + "client_id": "client_01EHWNCE74X7JSDV0X3SZ3KJNY", + "actor": { + "id": "user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "source": "api", + "name": "Jane Doe" + }, + "previous_attributes": { + "key": {} + } + } +} diff --git a/tests/fixtures/profile.json b/tests/fixtures/profile.json index 09dcaa63..64a4fcb4 100644 --- a/tests/fixtures/profile.json +++ b/tests/fixtures/profile.json @@ -3,7 +3,7 @@ "id": "prof_01DMC79VCBZ0NY2099737PSVF1", "organization_id": "org_01EHQMYV6MBK39QC5PZXHY59C3", "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", - "connection_type": "GoogleOAuth", + "connection_type": "OktaSAML", "idp_id": "103456789012345678901", "email": "todd@example.com", "first_name": "Todd", diff --git a/tests/fixtures/radar_standalone_assess_request.json b/tests/fixtures/radar_standalone_assess_request.json index 6f3673e8..710b5312 100644 --- a/tests/fixtures/radar_standalone_assess_request.json +++ b/tests/fixtures/radar_standalone_assess_request.json @@ -3,7 +3,5 @@ "user_agent": "Mozilla/5.0", "email": "user@example.com", "auth_method": "Password", - "action": "login", - "device_fingerprint": "fp_abc123", - "bot_score": "0.1" + "action": "sign-in" } diff --git a/tests/fixtures/rekey_request.json b/tests/fixtures/rekey_request.json new file mode 100644 index 00000000..61cdafca --- /dev/null +++ b/tests/fixtures/rekey_request.json @@ -0,0 +1,6 @@ +{ + "context": { + "organization_id": "org_01K8ZYT4AWJ6XP0E0S8CTBHE3P" + }, + "encrypted_keys": "V09TLkVLTS52MQBiZjUxY2NlYy03OGI0LTUyMDAtYjM4My0zNTczMGU3MWVmNjEBATEBJGJmNjVlMzI2LTQzYTAtNGIyMC04OGM0LTA3ZmYzZGU1NDM0YwF0YmY2NWUzMjYtNDNhMC00YjIwLTg4YzQtMDdmZjNkZTU0MzRj" +} diff --git a/tests/fixtures/reset_password_response.json b/tests/fixtures/reset_password_response.json index 647d4c25..6066b643 100644 --- a/tests/fixtures/reset_password_response.json +++ b/tests/fixtures/reset_password_response.json @@ -11,7 +11,7 @@ "metadata": { "timezone": "America/New_York" }, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" diff --git a/tests/fixtures/role_created.json b/tests/fixtures/role_created.json index 6aec0ba9..2a62b943 100644 --- a/tests/fixtures/role_created.json +++ b/tests/fixtures/role_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "role.created", "data": { @@ -32,6 +33,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/role_deleted.json b/tests/fixtures/role_deleted.json index d5e48309..83cbdb67 100644 --- a/tests/fixtures/role_deleted.json +++ b/tests/fixtures/role_deleted.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "role.deleted", "data": { @@ -32,6 +33,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/role_updated.json b/tests/fixtures/role_updated.json index 575f4513..4d636945 100644 --- a/tests/fixtures/role_updated.json +++ b/tests/fixtures/role_updated.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "role.updated", "data": { @@ -32,6 +33,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/send_verification_email_response.json b/tests/fixtures/send_verification_email_response.json index 647d4c25..6066b643 100644 --- a/tests/fixtures/send_verification_email_response.json +++ b/tests/fixtures/send_verification_email_response.json @@ -11,7 +11,7 @@ "metadata": { "timezone": "America/New_York" }, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" diff --git a/tests/fixtures/session_created.json b/tests/fixtures/session_created.json index e21f6b79..a52b672b 100644 --- a/tests/fixtures/session_created.json +++ b/tests/fixtures/session_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "session.created", "data": { @@ -39,6 +40,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/session_revoked.json b/tests/fixtures/session_revoked.json index 4234650e..cb68916c 100644 --- a/tests/fixtures/session_revoked.json +++ b/tests/fixtures/session_revoked.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "session.revoked", "data": { @@ -39,6 +40,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/sso_token_response.json b/tests/fixtures/sso_token_response.json index 1f627a4a..4c45d949 100644 --- a/tests/fixtures/sso_token_response.json +++ b/tests/fixtures/sso_token_response.json @@ -7,7 +7,7 @@ "id": "prof_01DMC79VCBZ0NY2099737PSVF1", "organization_id": "org_01EHQMYV6MBK39QC5PZXHY59C3", "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", - "connection_type": "GoogleOAuth", + "connection_type": "OktaSAML", "idp_id": "103456789012345678901", "email": "todd@example.com", "first_name": "Todd", diff --git a/tests/fixtures/update_object_request.json b/tests/fixtures/update_object_request.json new file mode 100644 index 00000000..91ffa2e5 --- /dev/null +++ b/tests/fixtures/update_object_request.json @@ -0,0 +1,4 @@ +{ + "value": "upd4t3d-v4lu3", + "version_check": "c3d4e5f6-7890-abcd-ef12-34567890abcd" +} diff --git a/tests/fixtures/user.json b/tests/fixtures/user.json index ea8be141..60e76ab9 100644 --- a/tests/fixtures/user.json +++ b/tests/fixtures/user.json @@ -10,7 +10,7 @@ "metadata": { "timezone": "America/New_York" }, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" diff --git a/tests/fixtures/user_api_key.json b/tests/fixtures/user_api_key.json index 0b527caf..e669b312 100644 --- a/tests/fixtures/user_api_key.json +++ b/tests/fixtures/user_api_key.json @@ -9,6 +9,7 @@ "name": "Production API Key", "obfuscated_value": "sk_...3456", "last_used_at": null, + "expires_at": null, "permissions": [ "posts:read", "posts:write" diff --git a/tests/fixtures/user_api_key_with_value.json b/tests/fixtures/user_api_key_with_value.json index 99d28c9a..7aec864a 100644 --- a/tests/fixtures/user_api_key_with_value.json +++ b/tests/fixtures/user_api_key_with_value.json @@ -9,6 +9,7 @@ "name": "Production API Key", "obfuscated_value": "sk_...3456", "last_used_at": null, + "expires_at": "2030-01-01T00:00:00.000Z", "permissions": [ "posts:read", "posts:write" diff --git a/tests/fixtures/user_created.json b/tests/fixtures/user_created.json index b1082b0a..36057d91 100644 --- a/tests/fixtures/user_created.json +++ b/tests/fixtures/user_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "user.created", "data": { @@ -13,7 +14,7 @@ "metadata": { "timezone": "America/New_York" }, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" @@ -38,6 +39,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/user_deleted.json b/tests/fixtures/user_deleted.json index 94b795f0..41f9125f 100644 --- a/tests/fixtures/user_deleted.json +++ b/tests/fixtures/user_deleted.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "user.deleted", "data": { @@ -13,7 +14,7 @@ "metadata": { "timezone": "America/New_York" }, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" @@ -38,6 +39,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/user_organization_membership.json b/tests/fixtures/user_organization_membership.json index 184279d9..0b578e52 100644 --- a/tests/fixtures/user_organization_membership.json +++ b/tests/fixtures/user_organization_membership.json @@ -28,7 +28,7 @@ "metadata": { "timezone": "America/New_York" }, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" diff --git a/tests/fixtures/user_organization_membership_base_list_data.json b/tests/fixtures/user_organization_membership_base_list_data.json index f3a20339..d2e9cd47 100644 --- a/tests/fixtures/user_organization_membership_base_list_data.json +++ b/tests/fixtures/user_organization_membership_base_list_data.json @@ -25,7 +25,7 @@ "metadata": { "timezone": "America/New_York" }, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" diff --git a/tests/fixtures/user_updated.json b/tests/fixtures/user_updated.json index 1694e77d..dc5561f8 100644 --- a/tests/fixtures/user_updated.json +++ b/tests/fixtures/user_updated.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "user.updated", "data": { @@ -13,7 +14,7 @@ "metadata": { "timezone": "America/New_York" }, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" @@ -38,6 +39,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/vault_byok_key_deleted.json b/tests/fixtures/vault_byok_key_deleted.json index cd179cb3..8b007c27 100644 --- a/tests/fixtures/vault_byok_key_deleted.json +++ b/tests/fixtures/vault_byok_key_deleted.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.byok_key.deleted", "data": { @@ -25,6 +26,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/vault_byok_key_verification_completed.json b/tests/fixtures/vault_byok_key_verification_completed.json index 06e645c8..d5a4042f 100644 --- a/tests/fixtures/vault_byok_key_verification_completed.json +++ b/tests/fixtures/vault_byok_key_verification_completed.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.byok_key.verification_completed", "data": { @@ -26,6 +27,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/vault_data_created.json b/tests/fixtures/vault_data_created.json index d84b80fa..c8ca2ba0 100644 --- a/tests/fixtures/vault_data_created.json +++ b/tests/fixtures/vault_data_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.data.created", "data": { @@ -31,6 +32,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/vault_data_deleted.json b/tests/fixtures/vault_data_deleted.json index bedbef03..671d905f 100644 --- a/tests/fixtures/vault_data_deleted.json +++ b/tests/fixtures/vault_data_deleted.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.data.deleted", "data": { @@ -27,6 +28,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/vault_data_read.json b/tests/fixtures/vault_data_read.json index 27ba4181..e385cf8e 100644 --- a/tests/fixtures/vault_data_read.json +++ b/tests/fixtures/vault_data_read.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.data.read", "data": { @@ -28,6 +29,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/vault_data_updated.json b/tests/fixtures/vault_data_updated.json index 2edb07da..59e66f16 100644 --- a/tests/fixtures/vault_data_updated.json +++ b/tests/fixtures/vault_data_updated.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.data.updated", "data": { @@ -31,6 +32,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/vault_dek_decrypted.json b/tests/fixtures/vault_dek_decrypted.json index 632186c5..fef2bf45 100644 --- a/tests/fixtures/vault_dek_decrypted.json +++ b/tests/fixtures/vault_dek_decrypted.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.dek.decrypted", "data": { @@ -27,6 +28,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/vault_dek_read.json b/tests/fixtures/vault_dek_read.json index 3c12bc57..c19f1b61 100644 --- a/tests/fixtures/vault_dek_read.json +++ b/tests/fixtures/vault_dek_read.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.dek.read", "data": { @@ -32,6 +33,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/vault_kek_created.json b/tests/fixtures/vault_kek_created.json index 9321861b..e1fb54b5 100644 --- a/tests/fixtures/vault_kek_created.json +++ b/tests/fixtures/vault_kek_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.kek.created", "data": { @@ -28,6 +29,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/vault_metadata_read.json b/tests/fixtures/vault_metadata_read.json index 102b4ef6..e4f0747a 100644 --- a/tests/fixtures/vault_metadata_read.json +++ b/tests/fixtures/vault_metadata_read.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.metadata.read", "data": { @@ -27,6 +28,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/vault_names_listed.json b/tests/fixtures/vault_names_listed.json index b91d9539..69e75aa9 100644 --- a/tests/fixtures/vault_names_listed.json +++ b/tests/fixtures/vault_names_listed.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.names.listed", "data": { @@ -26,6 +27,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/vault_object.json b/tests/fixtures/vault_object.json index 19e91740..214688ed 100644 --- a/tests/fixtures/vault_object.json +++ b/tests/fixtures/vault_object.json @@ -1,17 +1,19 @@ { - "id": "vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C", + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "metadata": { - "context": {"tenant": "acme"}, - "environment_id": "environment_01EHDAK2BFGWCSZXP9HGZ3VK8C", - "id": "vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C", - "key_id": "vault_key_01EHDAK2BFGWCSZXP9HGZ3VK8C", - "updated_at": "2025-01-01T00:00:00.000Z", + "context": { + "organization_id": "org_01K8ZYT4AWJ6XP0E0S8CTBHE3P" + }, + "environment_id": "environment_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "key_id": "bf65e326-43a0-4b20-88c4-07ff3de5434c", + "updated_at": "2024-06-15T10:30:00.000Z", "updated_by": { - "id": "key_01EHDAK2BFGWCSZXP9HGZ3VK8C", + "id": "key_01K8ZYT4AWJ6XP0E0S8CTBHE3P", "name": "My API Key" }, - "version_id": "vault_ver_01EHDAK2BFGWCSZXP9HGZ3VK8C" + "version_id": "c3d4e5f6-7890-abcd-ef12-34567890abcd" }, "name": "my-secret", - "value": "super-secret-value" + "value": "s3cr3t-v4lu3" } diff --git a/tests/fixtures/verify_email_response.json b/tests/fixtures/verify_email_response.json index 647d4c25..6066b643 100644 --- a/tests/fixtures/verify_email_response.json +++ b/tests/fixtures/verify_email_response.json @@ -11,7 +11,7 @@ "metadata": { "timezone": "America/New_York" }, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" diff --git a/tests/fixtures/version_list_response.json b/tests/fixtures/version_list_response.json new file mode 100644 index 00000000..6041bad4 --- /dev/null +++ b/tests/fixtures/version_list_response.json @@ -0,0 +1,15 @@ +{ + "data": [ + { + "created_at": "2024-06-15T10:30:00.000Z", + "current_version": true, + "etag": "d41d8cd98f00b204e9800998ecf8427e", + "id": "c3d4e5f6-7890-abcd-ef12-34567890abcd", + "size": 256 + } + ], + "list_metadata": { + "after": "b21f3a8c-7e4d-4b1a-9c5e-2d8f6a7b3c4e", + "before": "a10e2b7d-6c3f-4a2b-8d1e-3f9a5b8c7d6e" + } +} diff --git a/tests/fixtures/waitlist_user_approved.json b/tests/fixtures/waitlist_user_approved.json index eddf230b..848d68b9 100644 --- a/tests/fixtures/waitlist_user_approved.json +++ b/tests/fixtures/waitlist_user_approved.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "waitlist_user.approved", "data": { @@ -30,6 +31,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/waitlist_user_created.json b/tests/fixtures/waitlist_user_created.json index c3faaad7..ab5b52cf 100644 --- a/tests/fixtures/waitlist_user_created.json +++ b/tests/fixtures/waitlist_user_created.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "waitlist_user.created", "data": { @@ -30,6 +31,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/waitlist_user_denied.json b/tests/fixtures/waitlist_user_denied.json index 6079919b..34abc6e0 100644 --- a/tests/fixtures/waitlist_user_denied.json +++ b/tests/fixtures/waitlist_user_denied.json @@ -1,4 +1,5 @@ { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "waitlist_user.denied", "data": { @@ -30,6 +31,5 @@ "previous_attributes": { "key": {} } - }, - "object": "event" + } } diff --git a/tests/fixtures/webhook_endpoint.json b/tests/fixtures/webhook_endpoint.json new file mode 100644 index 00000000..3f37fa02 --- /dev/null +++ b/tests/fixtures/webhook_endpoint.json @@ -0,0 +1,13 @@ +{ + "object": "webhook_endpoint", + "id": "we_0123456789", + "endpoint_url": "https://example.com/webhooks", + "secret": "whsec_0FWAiVGkEfGBqqsJH4aNAGBJ4", + "status": "enabled", + "events": [ + "user.created", + "dsync.user.created" + ], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z" +} diff --git a/tests/smoke_test.py b/tests/smoke_test.py index 51ac21ca..52833dbb 100644 --- a/tests/smoke_test.py +++ b/tests/smoke_test.py @@ -143,13 +143,11 @@ def test_core_types_importable() -> None: from workos.user_management.models import ( AuthenticateResponse, Invitation, - OrganizationMembership, User, ) assert AuthenticateResponse is not None assert Invitation is not None - assert OrganizationMembership is not None assert User is not None from workos.events.models import EventSchema diff --git a/tests/test_audit_logs.py b/tests/test_audit_logs.py index 2608de20..d15bcb97 100644 --- a/tests/test_audit_logs.py +++ b/tests/test_audit_logs.py @@ -7,14 +7,14 @@ from tests.generated_helpers import load_fixture from workos.audit_logs.models import ( - AuditLogActionJson, + AuditLogAction, AuditLogEvent, AuditLogEventCreateResponse, - AuditLogExportJson, - AuditLogSchemaJson, + AuditLogExport, + AuditLogSchema, ) from workos.common.models import PaginationOrder -from workos.organizations.models import AuditLogsRetentionJson +from workos.organizations.models import AuditLogsRetention from workos._pagination import AsyncPage, SyncPage from workos._errors import ( AuthenticationError, @@ -29,10 +29,10 @@ class TestAuditLogs: def test_get_organization_audit_logs_retention(self, workos, httpx_mock): httpx_mock.add_response( - json=load_fixture("audit_logs_retention_json.json"), + json=load_fixture("audit_logs_retention.json"), ) result = workos.audit_logs.get_organization_audit_logs_retention("test_id") - assert isinstance(result, AuditLogsRetentionJson) + assert isinstance(result, AuditLogsRetention) assert result.retention_period_in_days == 30 request = httpx_mock.get_request() assert request.method == "GET" @@ -40,12 +40,12 @@ def test_get_organization_audit_logs_retention(self, workos, httpx_mock): def test_update_organization_audit_logs_retention(self, workos, httpx_mock): httpx_mock.add_response( - json=load_fixture("audit_logs_retention_json.json"), + json=load_fixture("audit_logs_retention.json"), ) result = workos.audit_logs.update_organization_audit_logs_retention( "test_id", retention_period_in_days=1 ) - assert isinstance(result, AuditLogsRetentionJson) + assert isinstance(result, AuditLogsRetention) assert result.retention_period_in_days == 30 request = httpx_mock.get_request() assert request.method == "PUT" @@ -55,12 +55,12 @@ def test_update_organization_audit_logs_retention(self, workos, httpx_mock): def test_list_actions(self, workos, httpx_mock): httpx_mock.add_response( - json=load_fixture("list_audit_log_action_json.json"), + json=load_fixture("list_audit_log_action.json"), ) page = workos.audit_logs.list_actions() assert isinstance(page, SyncPage) assert len(page.data) == 1 - assert isinstance(page.data[0], AuditLogActionJson) + assert isinstance(page.data[0], AuditLogAction) def test_list_actions_empty_page(self, workos, httpx_mock): httpx_mock.add_response(json={"data": [], "list_metadata": {}}) @@ -84,12 +84,12 @@ def test_list_actions_encodes_query_params(self, workos, httpx_mock): def test_list_action_schemas(self, workos, httpx_mock): httpx_mock.add_response( - json=load_fixture("list_audit_log_schema_json.json"), + json=load_fixture("list_audit_log_schema.json"), ) page = workos.audit_logs.list_action_schemas("test_actionName") assert isinstance(page, SyncPage) assert len(page.data) == 1 - assert isinstance(page.data[0], AuditLogSchemaJson) + assert isinstance(page.data[0], AuditLogSchema) def test_list_action_schemas_empty_page(self, workos, httpx_mock): httpx_mock.add_response(json={"data": [], "list_metadata": {}}) @@ -114,10 +114,10 @@ def test_list_action_schemas_encodes_query_params(self, workos, httpx_mock): def test_create_schema(self, workos, httpx_mock): httpx_mock.add_response( - json=load_fixture("audit_log_schema_json.json"), + json=load_fixture("audit_log_schema.json"), ) result = workos.audit_logs.create_schema("test_actionName", targets=[]) - assert isinstance(result, AuditLogSchemaJson) + assert isinstance(result, AuditLogSchema) assert result.object == "audit_log_schema" assert result.version == 1 request = httpx_mock.get_request() @@ -145,14 +145,14 @@ def test_create_event(self, workos, httpx_mock): def test_create_export(self, workos, httpx_mock): httpx_mock.add_response( - json=load_fixture("audit_log_export_json.json"), + json=load_fixture("audit_log_export.json"), ) result = workos.audit_logs.create_export( organization_id="test_organization_id", range_start="test_range_start", range_end="test_range_end", ) - assert isinstance(result, AuditLogExportJson) + assert isinstance(result, AuditLogExport) assert result.object == "audit_log_export" assert result.id == "audit_log_export_01GBZK5MP7TD1YCFQHFR22180V" request = httpx_mock.get_request() @@ -165,10 +165,10 @@ def test_create_export(self, workos, httpx_mock): def test_get_export(self, workos, httpx_mock): httpx_mock.add_response( - json=load_fixture("audit_log_export_json.json"), + json=load_fixture("audit_log_export.json"), ) result = workos.audit_logs.get_export("test_auditLogExportId") - assert isinstance(result, AuditLogExportJson) + assert isinstance(result, AuditLogExport) assert result.object == "audit_log_export" assert result.id == "audit_log_export_01GBZK5MP7TD1YCFQHFR22180V" request = httpx_mock.get_request() @@ -178,7 +178,7 @@ def test_get_export(self, workos, httpx_mock): def test_get_organization_audit_logs_retention_with_request_options( self, workos, httpx_mock ): - httpx_mock.add_response(json=load_fixture("audit_logs_retention_json.json")) + httpx_mock.add_response(json=load_fixture("audit_logs_retention.json")) workos.audit_logs.get_organization_audit_logs_retention( "test_id", request_options={"extra_headers": {"X-Custom": "value"}} ) @@ -260,11 +260,11 @@ class TestAsyncAuditLogs: async def test_get_organization_audit_logs_retention( self, async_workos, httpx_mock ): - httpx_mock.add_response(json=load_fixture("audit_logs_retention_json.json")) + httpx_mock.add_response(json=load_fixture("audit_logs_retention.json")) result = await async_workos.audit_logs.get_organization_audit_logs_retention( "test_id" ) - assert isinstance(result, AuditLogsRetentionJson) + assert isinstance(result, AuditLogsRetention) assert result.retention_period_in_days == 30 request = httpx_mock.get_request() assert request.method == "GET" @@ -274,11 +274,11 @@ async def test_get_organization_audit_logs_retention( async def test_update_organization_audit_logs_retention( self, async_workos, httpx_mock ): - httpx_mock.add_response(json=load_fixture("audit_logs_retention_json.json")) + httpx_mock.add_response(json=load_fixture("audit_logs_retention.json")) result = await async_workos.audit_logs.update_organization_audit_logs_retention( "test_id", retention_period_in_days=1 ) - assert isinstance(result, AuditLogsRetentionJson) + assert isinstance(result, AuditLogsRetention) assert result.retention_period_in_days == 30 request = httpx_mock.get_request() assert request.method == "PUT" @@ -286,11 +286,11 @@ async def test_update_organization_audit_logs_retention( @pytest.mark.asyncio async def test_list_actions(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("list_audit_log_action_json.json")) + httpx_mock.add_response(json=load_fixture("list_audit_log_action.json")) page = await async_workos.audit_logs.list_actions() assert isinstance(page, AsyncPage) assert len(page.data) == 1 - assert isinstance(page.data[0], AuditLogActionJson) + assert isinstance(page.data[0], AuditLogAction) @pytest.mark.asyncio async def test_list_actions_empty_page(self, async_workos, httpx_mock): @@ -316,11 +316,11 @@ async def test_list_actions_encodes_query_params(self, async_workos, httpx_mock) @pytest.mark.asyncio async def test_list_action_schemas(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("list_audit_log_schema_json.json")) + httpx_mock.add_response(json=load_fixture("list_audit_log_schema.json")) page = await async_workos.audit_logs.list_action_schemas("test_actionName") assert isinstance(page, AsyncPage) assert len(page.data) == 1 - assert isinstance(page.data[0], AuditLogSchemaJson) + assert isinstance(page.data[0], AuditLogSchema) @pytest.mark.asyncio async def test_list_action_schemas_empty_page(self, async_workos, httpx_mock): @@ -349,11 +349,11 @@ async def test_list_action_schemas_encodes_query_params( @pytest.mark.asyncio async def test_create_schema(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("audit_log_schema_json.json")) + httpx_mock.add_response(json=load_fixture("audit_log_schema.json")) result = await async_workos.audit_logs.create_schema( "test_actionName", targets=[] ) - assert isinstance(result, AuditLogSchemaJson) + assert isinstance(result, AuditLogSchema) assert result.object == "audit_log_schema" assert result.version == 1 request = httpx_mock.get_request() @@ -377,13 +377,13 @@ async def test_create_event(self, async_workos, httpx_mock): @pytest.mark.asyncio async def test_create_export(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("audit_log_export_json.json")) + httpx_mock.add_response(json=load_fixture("audit_log_export.json")) result = await async_workos.audit_logs.create_export( organization_id="test_organization_id", range_start="test_range_start", range_end="test_range_end", ) - assert isinstance(result, AuditLogExportJson) + assert isinstance(result, AuditLogExport) assert result.object == "audit_log_export" assert result.id == "audit_log_export_01GBZK5MP7TD1YCFQHFR22180V" request = httpx_mock.get_request() @@ -392,9 +392,9 @@ async def test_create_export(self, async_workos, httpx_mock): @pytest.mark.asyncio async def test_get_export(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("audit_log_export_json.json")) + httpx_mock.add_response(json=load_fixture("audit_log_export.json")) result = await async_workos.audit_logs.get_export("test_auditLogExportId") - assert isinstance(result, AuditLogExportJson) + assert isinstance(result, AuditLogExport) assert result.object == "audit_log_export" assert result.id == "audit_log_export_01GBZK5MP7TD1YCFQHFR22180V" request = httpx_mock.get_request() @@ -405,7 +405,7 @@ async def test_get_export(self, async_workos, httpx_mock): async def test_get_organization_audit_logs_retention_with_request_options( self, async_workos, httpx_mock ): - httpx_mock.add_response(json=load_fixture("audit_logs_retention_json.json")) + httpx_mock.add_response(json=load_fixture("audit_logs_retention.json")) await async_workos.audit_logs.get_organization_audit_logs_retention( "test_id", request_options={"extra_headers": {"X-Custom": "value"}} ) diff --git a/tests/test_authorization.py b/tests/test_authorization.py index dbaae3cf..2805ab1f 100644 --- a/tests/test_authorization.py +++ b/tests/test_authorization.py @@ -210,12 +210,23 @@ def test_list_role_assignments_encodes_query_params(self, workos, httpx_mock): before="cursor before", after="cursor/after", order=PaginationOrder("value_order"), + resource_id="value resource_id/test", + resource_external_id="value resource_external_id/test", + resource_type_slug="value resource_type_slug/test", ) request = httpx_mock.get_request() assert request.url.params["limit"] == "10" assert request.url.params["before"] == "cursor before" assert request.url.params["after"] == "cursor/after" assert request.url.params["order"] == "value_order" + assert request.url.params["resource_id"] == "value resource_id/test" + assert ( + request.url.params["resource_external_id"] + == "value resource_external_id/test" + ) + assert ( + request.url.params["resource_type_slug"] == "value resource_type_slug/test" + ) def test_assign_role(self, workos, httpx_mock): httpx_mock.add_response( @@ -531,12 +542,14 @@ def test_list_role_assignments_for_resource_by_external_id_encodes_query_params( before="cursor before", after="cursor/after", order=PaginationOrder("value_order"), + role_slug="value role_slug/test", ) request = httpx_mock.get_request() assert request.url.params["limit"] == "10" assert request.url.params["before"] == "cursor before" assert request.url.params["after"] == "cursor/after" assert request.url.params["order"] == "value_order" + assert request.url.params["role_slug"] == "value role_slug/test" def test_list_resources(self, workos, httpx_mock): httpx_mock.add_response( @@ -568,7 +581,6 @@ def test_list_resources_encodes_query_params(self, workos, httpx_mock): organization_id="value organization_id/test", resource_type_slug="value resource_type_slug/test", resource_external_id="value resource_external_id/test", - search="value search/test", ) request = httpx_mock.get_request() assert ( @@ -586,7 +598,6 @@ def test_list_resources_encodes_query_params(self, workos, httpx_mock): request.url.params["resource_external_id"] == "value resource_external_id/test" ) - assert request.url.params["search"] == "value search/test" def test_create_resource(self, workos, httpx_mock): httpx_mock.add_response( @@ -721,12 +732,14 @@ def test_list_role_assignments_for_resource_encodes_query_params( before="cursor before", after="cursor/after", order=PaginationOrder("value_order"), + role_slug="value role_slug/test", ) request = httpx_mock.get_request() assert request.url.params["limit"] == "10" assert request.url.params["before"] == "cursor before" assert request.url.params["after"] == "cursor/after" assert request.url.params["order"] == "value_order" + assert request.url.params["role_slug"] == "value role_slug/test" def test_list_environment_roles(self, workos, httpx_mock): httpx_mock.add_response( @@ -1182,12 +1195,23 @@ async def test_list_role_assignments_encodes_query_params( before="cursor before", after="cursor/after", order=PaginationOrder("value_order"), + resource_id="value resource_id/test", + resource_external_id="value resource_external_id/test", + resource_type_slug="value resource_type_slug/test", ) request = httpx_mock.get_request() assert request.url.params["limit"] == "10" assert request.url.params["before"] == "cursor before" assert request.url.params["after"] == "cursor/after" assert request.url.params["order"] == "value_order" + assert request.url.params["resource_id"] == "value resource_id/test" + assert ( + request.url.params["resource_external_id"] + == "value resource_external_id/test" + ) + assert ( + request.url.params["resource_type_slug"] == "value resource_type_slug/test" + ) @pytest.mark.asyncio async def test_assign_role(self, async_workos, httpx_mock): @@ -1500,12 +1524,14 @@ async def test_list_role_assignments_for_resource_by_external_id_encodes_query_p before="cursor before", after="cursor/after", order=PaginationOrder("value_order"), + role_slug="value role_slug/test", ) request = httpx_mock.get_request() assert request.url.params["limit"] == "10" assert request.url.params["before"] == "cursor before" assert request.url.params["after"] == "cursor/after" assert request.url.params["order"] == "value_order" + assert request.url.params["role_slug"] == "value role_slug/test" @pytest.mark.asyncio async def test_list_resources(self, async_workos, httpx_mock): @@ -1538,7 +1564,6 @@ async def test_list_resources_encodes_query_params(self, async_workos, httpx_moc organization_id="value organization_id/test", resource_type_slug="value resource_type_slug/test", resource_external_id="value resource_external_id/test", - search="value search/test", ) request = httpx_mock.get_request() assert ( @@ -1556,7 +1581,6 @@ async def test_list_resources_encodes_query_params(self, async_workos, httpx_moc request.url.params["resource_external_id"] == "value resource_external_id/test" ) - assert request.url.params["search"] == "value search/test" @pytest.mark.asyncio async def test_create_resource(self, async_workos, httpx_mock): @@ -1695,12 +1719,14 @@ async def test_list_role_assignments_for_resource_encodes_query_params( before="cursor before", after="cursor/after", order=PaginationOrder("value_order"), + role_slug="value role_slug/test", ) request = httpx_mock.get_request() assert request.url.params["limit"] == "10" assert request.url.params["before"] == "cursor before" assert request.url.params["after"] == "cursor/after" assert request.url.params["order"] == "value_order" + assert request.url.params["role_slug"] == "value role_slug/test" @pytest.mark.asyncio async def test_list_environment_roles(self, async_workos, httpx_mock): diff --git a/tests/test_connect.py b/tests/test_connect.py index e031957b..03499bd4 100644 --- a/tests/test_connect.py +++ b/tests/test_connect.py @@ -6,7 +6,7 @@ from workos import WorkOSClient, AsyncWorkOSClient from tests.generated_helpers import load_fixture -from workos.common.models import ConnectApplication, PaginationOrder +from workos.common.models import ConnectApplicationOAuth, PaginationOrder from workos.connect.models import ( ApplicationCredentialsListItem, ExternalAuthCompleteResponse, @@ -52,7 +52,7 @@ def test_list_applications(self, workos, httpx_mock): page = workos.connect.list_applications() assert isinstance(page, SyncPage) assert len(page.data) == 1 - assert isinstance(page.data[0], ConnectApplication) + assert isinstance(page.data[0], ConnectApplicationOAuth) def test_list_applications_empty_page(self, workos, httpx_mock): httpx_mock.add_response(json={"data": [], "list_metadata": {}}) @@ -83,7 +83,7 @@ def test_create_application(self, workos, httpx_mock): result = workos.connect.create_application( body=load_fixture("create_oauth_application.json") ) - assert isinstance(result, ConnectApplication) + assert isinstance(result, ConnectApplicationOAuth) assert result.object == "connect_application" assert result.id == "conn_app_01HXYZ123456789ABCDEFGHIJ" request = httpx_mock.get_request() @@ -95,7 +95,7 @@ def test_get_application(self, workos, httpx_mock): json=load_fixture("connect_application.json"), ) result = workos.connect.get_application("test_id") - assert isinstance(result, ConnectApplication) + assert isinstance(result, ConnectApplicationOAuth) assert result.object == "connect_application" assert result.id == "conn_app_01HXYZ123456789ABCDEFGHIJ" request = httpx_mock.get_request() @@ -107,7 +107,7 @@ def test_update_application(self, workos, httpx_mock): json=load_fixture("connect_application.json"), ) result = workos.connect.update_application("test_id") - assert isinstance(result, ConnectApplication) + assert isinstance(result, ConnectApplicationOAuth) assert result.object == "connect_application" assert result.id == "conn_app_01HXYZ123456789ABCDEFGHIJ" request = httpx_mock.get_request() @@ -156,7 +156,7 @@ def test_create_oauth_application(self, workos, httpx_mock): result = workos.connect.create_oauth_application( name="test_name", is_first_party=True ) - assert isinstance(result, ConnectApplication) + assert isinstance(result, ConnectApplicationOAuth) request = httpx_mock.get_request() assert request.method == "POST" body = json.loads(request.content) @@ -167,7 +167,7 @@ def test_create_m2m_application(self, workos, httpx_mock): result = workos.connect.create_m2m_application( name="test_name", organization_id="test_organization_id" ) - assert isinstance(result, ConnectApplication) + assert isinstance(result, ConnectApplicationOAuth) request = httpx_mock.get_request() assert request.method == "POST" body = json.loads(request.content) @@ -296,7 +296,7 @@ async def test_list_applications(self, async_workos, httpx_mock): page = await async_workos.connect.list_applications() assert isinstance(page, AsyncPage) assert len(page.data) == 1 - assert isinstance(page.data[0], ConnectApplication) + assert isinstance(page.data[0], ConnectApplicationOAuth) @pytest.mark.asyncio async def test_list_applications_empty_page(self, async_workos, httpx_mock): @@ -330,7 +330,7 @@ async def test_create_application(self, async_workos, httpx_mock): result = await async_workos.connect.create_application( body=load_fixture("create_oauth_application.json") ) - assert isinstance(result, ConnectApplication) + assert isinstance(result, ConnectApplicationOAuth) assert result.object == "connect_application" assert result.id == "conn_app_01HXYZ123456789ABCDEFGHIJ" request = httpx_mock.get_request() @@ -341,7 +341,7 @@ async def test_create_application(self, async_workos, httpx_mock): async def test_get_application(self, async_workos, httpx_mock): httpx_mock.add_response(json=load_fixture("connect_application.json")) result = await async_workos.connect.get_application("test_id") - assert isinstance(result, ConnectApplication) + assert isinstance(result, ConnectApplicationOAuth) assert result.object == "connect_application" assert result.id == "conn_app_01HXYZ123456789ABCDEFGHIJ" request = httpx_mock.get_request() @@ -352,7 +352,7 @@ async def test_get_application(self, async_workos, httpx_mock): async def test_update_application(self, async_workos, httpx_mock): httpx_mock.add_response(json=load_fixture("connect_application.json")) result = await async_workos.connect.update_application("test_id") - assert isinstance(result, ConnectApplication) + assert isinstance(result, ConnectApplicationOAuth) assert result.object == "connect_application" assert result.id == "conn_app_01HXYZ123456789ABCDEFGHIJ" request = httpx_mock.get_request() @@ -406,7 +406,7 @@ async def test_create_oauth_application(self, async_workos, httpx_mock): result = await async_workos.connect.create_oauth_application( name="test_name", is_first_party=True ) - assert isinstance(result, ConnectApplication) + assert isinstance(result, ConnectApplicationOAuth) request = httpx_mock.get_request() assert request.method == "POST" body = json.loads(request.content) @@ -418,7 +418,7 @@ async def test_create_m2m_application(self, async_workos, httpx_mock): result = await async_workos.connect.create_m2m_application( name="test_name", organization_id="test_organization_id" ) - assert isinstance(result, ConnectApplication) + assert isinstance(result, ConnectApplicationOAuth) request = httpx_mock.get_request() assert request.method == "POST" body = json.loads(request.content) diff --git a/tests/test_events.py b/tests/test_events.py index 5b4e9686..d91a3765 100644 --- a/tests/test_events.py +++ b/tests/test_events.py @@ -5,7 +5,7 @@ from workos import WorkOSClient, AsyncWorkOSClient from tests.generated_helpers import load_fixture -from workos.common.models import DsyncUserCreated, PaginationOrder +from workos.common.models import ActionAuthenticationDenied, PaginationOrder from workos._pagination import AsyncPage, SyncPage from workos._errors import ( AuthenticationError, @@ -25,7 +25,7 @@ def test_list_events(self, workos, httpx_mock): page = workos.events.list_events() assert isinstance(page, SyncPage) assert len(page.data) == 1 - assert isinstance(page.data[0], DsyncUserCreated) + assert isinstance(page.data[0], ActionAuthenticationDenied) def test_list_events_empty_page(self, workos, httpx_mock): httpx_mock.add_response(json={"data": [], "list_metadata": {}}) @@ -138,7 +138,7 @@ async def test_list_events(self, async_workos, httpx_mock): page = await async_workos.events.list_events() assert isinstance(page, AsyncPage) assert len(page.data) == 1 - assert isinstance(page.data[0], DsyncUserCreated) + assert isinstance(page.data[0], ActionAuthenticationDenied) @pytest.mark.asyncio async def test_list_events_empty_page(self, async_workos, httpx_mock): diff --git a/tests/test_models_round_trip.py b/tests/test_models_round_trip.py index cc3ba292..a118065a 100644 --- a/tests/test_models_round_trip.py +++ b/tests/test_models_round_trip.py @@ -22,18 +22,18 @@ OrganizationApiKeyWithValueOwner, ) from workos.audit_logs.models import ( - AuditLogActionJson, + AuditLogAction, AuditLogEvent, AuditLogEventActor, AuditLogEventContext, AuditLogEventCreateResponse, AuditLogEventTarget, - AuditLogExportJson, + AuditLogExport, + AuditLogSchema, AuditLogSchemaActor, - AuditLogSchemaJson, - AuditLogSchemaJsonActor, - AuditLogSchemaJsonTarget, + AuditLogSchemaActorInput, AuditLogSchemaTarget, + AuditLogSchemaTargetInput, ) from workos.authorization.models import ( AuthorizationCheck, @@ -104,6 +104,9 @@ AuthenticationSSOTimedOutData, AuthenticationSSOTimedOutDataError, AuthenticationSSOTimedOutDataSSO, + ConnectApplicationM2M, + ConnectApplicationOAuth, + ConnectApplicationOAuthRedirectUris, ConnectionActivated, ConnectionActivatedData, ConnectionActivatedDataDomain, @@ -145,6 +148,7 @@ DsyncUserUpdatedDataEmail, EmailVerificationCreated, EmailVerificationCreatedData, + ErrorResponse, EventContext, EventContextActor, EventContextGoogleAnalyticsSession, @@ -238,6 +242,10 @@ PermissionDeletedData, PermissionUpdated, PermissionUpdatedData, + PipeConnectedAccount, + PipesConnectedAccountConnected, + PipesConnectedAccountDisconnected, + PipesConnectedAccountReauthorizationNeeded, RoleCreated, RoleCreatedData, RoleDeleted, @@ -285,6 +293,7 @@ from workos.connect.models import ( ApplicationCredentialsListItem, ConnectApplication, + ConnectApplicationUnknown, ExternalAuthCompleteResponse, NewConnectApplicationSecret, RedirectUriInput, @@ -318,10 +327,14 @@ OrganizationDomain, OrganizationDomainStandAlone, ) +from workos.organization_membership.models import ( + OrganizationMembership, + UserOrganizationMembership, +) from workos.organizations.models import ( AuditLogConfiguration, AuditLogConfigurationLogStream, - AuditLogsRetentionJson, + AuditLogsRetention, Organization, OrganizationDomainData, ) @@ -364,7 +377,6 @@ JwksResponse, JwksResponseKeys, MagicAuth, - OrganizationMembership, PasswordReset, RedirectUri, ResetPasswordResponse, @@ -376,12 +388,24 @@ UserApiKeyWithValueOwner, UserIdentitiesGetItem, UserInvite, - UserOrganizationMembership, UserSessionsImpersonator, UserSessionsListItem, VerifyEmailResponse, ) -from workos.webhooks.models import WebhookEndpointJson +from workos.vault.models import ( + Actor, + CreateDataKeyResponse, + DecryptResponse, + DeleteObjectResponse, + ListMetadata, + ObjectMetadata, + ObjectSummary, + ObjectVersion, + ObjectWithoutValue, + VaultObject, + VersionListResponse, +) +from workos.webhooks.models import WebhookEndpoint from workos.widgets.models import WidgetSessionTokenResponse @@ -528,7 +552,7 @@ def test_audit_log_event_round_trip(self): def test_audit_log_event_minimal_payload(self): data = { "action": "user.signed_in", - "occurred_at": "2026-02-02T16:35:39.317Z", + "occurred_at": "2026-02-02T16:35:39.000Z", "actor": { "id": "user_TF4C5938", "type": "user", @@ -559,7 +583,7 @@ def test_audit_log_event_minimal_payload(self): def test_audit_log_event_omits_absent_optional_non_nullable_fields(self): data = { "action": "user.signed_in", - "occurred_at": "2026-02-02T16:35:39.317Z", + "occurred_at": "2026-02-02T16:35:39.000Z", "actor": { "id": "user_TF4C5938", "type": "user", @@ -584,39 +608,41 @@ def test_audit_log_event_omits_absent_optional_non_nullable_fields(self): assert "metadata" not in serialized assert "version" not in serialized - def test_audit_log_schema_actor_round_trip(self): - data = load_fixture("audit_log_schema_actor.json") - instance = AuditLogSchemaActor.from_dict(data) + def test_audit_log_schema_actor_input_round_trip(self): + data = load_fixture("audit_log_schema_actor_input.json") + instance = AuditLogSchemaActorInput.from_dict(data) serialized = instance.to_dict() assert serialized == data - restored = AuditLogSchemaActor.from_dict(serialized) + restored = AuditLogSchemaActorInput.from_dict(serialized) assert restored.to_dict() == serialized - def test_audit_log_schema_actor_minimal_payload(self): + def test_audit_log_schema_actor_input_minimal_payload(self): data = { "metadata": {"type": "object", "properties": {"role": {"type": "string"}}} } - instance = AuditLogSchemaActor.from_dict(data) + instance = AuditLogSchemaActorInput.from_dict(data) serialized = instance.to_dict() assert serialized["metadata"] == data["metadata"] - def test_audit_log_schema_target_round_trip(self): - data = load_fixture("audit_log_schema_target.json") - instance = AuditLogSchemaTarget.from_dict(data) + def test_audit_log_schema_target_input_round_trip(self): + data = load_fixture("audit_log_schema_target_input.json") + instance = AuditLogSchemaTargetInput.from_dict(data) serialized = instance.to_dict() assert serialized == data - restored = AuditLogSchemaTarget.from_dict(serialized) + restored = AuditLogSchemaTargetInput.from_dict(serialized) assert restored.to_dict() == serialized - def test_audit_log_schema_target_minimal_payload(self): + def test_audit_log_schema_target_input_minimal_payload(self): data = {"type": "invoice"} - instance = AuditLogSchemaTarget.from_dict(data) + instance = AuditLogSchemaTargetInput.from_dict(data) serialized = instance.to_dict() assert serialized["type"] == data["type"] - def test_audit_log_schema_target_omits_absent_optional_non_nullable_fields(self): + def test_audit_log_schema_target_input_omits_absent_optional_non_nullable_fields( + self, + ): data = {"type": "invoice"} - instance = AuditLogSchemaTarget.from_dict(data) + instance = AuditLogSchemaTargetInput.from_dict(data) serialized = instance.to_dict() assert "metadata" not in serialized @@ -704,6 +730,298 @@ def test_intent_options_omits_absent_optional_non_nullable_fields(self): assert "sso" not in serialized assert "domain_verification" not in serialized + def test_actor_round_trip(self): + data = load_fixture("actor.json") + instance = Actor.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = Actor.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_actor_minimal_payload(self): + data = {"id": "key_01K8ZYT4AWJ6XP0E0S8CTBHE3P", "name": "My API Key"} + instance = Actor.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["name"] == data["name"] + + def test_create_data_key_response_round_trip(self): + data = load_fixture("create_data_key_response.json") + instance = CreateDataKeyResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = CreateDataKeyResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_create_data_key_response_minimal_payload(self): + data = { + "context": {"organization_id": "org_01K8ZYT4AWJ6XP0E0S8CTBHE3P"}, + "data_key": "DR9idtey9MpMrA1VRFrz30HB1yNgL2PoHZyjAkFeWgg=", + "encrypted_keys": "V09TLkVLTS52MQBiZjUxY2NlYy03OGI0LTUyMDAtYjM4My0zNTczMGU3MWVmNjEBATEBJGJmNjVlMzI2LTQzYTAtNGIyMC04OGM0LTA3ZmYzZGU1NDM0YwF0YmY2NWUzMjYtNDNhMC00YjIwLTg4YzQtMDdmZjNkZTU0MzRj", + "id": "bf51ccec-78b4-5200-b383-35730e71ef61", + } + instance = CreateDataKeyResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["context"] == data["context"] + assert serialized["data_key"] == data["data_key"] + assert serialized["encrypted_keys"] == data["encrypted_keys"] + assert serialized["id"] == data["id"] + + def test_decrypt_response_round_trip(self): + data = load_fixture("decrypt_response.json") + instance = DecryptResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DecryptResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_decrypt_response_minimal_payload(self): + data = { + "data_key": "DR9idtey9MpMrA1VRFrz30HB1yNgL2PoHZyjAkFeWgg=", + "id": "bf51ccec-78b4-5200-b383-35730e71ef61", + } + instance = DecryptResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["data_key"] == data["data_key"] + assert serialized["id"] == data["id"] + + def test_delete_object_response_round_trip(self): + data = load_fixture("delete_object_response.json") + instance = DeleteObjectResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = DeleteObjectResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_delete_object_response_minimal_payload(self): + data = {"name": "my-secret", "success": True} + instance = DeleteObjectResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["name"] == data["name"] + assert serialized["success"] == data["success"] + + def test_error_response_round_trip(self): + data = load_fixture("error_response.json") + instance = ErrorResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ErrorResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_error_response_minimal_payload(self): + data = {"error": "Invalid request parameters."} + instance = ErrorResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["error"] == data["error"] + + def test_list_metadata_round_trip(self): + data = load_fixture("list_metadata.json") + instance = ListMetadata.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ListMetadata.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_list_metadata_minimal_payload(self): + data = {} + instance = ListMetadata.from_dict(data) + assert instance.to_dict() is not None + + def test_list_metadata_preserves_nullable_fields(self): + data = {"after": None, "before": None} + instance = ListMetadata.from_dict(data) + serialized = instance.to_dict() + assert serialized["after"] is None + assert serialized["before"] is None + + def test_vault_object_round_trip(self): + data = load_fixture("vault_object.json") + instance = VaultObject.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VaultObject.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_vault_object_minimal_payload(self): + data = { + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "metadata": { + "context": {"organization_id": "org_01K8ZYT4AWJ6XP0E0S8CTBHE3P"}, + "environment_id": "environment_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "key_id": "bf65e326-43a0-4b20-88c4-07ff3de5434c", + "updated_at": "2024-06-15T10:30:00.000Z", + "updated_by": { + "id": "key_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "name": "My API Key", + }, + "version_id": "c3d4e5f6-7890-abcd-ef12-34567890abcd", + }, + "name": "my-secret", + "value": "s3cr3t-v4lu3", + } + instance = VaultObject.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["metadata"] == data["metadata"] + assert serialized["name"] == data["name"] + assert serialized["value"] == data["value"] + + def test_object_metadata_round_trip(self): + data = load_fixture("object_metadata.json") + instance = ObjectMetadata.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ObjectMetadata.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_object_metadata_minimal_payload(self): + data = { + "context": {"organization_id": "org_01K8ZYT4AWJ6XP0E0S8CTBHE3P"}, + "environment_id": "environment_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "key_id": "bf65e326-43a0-4b20-88c4-07ff3de5434c", + "updated_at": "2024-06-15T10:30:00.000Z", + "updated_by": { + "id": "key_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "name": "My API Key", + }, + } + instance = ObjectMetadata.from_dict(data) + serialized = instance.to_dict() + assert serialized["context"] == data["context"] + assert serialized["environment_id"] == data["environment_id"] + assert serialized["id"] == data["id"] + assert serialized["key_id"] == data["key_id"] + assert serialized["updated_at"] == data["updated_at"] + assert serialized["updated_by"] == data["updated_by"] + + def test_object_metadata_preserves_nullable_fields(self): + data = { + "context": {"organization_id": "org_01K8ZYT4AWJ6XP0E0S8CTBHE3P"}, + "environment_id": "environment_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "key_id": "bf65e326-43a0-4b20-88c4-07ff3de5434c", + "updated_at": "2024-06-15T10:30:00.000Z", + "updated_by": { + "id": "key_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "name": "My API Key", + }, + "version_id": None, + } + instance = ObjectMetadata.from_dict(data) + serialized = instance.to_dict() + assert serialized["version_id"] is None + + def test_object_summary_round_trip(self): + data = load_fixture("object_summary.json") + instance = ObjectSummary.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ObjectSummary.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_object_summary_minimal_payload(self): + data = {"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "my-secret"} + instance = ObjectSummary.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["name"] == data["name"] + + def test_object_summary_preserves_nullable_fields(self): + data = { + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "name": "my-secret", + "updated_at": None, + } + instance = ObjectSummary.from_dict(data) + serialized = instance.to_dict() + assert serialized["updated_at"] is None + + def test_object_version_round_trip(self): + data = load_fixture("object_version.json") + instance = ObjectVersion.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ObjectVersion.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_object_version_minimal_payload(self): + data = { + "created_at": "2024-06-15T10:30:00.000Z", + "current_version": True, + "etag": "d41d8cd98f00b204e9800998ecf8427e", + "id": "c3d4e5f6-7890-abcd-ef12-34567890abcd", + "size": 256, + } + instance = ObjectVersion.from_dict(data) + serialized = instance.to_dict() + assert serialized["created_at"] == data["created_at"] + assert serialized["current_version"] == data["current_version"] + assert serialized["etag"] == data["etag"] + assert serialized["id"] == data["id"] + assert serialized["size"] == data["size"] + + def test_object_without_value_round_trip(self): + data = load_fixture("object_without_value.json") + instance = ObjectWithoutValue.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ObjectWithoutValue.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_object_without_value_minimal_payload(self): + data = { + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "metadata": { + "context": {"organization_id": "org_01K8ZYT4AWJ6XP0E0S8CTBHE3P"}, + "environment_id": "environment_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "key_id": "bf65e326-43a0-4b20-88c4-07ff3de5434c", + "updated_at": "2024-06-15T10:30:00.000Z", + "updated_by": { + "id": "key_01K8ZYT4AWJ6XP0E0S8CTBHE3P", + "name": "My API Key", + }, + "version_id": "c3d4e5f6-7890-abcd-ef12-34567890abcd", + }, + "name": "my-secret", + } + instance = ObjectWithoutValue.from_dict(data) + serialized = instance.to_dict() + assert serialized["id"] == data["id"] + assert serialized["metadata"] == data["metadata"] + assert serialized["name"] == data["name"] + + def test_version_list_response_round_trip(self): + data = load_fixture("version_list_response.json") + instance = VersionListResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = VersionListResponse.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_version_list_response_minimal_payload(self): + data = { + "data": [ + { + "created_at": "2024-06-15T10:30:00.000Z", + "current_version": True, + "etag": "d41d8cd98f00b204e9800998ecf8427e", + "id": "c3d4e5f6-7890-abcd-ef12-34567890abcd", + "size": 256, + } + ], + "list_metadata": { + "after": "b21f3a8c-7e4d-4b1a-9c5e-2d8f6a7b3c4e", + "before": "a10e2b7d-6c3f-4a2b-8d1e-3f9a5b8c7d6e", + }, + } + instance = VersionListResponse.from_dict(data) + serialized = instance.to_dict() + assert serialized["data"] == data["data"] + assert serialized["list_metadata"] == data["list_metadata"] + def test_external_auth_complete_response_round_trip(self): data = load_fixture("external_auth_complete_response.json") instance = ExternalAuthCompleteResponse.from_dict(data) @@ -736,6 +1054,7 @@ def test_api_key_minimal_payload(self): "name": "Production API Key", "obfuscated_value": "sk_...3456", "last_used_at": None, + "expires_at": None, "permissions": ["posts:read", "posts:write"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -748,6 +1067,7 @@ def test_api_key_minimal_payload(self): assert serialized["name"] == data["name"] assert serialized["obfuscated_value"] == data["obfuscated_value"] assert serialized["last_used_at"] == data["last_used_at"] + assert serialized["expires_at"] == data["expires_at"] assert serialized["permissions"] == data["permissions"] assert serialized["created_at"] == data["created_at"] assert serialized["updated_at"] == data["updated_at"] @@ -760,6 +1080,7 @@ def test_api_key_preserves_nullable_fields(self): "name": "Production API Key", "obfuscated_value": "sk_...3456", "last_used_at": None, + "expires_at": None, "permissions": ["posts:read", "posts:write"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -767,6 +1088,7 @@ def test_api_key_preserves_nullable_fields(self): instance = ApiKey.from_dict(data) serialized = instance.to_dict() assert serialized["last_used_at"] is None + assert serialized["expires_at"] is None def test_api_key_validation_response_round_trip(self): data = load_fixture("api_key_validation_response.json") @@ -788,15 +1110,15 @@ def test_api_key_validation_response_preserves_nullable_fields(self): serialized = instance.to_dict() assert serialized["api_key"] is None - def test_connect_application_round_trip(self): - data = load_fixture("connect_application.json") - instance = ConnectApplication.from_dict(data) + def test_connect_application_oauth_round_trip(self): + data = load_fixture("connect_application_oauth.json") + instance = ConnectApplicationOAuth.from_dict(data) serialized = instance.to_dict() assert serialized == data - restored = ConnectApplication.from_dict(serialized) + restored = ConnectApplicationOAuth.from_dict(serialized) assert restored.to_dict() == serialized - def test_connect_application_minimal_payload(self): + def test_connect_application_oauth_minimal_payload(self): data = { "object": "connect_application", "id": "conn_app_01HXYZ123456789ABCDEFGHIJ", @@ -806,8 +1128,12 @@ def test_connect_application_minimal_payload(self): "scopes": ["openid", "profile", "email"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", + "application_type": "oauth", + "redirect_uris": [{"uri": "https://example.com/callback", "default": True}], + "uses_pkce": True, + "is_first_party": True, } - instance = ConnectApplication.from_dict(data) + instance = ConnectApplicationOAuth.from_dict(data) serialized = instance.to_dict() assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] @@ -817,8 +1143,12 @@ def test_connect_application_minimal_payload(self): assert serialized["scopes"] == data["scopes"] assert serialized["created_at"] == data["created_at"] assert serialized["updated_at"] == data["updated_at"] + assert serialized["application_type"] == data["application_type"] + assert serialized["redirect_uris"] == data["redirect_uris"] + assert serialized["uses_pkce"] == data["uses_pkce"] + assert serialized["is_first_party"] == data["is_first_party"] - def test_connect_application_omits_absent_optional_non_nullable_fields(self): + def test_connect_application_oauth_omits_absent_optional_non_nullable_fields(self): data = { "object": "connect_application", "id": "conn_app_01HXYZ123456789ABCDEFGHIJ", @@ -828,13 +1158,87 @@ def test_connect_application_omits_absent_optional_non_nullable_fields(self): "scopes": ["openid", "profile", "email"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", + "application_type": "oauth", + "redirect_uris": [{"uri": "https://example.com/callback", "default": True}], + "uses_pkce": True, + "is_first_party": True, } - instance = ConnectApplication.from_dict(data) + instance = ConnectApplicationOAuth.from_dict(data) serialized = instance.to_dict() - assert "application_type" not in serialized + assert "was_dynamically_registered" not in serialized assert "organization_id" not in serialized - def test_connect_application_preserves_nullable_fields(self): + def test_connect_application_oauth_preserves_nullable_fields(self): + data = { + "object": "connect_application", + "id": "conn_app_01HXYZ123456789ABCDEFGHIJ", + "client_id": "client_01HXYZ123456789ABCDEFGHIJ", + "description": None, + "name": "My Application", + "scopes": ["openid", "profile", "email"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "application_type": "oauth", + "redirect_uris": [{"uri": "https://example.com/callback", "default": True}], + "uses_pkce": True, + "is_first_party": True, + "was_dynamically_registered": True, + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + } + instance = ConnectApplicationOAuth.from_dict(data) + serialized = instance.to_dict() + assert serialized["description"] is None + + def test_connect_application_oauth_redirect_uris_round_trip(self): + data = load_fixture("connect_application_oauth_redirect_uris.json") + instance = ConnectApplicationOAuthRedirectUris.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ConnectApplicationOAuthRedirectUris.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_connect_application_oauth_redirect_uris_minimal_payload(self): + data = {"uri": "https://example.com/callback", "default": True} + instance = ConnectApplicationOAuthRedirectUris.from_dict(data) + serialized = instance.to_dict() + assert serialized["uri"] == data["uri"] + assert serialized["default"] == data["default"] + + def test_connect_application_m2m_round_trip(self): + data = load_fixture("connect_application_m2m.json") + instance = ConnectApplicationM2M.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = ConnectApplicationM2M.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_connect_application_m2m_minimal_payload(self): + data = { + "object": "connect_application", + "id": "conn_app_01HXYZ123456789ABCDEFGHIJ", + "client_id": "client_01HXYZ123456789ABCDEFGHIJ", + "description": None, + "name": "My Application", + "scopes": ["openid", "profile", "email"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "application_type": "m2m", + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + } + instance = ConnectApplicationM2M.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["client_id"] == data["client_id"] + assert serialized["description"] == data["description"] + assert serialized["name"] == data["name"] + assert serialized["scopes"] == data["scopes"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + assert serialized["application_type"] == data["application_type"] + assert serialized["organization_id"] == data["organization_id"] + + def test_connect_application_m2m_preserves_nullable_fields(self): data = { "object": "connect_application", "id": "conn_app_01HXYZ123456789ABCDEFGHIJ", @@ -847,7 +1251,7 @@ def test_connect_application_preserves_nullable_fields(self): "application_type": "m2m", "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", } - instance = ConnectApplication.from_dict(data) + instance = ConnectApplicationM2M.from_dict(data) serialized = instance.to_dict() assert serialized["description"] is None @@ -907,15 +1311,15 @@ def test_audit_log_event_create_response_minimal_payload(self): serialized = instance.to_dict() assert serialized["success"] == data["success"] - def test_audit_log_export_json_round_trip(self): - data = load_fixture("audit_log_export_json.json") - instance = AuditLogExportJson.from_dict(data) + def test_audit_log_export_round_trip(self): + data = load_fixture("audit_log_export.json") + instance = AuditLogExport.from_dict(data) serialized = instance.to_dict() assert serialized == data - restored = AuditLogExportJson.from_dict(serialized) + restored = AuditLogExport.from_dict(serialized) assert restored.to_dict() == serialized - def test_audit_log_export_json_minimal_payload(self): + def test_audit_log_export_minimal_payload(self): data = { "object": "audit_log_export", "id": "audit_log_export_01GBZK5MP7TD1YCFQHFR22180V", @@ -923,7 +1327,7 @@ def test_audit_log_export_json_minimal_payload(self): "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", } - instance = AuditLogExportJson.from_dict(data) + instance = AuditLogExport.from_dict(data) serialized = instance.to_dict() assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] @@ -931,7 +1335,7 @@ def test_audit_log_export_json_minimal_payload(self): assert serialized["created_at"] == data["created_at"] assert serialized["updated_at"] == data["updated_at"] - def test_audit_log_export_json_preserves_nullable_fields(self): + def test_audit_log_export_preserves_nullable_fields(self): data = { "object": "audit_log_export", "id": "audit_log_export_01GBZK5MP7TD1YCFQHFR22180V", @@ -940,53 +1344,53 @@ def test_audit_log_export_json_preserves_nullable_fields(self): "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", } - instance = AuditLogExportJson.from_dict(data) + instance = AuditLogExport.from_dict(data) serialized = instance.to_dict() assert serialized["url"] is None - def test_audit_log_export_json_round_trips_unknown_enum_values(self): + def test_audit_log_export_round_trips_unknown_enum_values(self): data = { "object": "audit_log_export", "id": "audit_log_export_01GBZK5MP7TD1YCFQHFR22180V", - "state": "unexpected_audit_log_export_json_state", + "state": "unexpected_audit_log_export_state", "url": "https://exports.audit-logs.com/audit-log-exports/export.csv", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", } - instance = AuditLogExportJson.from_dict(data) + instance = AuditLogExport.from_dict(data) assert instance.to_dict() == data - def test_audit_logs_retention_json_round_trip(self): - data = load_fixture("audit_logs_retention_json.json") - instance = AuditLogsRetentionJson.from_dict(data) + def test_audit_logs_retention_round_trip(self): + data = load_fixture("audit_logs_retention.json") + instance = AuditLogsRetention.from_dict(data) serialized = instance.to_dict() assert serialized == data - restored = AuditLogsRetentionJson.from_dict(serialized) + restored = AuditLogsRetention.from_dict(serialized) assert restored.to_dict() == serialized - def test_audit_logs_retention_json_minimal_payload(self): + def test_audit_logs_retention_minimal_payload(self): data = {"retention_period_in_days": None} - instance = AuditLogsRetentionJson.from_dict(data) + instance = AuditLogsRetention.from_dict(data) serialized = instance.to_dict() assert ( serialized["retention_period_in_days"] == data["retention_period_in_days"] ) - def test_audit_logs_retention_json_preserves_nullable_fields(self): + def test_audit_logs_retention_preserves_nullable_fields(self): data = {"retention_period_in_days": None} - instance = AuditLogsRetentionJson.from_dict(data) + instance = AuditLogsRetention.from_dict(data) serialized = instance.to_dict() assert serialized["retention_period_in_days"] is None - def test_audit_log_schema_json_round_trip(self): - data = load_fixture("audit_log_schema_json.json") - instance = AuditLogSchemaJson.from_dict(data) + def test_audit_log_schema_round_trip(self): + data = load_fixture("audit_log_schema.json") + instance = AuditLogSchema.from_dict(data) serialized = instance.to_dict() assert serialized == data - restored = AuditLogSchemaJson.from_dict(serialized) + restored = AuditLogSchema.from_dict(serialized) assert restored.to_dict() == serialized - def test_audit_log_schema_json_minimal_payload(self): + def test_audit_log_schema_minimal_payload(self): data = { "object": "audit_log_schema", "version": 1, @@ -1001,14 +1405,14 @@ def test_audit_log_schema_json_minimal_payload(self): ], "created_at": "2026-01-15T12:00:00.000Z", } - instance = AuditLogSchemaJson.from_dict(data) + instance = AuditLogSchema.from_dict(data) serialized = instance.to_dict() assert serialized["object"] == data["object"] assert serialized["version"] == data["version"] assert serialized["targets"] == data["targets"] assert serialized["created_at"] == data["created_at"] - def test_audit_log_schema_json_omits_absent_optional_non_nullable_fields(self): + def test_audit_log_schema_omits_absent_optional_non_nullable_fields(self): data = { "object": "audit_log_schema", "version": 1, @@ -1023,20 +1427,20 @@ def test_audit_log_schema_json_omits_absent_optional_non_nullable_fields(self): ], "created_at": "2026-01-15T12:00:00.000Z", } - instance = AuditLogSchemaJson.from_dict(data) + instance = AuditLogSchema.from_dict(data) serialized = instance.to_dict() assert "actor" not in serialized assert "metadata" not in serialized - def test_audit_log_action_json_round_trip(self): - data = load_fixture("audit_log_action_json.json") - instance = AuditLogActionJson.from_dict(data) + def test_audit_log_action_round_trip(self): + data = load_fixture("audit_log_action.json") + instance = AuditLogAction.from_dict(data) serialized = instance.to_dict() assert serialized == data - restored = AuditLogActionJson.from_dict(serialized) + restored = AuditLogAction.from_dict(serialized) assert restored.to_dict() == serialized - def test_audit_log_action_json_minimal_payload(self): + def test_audit_log_action_minimal_payload(self): data = { "object": "audit_log_action", "name": "user.viewed_invoice", @@ -1067,7 +1471,7 @@ def test_audit_log_action_json_minimal_payload(self): "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", } - instance = AuditLogActionJson.from_dict(data) + instance = AuditLogAction.from_dict(data) serialized = instance.to_dict() assert serialized["object"] == data["object"] assert serialized["name"] == data["name"] @@ -1559,7 +1963,7 @@ def test_user_omits_absent_optional_non_nullable_fields(self): "email": "marcelina.davis@example.com", "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -2244,6 +2648,74 @@ def test_directory_user_round_trips_unknown_enum_values(self): instance = DirectoryUser.from_dict(data) assert instance.to_dict() == data + def test_pipe_connected_account_round_trip(self): + data = load_fixture("pipe_connected_account.json") + instance = PipeConnectedAccount.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PipeConnectedAccount.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_pipe_connected_account_minimal_payload(self): + data = { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": None, + "organization_id": None, + "scopes": ["repo", "user:email"], + "state": "connected", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = PipeConnectedAccount.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["data_integration_id"] == data["data_integration_id"] + assert serialized["provider_slug"] == data["provider_slug"] + assert serialized["user_id"] == data["user_id"] + assert serialized["organization_id"] == data["organization_id"] + assert serialized["scopes"] == data["scopes"] + assert serialized["state"] == data["state"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_pipe_connected_account_preserves_nullable_fields(self): + data = { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": None, + "organization_id": None, + "scopes": ["repo", "user:email"], + "state": "connected", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = PipeConnectedAccount.from_dict(data) + serialized = instance.to_dict() + assert serialized["user_id"] is None + assert serialized["organization_id"] is None + + def test_pipe_connected_account_round_trips_unknown_enum_values(self): + data = { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "scopes": ["repo", "user:email"], + "state": "unexpected_pipe_connected_account_state", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = PipeConnectedAccount.from_dict(data) + assert instance.to_dict() == data + def test_waitlist_user_round_trip(self): data = load_fixture("waitlist_user.json") instance = WaitlistUser.from_dict(data) @@ -2309,6 +2781,7 @@ def test_action_authentication_denied_round_trip(self): def test_action_authentication_denied_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "action.authentication.denied", "data": { @@ -2323,20 +2796,20 @@ def test_action_authentication_denied_minimal_payload(self): "user_agent": "Mozilla/5.0", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = ActionAuthenticationDenied.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_action_authentication_denied_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "action.authentication.denied", "data": { @@ -2351,7 +2824,6 @@ def test_action_authentication_denied_omits_absent_optional_non_nullable_fields( "user_agent": "Mozilla/5.0", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = ActionAuthenticationDenied.from_dict(data) serialized = instance.to_dict() @@ -2417,6 +2889,7 @@ def test_action_user_registration_denied_round_trip(self): def test_action_user_registration_denied_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "action.user_registration.denied", "data": { @@ -2430,20 +2903,20 @@ def test_action_user_registration_denied_minimal_payload(self): "user_agent": "Mozilla/5.0", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = ActionUserRegistrationDenied.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_action_user_registration_denied_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "action.user_registration.denied", "data": { @@ -2457,7 +2930,6 @@ def test_action_user_registration_denied_omits_absent_optional_non_nullable_fiel "user_agent": "Mozilla/5.0", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = ActionUserRegistrationDenied.from_dict(data) serialized = instance.to_dict() @@ -2520,6 +2992,7 @@ def test_api_key_created_round_trip(self): def test_api_key_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "api_key.created", "data": { @@ -2532,23 +3005,24 @@ def test_api_key_created_minimal_payload(self): "name": "My API Key", "obfuscated_value": "sk_test_...1234", "last_used_at": "2026-01-15T12:00:00.000Z", + "expires_at": None, "permissions": ["users:read", "users:write"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = ApiKeyCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_api_key_created_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "api_key.created", "data": { @@ -2561,12 +3035,12 @@ def test_api_key_created_omits_absent_optional_non_nullable_fields(self): "name": "My API Key", "obfuscated_value": "sk_test_...1234", "last_used_at": "2026-01-15T12:00:00.000Z", + "expires_at": None, "permissions": ["users:read", "users:write"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = ApiKeyCreated.from_dict(data) serialized = instance.to_dict() @@ -2612,6 +3086,7 @@ def test_api_key_created_data_preserves_nullable_fields(self): "name": "My API Key", "obfuscated_value": "sk_test_...1234", "last_used_at": None, + "expires_at": None, "permissions": ["users:read", "users:write"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -2619,6 +3094,7 @@ def test_api_key_created_data_preserves_nullable_fields(self): instance = ApiKeyCreatedData.from_dict(data) serialized = instance.to_dict() assert serialized["last_used_at"] is None + assert serialized["expires_at"] is None def test_api_key_created_data_owner_round_trip(self): data = load_fixture("api_key_created_data_owner.json") @@ -2665,6 +3141,7 @@ def test_api_key_revoked_round_trip(self): def test_api_key_revoked_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "api_key.revoked", "data": { @@ -2677,23 +3154,24 @@ def test_api_key_revoked_minimal_payload(self): "name": "My API Key", "obfuscated_value": "sk_test_...1234", "last_used_at": "2026-01-15T12:00:00.000Z", + "expires_at": None, "permissions": ["users:read", "users:write"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = ApiKeyRevoked.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_api_key_revoked_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "api_key.revoked", "data": { @@ -2706,12 +3184,12 @@ def test_api_key_revoked_omits_absent_optional_non_nullable_fields(self): "name": "My API Key", "obfuscated_value": "sk_test_...1234", "last_used_at": "2026-01-15T12:00:00.000Z", + "expires_at": None, "permissions": ["users:read", "users:write"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = ApiKeyRevoked.from_dict(data) serialized = instance.to_dict() @@ -2757,6 +3235,7 @@ def test_api_key_revoked_data_preserves_nullable_fields(self): "name": "My API Key", "obfuscated_value": "sk_test_...1234", "last_used_at": None, + "expires_at": None, "permissions": ["users:read", "users:write"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -2764,6 +3243,7 @@ def test_api_key_revoked_data_preserves_nullable_fields(self): instance = ApiKeyRevokedData.from_dict(data) serialized = instance.to_dict() assert serialized["last_used_at"] is None + assert serialized["expires_at"] is None def test_api_key_revoked_data_owner_round_trip(self): data = load_fixture("api_key_revoked_data_owner.json") @@ -2810,6 +3290,7 @@ def test_authentication_email_verification_failed_round_trip(self): def test_authentication_email_verification_failed_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.email_verification_failed", "data": { @@ -2825,20 +3306,20 @@ def test_authentication_email_verification_failed_minimal_payload(self): }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationEmailVerificationFailed.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_authentication_email_verification_failed_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.email_verification_failed", "data": { @@ -2854,7 +3335,6 @@ def test_authentication_email_verification_failed_omits_absent_optional_non_null }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationEmailVerificationFailed.from_dict(data) serialized = instance.to_dict() @@ -2941,6 +3421,7 @@ def test_authentication_email_verification_succeeded_round_trip(self): def test_authentication_email_verification_succeeded_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.email_verification_succeeded", "data": { @@ -2952,20 +3433,20 @@ def test_authentication_email_verification_succeeded_minimal_payload(self): "email": "user@example.com", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationEmailVerificationSucceeded.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_authentication_email_verification_succeeded_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.email_verification_succeeded", "data": { @@ -2977,7 +3458,6 @@ def test_authentication_email_verification_succeeded_omits_absent_optional_non_n "email": "user@example.com", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationEmailVerificationSucceeded.from_dict(data) serialized = instance.to_dict() @@ -3035,6 +3515,7 @@ def test_authentication_magic_auth_failed_round_trip(self): def test_authentication_magic_auth_failed_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.magic_auth_failed", "data": { @@ -3050,20 +3531,20 @@ def test_authentication_magic_auth_failed_minimal_payload(self): }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationMagicAuthFailed.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_authentication_magic_auth_failed_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.magic_auth_failed", "data": { @@ -3079,7 +3560,6 @@ def test_authentication_magic_auth_failed_omits_absent_optional_non_nullable_fie }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationMagicAuthFailed.from_dict(data) serialized = instance.to_dict() @@ -3164,6 +3644,7 @@ def test_authentication_magic_auth_succeeded_round_trip(self): def test_authentication_magic_auth_succeeded_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.magic_auth_succeeded", "data": { @@ -3175,20 +3656,20 @@ def test_authentication_magic_auth_succeeded_minimal_payload(self): "email": "user@example.com", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationMagicAuthSucceeded.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_authentication_magic_auth_succeeded_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.magic_auth_succeeded", "data": { @@ -3200,7 +3681,6 @@ def test_authentication_magic_auth_succeeded_omits_absent_optional_non_nullable_ "email": "user@example.com", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationMagicAuthSucceeded.from_dict(data) serialized = instance.to_dict() @@ -3256,6 +3736,7 @@ def test_authentication_mfa_failed_round_trip(self): def test_authentication_mfa_failed_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.mfa_failed", "data": { @@ -3271,18 +3752,18 @@ def test_authentication_mfa_failed_minimal_payload(self): }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationMFAFailed.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_authentication_mfa_failed_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.mfa_failed", "data": { @@ -3298,7 +3779,6 @@ def test_authentication_mfa_failed_omits_absent_optional_non_nullable_fields(sel }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationMFAFailed.from_dict(data) serialized = instance.to_dict() @@ -3383,6 +3863,7 @@ def test_authentication_mfa_succeeded_round_trip(self): def test_authentication_mfa_succeeded_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.mfa_succeeded", "data": { @@ -3394,20 +3875,20 @@ def test_authentication_mfa_succeeded_minimal_payload(self): "email": "user@example.com", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationMFASucceeded.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_authentication_mfa_succeeded_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.mfa_succeeded", "data": { @@ -3419,7 +3900,6 @@ def test_authentication_mfa_succeeded_omits_absent_optional_non_nullable_fields( "email": "user@example.com", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationMFASucceeded.from_dict(data) serialized = instance.to_dict() @@ -3475,6 +3955,7 @@ def test_authentication_oauth_failed_round_trip(self): def test_authentication_oauth_failed_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.oauth_failed", "data": { @@ -3490,20 +3971,20 @@ def test_authentication_oauth_failed_minimal_payload(self): }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationOAuthFailed.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_authentication_oauth_failed_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.oauth_failed", "data": { @@ -3519,7 +4000,6 @@ def test_authentication_oauth_failed_omits_absent_optional_non_nullable_fields( }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationOAuthFailed.from_dict(data) serialized = instance.to_dict() @@ -3604,6 +4084,7 @@ def test_authentication_oauth_succeeded_round_trip(self): def test_authentication_oauth_succeeded_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.oauth_succeeded", "data": { @@ -3615,20 +4096,20 @@ def test_authentication_oauth_succeeded_minimal_payload(self): "email": "user@example.com", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationOAuthSucceeded.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_authentication_oauth_succeeded_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.oauth_succeeded", "data": { @@ -3640,7 +4121,6 @@ def test_authentication_oauth_succeeded_omits_absent_optional_non_nullable_field "email": "user@example.com", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationOAuthSucceeded.from_dict(data) serialized = instance.to_dict() @@ -3697,6 +4177,7 @@ def test_authentication_passkey_failed_round_trip(self): def test_authentication_passkey_failed_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.passkey_failed", "data": { @@ -3712,20 +4193,20 @@ def test_authentication_passkey_failed_minimal_payload(self): }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationPasskeyFailed.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_authentication_passkey_failed_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.passkey_failed", "data": { @@ -3741,7 +4222,6 @@ def test_authentication_passkey_failed_omits_absent_optional_non_nullable_fields }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationPasskeyFailed.from_dict(data) serialized = instance.to_dict() @@ -3826,6 +4306,7 @@ def test_authentication_passkey_succeeded_round_trip(self): def test_authentication_passkey_succeeded_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.passkey_succeeded", "data": { @@ -3837,20 +4318,20 @@ def test_authentication_passkey_succeeded_minimal_payload(self): "email": "user@example.com", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationPasskeySucceeded.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_authentication_passkey_succeeded_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.passkey_succeeded", "data": { @@ -3862,7 +4343,6 @@ def test_authentication_passkey_succeeded_omits_absent_optional_non_nullable_fie "email": "user@example.com", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationPasskeySucceeded.from_dict(data) serialized = instance.to_dict() @@ -3918,6 +4398,7 @@ def test_authentication_password_failed_round_trip(self): def test_authentication_password_failed_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.password_failed", "data": { @@ -3933,20 +4414,20 @@ def test_authentication_password_failed_minimal_payload(self): }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationPasswordFailed.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_authentication_password_failed_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.password_failed", "data": { @@ -3962,7 +4443,6 @@ def test_authentication_password_failed_omits_absent_optional_non_nullable_field }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationPasswordFailed.from_dict(data) serialized = instance.to_dict() @@ -4047,6 +4527,7 @@ def test_authentication_password_succeeded_round_trip(self): def test_authentication_password_succeeded_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.password_succeeded", "data": { @@ -4058,20 +4539,20 @@ def test_authentication_password_succeeded_minimal_payload(self): "email": "user@example.com", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationPasswordSucceeded.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_authentication_password_succeeded_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.password_succeeded", "data": { @@ -4083,7 +4564,6 @@ def test_authentication_password_succeeded_omits_absent_optional_non_nullable_fi "email": "user@example.com", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationPasswordSucceeded.from_dict(data) serialized = instance.to_dict() @@ -4139,6 +4619,7 @@ def test_authentication_radar_risk_detected_round_trip(self): def test_authentication_radar_risk_detected_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.radar_risk_detected", "data": { @@ -4152,20 +4633,20 @@ def test_authentication_radar_risk_detected_minimal_payload(self): "email": "user@example.com", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationRadarRiskDetected.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_authentication_radar_risk_detected_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.radar_risk_detected", "data": { @@ -4179,7 +4660,6 @@ def test_authentication_radar_risk_detected_omits_absent_optional_non_nullable_f "email": "user@example.com", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationRadarRiskDetected.from_dict(data) serialized = instance.to_dict() @@ -4259,6 +4739,7 @@ def test_authentication_sso_failed_round_trip(self): def test_authentication_sso_failed_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.sso_failed", "data": { @@ -4279,18 +4760,18 @@ def test_authentication_sso_failed_minimal_payload(self): }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationSSOFailed.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_authentication_sso_failed_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.sso_failed", "data": { @@ -4311,7 +4792,6 @@ def test_authentication_sso_failed_omits_absent_optional_non_nullable_fields(sel }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationSSOFailed.from_dict(data) serialized = instance.to_dict() @@ -4431,6 +4911,7 @@ def test_authentication_sso_started_round_trip(self): def test_authentication_sso_started_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.sso_started", "data": { @@ -4447,18 +4928,18 @@ def test_authentication_sso_started_minimal_payload(self): }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationSSOStarted.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_authentication_sso_started_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.sso_started", "data": { @@ -4475,7 +4956,6 @@ def test_authentication_sso_started_omits_absent_optional_non_nullable_fields(se }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationSSOStarted.from_dict(data) serialized = instance.to_dict() @@ -4568,6 +5048,7 @@ def test_authentication_sso_succeeded_round_trip(self): def test_authentication_sso_succeeded_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.sso_succeeded", "data": { @@ -4584,20 +5065,20 @@ def test_authentication_sso_succeeded_minimal_payload(self): }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationSSOSucceeded.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_authentication_sso_succeeded_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.sso_succeeded", "data": { @@ -4614,7 +5095,6 @@ def test_authentication_sso_succeeded_omits_absent_optional_non_nullable_fields( }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationSSOSucceeded.from_dict(data) serialized = instance.to_dict() @@ -4706,6 +5186,7 @@ def test_authentication_sso_timed_out_round_trip(self): def test_authentication_sso_timed_out_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.sso_timed_out", "data": { @@ -4726,20 +5207,20 @@ def test_authentication_sso_timed_out_minimal_payload(self): }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationSSOTimedOut.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_authentication_sso_timed_out_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "authentication.sso_timed_out", "data": { @@ -4760,7 +5241,6 @@ def test_authentication_sso_timed_out_omits_absent_optional_non_nullable_fields( }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = AuthenticationSSOTimedOut.from_dict(data) serialized = instance.to_dict() @@ -4880,6 +5360,7 @@ def test_connection_activated_round_trip(self): def test_connection_activated_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "connection.activated", "data": { @@ -4902,18 +5383,18 @@ def test_connection_activated_minimal_payload(self): ], }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = ConnectionActivated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_connection_activated_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "connection.activated", "data": { @@ -4936,7 +5417,6 @@ def test_connection_activated_omits_absent_optional_non_nullable_fields(self): ], }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = ConnectionActivated.from_dict(data) serialized = instance.to_dict() @@ -5058,6 +5538,7 @@ def test_connection_deactivated_round_trip(self): def test_connection_deactivated_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "connection.deactivated", "data": { @@ -5080,18 +5561,18 @@ def test_connection_deactivated_minimal_payload(self): ], }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = ConnectionDeactivated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_connection_deactivated_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "connection.deactivated", "data": { @@ -5114,7 +5595,6 @@ def test_connection_deactivated_omits_absent_optional_non_nullable_fields(self): ], }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = ConnectionDeactivated.from_dict(data) serialized = instance.to_dict() @@ -5238,6 +5718,7 @@ def test_connection_deleted_round_trip(self): def test_connection_deleted_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "connection.deleted", "data": { @@ -5251,18 +5732,18 @@ def test_connection_deleted_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = ConnectionDeleted.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_connection_deleted_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "connection.deleted", "data": { @@ -5276,7 +5757,6 @@ def test_connection_deleted_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = ConnectionDeleted.from_dict(data) serialized = instance.to_dict() @@ -5348,6 +5828,7 @@ def test_connection_saml_certificate_renewal_required_round_trip(self): def test_connection_saml_certificate_renewal_required_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "connection.saml_certificate_renewal_required", "data": { @@ -5363,20 +5844,20 @@ def test_connection_saml_certificate_renewal_required_minimal_payload(self): "days_until_expiry": 30, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = ConnectionSAMLCertificateRenewalRequired.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_connection_saml_certificate_renewal_required_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "connection.saml_certificate_renewal_required", "data": { @@ -5392,7 +5873,6 @@ def test_connection_saml_certificate_renewal_required_omits_absent_optional_non_ "days_until_expiry": 30, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = ConnectionSAMLCertificateRenewalRequired.from_dict(data) serialized = instance.to_dict() @@ -5516,6 +5996,7 @@ def test_connection_saml_certificate_renewed_round_trip(self): def test_connection_saml_certificate_renewed_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "connection.saml_certificate_renewed", "data": { @@ -5530,20 +6011,20 @@ def test_connection_saml_certificate_renewed_minimal_payload(self): "renewed_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = ConnectionSAMLCertificateRenewed.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_connection_saml_certificate_renewed_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "connection.saml_certificate_renewed", "data": { @@ -5558,7 +6039,6 @@ def test_connection_saml_certificate_renewed_omits_absent_optional_non_nullable_ "renewed_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = ConnectionSAMLCertificateRenewed.from_dict(data) serialized = instance.to_dict() @@ -5650,6 +6130,7 @@ def test_dsync_activated_round_trip(self): def test_dsync_activated_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.activated", "data": { @@ -5671,18 +6152,18 @@ def test_dsync_activated_minimal_payload(self): ], }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncActivated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_dsync_activated_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.activated", "data": { @@ -5704,7 +6185,6 @@ def test_dsync_activated_omits_absent_optional_non_nullable_fields(self): ], }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncActivated.from_dict(data) serialized = instance.to_dict() @@ -5822,6 +6302,7 @@ def test_dsync_deactivated_round_trip(self): def test_dsync_deactivated_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.deactivated", "data": { @@ -5843,18 +6324,18 @@ def test_dsync_deactivated_minimal_payload(self): ], }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncDeactivated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_dsync_deactivated_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.deactivated", "data": { @@ -5876,7 +6357,6 @@ def test_dsync_deactivated_omits_absent_optional_non_nullable_fields(self): ], }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncDeactivated.from_dict(data) serialized = instance.to_dict() @@ -5994,6 +6474,7 @@ def test_dsync_deleted_round_trip(self): def test_dsync_deleted_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.deleted", "data": { @@ -6007,18 +6488,18 @@ def test_dsync_deleted_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncDeleted.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_dsync_deleted_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.deleted", "data": { @@ -6032,7 +6513,6 @@ def test_dsync_deleted_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncDeleted.from_dict(data) serialized = instance.to_dict() @@ -6104,6 +6584,7 @@ def test_dsync_group_created_round_trip(self): def test_dsync_group_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.group.created", "data": { @@ -6118,18 +6599,18 @@ def test_dsync_group_created_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncGroupCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_dsync_group_created_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.group.created", "data": { @@ -6144,7 +6625,6 @@ def test_dsync_group_created_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncGroupCreated.from_dict(data) serialized = instance.to_dict() @@ -6160,6 +6640,7 @@ def test_dsync_group_deleted_round_trip(self): def test_dsync_group_deleted_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.group.deleted", "data": { @@ -6174,18 +6655,18 @@ def test_dsync_group_deleted_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncGroupDeleted.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_dsync_group_deleted_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.group.deleted", "data": { @@ -6200,7 +6681,6 @@ def test_dsync_group_deleted_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncGroupDeleted.from_dict(data) serialized = instance.to_dict() @@ -6216,6 +6696,7 @@ def test_dsync_group_updated_round_trip(self): def test_dsync_group_updated_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.group.updated", "data": { @@ -6231,18 +6712,18 @@ def test_dsync_group_updated_minimal_payload(self): "previous_attributes": {"key": {}}, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncGroupUpdated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_dsync_group_updated_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.group.updated", "data": { @@ -6258,7 +6739,6 @@ def test_dsync_group_updated_omits_absent_optional_non_nullable_fields(self): "previous_attributes": {"key": {}}, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncGroupUpdated.from_dict(data) serialized = instance.to_dict() @@ -6320,6 +6800,7 @@ def test_dsync_group_user_added_round_trip(self): def test_dsync_group_user_added_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.group.user_added", "data": { @@ -6367,18 +6848,18 @@ def test_dsync_group_user_added_minimal_payload(self): }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncGroupUserAdded.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_dsync_group_user_added_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.group.user_added", "data": { @@ -6426,7 +6907,6 @@ def test_dsync_group_user_added_omits_absent_optional_non_nullable_fields(self): }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncGroupUserAdded.from_dict(data) serialized = instance.to_dict() @@ -6501,6 +6981,7 @@ def test_dsync_user_created_round_trip(self): def test_dsync_user_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.user.created", "data": { @@ -6534,18 +7015,18 @@ def test_dsync_user_created_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncUserCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_dsync_user_created_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.user.created", "data": { @@ -6579,7 +7060,6 @@ def test_dsync_user_created_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncUserCreated.from_dict(data) serialized = instance.to_dict() @@ -6595,6 +7075,7 @@ def test_dsync_user_deleted_round_trip(self): def test_dsync_user_deleted_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.user.deleted", "data": { @@ -6628,18 +7109,18 @@ def test_dsync_user_deleted_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncUserDeleted.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_dsync_user_deleted_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.user.deleted", "data": { @@ -6673,7 +7154,6 @@ def test_dsync_user_deleted_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncUserDeleted.from_dict(data) serialized = instance.to_dict() @@ -6689,6 +7169,7 @@ def test_dsync_group_user_removed_round_trip(self): def test_dsync_group_user_removed_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.group.user_removed", "data": { @@ -6736,18 +7217,18 @@ def test_dsync_group_user_removed_minimal_payload(self): }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncGroupUserRemoved.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_dsync_group_user_removed_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.group.user_removed", "data": { @@ -6795,7 +7276,6 @@ def test_dsync_group_user_removed_omits_absent_optional_non_nullable_fields(self }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncGroupUserRemoved.from_dict(data) serialized = instance.to_dict() @@ -6870,6 +7350,7 @@ def test_dsync_user_updated_round_trip(self): def test_dsync_user_updated_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.user.updated", "data": { @@ -6904,18 +7385,18 @@ def test_dsync_user_updated_minimal_payload(self): "previous_attributes": {"key": {}}, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncUserUpdated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_dsync_user_updated_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "dsync.user.updated", "data": { @@ -6950,7 +7431,6 @@ def test_dsync_user_updated_omits_absent_optional_non_nullable_fields(self): "previous_attributes": {"key": {}}, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = DsyncUserUpdated.from_dict(data) serialized = instance.to_dict() @@ -7138,6 +7618,7 @@ def test_email_verification_created_round_trip(self): def test_email_verification_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "email_verification.created", "data": { @@ -7150,18 +7631,18 @@ def test_email_verification_created_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = EmailVerificationCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_email_verification_created_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "email_verification.created", "data": { @@ -7174,7 +7655,6 @@ def test_email_verification_created_omits_absent_optional_non_nullable_fields(se "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = EmailVerificationCreated.from_dict(data) serialized = instance.to_dict() @@ -7218,6 +7698,7 @@ def test_flag_created_round_trip(self): def test_flag_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "flag.created", "data": { @@ -7247,16 +7728,15 @@ def test_flag_created_minimal_payload(self): "name": "Jane Doe", }, }, - "object": "event", } instance = FlagCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] assert serialized["context"] == data["context"] - assert serialized["object"] == data["object"] def test_flag_created_data_round_trip(self): data = load_fixture("flag_created_data.json") @@ -7402,6 +7882,7 @@ def test_flag_deleted_round_trip(self): def test_flag_deleted_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "flag.deleted", "data": { @@ -7431,16 +7912,15 @@ def test_flag_deleted_minimal_payload(self): "name": "Jane Doe", }, }, - "object": "event", } instance = FlagDeleted.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] assert serialized["context"] == data["context"] - assert serialized["object"] == data["object"] def test_flag_deleted_data_round_trip(self): data = load_fixture("flag_deleted_data.json") @@ -7586,6 +8066,7 @@ def test_flag_rule_updated_round_trip(self): def test_flag_rule_updated_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "flag.rule_updated", "data": { @@ -7647,16 +8128,15 @@ def test_flag_rule_updated_minimal_payload(self): }, }, }, - "object": "event", } instance = FlagRuleUpdated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] assert serialized["context"] == data["context"] - assert serialized["object"] == data["object"] def test_flag_rule_updated_data_round_trip(self): data = load_fixture("flag_rule_updated_data.json") @@ -8119,6 +8599,7 @@ def test_flag_updated_round_trip(self): def test_flag_updated_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "flag.updated", "data": { @@ -8157,16 +8638,15 @@ def test_flag_updated_minimal_payload(self): } }, }, - "object": "event", } instance = FlagUpdated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] assert serialized["context"] == data["context"] - assert serialized["object"] == data["object"] def test_flag_updated_data_round_trip(self): data = load_fixture("flag_updated_data.json") @@ -8384,6 +8864,7 @@ def test_group_created_round_trip(self): def test_group_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "group.created", "data": { @@ -8396,18 +8877,18 @@ def test_group_created_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = GroupCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_group_created_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "group.created", "data": { @@ -8420,7 +8901,6 @@ def test_group_created_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = GroupCreated.from_dict(data) serialized = instance.to_dict() @@ -8436,6 +8916,7 @@ def test_group_deleted_round_trip(self): def test_group_deleted_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "group.deleted", "data": { @@ -8448,18 +8929,18 @@ def test_group_deleted_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = GroupDeleted.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_group_deleted_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "group.deleted", "data": { @@ -8472,7 +8953,6 @@ def test_group_deleted_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = GroupDeleted.from_dict(data) serialized = instance.to_dict() @@ -8488,6 +8968,7 @@ def test_group_member_added_round_trip(self): def test_group_member_added_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "group.member_added", "data": { @@ -8495,18 +8976,18 @@ def test_group_member_added_minimal_payload(self): "organization_membership_id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = GroupMemberAdded.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_group_member_added_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "group.member_added", "data": { @@ -8514,7 +8995,6 @@ def test_group_member_added_omits_absent_optional_non_nullable_fields(self): "organization_membership_id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = GroupMemberAdded.from_dict(data) serialized = instance.to_dict() @@ -8551,6 +9031,7 @@ def test_group_member_removed_round_trip(self): def test_group_member_removed_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "group.member_removed", "data": { @@ -8558,18 +9039,18 @@ def test_group_member_removed_minimal_payload(self): "organization_membership_id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = GroupMemberRemoved.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_group_member_removed_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "group.member_removed", "data": { @@ -8577,7 +9058,6 @@ def test_group_member_removed_omits_absent_optional_non_nullable_fields(self): "organization_membership_id": "om_01EHWNCE74X7JSDV0X3SZ3KJNY", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = GroupMemberRemoved.from_dict(data) serialized = instance.to_dict() @@ -8614,6 +9094,7 @@ def test_group_updated_round_trip(self): def test_group_updated_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "group.updated", "data": { @@ -8626,18 +9107,18 @@ def test_group_updated_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = GroupUpdated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_group_updated_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "group.updated", "data": { @@ -8650,7 +9131,6 @@ def test_group_updated_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = GroupUpdated.from_dict(data) serialized = instance.to_dict() @@ -8666,6 +9146,7 @@ def test_invitation_accepted_round_trip(self): def test_invitation_accepted_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "invitation.accepted", "data": { @@ -8684,18 +9165,18 @@ def test_invitation_accepted_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = InvitationAccepted.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_invitation_accepted_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "invitation.accepted", "data": { @@ -8714,7 +9195,6 @@ def test_invitation_accepted_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = InvitationAccepted.from_dict(data) serialized = instance.to_dict() @@ -8814,6 +9294,7 @@ def test_invitation_created_round_trip(self): def test_invitation_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "invitation.created", "data": { @@ -8832,18 +9313,18 @@ def test_invitation_created_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = InvitationCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_invitation_created_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "invitation.created", "data": { @@ -8862,7 +9343,6 @@ def test_invitation_created_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = InvitationCreated.from_dict(data) serialized = instance.to_dict() @@ -8962,6 +9442,7 @@ def test_invitation_resent_round_trip(self): def test_invitation_resent_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "invitation.resent", "data": { @@ -8980,18 +9461,18 @@ def test_invitation_resent_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = InvitationResent.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_invitation_resent_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "invitation.resent", "data": { @@ -9010,7 +9491,6 @@ def test_invitation_resent_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = InvitationResent.from_dict(data) serialized = instance.to_dict() @@ -9110,6 +9590,7 @@ def test_invitation_revoked_round_trip(self): def test_invitation_revoked_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "invitation.revoked", "data": { @@ -9128,18 +9609,18 @@ def test_invitation_revoked_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = InvitationRevoked.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_invitation_revoked_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "invitation.revoked", "data": { @@ -9158,7 +9639,6 @@ def test_invitation_revoked_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = InvitationRevoked.from_dict(data) serialized = instance.to_dict() @@ -9258,6 +9738,7 @@ def test_magic_auth_created_round_trip(self): def test_magic_auth_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "magic_auth.created", "data": { @@ -9270,18 +9751,18 @@ def test_magic_auth_created_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = MagicAuthCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_magic_auth_created_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "magic_auth.created", "data": { @@ -9294,7 +9775,6 @@ def test_magic_auth_created_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = MagicAuthCreated.from_dict(data) serialized = instance.to_dict() @@ -9338,6 +9818,7 @@ def test_organization_created_round_trip(self): def test_organization_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization.created", "data": { @@ -9365,18 +9846,18 @@ def test_organization_created_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_organization_created_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization.created", "data": { @@ -9404,7 +9885,6 @@ def test_organization_created_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationCreated.from_dict(data) serialized = instance.to_dict() @@ -9580,6 +10060,7 @@ def test_organization_deleted_round_trip(self): def test_organization_deleted_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization.deleted", "data": { @@ -9607,18 +10088,18 @@ def test_organization_deleted_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationDeleted.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_organization_deleted_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization.deleted", "data": { @@ -9646,7 +10127,6 @@ def test_organization_deleted_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationDeleted.from_dict(data) serialized = instance.to_dict() @@ -9822,6 +10302,7 @@ def test_organization_domain_created_round_trip(self): def test_organization_domain_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_domain.created", "data": { @@ -9837,20 +10318,20 @@ def test_organization_domain_created_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationDomainCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_organization_domain_created_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_domain.created", "data": { @@ -9866,7 +10347,6 @@ def test_organization_domain_created_omits_absent_optional_non_nullable_fields( "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationDomainCreated.from_dict(data) serialized = instance.to_dict() @@ -9942,6 +10422,7 @@ def test_organization_domain_deleted_round_trip(self): def test_organization_domain_deleted_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_domain.deleted", "data": { @@ -9957,20 +10438,20 @@ def test_organization_domain_deleted_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationDomainDeleted.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_organization_domain_deleted_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_domain.deleted", "data": { @@ -9986,7 +10467,6 @@ def test_organization_domain_deleted_omits_absent_optional_non_nullable_fields( "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationDomainDeleted.from_dict(data) serialized = instance.to_dict() @@ -10062,6 +10542,7 @@ def test_organization_domain_updated_round_trip(self): def test_organization_domain_updated_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_domain.updated", "data": { @@ -10077,20 +10558,20 @@ def test_organization_domain_updated_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationDomainUpdated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_organization_domain_updated_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_domain.updated", "data": { @@ -10106,7 +10587,6 @@ def test_organization_domain_updated_omits_absent_optional_non_nullable_fields( "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationDomainUpdated.from_dict(data) serialized = instance.to_dict() @@ -10182,6 +10662,7 @@ def test_organization_domain_verification_failed_round_trip(self): def test_organization_domain_verification_failed_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_domain.verification_failed", "data": { @@ -10200,20 +10681,20 @@ def test_organization_domain_verification_failed_minimal_payload(self): }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationDomainVerificationFailed.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_organization_domain_verification_failed_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_domain.verification_failed", "data": { @@ -10232,7 +10713,6 @@ def test_organization_domain_verification_failed_omits_absent_optional_non_nulla }, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationDomainVerificationFailed.from_dict(data) serialized = instance.to_dict() @@ -10376,6 +10856,7 @@ def test_organization_domain_verified_round_trip(self): def test_organization_domain_verified_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_domain.verified", "data": { @@ -10391,20 +10872,20 @@ def test_organization_domain_verified_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationDomainVerified.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_organization_domain_verified_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_domain.verified", "data": { @@ -10420,7 +10901,6 @@ def test_organization_domain_verified_omits_absent_optional_non_nullable_fields( "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationDomainVerified.from_dict(data) serialized = instance.to_dict() @@ -10496,6 +10976,7 @@ def test_organization_membership_created_round_trip(self): def test_organization_membership_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_membership.created", "data": { @@ -10512,20 +10993,20 @@ def test_organization_membership_created_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationMembershipCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_organization_membership_created_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_membership.created", "data": { @@ -10542,7 +11023,6 @@ def test_organization_membership_created_omits_absent_optional_non_nullable_fiel "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationMembershipCreated.from_dict(data) serialized = instance.to_dict() @@ -10628,6 +11108,7 @@ def test_organization_membership_deleted_round_trip(self): def test_organization_membership_deleted_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_membership.deleted", "data": { @@ -10644,20 +11125,20 @@ def test_organization_membership_deleted_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationMembershipDeleted.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_organization_membership_deleted_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_membership.deleted", "data": { @@ -10674,7 +11155,6 @@ def test_organization_membership_deleted_omits_absent_optional_non_nullable_fiel "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationMembershipDeleted.from_dict(data) serialized = instance.to_dict() @@ -10760,6 +11240,7 @@ def test_organization_membership_updated_round_trip(self): def test_organization_membership_updated_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_membership.updated", "data": { @@ -10776,20 +11257,20 @@ def test_organization_membership_updated_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationMembershipUpdated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_organization_membership_updated_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_membership.updated", "data": { @@ -10806,7 +11287,6 @@ def test_organization_membership_updated_omits_absent_optional_non_nullable_fiel "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationMembershipUpdated.from_dict(data) serialized = instance.to_dict() @@ -10892,6 +11372,7 @@ def test_organization_role_created_round_trip(self): def test_organization_role_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_role.created", "data": { @@ -10906,18 +11387,18 @@ def test_organization_role_created_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationRoleCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_organization_role_created_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_role.created", "data": { @@ -10932,7 +11413,6 @@ def test_organization_role_created_omits_absent_optional_non_nullable_fields(sel "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationRoleCreated.from_dict(data) serialized = instance.to_dict() @@ -10996,6 +11476,7 @@ def test_organization_role_deleted_round_trip(self): def test_organization_role_deleted_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_role.deleted", "data": { @@ -11010,18 +11491,18 @@ def test_organization_role_deleted_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationRoleDeleted.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_organization_role_deleted_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_role.deleted", "data": { @@ -11036,7 +11517,6 @@ def test_organization_role_deleted_omits_absent_optional_non_nullable_fields(sel "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationRoleDeleted.from_dict(data) serialized = instance.to_dict() @@ -11100,6 +11580,7 @@ def test_organization_role_updated_round_trip(self): def test_organization_role_updated_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_role.updated", "data": { @@ -11114,18 +11595,18 @@ def test_organization_role_updated_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationRoleUpdated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_organization_role_updated_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization_role.updated", "data": { @@ -11140,7 +11621,6 @@ def test_organization_role_updated_omits_absent_optional_non_nullable_fields(sel "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationRoleUpdated.from_dict(data) serialized = instance.to_dict() @@ -11204,6 +11684,7 @@ def test_organization_updated_round_trip(self): def test_organization_updated_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization.updated", "data": { @@ -11231,18 +11712,18 @@ def test_organization_updated_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationUpdated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_organization_updated_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "organization.updated", "data": { @@ -11270,7 +11751,6 @@ def test_organization_updated_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = OrganizationUpdated.from_dict(data) serialized = instance.to_dict() @@ -11446,6 +11926,7 @@ def test_password_reset_created_round_trip(self): def test_password_reset_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "password_reset.created", "data": { @@ -11457,18 +11938,18 @@ def test_password_reset_created_minimal_payload(self): "created_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = PasswordResetCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_password_reset_created_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "password_reset.created", "data": { @@ -11480,7 +11961,6 @@ def test_password_reset_created_omits_absent_optional_non_nullable_fields(self): "created_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = PasswordResetCreated.from_dict(data) serialized = instance.to_dict() @@ -11522,6 +12002,7 @@ def test_password_reset_succeeded_round_trip(self): def test_password_reset_succeeded_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "password_reset.succeeded", "data": { @@ -11533,18 +12014,18 @@ def test_password_reset_succeeded_minimal_payload(self): "created_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = PasswordResetSucceeded.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_password_reset_succeeded_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "password_reset.succeeded", "data": { @@ -11556,7 +12037,6 @@ def test_password_reset_succeeded_omits_absent_optional_non_nullable_fields(self "created_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = PasswordResetSucceeded.from_dict(data) serialized = instance.to_dict() @@ -11598,6 +12078,7 @@ def test_permission_created_round_trip(self): def test_permission_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "permission.created", "data": { @@ -11611,18 +12092,18 @@ def test_permission_created_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = PermissionCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_permission_created_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "permission.created", "data": { @@ -11636,7 +12117,6 @@ def test_permission_created_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = PermissionCreated.from_dict(data) serialized = instance.to_dict() @@ -11697,6 +12177,7 @@ def test_permission_deleted_round_trip(self): def test_permission_deleted_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "permission.deleted", "data": { @@ -11710,18 +12191,18 @@ def test_permission_deleted_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = PermissionDeleted.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_permission_deleted_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "permission.deleted", "data": { @@ -11735,7 +12216,6 @@ def test_permission_deleted_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = PermissionDeleted.from_dict(data) serialized = instance.to_dict() @@ -11796,6 +12276,32 @@ def test_permission_updated_round_trip(self): def test_permission_updated_minimal_payload(self): data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "permission.updated", + "data": { + "object": "permission", + "id": "perm_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing:manage", + "name": "Manage Billing", + "description": "Allows managing billing settings.", + "system": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PermissionUpdated.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_permission_updated_omits_absent_optional_non_nullable_fields(self): + data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "permission.updated", "data": { @@ -11809,81 +12315,235 @@ def test_permission_updated_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PermissionUpdated.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_permission_updated_data_round_trip(self): + data = load_fixture("permission_updated_data.json") + instance = PermissionUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PermissionUpdatedData.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_permission_updated_data_minimal_payload(self): + data = { + "object": "permission", + "id": "perm_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing:manage", + "name": "Manage Billing", + "description": None, + "system": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = PermissionUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["slug"] == data["slug"] + assert serialized["name"] == data["name"] + assert serialized["description"] == data["description"] + assert serialized["system"] == data["system"] + assert serialized["created_at"] == data["created_at"] + assert serialized["updated_at"] == data["updated_at"] + + def test_permission_updated_data_preserves_nullable_fields(self): + data = { + "object": "permission", + "id": "perm_01EHWNCE74X7JSDV0X3SZ3KJNY", + "slug": "billing:manage", + "name": "Manage Billing", + "description": None, + "system": False, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + } + instance = PermissionUpdatedData.from_dict(data) + serialized = instance.to_dict() + assert serialized["description"] is None + + def test_pipes_connected_account_connected_round_trip(self): + data = load_fixture("pipes_connected_account_connected.json") + instance = PipesConnectedAccountConnected.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PipesConnectedAccountConnected.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_pipes_connected_account_connected_minimal_payload(self): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "pipes.connected_account.connected", + "data": { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "scopes": ["repo", "user:email"], + "state": "connected", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PipesConnectedAccountConnected.from_dict(data) + serialized = instance.to_dict() + assert serialized["object"] == data["object"] + assert serialized["id"] == data["id"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] + assert serialized["created_at"] == data["created_at"] + + def test_pipes_connected_account_connected_omits_absent_optional_non_nullable_fields( + self, + ): + data = { + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "pipes.connected_account.connected", + "data": { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "scopes": ["repo", "user:email"], + "state": "connected", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", + } + instance = PipesConnectedAccountConnected.from_dict(data) + serialized = instance.to_dict() + assert "context" not in serialized + + def test_pipes_connected_account_disconnected_round_trip(self): + data = load_fixture("pipes_connected_account_disconnected.json") + instance = PipesConnectedAccountDisconnected.from_dict(data) + serialized = instance.to_dict() + assert serialized == data + restored = PipesConnectedAccountDisconnected.from_dict(serialized) + assert restored.to_dict() == serialized + + def test_pipes_connected_account_disconnected_minimal_payload(self): + data = { "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "pipes.connected_account.disconnected", + "data": { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "scopes": ["repo", "user:email"], + "state": "connected", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, + "created_at": "2026-01-15T12:00:00.000Z", } - instance = PermissionUpdated.from_dict(data) + instance = PipesConnectedAccountDisconnected.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] - def test_permission_updated_omits_absent_optional_non_nullable_fields(self): + def test_pipes_connected_account_disconnected_omits_absent_optional_non_nullable_fields( + self, + ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", - "event": "permission.updated", + "event": "pipes.connected_account.disconnected", "data": { - "object": "permission", - "id": "perm_01EHWNCE74X7JSDV0X3SZ3KJNY", - "slug": "billing:manage", - "name": "Manage Billing", - "description": "Allows managing billing settings.", - "system": False, + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "scopes": ["repo", "user:email"], + "state": "connected", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } - instance = PermissionUpdated.from_dict(data) + instance = PipesConnectedAccountDisconnected.from_dict(data) serialized = instance.to_dict() assert "context" not in serialized - def test_permission_updated_data_round_trip(self): - data = load_fixture("permission_updated_data.json") - instance = PermissionUpdatedData.from_dict(data) + def test_pipes_connected_account_reauthorization_needed_round_trip(self): + data = load_fixture("pipes_connected_account_reauthorization_needed.json") + instance = PipesConnectedAccountReauthorizationNeeded.from_dict(data) serialized = instance.to_dict() assert serialized == data - restored = PermissionUpdatedData.from_dict(serialized) + restored = PipesConnectedAccountReauthorizationNeeded.from_dict(serialized) assert restored.to_dict() == serialized - def test_permission_updated_data_minimal_payload(self): + def test_pipes_connected_account_reauthorization_needed_minimal_payload(self): data = { - "object": "permission", - "id": "perm_01EHWNCE74X7JSDV0X3SZ3KJNY", - "slug": "billing:manage", - "name": "Manage Billing", - "description": None, - "system": False, + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "pipes.connected_account.reauthorization_needed", + "data": { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "scopes": ["repo", "user:email"], + "state": "connected", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, "created_at": "2026-01-15T12:00:00.000Z", - "updated_at": "2026-01-15T12:00:00.000Z", } - instance = PermissionUpdatedData.from_dict(data) + instance = PipesConnectedAccountReauthorizationNeeded.from_dict(data) serialized = instance.to_dict() assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] - assert serialized["slug"] == data["slug"] - assert serialized["name"] == data["name"] - assert serialized["description"] == data["description"] - assert serialized["system"] == data["system"] + assert serialized["event"] == data["event"] + assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["updated_at"] == data["updated_at"] - def test_permission_updated_data_preserves_nullable_fields(self): + def test_pipes_connected_account_reauthorization_needed_omits_absent_optional_non_nullable_fields( + self, + ): data = { - "object": "permission", - "id": "perm_01EHWNCE74X7JSDV0X3SZ3KJNY", - "slug": "billing:manage", - "name": "Manage Billing", - "description": None, - "system": False, + "object": "event", + "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", + "event": "pipes.connected_account.reauthorization_needed", + "data": { + "object": "connected_account", + "id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "data_integration_id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", + "provider_slug": "github", + "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "scopes": ["repo", "user:email"], + "state": "connected", + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + }, "created_at": "2026-01-15T12:00:00.000Z", - "updated_at": "2026-01-15T12:00:00.000Z", } - instance = PermissionUpdatedData.from_dict(data) + instance = PipesConnectedAccountReauthorizationNeeded.from_dict(data) serialized = instance.to_dict() - assert serialized["description"] is None + assert "context" not in serialized def test_role_created_round_trip(self): data = load_fixture("role_created.json") @@ -11895,6 +12555,7 @@ def test_role_created_round_trip(self): def test_role_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "role.created", "data": { @@ -11906,18 +12567,18 @@ def test_role_created_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = RoleCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_role_created_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "role.created", "data": { @@ -11929,7 +12590,6 @@ def test_role_created_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = RoleCreated.from_dict(data) serialized = instance.to_dict() @@ -11981,6 +12641,7 @@ def test_role_deleted_round_trip(self): def test_role_deleted_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "role.deleted", "data": { @@ -11992,18 +12653,18 @@ def test_role_deleted_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = RoleDeleted.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_role_deleted_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "role.deleted", "data": { @@ -12015,7 +12676,6 @@ def test_role_deleted_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = RoleDeleted.from_dict(data) serialized = instance.to_dict() @@ -12067,6 +12727,7 @@ def test_role_updated_round_trip(self): def test_role_updated_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "role.updated", "data": { @@ -12078,18 +12739,18 @@ def test_role_updated_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = RoleUpdated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_role_updated_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "role.updated", "data": { @@ -12101,7 +12762,6 @@ def test_role_updated_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = RoleUpdated.from_dict(data) serialized = instance.to_dict() @@ -12153,6 +12813,7 @@ def test_session_created_round_trip(self): def test_session_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "session.created", "data": { @@ -12174,18 +12835,18 @@ def test_session_created_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = SessionCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_session_created_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "session.created", "data": { @@ -12207,7 +12868,6 @@ def test_session_created_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = SessionCreated.from_dict(data) serialized = instance.to_dict() @@ -12346,6 +13006,7 @@ def test_session_revoked_round_trip(self): def test_session_revoked_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "session.revoked", "data": { @@ -12367,18 +13028,18 @@ def test_session_revoked_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = SessionRevoked.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_session_revoked_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "session.revoked", "data": { @@ -12400,7 +13061,6 @@ def test_session_revoked_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = SessionRevoked.from_dict(data) serialized = instance.to_dict() @@ -12539,6 +13199,7 @@ def test_user_created_round_trip(self): def test_user_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "user.created", "data": { @@ -12551,24 +13212,24 @@ def test_user_created_minimal_payload(self): "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = UserCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_user_created_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "user.created", "data": { @@ -12581,13 +13242,12 @@ def test_user_created_omits_absent_optional_non_nullable_fields(self): "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = UserCreated.from_dict(data) serialized = instance.to_dict() @@ -12603,6 +13263,7 @@ def test_user_deleted_round_trip(self): def test_user_deleted_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "user.deleted", "data": { @@ -12615,24 +13276,24 @@ def test_user_deleted_minimal_payload(self): "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = UserDeleted.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_user_deleted_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "user.deleted", "data": { @@ -12645,13 +13306,12 @@ def test_user_deleted_omits_absent_optional_non_nullable_fields(self): "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = UserDeleted.from_dict(data) serialized = instance.to_dict() @@ -12667,6 +13327,7 @@ def test_user_updated_round_trip(self): def test_user_updated_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "user.updated", "data": { @@ -12679,24 +13340,24 @@ def test_user_updated_minimal_payload(self): "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = UserUpdated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_user_updated_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "user.updated", "data": { @@ -12709,13 +13370,12 @@ def test_user_updated_omits_absent_optional_non_nullable_fields(self): "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = UserUpdated.from_dict(data) serialized = instance.to_dict() @@ -12731,6 +13391,7 @@ def test_vault_byok_key_deleted_round_trip(self): def test_vault_byok_key_deleted_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.byok_key.deleted", "data": { @@ -12738,18 +13399,18 @@ def test_vault_byok_key_deleted_minimal_payload(self): "key_provider": "AWS_KMS", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultByokKeyDeleted.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_vault_byok_key_deleted_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.byok_key.deleted", "data": { @@ -12757,7 +13418,6 @@ def test_vault_byok_key_deleted_omits_absent_optional_non_nullable_fields(self): "key_provider": "AWS_KMS", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultByokKeyDeleted.from_dict(data) serialized = instance.to_dict() @@ -12799,6 +13459,7 @@ def test_vault_byok_key_verification_completed_round_trip(self): def test_vault_byok_key_verification_completed_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.byok_key.verification_completed", "data": { @@ -12807,20 +13468,20 @@ def test_vault_byok_key_verification_completed_minimal_payload(self): "verified": True, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultByokKeyVerificationCompleted.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_vault_byok_key_verification_completed_omits_absent_optional_non_nullable_fields( self, ): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.byok_key.verification_completed", "data": { @@ -12829,7 +13490,6 @@ def test_vault_byok_key_verification_completed_omits_absent_optional_non_nullabl "verified": True, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultByokKeyVerificationCompleted.from_dict(data) serialized = instance.to_dict() @@ -12876,6 +13536,7 @@ def test_vault_data_created_round_trip(self): def test_vault_data_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.data.created", "data": { @@ -12887,18 +13548,18 @@ def test_vault_data_created_minimal_payload(self): "key_context": {"key": "test_value"}, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultDataCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_vault_data_created_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.data.created", "data": { @@ -12910,7 +13571,6 @@ def test_vault_data_created_omits_absent_optional_non_nullable_fields(self): "key_context": {"key": "test_value"}, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultDataCreated.from_dict(data) serialized = instance.to_dict() @@ -12964,6 +13624,7 @@ def test_vault_data_deleted_round_trip(self): def test_vault_data_deleted_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.data.deleted", "data": { @@ -12973,18 +13634,18 @@ def test_vault_data_deleted_minimal_payload(self): "kv_name": "user-secrets", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultDataDeleted.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_vault_data_deleted_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.data.deleted", "data": { @@ -12994,7 +13655,6 @@ def test_vault_data_deleted_omits_absent_optional_non_nullable_fields(self): "kv_name": "user-secrets", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultDataDeleted.from_dict(data) serialized = instance.to_dict() @@ -13042,6 +13702,7 @@ def test_vault_data_read_round_trip(self): def test_vault_data_read_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.data.read", "data": { @@ -13052,18 +13713,18 @@ def test_vault_data_read_minimal_payload(self): "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultDataRead.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_vault_data_read_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.data.read", "data": { @@ -13074,7 +13735,6 @@ def test_vault_data_read_omits_absent_optional_non_nullable_fields(self): "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultDataRead.from_dict(data) serialized = instance.to_dict() @@ -13125,6 +13785,7 @@ def test_vault_data_updated_round_trip(self): def test_vault_data_updated_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.data.updated", "data": { @@ -13136,18 +13797,18 @@ def test_vault_data_updated_minimal_payload(self): "key_context": {"key": "test_value"}, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultDataUpdated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_vault_data_updated_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.data.updated", "data": { @@ -13159,7 +13820,6 @@ def test_vault_data_updated_omits_absent_optional_non_nullable_fields(self): "key_context": {"key": "test_value"}, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultDataUpdated.from_dict(data) serialized = instance.to_dict() @@ -13213,6 +13873,7 @@ def test_vault_dek_decrypted_round_trip(self): def test_vault_dek_decrypted_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.dek.decrypted", "data": { @@ -13222,18 +13883,18 @@ def test_vault_dek_decrypted_minimal_payload(self): "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultDekDecrypted.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_vault_dek_decrypted_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.dek.decrypted", "data": { @@ -13243,7 +13904,6 @@ def test_vault_dek_decrypted_omits_absent_optional_non_nullable_fields(self): "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultDekDecrypted.from_dict(data) serialized = instance.to_dict() @@ -13291,6 +13951,7 @@ def test_vault_dek_read_round_trip(self): def test_vault_dek_read_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.dek.read", "data": { @@ -13301,18 +13962,18 @@ def test_vault_dek_read_minimal_payload(self): "key_context": {"key": "test_value"}, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultDekRead.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_vault_dek_read_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.dek.read", "data": { @@ -13323,7 +13984,6 @@ def test_vault_dek_read_omits_absent_optional_non_nullable_fields(self): "key_context": {"key": "test_value"}, }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultDekRead.from_dict(data) serialized = instance.to_dict() @@ -13374,6 +14034,7 @@ def test_vault_kek_created_round_trip(self): def test_vault_kek_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.kek.created", "data": { @@ -13384,18 +14045,18 @@ def test_vault_kek_created_minimal_payload(self): "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultKekCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_vault_kek_created_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.kek.created", "data": { @@ -13406,7 +14067,6 @@ def test_vault_kek_created_omits_absent_optional_non_nullable_fields(self): "key_id": "key_01EHWNCE74X7JSDV0X3SZ3KJNY", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultKekCreated.from_dict(data) serialized = instance.to_dict() @@ -13457,6 +14117,7 @@ def test_vault_metadata_read_round_trip(self): def test_vault_metadata_read_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.metadata.read", "data": { @@ -13466,18 +14127,18 @@ def test_vault_metadata_read_minimal_payload(self): "kv_name": "user-secrets", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultMetadataRead.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_vault_metadata_read_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.metadata.read", "data": { @@ -13487,7 +14148,6 @@ def test_vault_metadata_read_omits_absent_optional_non_nullable_fields(self): "kv_name": "user-secrets", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultMetadataRead.from_dict(data) serialized = instance.to_dict() @@ -13535,6 +14195,7 @@ def test_vault_names_listed_round_trip(self): def test_vault_names_listed_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.names.listed", "data": { @@ -13543,18 +14204,18 @@ def test_vault_names_listed_minimal_payload(self): "actor_name": "Jane Doe", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultNamesListed.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_vault_names_listed_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "vault.names.listed", "data": { @@ -13563,7 +14224,6 @@ def test_vault_names_listed_omits_absent_optional_non_nullable_fields(self): "actor_name": "Jane Doe", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = VaultNamesListed.from_dict(data) serialized = instance.to_dict() @@ -13608,6 +14268,7 @@ def test_waitlist_user_approved_round_trip(self): def test_waitlist_user_approved_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "waitlist_user.approved", "data": { @@ -13620,18 +14281,18 @@ def test_waitlist_user_approved_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = WaitlistUserApproved.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_waitlist_user_approved_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "waitlist_user.approved", "data": { @@ -13644,7 +14305,6 @@ def test_waitlist_user_approved_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = WaitlistUserApproved.from_dict(data) serialized = instance.to_dict() @@ -13660,6 +14320,7 @@ def test_waitlist_user_created_round_trip(self): def test_waitlist_user_created_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "waitlist_user.created", "data": { @@ -13672,18 +14333,18 @@ def test_waitlist_user_created_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = WaitlistUserCreated.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_waitlist_user_created_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "waitlist_user.created", "data": { @@ -13696,7 +14357,6 @@ def test_waitlist_user_created_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = WaitlistUserCreated.from_dict(data) serialized = instance.to_dict() @@ -13712,6 +14372,7 @@ def test_waitlist_user_denied_round_trip(self): def test_waitlist_user_denied_minimal_payload(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "waitlist_user.denied", "data": { @@ -13724,18 +14385,18 @@ def test_waitlist_user_denied_minimal_payload(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = WaitlistUserDenied.from_dict(data) serialized = instance.to_dict() + assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] assert serialized["event"] == data["event"] assert serialized["data"] == data["data"] assert serialized["created_at"] == data["created_at"] - assert serialized["object"] == data["object"] def test_waitlist_user_denied_omits_absent_optional_non_nullable_fields(self): data = { + "object": "event", "id": "event_01EHZNVPK3SFK441A1RGBFSHRT", "event": "waitlist_user.denied", "data": { @@ -13748,7 +14409,6 @@ def test_waitlist_user_denied_omits_absent_optional_non_nullable_fields(self): "updated_at": "2026-01-15T12:00:00.000Z", }, "created_at": "2026-01-15T12:00:00.000Z", - "object": "event", } instance = WaitlistUserDenied.from_dict(data) serialized = instance.to_dict() @@ -13885,6 +14545,7 @@ def test_organization_api_key_minimal_payload(self): "name": "Production API Key", "obfuscated_value": "sk_...3456", "last_used_at": None, + "expires_at": None, "permissions": ["posts:read", "posts:write"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -13897,6 +14558,7 @@ def test_organization_api_key_minimal_payload(self): assert serialized["name"] == data["name"] assert serialized["obfuscated_value"] == data["obfuscated_value"] assert serialized["last_used_at"] == data["last_used_at"] + assert serialized["expires_at"] == data["expires_at"] assert serialized["permissions"] == data["permissions"] assert serialized["created_at"] == data["created_at"] assert serialized["updated_at"] == data["updated_at"] @@ -13909,6 +14571,7 @@ def test_organization_api_key_preserves_nullable_fields(self): "name": "Production API Key", "obfuscated_value": "sk_...3456", "last_used_at": None, + "expires_at": None, "permissions": ["posts:read", "posts:write"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -13916,6 +14579,7 @@ def test_organization_api_key_preserves_nullable_fields(self): instance = OrganizationApiKey.from_dict(data) serialized = instance.to_dict() assert serialized["last_used_at"] is None + assert serialized["expires_at"] is None def test_organization_api_key_with_value_round_trip(self): data = load_fixture("organization_api_key_with_value.json") @@ -13933,6 +14597,7 @@ def test_organization_api_key_with_value_minimal_payload(self): "name": "Production API Key", "obfuscated_value": "sk_...3456", "last_used_at": None, + "expires_at": None, "permissions": ["posts:read", "posts:write"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -13946,6 +14611,7 @@ def test_organization_api_key_with_value_minimal_payload(self): assert serialized["name"] == data["name"] assert serialized["obfuscated_value"] == data["obfuscated_value"] assert serialized["last_used_at"] == data["last_used_at"] + assert serialized["expires_at"] == data["expires_at"] assert serialized["permissions"] == data["permissions"] assert serialized["created_at"] == data["created_at"] assert serialized["updated_at"] == data["updated_at"] @@ -13959,6 +14625,7 @@ def test_organization_api_key_with_value_preserves_nullable_fields(self): "name": "Production API Key", "obfuscated_value": "sk_...3456", "last_used_at": None, + "expires_at": None, "permissions": ["posts:read", "posts:write"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -13967,6 +14634,7 @@ def test_organization_api_key_with_value_preserves_nullable_fields(self): instance = OrganizationApiKeyWithValue.from_dict(data) serialized = instance.to_dict() assert serialized["last_used_at"] is None + assert serialized["expires_at"] is None def test_organization_round_trip(self): data = load_fixture("organization.json") @@ -14569,7 +15237,7 @@ def test_user_organization_membership_minimal_payload(self): "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -14611,7 +15279,7 @@ def test_user_organization_membership_omits_absent_optional_non_nullable_fields( "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -14649,7 +15317,7 @@ def test_user_organization_membership_round_trips_unknown_enum_values(self): "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -14678,6 +15346,7 @@ def test_user_api_key_minimal_payload(self): "name": "Production API Key", "obfuscated_value": "sk_...3456", "last_used_at": None, + "expires_at": None, "permissions": ["posts:read", "posts:write"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -14690,6 +15359,7 @@ def test_user_api_key_minimal_payload(self): assert serialized["name"] == data["name"] assert serialized["obfuscated_value"] == data["obfuscated_value"] assert serialized["last_used_at"] == data["last_used_at"] + assert serialized["expires_at"] == data["expires_at"] assert serialized["permissions"] == data["permissions"] assert serialized["created_at"] == data["created_at"] assert serialized["updated_at"] == data["updated_at"] @@ -14706,6 +15376,7 @@ def test_user_api_key_preserves_nullable_fields(self): "name": "Production API Key", "obfuscated_value": "sk_...3456", "last_used_at": None, + "expires_at": None, "permissions": ["posts:read", "posts:write"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -14713,6 +15384,7 @@ def test_user_api_key_preserves_nullable_fields(self): instance = UserApiKey.from_dict(data) serialized = instance.to_dict() assert serialized["last_used_at"] is None + assert serialized["expires_at"] is None def test_user_api_key_with_value_round_trip(self): data = load_fixture("user_api_key_with_value.json") @@ -14734,6 +15406,7 @@ def test_user_api_key_with_value_minimal_payload(self): "name": "Production API Key", "obfuscated_value": "sk_...3456", "last_used_at": None, + "expires_at": None, "permissions": ["posts:read", "posts:write"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -14747,6 +15420,7 @@ def test_user_api_key_with_value_minimal_payload(self): assert serialized["name"] == data["name"] assert serialized["obfuscated_value"] == data["obfuscated_value"] assert serialized["last_used_at"] == data["last_used_at"] + assert serialized["expires_at"] == data["expires_at"] assert serialized["permissions"] == data["permissions"] assert serialized["created_at"] == data["created_at"] assert serialized["updated_at"] == data["updated_at"] @@ -14764,6 +15438,7 @@ def test_user_api_key_with_value_preserves_nullable_fields(self): "name": "Production API Key", "obfuscated_value": "sk_...3456", "last_used_at": None, + "expires_at": None, "permissions": ["posts:read", "posts:write"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -14772,6 +15447,7 @@ def test_user_api_key_with_value_preserves_nullable_fields(self): instance = UserApiKeyWithValue.from_dict(data) serialized = instance.to_dict() assert serialized["last_used_at"] is None + assert serialized["expires_at"] is None def test_email_verification_round_trip(self): data = load_fixture("email_verification.json") @@ -14823,7 +15499,7 @@ def test_send_verification_email_response_minimal_payload(self): "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -14853,7 +15529,7 @@ def test_verify_email_response_minimal_payload(self): "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -14913,7 +15589,7 @@ def test_reset_password_response_minimal_payload(self): "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -14944,7 +15620,7 @@ def test_email_change_minimal_payload(self): "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -14981,7 +15657,7 @@ def test_authenticate_response_minimal_payload(self): "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -15007,7 +15683,7 @@ def test_authenticate_response_omits_absent_optional_non_nullable_fields(self): "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -15035,7 +15711,7 @@ def test_authenticate_response_round_trips_unknown_enum_values(self): "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -15096,15 +15772,15 @@ def test_device_authorization_response_omits_absent_optional_non_nullable_fields assert "verification_uri_complete" not in serialized assert "interval" not in serialized - def test_webhook_endpoint_json_round_trip(self): - data = load_fixture("webhook_endpoint_json.json") - instance = WebhookEndpointJson.from_dict(data) + def test_webhook_endpoint_round_trip(self): + data = load_fixture("webhook_endpoint.json") + instance = WebhookEndpoint.from_dict(data) serialized = instance.to_dict() assert serialized == data - restored = WebhookEndpointJson.from_dict(serialized) + restored = WebhookEndpoint.from_dict(serialized) assert restored.to_dict() == serialized - def test_webhook_endpoint_json_minimal_payload(self): + def test_webhook_endpoint_minimal_payload(self): data = { "object": "webhook_endpoint", "id": "we_0123456789", @@ -15115,7 +15791,7 @@ def test_webhook_endpoint_json_minimal_payload(self): "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", } - instance = WebhookEndpointJson.from_dict(data) + instance = WebhookEndpoint.from_dict(data) serialized = instance.to_dict() assert serialized["object"] == data["object"] assert serialized["id"] == data["id"] @@ -15126,18 +15802,18 @@ def test_webhook_endpoint_json_minimal_payload(self): assert serialized["created_at"] == data["created_at"] assert serialized["updated_at"] == data["updated_at"] - def test_webhook_endpoint_json_round_trips_unknown_enum_values(self): + def test_webhook_endpoint_round_trips_unknown_enum_values(self): data = { "object": "webhook_endpoint", "id": "we_0123456789", "endpoint_url": "https://example.com/webhooks", "secret": "whsec_0FWAiVGkEfGBqqsJH4aNAGBJ4", - "status": "unexpected_webhook_endpoint_json_status", + "status": "unexpected_webhook_endpoint_status", "events": ["user.created", "dsync.user.created"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", } - instance = WebhookEndpointJson.from_dict(data) + instance = WebhookEndpoint.from_dict(data) assert instance.to_dict() == data def test_widget_session_token_response_round_trip(self): @@ -15184,7 +15860,7 @@ def test_profile_minimal_payload(self): "id": "prof_01DMC79VCBZ0NY2099737PSVF1", "organization_id": None, "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", - "connection_type": "GoogleOAuth", + "connection_type": "OktaSAML", "idp_id": "103456789012345678901", "email": "todd@example.com", "first_name": None, @@ -15212,7 +15888,7 @@ def test_profile_omits_absent_optional_non_nullable_fields(self): "id": "prof_01DMC79VCBZ0NY2099737PSVF1", "organization_id": "org_01EHQMYV6MBK39QC5PZXHY59C3", "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", - "connection_type": "GoogleOAuth", + "connection_type": "OktaSAML", "idp_id": "103456789012345678901", "email": "todd@example.com", "first_name": "Todd", @@ -15233,7 +15909,7 @@ def test_profile_preserves_nullable_fields(self): "id": "prof_01DMC79VCBZ0NY2099737PSVF1", "organization_id": None, "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", - "connection_type": "GoogleOAuth", + "connection_type": "OktaSAML", "idp_id": "103456789012345678901", "email": "todd@example.com", "first_name": None, @@ -15293,7 +15969,7 @@ def test_sso_token_response_minimal_payload(self): "id": "prof_01DMC79VCBZ0NY2099737PSVF1", "organization_id": "org_01EHQMYV6MBK39QC5PZXHY59C3", "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", - "connection_type": "GoogleOAuth", + "connection_type": "OktaSAML", "idp_id": "103456789012345678901", "email": "todd@example.com", "first_name": "Todd", @@ -15323,7 +15999,7 @@ def test_sso_token_response_omits_absent_optional_non_nullable_fields(self): "id": "prof_01DMC79VCBZ0NY2099737PSVF1", "organization_id": "org_01EHQMYV6MBK39QC5PZXHY59C3", "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5", - "connection_type": "GoogleOAuth", + "connection_type": "OktaSAML", "idp_id": "103456789012345678901", "email": "todd@example.com", "first_name": "Todd", @@ -15926,7 +16602,7 @@ def test_user_organization_membership_base_list_data_minimal_payload(self): "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -15966,7 +16642,7 @@ def test_user_organization_membership_base_list_data_omits_absent_optional_non_n "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -16005,7 +16681,7 @@ def test_user_organization_membership_base_list_data_round_trips_unknown_enum_va "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -16184,39 +16860,37 @@ def test_authentication_factor_enrolled_totp_minimal_payload(self): assert serialized["qr_code"] == data["qr_code"] assert serialized["uri"] == data["uri"] - def test_audit_log_schema_json_actor_round_trip(self): - data = load_fixture("audit_log_schema_json_actor.json") - instance = AuditLogSchemaJsonActor.from_dict(data) + def test_audit_log_schema_actor_round_trip(self): + data = load_fixture("audit_log_schema_actor.json") + instance = AuditLogSchemaActor.from_dict(data) serialized = instance.to_dict() assert serialized == data - restored = AuditLogSchemaJsonActor.from_dict(serialized) + restored = AuditLogSchemaActor.from_dict(serialized) assert restored.to_dict() == serialized - def test_audit_log_schema_json_actor_minimal_payload(self): + def test_audit_log_schema_actor_minimal_payload(self): data = {"metadata": {"key": {}}} - instance = AuditLogSchemaJsonActor.from_dict(data) + instance = AuditLogSchemaActor.from_dict(data) serialized = instance.to_dict() assert serialized["metadata"] == data["metadata"] - def test_audit_log_schema_json_target_round_trip(self): - data = load_fixture("audit_log_schema_json_target.json") - instance = AuditLogSchemaJsonTarget.from_dict(data) + def test_audit_log_schema_target_round_trip(self): + data = load_fixture("audit_log_schema_target.json") + instance = AuditLogSchemaTarget.from_dict(data) serialized = instance.to_dict() assert serialized == data - restored = AuditLogSchemaJsonTarget.from_dict(serialized) + restored = AuditLogSchemaTarget.from_dict(serialized) assert restored.to_dict() == serialized - def test_audit_log_schema_json_target_minimal_payload(self): + def test_audit_log_schema_target_minimal_payload(self): data = {"type": "invoice"} - instance = AuditLogSchemaJsonTarget.from_dict(data) + instance = AuditLogSchemaTarget.from_dict(data) serialized = instance.to_dict() assert serialized["type"] == data["type"] - def test_audit_log_schema_json_target_omits_absent_optional_non_nullable_fields( - self, - ): + def test_audit_log_schema_target_omits_absent_optional_non_nullable_fields(self): data = {"type": "invoice"} - instance = AuditLogSchemaJsonTarget.from_dict(data) + instance = AuditLogSchemaTarget.from_dict(data) serialized = instance.to_dict() assert "metadata" not in serialized @@ -16242,7 +16916,13 @@ def test_authorized_connect_application_list_data_minimal_payload(self): "scopes": ["openid", "profile", "email"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", - "application_type": "m2m", + "application_type": "oauth", + "redirect_uris": [ + {"uri": "https://example.com/callback", "default": True} + ], + "uses_pkce": True, + "is_first_party": True, + "was_dynamically_registered": True, "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", }, } @@ -16269,7 +16949,13 @@ def test_authorized_connect_application_list_data_omits_absent_optional_non_null "scopes": ["openid", "profile", "email"], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", - "application_type": "m2m", + "application_type": "oauth", + "redirect_uris": [ + {"uri": "https://example.com/callback", "default": True} + ], + "uses_pkce": True, + "is_first_party": True, + "was_dynamically_registered": True, "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", }, } @@ -16598,7 +17284,7 @@ def test_organization_membership_minimal_payload(self): "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -16638,7 +17324,7 @@ def test_organization_membership_omits_absent_optional_non_nullable_fields(self) "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -16676,7 +17362,7 @@ def test_organization_membership_round_trips_unknown_enum_values(self): "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -16706,7 +17392,7 @@ def test_email_change_confirmation_minimal_payload(self): "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", "metadata": {"timezone": "America/New_York"}, - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -16765,7 +17451,7 @@ def test_email_change_confirmation_user_omits_absent_optional_non_nullable_field "email": "new.email@example.com", "email_verified": True, "external_id": "f1ffa2b2-c20b-4d39-be5c-212726e11222", - "last_sign_in_at": "2025-06-25T19:07:33.155Z", + "last_sign_in_at": "2025-06-25T19:07:33.000Z", "locale": "en-US", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", @@ -17043,6 +17729,30 @@ def test_data_integrations_list_response_data_connected_account_round_trips_unkn class TestDiscriminatorDispatch: + def test_connect_application_dispatches_known_variant(self): + data = load_fixture("connect_application_m2m.json") + result = ConnectApplication.from_dict(data) + assert isinstance(result, ConnectApplicationM2M) + + def test_connect_application_returns_unknown_for_unrecognized_type(self): + data = load_fixture("connect_application_m2m.json") + data = {**data, "application_type": "future.unrecognized.type"} + result = ConnectApplication.from_dict(data) + assert isinstance(result, ConnectApplicationUnknown) + assert result.raw_data == data + + def test_connect_application_raises_on_missing_discriminator(self): + data = load_fixture("connect_application_m2m.json") + data = {k: v for k, v in data.items() if k != "application_type"} + with pytest.raises(Exception): + ConnectApplication.from_dict(data) + + def test_connect_application_raises_on_none_discriminator(self): + data = load_fixture("connect_application_m2m.json") + data = {**data, "application_type": None} + with pytest.raises(Exception): + ConnectApplication.from_dict(data) + def test_event_schema_dispatches_known_variant(self): data = load_fixture("action_authentication_denied.json") result = EventSchema.from_dict(data) diff --git a/tests/test_organization_membership.py b/tests/test_organization_membership.py new file mode 100644 index 00000000..20dc3360 --- /dev/null +++ b/tests/test_organization_membership.py @@ -0,0 +1,532 @@ +# This file is auto-generated by oagen. Do not edit. + +import json + +import pytest +from workos import WorkOSClient, AsyncWorkOSClient +from tests.generated_helpers import load_fixture + +from workos.common.models import Group, PaginationOrder +from workos.organization_membership.models import ( + OrganizationMembership, + UserOrganizationMembership, +) +from workos._pagination import AsyncPage, SyncPage +from workos._errors import ( + AuthenticationError, + BadRequestError, + NotFoundError, + RateLimitExceededError, + ServerError, + UnprocessableEntityError, +) +from workos.organization_membership._resource import RoleSingle + + +class TestOrganizationMembership: + def test_list_organization_memberships(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("list_user_organization_membership.json"), + ) + page = workos.organization_membership.list_organization_memberships() + assert isinstance(page, SyncPage) + assert len(page.data) == 1 + assert isinstance(page.data[0], UserOrganizationMembership) + + def test_list_organization_memberships_empty_page(self, workos, httpx_mock): + httpx_mock.add_response(json={"data": [], "list_metadata": {}}) + page = workos.organization_membership.list_organization_memberships() + assert isinstance(page, SyncPage) + assert page.data == [] + + def test_list_organization_memberships_encodes_query_params( + self, workos, httpx_mock + ): + httpx_mock.add_response(json={"data": [], "list_metadata": {}}) + workos.organization_membership.list_organization_memberships( + limit=10, + before="cursor before", + after="cursor/after", + order=PaginationOrder("value_order"), + organization_id="value organization_id/test", + statuses=["val1", "val2"], + user_id="value user_id/test", + ) + request = httpx_mock.get_request() + assert request.url.params["limit"] == "10" + assert request.url.params["before"] == "cursor before" + assert request.url.params["after"] == "cursor/after" + assert request.url.params["order"] == "value_order" + assert request.url.params["organization_id"] == "value organization_id/test" + assert request.url.params["statuses"] == "val1,val2" + assert request.url.params["user_id"] == "value user_id/test" + + def test_create_organization_membership(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("organization_membership.json"), + ) + result = workos.organization_membership.create_organization_membership( + user_id="test_user_id", + organization_id="test_organization_id", + role=RoleSingle(role_slug="test_value"), + ) + assert isinstance(result, OrganizationMembership) + assert result.object == "organization_membership" + assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" + request = httpx_mock.get_request() + assert request.method == "POST" + assert request.url.path.endswith("/user_management/organization_memberships") + body = json.loads(request.content) + assert body["user_id"] == "test_user_id" + assert body["organization_id"] == "test_organization_id" + + def test_get_organization_membership(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("user_organization_membership.json"), + ) + result = workos.organization_membership.get_organization_membership("test_id") + assert isinstance(result, UserOrganizationMembership) + assert result.object == "organization_membership" + assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" + request = httpx_mock.get_request() + assert request.method == "GET" + assert request.url.path.endswith( + "/user_management/organization_memberships/test_id" + ) + + def test_update_organization_membership(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("user_organization_membership.json"), + ) + result = workos.organization_membership.update_organization_membership( + "test_id", role=RoleSingle(role_slug="test_value") + ) + assert isinstance(result, UserOrganizationMembership) + assert result.object == "organization_membership" + assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" + request = httpx_mock.get_request() + assert request.method == "PUT" + assert request.url.path.endswith( + "/user_management/organization_memberships/test_id" + ) + + def test_delete_organization_membership(self, workos, httpx_mock): + httpx_mock.add_response(status_code=204) + result = workos.organization_membership.delete_organization_membership( + "test_id" + ) + assert result is None + request = httpx_mock.get_request() + assert request.method == "DELETE" + assert request.url.path.endswith( + "/user_management/organization_memberships/test_id" + ) + + def test_deactivate_organization_membership(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("organization_membership.json"), + ) + result = workos.organization_membership.deactivate_organization_membership( + "test_id" + ) + assert isinstance(result, OrganizationMembership) + assert result.object == "organization_membership" + assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" + request = httpx_mock.get_request() + assert request.method == "PUT" + assert request.url.path.endswith( + "/user_management/organization_memberships/test_id/deactivate" + ) + + def test_reactivate_organization_membership(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("user_organization_membership.json"), + ) + result = workos.organization_membership.reactivate_organization_membership( + "test_id" + ) + assert isinstance(result, UserOrganizationMembership) + assert result.object == "organization_membership" + assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" + request = httpx_mock.get_request() + assert request.method == "PUT" + assert request.url.path.endswith( + "/user_management/organization_memberships/test_id/reactivate" + ) + + def test_list_organization_membership_groups(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("list_group.json"), + ) + page = workos.organization_membership.list_organization_membership_groups( + "test_omId" + ) + assert isinstance(page, SyncPage) + assert len(page.data) == 1 + assert isinstance(page.data[0], Group) + + def test_list_organization_membership_groups_empty_page(self, workos, httpx_mock): + httpx_mock.add_response(json={"data": [], "list_metadata": {}}) + page = workos.organization_membership.list_organization_membership_groups( + "test_omId" + ) + assert isinstance(page, SyncPage) + assert page.data == [] + + def test_list_organization_membership_groups_encodes_query_params( + self, workos, httpx_mock + ): + httpx_mock.add_response(json={"data": [], "list_metadata": {}}) + workos.organization_membership.list_organization_membership_groups( + "test_omId", + limit=10, + before="cursor before", + after="cursor/after", + order=PaginationOrder("value_order"), + ) + request = httpx_mock.get_request() + assert request.url.params["limit"] == "10" + assert request.url.params["before"] == "cursor before" + assert request.url.params["after"] == "cursor/after" + assert request.url.params["order"] == "value_order" + + def test_list_organization_memberships_with_request_options( + self, workos, httpx_mock + ): + httpx_mock.add_response(json={"data": [], "list_metadata": {}}) + workos.organization_membership.list_organization_memberships( + request_options={"extra_headers": {"X-Custom": "value"}} + ) + request = httpx_mock.get_request() + assert request.headers["X-Custom"] == "value" + + def test_list_organization_memberships_unauthorized(self, workos, httpx_mock): + httpx_mock.add_response( + status_code=401, + json={"message": "Unauthorized"}, + ) + with pytest.raises(AuthenticationError): + workos.organization_membership.list_organization_memberships() + + def test_list_organization_memberships_not_found(self, httpx_mock): + workos = WorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response(status_code=404, json={"message": "Not found"}) + with pytest.raises(NotFoundError): + workos.organization_membership.list_organization_memberships() + finally: + workos.close() + + def test_list_organization_memberships_rate_limited(self, httpx_mock): + workos = WorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response( + status_code=429, + headers={"Retry-After": "0"}, + json={"message": "Slow down"}, + ) + with pytest.raises(RateLimitExceededError): + workos.organization_membership.list_organization_memberships() + finally: + workos.close() + + def test_list_organization_memberships_server_error(self, httpx_mock): + workos = WorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response(status_code=500, json={"message": "Server error"}) + with pytest.raises(ServerError): + workos.organization_membership.list_organization_memberships() + finally: + workos.close() + + def test_list_organization_memberships_bad_request(self, httpx_mock): + workos = WorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response(status_code=400, json={"message": "Bad request"}) + with pytest.raises(BadRequestError): + workos.organization_membership.list_organization_memberships() + finally: + workos.close() + + def test_list_organization_memberships_unprocessable(self, httpx_mock): + workos = WorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response(status_code=422, json={"message": "Unprocessable"}) + with pytest.raises(UnprocessableEntityError): + workos.organization_membership.list_organization_memberships() + finally: + workos.close() + + +class TestAsyncOrganizationMembership: + @pytest.mark.asyncio + async def test_list_organization_memberships(self, async_workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("list_user_organization_membership.json") + ) + page = ( + await async_workos.organization_membership.list_organization_memberships() + ) + assert isinstance(page, AsyncPage) + assert len(page.data) == 1 + assert isinstance(page.data[0], UserOrganizationMembership) + + @pytest.mark.asyncio + async def test_list_organization_memberships_empty_page( + self, async_workos, httpx_mock + ): + httpx_mock.add_response(json={"data": [], "list_metadata": {}}) + page = ( + await async_workos.organization_membership.list_organization_memberships() + ) + assert isinstance(page, AsyncPage) + assert page.data == [] + + @pytest.mark.asyncio + async def test_list_organization_memberships_encodes_query_params( + self, async_workos, httpx_mock + ): + httpx_mock.add_response(json={"data": [], "list_metadata": {}}) + await async_workos.organization_membership.list_organization_memberships( + limit=10, + before="cursor before", + after="cursor/after", + order=PaginationOrder("value_order"), + organization_id="value organization_id/test", + statuses=["val1", "val2"], + user_id="value user_id/test", + ) + request = httpx_mock.get_request() + assert request.url.params["limit"] == "10" + assert request.url.params["before"] == "cursor before" + assert request.url.params["after"] == "cursor/after" + assert request.url.params["order"] == "value_order" + assert request.url.params["organization_id"] == "value organization_id/test" + assert request.url.params["statuses"] == "val1,val2" + assert request.url.params["user_id"] == "value user_id/test" + + @pytest.mark.asyncio + async def test_create_organization_membership(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("organization_membership.json")) + result = ( + await async_workos.organization_membership.create_organization_membership( + user_id="test_user_id", + organization_id="test_organization_id", + role=RoleSingle(role_slug="test_value"), + ) + ) + assert isinstance(result, OrganizationMembership) + assert result.object == "organization_membership" + assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" + request = httpx_mock.get_request() + assert request.method == "POST" + assert request.url.path.endswith("/user_management/organization_memberships") + + @pytest.mark.asyncio + async def test_get_organization_membership(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("user_organization_membership.json")) + result = await async_workos.organization_membership.get_organization_membership( + "test_id" + ) + assert isinstance(result, UserOrganizationMembership) + assert result.object == "organization_membership" + assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" + request = httpx_mock.get_request() + assert request.method == "GET" + assert request.url.path.endswith( + "/user_management/organization_memberships/test_id" + ) + + @pytest.mark.asyncio + async def test_update_organization_membership(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("user_organization_membership.json")) + result = ( + await async_workos.organization_membership.update_organization_membership( + "test_id", role=RoleSingle(role_slug="test_value") + ) + ) + assert isinstance(result, UserOrganizationMembership) + assert result.object == "organization_membership" + assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" + request = httpx_mock.get_request() + assert request.method == "PUT" + assert request.url.path.endswith( + "/user_management/organization_memberships/test_id" + ) + + @pytest.mark.asyncio + async def test_delete_organization_membership(self, async_workos, httpx_mock): + httpx_mock.add_response(status_code=204) + result = ( + await async_workos.organization_membership.delete_organization_membership( + "test_id" + ) + ) + assert result is None + request = httpx_mock.get_request() + assert request.method == "DELETE" + assert request.url.path.endswith( + "/user_management/organization_memberships/test_id" + ) + + @pytest.mark.asyncio + async def test_deactivate_organization_membership(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("organization_membership.json")) + result = await async_workos.organization_membership.deactivate_organization_membership( + "test_id" + ) + assert isinstance(result, OrganizationMembership) + assert result.object == "organization_membership" + assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" + request = httpx_mock.get_request() + assert request.method == "PUT" + assert request.url.path.endswith( + "/user_management/organization_memberships/test_id/deactivate" + ) + + @pytest.mark.asyncio + async def test_reactivate_organization_membership(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("user_organization_membership.json")) + result = await async_workos.organization_membership.reactivate_organization_membership( + "test_id" + ) + assert isinstance(result, UserOrganizationMembership) + assert result.object == "organization_membership" + assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" + request = httpx_mock.get_request() + assert request.method == "PUT" + assert request.url.path.endswith( + "/user_management/organization_memberships/test_id/reactivate" + ) + + @pytest.mark.asyncio + async def test_list_organization_membership_groups(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("list_group.json")) + page = await async_workos.organization_membership.list_organization_membership_groups( + "test_omId" + ) + assert isinstance(page, AsyncPage) + assert len(page.data) == 1 + assert isinstance(page.data[0], Group) + + @pytest.mark.asyncio + async def test_list_organization_membership_groups_empty_page( + self, async_workos, httpx_mock + ): + httpx_mock.add_response(json={"data": [], "list_metadata": {}}) + page = await async_workos.organization_membership.list_organization_membership_groups( + "test_omId" + ) + assert isinstance(page, AsyncPage) + assert page.data == [] + + @pytest.mark.asyncio + async def test_list_organization_membership_groups_encodes_query_params( + self, async_workos, httpx_mock + ): + httpx_mock.add_response(json={"data": [], "list_metadata": {}}) + await async_workos.organization_membership.list_organization_membership_groups( + "test_omId", + limit=10, + before="cursor before", + after="cursor/after", + order=PaginationOrder("value_order"), + ) + request = httpx_mock.get_request() + assert request.url.params["limit"] == "10" + assert request.url.params["before"] == "cursor before" + assert request.url.params["after"] == "cursor/after" + assert request.url.params["order"] == "value_order" + + @pytest.mark.asyncio + async def test_list_organization_memberships_with_request_options( + self, async_workos, httpx_mock + ): + httpx_mock.add_response(json={"data": [], "list_metadata": {}}) + await async_workos.organization_membership.list_organization_memberships( + request_options={"extra_headers": {"X-Custom": "value"}} + ) + request = httpx_mock.get_request() + assert request.headers["X-Custom"] == "value" + + @pytest.mark.asyncio + async def test_list_organization_memberships_unauthorized( + self, async_workos, httpx_mock + ): + httpx_mock.add_response(status_code=401, json={"message": "Unauthorized"}) + with pytest.raises(AuthenticationError): + await async_workos.organization_membership.list_organization_memberships() + + @pytest.mark.asyncio + async def test_list_organization_memberships_not_found(self, httpx_mock): + workos = AsyncWorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response(status_code=404, json={"message": "Not found"}) + with pytest.raises(NotFoundError): + await workos.organization_membership.list_organization_memberships() + finally: + await workos.close() + + @pytest.mark.asyncio + async def test_list_organization_memberships_rate_limited(self, httpx_mock): + workos = AsyncWorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response( + status_code=429, + headers={"Retry-After": "0"}, + json={"message": "Slow down"}, + ) + with pytest.raises(RateLimitExceededError): + await workos.organization_membership.list_organization_memberships() + finally: + await workos.close() + + @pytest.mark.asyncio + async def test_list_organization_memberships_server_error(self, httpx_mock): + workos = AsyncWorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response(status_code=500, json={"message": "Server error"}) + with pytest.raises(ServerError): + await workos.organization_membership.list_organization_memberships() + finally: + await workos.close() + + @pytest.mark.asyncio + async def test_list_organization_memberships_bad_request(self, httpx_mock): + workos = AsyncWorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response(status_code=400, json={"message": "Bad request"}) + with pytest.raises(BadRequestError): + await workos.organization_membership.list_organization_memberships() + finally: + await workos.close() + + @pytest.mark.asyncio + async def test_list_organization_memberships_unprocessable(self, httpx_mock): + workos = AsyncWorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response(status_code=422, json={"message": "Unprocessable"}) + with pytest.raises(UnprocessableEntityError): + await workos.organization_membership.list_organization_memberships() + finally: + await workos.close() diff --git a/tests/test_radar.py b/tests/test_radar.py index 02a75abd..6a6c4903 100644 --- a/tests/test_radar.py +++ b/tests/test_radar.py @@ -34,7 +34,7 @@ def test_create_attempt(self, workos, httpx_mock): user_agent="test_user_agent", email="test_email", auth_method=RadarStandaloneAssessRequestAuthMethod("Password"), - action=RadarStandaloneAssessRequestAction("login"), + action=RadarStandaloneAssessRequestAction("sign-up"), ) assert isinstance(result, RadarStandaloneResponse) assert result.verdict == "block" @@ -47,7 +47,7 @@ def test_create_attempt(self, workos, httpx_mock): assert body["user_agent"] == "test_user_agent" assert body["email"] == "test_email" assert body["auth_method"] == RadarStandaloneAssessRequestAuthMethod("Password") - assert body["action"] == RadarStandaloneAssessRequestAction("login") + assert body["action"] == RadarStandaloneAssessRequestAction("sign-up") def test_update_attempt(self, workos, httpx_mock): httpx_mock.add_response(json={}) @@ -88,7 +88,7 @@ def test_create_attempt_with_request_options(self, workos, httpx_mock): user_agent="test_user_agent", email="test_email", auth_method=RadarStandaloneAssessRequestAuthMethod("Password"), - action=RadarStandaloneAssessRequestAction("login"), + action=RadarStandaloneAssessRequestAction("sign-up"), request_options={"extra_headers": {"X-Custom": "value"}}, ) request = httpx_mock.get_request() @@ -105,7 +105,7 @@ def test_create_attempt_unauthorized(self, workos, httpx_mock): user_agent="test_user_agent", email="test_email", auth_method=RadarStandaloneAssessRequestAuthMethod("Password"), - action=RadarStandaloneAssessRequestAction("login"), + action=RadarStandaloneAssessRequestAction("sign-up"), ) def test_create_attempt_not_found(self, httpx_mock): @@ -120,7 +120,7 @@ def test_create_attempt_not_found(self, httpx_mock): user_agent="test_user_agent", email="test_email", auth_method=RadarStandaloneAssessRequestAuthMethod("Password"), - action=RadarStandaloneAssessRequestAction("login"), + action=RadarStandaloneAssessRequestAction("sign-up"), ) finally: workos.close() @@ -141,7 +141,7 @@ def test_create_attempt_rate_limited(self, httpx_mock): user_agent="test_user_agent", email="test_email", auth_method=RadarStandaloneAssessRequestAuthMethod("Password"), - action=RadarStandaloneAssessRequestAction("login"), + action=RadarStandaloneAssessRequestAction("sign-up"), ) finally: workos.close() @@ -158,7 +158,7 @@ def test_create_attempt_server_error(self, httpx_mock): user_agent="test_user_agent", email="test_email", auth_method=RadarStandaloneAssessRequestAuthMethod("Password"), - action=RadarStandaloneAssessRequestAction("login"), + action=RadarStandaloneAssessRequestAction("sign-up"), ) finally: workos.close() @@ -175,7 +175,7 @@ def test_create_attempt_bad_request(self, httpx_mock): user_agent="test_user_agent", email="test_email", auth_method=RadarStandaloneAssessRequestAuthMethod("Password"), - action=RadarStandaloneAssessRequestAction("login"), + action=RadarStandaloneAssessRequestAction("sign-up"), ) finally: workos.close() @@ -192,7 +192,7 @@ def test_create_attempt_unprocessable(self, httpx_mock): user_agent="test_user_agent", email="test_email", auth_method=RadarStandaloneAssessRequestAuthMethod("Password"), - action=RadarStandaloneAssessRequestAction("login"), + action=RadarStandaloneAssessRequestAction("sign-up"), ) finally: workos.close() @@ -207,7 +207,7 @@ async def test_create_attempt(self, async_workos, httpx_mock): user_agent="test_user_agent", email="test_email", auth_method=RadarStandaloneAssessRequestAuthMethod("Password"), - action=RadarStandaloneAssessRequestAction("login"), + action=RadarStandaloneAssessRequestAction("sign-up"), ) assert isinstance(result, RadarStandaloneResponse) assert result.verdict == "block" @@ -257,7 +257,7 @@ async def test_create_attempt_with_request_options(self, async_workos, httpx_moc user_agent="test_user_agent", email="test_email", auth_method=RadarStandaloneAssessRequestAuthMethod("Password"), - action=RadarStandaloneAssessRequestAction("login"), + action=RadarStandaloneAssessRequestAction("sign-up"), request_options={"extra_headers": {"X-Custom": "value"}}, ) request = httpx_mock.get_request() @@ -272,7 +272,7 @@ async def test_create_attempt_unauthorized(self, async_workos, httpx_mock): user_agent="test_user_agent", email="test_email", auth_method=RadarStandaloneAssessRequestAuthMethod("Password"), - action=RadarStandaloneAssessRequestAction("login"), + action=RadarStandaloneAssessRequestAction("sign-up"), ) @pytest.mark.asyncio @@ -288,7 +288,7 @@ async def test_create_attempt_not_found(self, httpx_mock): user_agent="test_user_agent", email="test_email", auth_method=RadarStandaloneAssessRequestAuthMethod("Password"), - action=RadarStandaloneAssessRequestAction("login"), + action=RadarStandaloneAssessRequestAction("sign-up"), ) finally: await workos.close() @@ -310,7 +310,7 @@ async def test_create_attempt_rate_limited(self, httpx_mock): user_agent="test_user_agent", email="test_email", auth_method=RadarStandaloneAssessRequestAuthMethod("Password"), - action=RadarStandaloneAssessRequestAction("login"), + action=RadarStandaloneAssessRequestAction("sign-up"), ) finally: await workos.close() @@ -328,7 +328,7 @@ async def test_create_attempt_server_error(self, httpx_mock): user_agent="test_user_agent", email="test_email", auth_method=RadarStandaloneAssessRequestAuthMethod("Password"), - action=RadarStandaloneAssessRequestAction("login"), + action=RadarStandaloneAssessRequestAction("sign-up"), ) finally: await workos.close() @@ -346,7 +346,7 @@ async def test_create_attempt_bad_request(self, httpx_mock): user_agent="test_user_agent", email="test_email", auth_method=RadarStandaloneAssessRequestAuthMethod("Password"), - action=RadarStandaloneAssessRequestAction("login"), + action=RadarStandaloneAssessRequestAction("sign-up"), ) finally: await workos.close() @@ -364,7 +364,7 @@ async def test_create_attempt_unprocessable(self, httpx_mock): user_agent="test_user_agent", email="test_email", auth_method=RadarStandaloneAssessRequestAuthMethod("Password"), - action=RadarStandaloneAssessRequestAction("login"), + action=RadarStandaloneAssessRequestAction("sign-up"), ) finally: await workos.close() diff --git a/tests/test_user_management.py b/tests/test_user_management.py index 52da6242..3b873140 100644 --- a/tests/test_user_management.py +++ b/tests/test_user_management.py @@ -19,7 +19,6 @@ JWTTemplateResponse, JwksResponse, MagicAuth, - OrganizationMembership, PasswordReset, RedirectUri, ResetPasswordResponse, @@ -28,7 +27,6 @@ UserApiKeyWithValue, UserIdentitiesGetItem, UserInvite, - UserOrganizationMembership, VerifyEmailResponse, ) from workos._pagination import AsyncPage, SyncPage @@ -40,7 +38,7 @@ ServerError, UnprocessableEntityError, ) -from workos.user_management._resource import PasswordPlaintext, RoleSingle +from workos.user_management._resource import PasswordPlaintext class TestUserManagement: @@ -529,130 +527,6 @@ def test_get_magic_auth(self, workos, httpx_mock): assert request.method == "GET" assert request.url.path.endswith("/user_management/magic_auth/test_id") - def test_list_organization_memberships(self, workos, httpx_mock): - httpx_mock.add_response( - json=load_fixture("list_user_organization_membership.json"), - ) - page = workos.user_management.list_organization_memberships() - assert isinstance(page, SyncPage) - assert len(page.data) == 1 - assert isinstance(page.data[0], UserOrganizationMembership) - - def test_list_organization_memberships_empty_page(self, workos, httpx_mock): - httpx_mock.add_response(json={"data": [], "list_metadata": {}}) - page = workos.user_management.list_organization_memberships() - assert isinstance(page, SyncPage) - assert page.data == [] - - def test_list_organization_memberships_encodes_query_params( - self, workos, httpx_mock - ): - httpx_mock.add_response(json={"data": [], "list_metadata": {}}) - workos.user_management.list_organization_memberships( - limit=10, - before="cursor before", - after="cursor/after", - order=PaginationOrder("value_order"), - organization_id="value organization_id/test", - statuses=["val1", "val2"], - user_id="value user_id/test", - ) - request = httpx_mock.get_request() - assert request.url.params["limit"] == "10" - assert request.url.params["before"] == "cursor before" - assert request.url.params["after"] == "cursor/after" - assert request.url.params["order"] == "value_order" - assert request.url.params["organization_id"] == "value organization_id/test" - assert request.url.params["statuses"] == "val1,val2" - assert request.url.params["user_id"] == "value user_id/test" - - def test_create_organization_membership(self, workos, httpx_mock): - httpx_mock.add_response( - json=load_fixture("organization_membership.json"), - ) - result = workos.user_management.create_organization_membership( - user_id="test_user_id", - organization_id="test_organization_id", - role=RoleSingle(role_slug="test_value"), - ) - assert isinstance(result, OrganizationMembership) - assert result.object == "organization_membership" - assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" - request = httpx_mock.get_request() - assert request.method == "POST" - assert request.url.path.endswith("/user_management/organization_memberships") - body = json.loads(request.content) - assert body["user_id"] == "test_user_id" - assert body["organization_id"] == "test_organization_id" - - def test_get_organization_membership(self, workos, httpx_mock): - httpx_mock.add_response( - json=load_fixture("user_organization_membership.json"), - ) - result = workos.user_management.get_organization_membership("test_id") - assert isinstance(result, UserOrganizationMembership) - assert result.object == "organization_membership" - assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" - request = httpx_mock.get_request() - assert request.method == "GET" - assert request.url.path.endswith( - "/user_management/organization_memberships/test_id" - ) - - def test_update_organization_membership(self, workos, httpx_mock): - httpx_mock.add_response( - json=load_fixture("user_organization_membership.json"), - ) - result = workos.user_management.update_organization_membership( - "test_id", role=RoleSingle(role_slug="test_value") - ) - assert isinstance(result, UserOrganizationMembership) - assert result.object == "organization_membership" - assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" - request = httpx_mock.get_request() - assert request.method == "PUT" - assert request.url.path.endswith( - "/user_management/organization_memberships/test_id" - ) - - def test_delete_organization_membership(self, workos, httpx_mock): - httpx_mock.add_response(status_code=204) - result = workos.user_management.delete_organization_membership("test_id") - assert result is None - request = httpx_mock.get_request() - assert request.method == "DELETE" - assert request.url.path.endswith( - "/user_management/organization_memberships/test_id" - ) - - def test_deactivate_organization_membership(self, workos, httpx_mock): - httpx_mock.add_response( - json=load_fixture("organization_membership.json"), - ) - result = workos.user_management.deactivate_organization_membership("test_id") - assert isinstance(result, OrganizationMembership) - assert result.object == "organization_membership" - assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" - request = httpx_mock.get_request() - assert request.method == "PUT" - assert request.url.path.endswith( - "/user_management/organization_memberships/test_id/deactivate" - ) - - def test_reactivate_organization_membership(self, workos, httpx_mock): - httpx_mock.add_response( - json=load_fixture("user_organization_membership.json"), - ) - result = workos.user_management.reactivate_organization_membership("test_id") - assert isinstance(result, UserOrganizationMembership) - assert result.object == "organization_membership" - assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" - request = httpx_mock.get_request() - assert request.method == "PUT" - assert request.url.path.endswith( - "/user_management/organization_memberships/test_id/reactivate" - ) - def test_create_redirect_uri(self, workos, httpx_mock): httpx_mock.add_response( json=load_fixture("redirect_uri.json"), @@ -1391,136 +1265,6 @@ async def test_get_magic_auth(self, async_workos, httpx_mock): assert request.method == "GET" assert request.url.path.endswith("/user_management/magic_auth/test_id") - @pytest.mark.asyncio - async def test_list_organization_memberships(self, async_workos, httpx_mock): - httpx_mock.add_response( - json=load_fixture("list_user_organization_membership.json") - ) - page = await async_workos.user_management.list_organization_memberships() - assert isinstance(page, AsyncPage) - assert len(page.data) == 1 - assert isinstance(page.data[0], UserOrganizationMembership) - - @pytest.mark.asyncio - async def test_list_organization_memberships_empty_page( - self, async_workos, httpx_mock - ): - httpx_mock.add_response(json={"data": [], "list_metadata": {}}) - page = await async_workos.user_management.list_organization_memberships() - assert isinstance(page, AsyncPage) - assert page.data == [] - - @pytest.mark.asyncio - async def test_list_organization_memberships_encodes_query_params( - self, async_workos, httpx_mock - ): - httpx_mock.add_response(json={"data": [], "list_metadata": {}}) - await async_workos.user_management.list_organization_memberships( - limit=10, - before="cursor before", - after="cursor/after", - order=PaginationOrder("value_order"), - organization_id="value organization_id/test", - statuses=["val1", "val2"], - user_id="value user_id/test", - ) - request = httpx_mock.get_request() - assert request.url.params["limit"] == "10" - assert request.url.params["before"] == "cursor before" - assert request.url.params["after"] == "cursor/after" - assert request.url.params["order"] == "value_order" - assert request.url.params["organization_id"] == "value organization_id/test" - assert request.url.params["statuses"] == "val1,val2" - assert request.url.params["user_id"] == "value user_id/test" - - @pytest.mark.asyncio - async def test_create_organization_membership(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("organization_membership.json")) - result = await async_workos.user_management.create_organization_membership( - user_id="test_user_id", - organization_id="test_organization_id", - role=RoleSingle(role_slug="test_value"), - ) - assert isinstance(result, OrganizationMembership) - assert result.object == "organization_membership" - assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" - request = httpx_mock.get_request() - assert request.method == "POST" - assert request.url.path.endswith("/user_management/organization_memberships") - - @pytest.mark.asyncio - async def test_get_organization_membership(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("user_organization_membership.json")) - result = await async_workos.user_management.get_organization_membership( - "test_id" - ) - assert isinstance(result, UserOrganizationMembership) - assert result.object == "organization_membership" - assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" - request = httpx_mock.get_request() - assert request.method == "GET" - assert request.url.path.endswith( - "/user_management/organization_memberships/test_id" - ) - - @pytest.mark.asyncio - async def test_update_organization_membership(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("user_organization_membership.json")) - result = await async_workos.user_management.update_organization_membership( - "test_id", role=RoleSingle(role_slug="test_value") - ) - assert isinstance(result, UserOrganizationMembership) - assert result.object == "organization_membership" - assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" - request = httpx_mock.get_request() - assert request.method == "PUT" - assert request.url.path.endswith( - "/user_management/organization_memberships/test_id" - ) - - @pytest.mark.asyncio - async def test_delete_organization_membership(self, async_workos, httpx_mock): - httpx_mock.add_response(status_code=204) - result = await async_workos.user_management.delete_organization_membership( - "test_id" - ) - assert result is None - request = httpx_mock.get_request() - assert request.method == "DELETE" - assert request.url.path.endswith( - "/user_management/organization_memberships/test_id" - ) - - @pytest.mark.asyncio - async def test_deactivate_organization_membership(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("organization_membership.json")) - result = await async_workos.user_management.deactivate_organization_membership( - "test_id" - ) - assert isinstance(result, OrganizationMembership) - assert result.object == "organization_membership" - assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" - request = httpx_mock.get_request() - assert request.method == "PUT" - assert request.url.path.endswith( - "/user_management/organization_memberships/test_id/deactivate" - ) - - @pytest.mark.asyncio - async def test_reactivate_organization_membership(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("user_organization_membership.json")) - result = await async_workos.user_management.reactivate_organization_membership( - "test_id" - ) - assert isinstance(result, UserOrganizationMembership) - assert result.object == "organization_membership" - assert result.id == "om_01HXYZ123456789ABCDEFGHIJ" - request = httpx_mock.get_request() - assert request.method == "PUT" - assert request.url.path.endswith( - "/user_management/organization_memberships/test_id/reactivate" - ) - @pytest.mark.asyncio async def test_create_redirect_uri(self, async_workos, httpx_mock): httpx_mock.add_response(json=load_fixture("redirect_uri.json")) diff --git a/tests/test_user_management_organization_membership_groups.py b/tests/test_user_management_organization_membership_groups.py deleted file mode 100644 index 0ab43f00..00000000 --- a/tests/test_user_management_organization_membership_groups.py +++ /dev/null @@ -1,280 +0,0 @@ -# This file is auto-generated by oagen. Do not edit. - - -import pytest -from workos import WorkOSClient, AsyncWorkOSClient -from tests.generated_helpers import load_fixture - -from workos.common.models import Group, PaginationOrder -from workos._pagination import AsyncPage, SyncPage -from workos._errors import ( - AuthenticationError, - BadRequestError, - NotFoundError, - RateLimitExceededError, - ServerError, - UnprocessableEntityError, -) - - -class TestUserManagementOrganizationMembershipGroups: - def test_list_organization_membership_groups(self, workos, httpx_mock): - httpx_mock.add_response( - json=load_fixture("list_group.json"), - ) - page = workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId" - ) - assert isinstance(page, SyncPage) - assert len(page.data) == 1 - assert isinstance(page.data[0], Group) - - def test_list_organization_membership_groups_empty_page(self, workos, httpx_mock): - httpx_mock.add_response(json={"data": [], "list_metadata": {}}) - page = workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId" - ) - assert isinstance(page, SyncPage) - assert page.data == [] - - def test_list_organization_membership_groups_encodes_query_params( - self, workos, httpx_mock - ): - httpx_mock.add_response(json={"data": [], "list_metadata": {}}) - workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId", - limit=10, - before="cursor before", - after="cursor/after", - order=PaginationOrder("value_order"), - ) - request = httpx_mock.get_request() - assert request.url.params["limit"] == "10" - assert request.url.params["before"] == "cursor before" - assert request.url.params["after"] == "cursor/after" - assert request.url.params["order"] == "value_order" - - def test_list_organization_membership_groups_with_request_options( - self, workos, httpx_mock - ): - httpx_mock.add_response(json={"data": [], "list_metadata": {}}) - workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId", request_options={"extra_headers": {"X-Custom": "value"}} - ) - request = httpx_mock.get_request() - assert request.headers["X-Custom"] == "value" - - def test_list_organization_membership_groups_unauthorized(self, workos, httpx_mock): - httpx_mock.add_response( - status_code=401, - json={"message": "Unauthorized"}, - ) - with pytest.raises(AuthenticationError): - workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId" - ) - - def test_list_organization_membership_groups_not_found(self, httpx_mock): - workos = WorkOSClient( - api_key="sk_test_123", client_id="client_test", max_retries=0 - ) - try: - httpx_mock.add_response(status_code=404, json={"message": "Not found"}) - with pytest.raises(NotFoundError): - workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId" - ) - finally: - workos.close() - - def test_list_organization_membership_groups_rate_limited(self, httpx_mock): - workos = WorkOSClient( - api_key="sk_test_123", client_id="client_test", max_retries=0 - ) - try: - httpx_mock.add_response( - status_code=429, - headers={"Retry-After": "0"}, - json={"message": "Slow down"}, - ) - with pytest.raises(RateLimitExceededError): - workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId" - ) - finally: - workos.close() - - def test_list_organization_membership_groups_server_error(self, httpx_mock): - workos = WorkOSClient( - api_key="sk_test_123", client_id="client_test", max_retries=0 - ) - try: - httpx_mock.add_response(status_code=500, json={"message": "Server error"}) - with pytest.raises(ServerError): - workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId" - ) - finally: - workos.close() - - def test_list_organization_membership_groups_bad_request(self, httpx_mock): - workos = WorkOSClient( - api_key="sk_test_123", client_id="client_test", max_retries=0 - ) - try: - httpx_mock.add_response(status_code=400, json={"message": "Bad request"}) - with pytest.raises(BadRequestError): - workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId" - ) - finally: - workos.close() - - def test_list_organization_membership_groups_unprocessable(self, httpx_mock): - workos = WorkOSClient( - api_key="sk_test_123", client_id="client_test", max_retries=0 - ) - try: - httpx_mock.add_response(status_code=422, json={"message": "Unprocessable"}) - with pytest.raises(UnprocessableEntityError): - workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId" - ) - finally: - workos.close() - - -class TestAsyncUserManagementOrganizationMembershipGroups: - @pytest.mark.asyncio - async def test_list_organization_membership_groups(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("list_group.json")) - page = await async_workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId" - ) - assert isinstance(page, AsyncPage) - assert len(page.data) == 1 - assert isinstance(page.data[0], Group) - - @pytest.mark.asyncio - async def test_list_organization_membership_groups_empty_page( - self, async_workos, httpx_mock - ): - httpx_mock.add_response(json={"data": [], "list_metadata": {}}) - page = await async_workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId" - ) - assert isinstance(page, AsyncPage) - assert page.data == [] - - @pytest.mark.asyncio - async def test_list_organization_membership_groups_encodes_query_params( - self, async_workos, httpx_mock - ): - httpx_mock.add_response(json={"data": [], "list_metadata": {}}) - await async_workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId", - limit=10, - before="cursor before", - after="cursor/after", - order=PaginationOrder("value_order"), - ) - request = httpx_mock.get_request() - assert request.url.params["limit"] == "10" - assert request.url.params["before"] == "cursor before" - assert request.url.params["after"] == "cursor/after" - assert request.url.params["order"] == "value_order" - - @pytest.mark.asyncio - async def test_list_organization_membership_groups_with_request_options( - self, async_workos, httpx_mock - ): - httpx_mock.add_response(json={"data": [], "list_metadata": {}}) - await async_workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId", request_options={"extra_headers": {"X-Custom": "value"}} - ) - request = httpx_mock.get_request() - assert request.headers["X-Custom"] == "value" - - @pytest.mark.asyncio - async def test_list_organization_membership_groups_unauthorized( - self, async_workos, httpx_mock - ): - httpx_mock.add_response(status_code=401, json={"message": "Unauthorized"}) - with pytest.raises(AuthenticationError): - await async_workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId" - ) - - @pytest.mark.asyncio - async def test_list_organization_membership_groups_not_found(self, httpx_mock): - workos = AsyncWorkOSClient( - api_key="sk_test_123", client_id="client_test", max_retries=0 - ) - try: - httpx_mock.add_response(status_code=404, json={"message": "Not found"}) - with pytest.raises(NotFoundError): - await workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId" - ) - finally: - await workos.close() - - @pytest.mark.asyncio - async def test_list_organization_membership_groups_rate_limited(self, httpx_mock): - workos = AsyncWorkOSClient( - api_key="sk_test_123", client_id="client_test", max_retries=0 - ) - try: - httpx_mock.add_response( - status_code=429, - headers={"Retry-After": "0"}, - json={"message": "Slow down"}, - ) - with pytest.raises(RateLimitExceededError): - await workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId" - ) - finally: - await workos.close() - - @pytest.mark.asyncio - async def test_list_organization_membership_groups_server_error(self, httpx_mock): - workos = AsyncWorkOSClient( - api_key="sk_test_123", client_id="client_test", max_retries=0 - ) - try: - httpx_mock.add_response(status_code=500, json={"message": "Server error"}) - with pytest.raises(ServerError): - await workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId" - ) - finally: - await workos.close() - - @pytest.mark.asyncio - async def test_list_organization_membership_groups_bad_request(self, httpx_mock): - workos = AsyncWorkOSClient( - api_key="sk_test_123", client_id="client_test", max_retries=0 - ) - try: - httpx_mock.add_response(status_code=400, json={"message": "Bad request"}) - with pytest.raises(BadRequestError): - await workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId" - ) - finally: - await workos.close() - - @pytest.mark.asyncio - async def test_list_organization_membership_groups_unprocessable(self, httpx_mock): - workos = AsyncWorkOSClient( - api_key="sk_test_123", client_id="client_test", max_retries=0 - ) - try: - httpx_mock.add_response(status_code=422, json={"message": "Unprocessable"}) - with pytest.raises(UnprocessableEntityError): - await workos.user_management_organization_membership_groups.list_organization_membership_groups( - "test_omId" - ) - finally: - await workos.close() diff --git a/tests/test_vault.py b/tests/test_vault.py index dfa0c455..401d5479 100644 --- a/tests/test_vault.py +++ b/tests/test_vault.py @@ -1,206 +1,237 @@ -# @oagen-ignore-file +# This file is auto-generated by oagen. Do not edit. + import json import pytest from workos import WorkOSClient, AsyncWorkOSClient from tests.generated_helpers import load_fixture -from workos.vault import ( - DataKey, - DataKeyPair, - ObjectDigest, +from workos.vault.models import ( + CreateDataKeyResponse, + DecryptResponse, ObjectMetadata, - ObjectVersion, + ObjectSummary, + ObjectWithoutValue, VaultObject, + VersionListResponse, + VaultOrder, ) +from workos._pagination import AsyncPage, SyncPage from workos._errors import ( AuthenticationError, + BadRequestError, NotFoundError, RateLimitExceededError, ServerError, + UnprocessableEntityError, ) class TestVault: - def test_read_object(self, workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_object.json")) - result = workos.vault.read_object( - object_id="vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" + def test_create_data_key(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("create_data_key_response.json"), ) - assert isinstance(result, VaultObject) - assert result.id == "vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" - assert result.name == "my-secret" - assert result.value == "super-secret-value" - request = httpx_mock.get_request() - assert request.method == "GET" - assert request.url.path.endswith( - "/vault/v1/kv/vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" + result = workos.vault.create_data_key(context={}) + assert isinstance(result, CreateDataKeyResponse) + assert result.data_key == "DR9idtey9MpMrA1VRFrz30HB1yNgL2PoHZyjAkFeWgg=" + assert ( + result.encrypted_keys + == "V09TLkVLTS52MQBiZjUxY2NlYy03OGI0LTUyMDAtYjM4My0zNTczMGU3MWVmNjEBATEBJGJmNjVlMzI2LTQzYTAtNGIyMC04OGM0LTA3ZmYzZGU1NDM0YwF0YmY2NWUzMjYtNDNhMC00YjIwLTg4YzQtMDdmZjNkZTU0MzRj" ) - - def test_read_object_by_name(self, workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_object.json")) - result = workos.vault.read_object_by_name(name="my-secret") - assert isinstance(result, VaultObject) - assert result.name == "my-secret" request = httpx_mock.get_request() - assert request.method == "GET" - assert request.url.path.endswith("/vault/v1/kv/name/my-secret") + assert request.method == "POST" + assert request.url.path.endswith("/vault/v1/keys/data-key") + body = json.loads(request.content) + assert "context" in body - def test_get_object_metadata(self, workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_object_metadata.json")) - result = workos.vault.get_object_metadata( - object_id="vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" - ) - assert isinstance(result, VaultObject) - assert result.id == "vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" - assert result.name == "my-secret" - assert result.value is None - request = httpx_mock.get_request() - assert request.method == "GET" - assert request.url.path.endswith( - "/vault/v1/kv/vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C/metadata" + def test_create_decrypt(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("decrypt_response.json"), ) - - def test_list_objects(self, workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_list_objects.json")) - result = workos.vault.list_objects() - assert len(result) == 1 - assert isinstance(result[0], ObjectDigest) - assert result[0].id == "vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" + result = workos.vault.create_decrypt(keys="test_keys") + assert isinstance(result, DecryptResponse) + assert result.data_key == "DR9idtey9MpMrA1VRFrz30HB1yNgL2PoHZyjAkFeWgg=" + assert result.id == "bf51ccec-78b4-5200-b383-35730e71ef61" request = httpx_mock.get_request() - assert request.method == "GET" - assert request.url.path.endswith("/vault/v1/kv") + assert request.method == "POST" + assert request.url.path.endswith("/vault/v1/keys/decrypt") + body = json.loads(request.content) + assert body["keys"] == "test_keys" - def test_list_objects_with_params(self, workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_list_objects.json")) - workos.vault.list_objects(limit=5, after="cursor_abc") + def test_create_rekey(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("create_data_key_response.json"), + ) + result = workos.vault.create_rekey( + context={}, encrypted_keys="test_encrypted_keys" + ) + assert isinstance(result, CreateDataKeyResponse) + assert result.data_key == "DR9idtey9MpMrA1VRFrz30HB1yNgL2PoHZyjAkFeWgg=" + assert ( + result.encrypted_keys + == "V09TLkVLTS52MQBiZjUxY2NlYy03OGI0LTUyMDAtYjM4My0zNTczMGU3MWVmNjEBATEBJGJmNjVlMzI2LTQzYTAtNGIyMC04OGM0LTA3ZmYzZGU1NDM0YwF0YmY2NWUzMjYtNDNhMC00YjIwLTg4YzQtMDdmZjNkZTU0MzRj" + ) request = httpx_mock.get_request() - assert "limit=5" in str(request.url) - assert "after=cursor_abc" in str(request.url) + assert request.method == "POST" + assert request.url.path.endswith("/vault/v1/keys/rekey") + body = json.loads(request.content) + assert "context" in body + assert body["encrypted_keys"] == "test_encrypted_keys" - def test_list_object_versions(self, workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_list_object_versions.json")) - result = workos.vault.list_object_versions( - object_id="vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" + def test_list_kv(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("list_object_summary.json"), + ) + page = workos.vault.list_kv() + assert isinstance(page, SyncPage) + assert len(page.data) == 1 + assert isinstance(page.data[0], ObjectSummary) + + def test_list_kv_empty_page(self, workos, httpx_mock): + httpx_mock.add_response(json={"data": [], "list_metadata": {}}) + page = workos.vault.list_kv() + assert isinstance(page, SyncPage) + assert page.data == [] + + def test_list_kv_encodes_query_params(self, workos, httpx_mock): + httpx_mock.add_response(json={"data": [], "list_metadata": {}}) + workos.vault.list_kv( + limit=10, + before="cursor before", + after="cursor/after", + order=VaultOrder("asc"), + search="value search/test", + updated_after="value updatedAfter/test", ) - assert len(result) == 1 - assert isinstance(result[0], ObjectVersion) - assert result[0].current_version is True request = httpx_mock.get_request() - assert request.method == "GET" - assert request.url.path.endswith( - "/vault/v1/kv/vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C/versions" + assert request.url.params["limit"] == "10" + assert request.url.params["before"] == "cursor before" + assert request.url.params["after"] == "cursor/after" + assert request.url.params["order"] == "asc" + assert request.url.params["search"] == "value search/test" + assert request.url.params["updatedAfter"] == "value updatedAfter/test" + + def test_create_kv(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("object_metadata.json"), ) - - def test_create_object(self, workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_create_object.json")) - result = workos.vault.create_object( - name="my-secret", - value="super-secret-value", - key_context={"tenant": "acme"}, + result = workos.vault.create_kv( + key_context={}, name="test_name", value="test_value" ) assert isinstance(result, ObjectMetadata) - assert result.id == "vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" + assert result.environment_id == "environment_01K8ZYT4AWJ6XP0E0S8CTBHE3P" + assert result.id == "a1b2c3d4-e5f6-7890-abcd-ef1234567890" request = httpx_mock.get_request() assert request.method == "POST" assert request.url.path.endswith("/vault/v1/kv") body = json.loads(request.content) - assert body["name"] == "my-secret" - assert body["value"] == "super-secret-value" - assert body["key_context"] == {"tenant": "acme"} + assert "key_context" in body + assert body["name"] == "test_name" + assert body["value"] == "test_value" - def test_update_object(self, workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_object.json")) - result = workos.vault.update_object( - object_id="vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C", - value="new-secret-value", + def test_get_name(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("vault_object.json"), ) + result = workos.vault.get_name("test_name") assert isinstance(result, VaultObject) + assert result.id == "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + assert result.name == "my-secret" request = httpx_mock.get_request() - assert request.method == "PUT" - assert request.url.path.endswith( - "/vault/v1/kv/vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" + assert request.method == "GET" + assert request.url.path.endswith("/vault/v1/kv/name/test_name") + + def test_get_kv(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("vault_object.json"), ) - body = json.loads(request.content) - assert body["value"] == "new-secret-value" + result = workos.vault.get_kv("test_id") + assert isinstance(result, VaultObject) + assert result.id == "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + assert result.name == "my-secret" + request = httpx_mock.get_request() + assert request.method == "GET" + assert request.url.path.endswith("/vault/v1/kv/test_id") - def test_update_object_with_version_check(self, workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_object.json")) - workos.vault.update_object( - object_id="vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C", - value="new-secret-value", - version_check="vault_ver_01EHDAK2BFGWCSZXP9HGZ3VK8C", + def test_update_kv(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("object_without_value.json"), ) + result = workos.vault.update_kv("test_id", value="test_value") + assert isinstance(result, ObjectWithoutValue) + assert result.id == "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + assert result.name == "my-secret" request = httpx_mock.get_request() + assert request.method == "PUT" + assert request.url.path.endswith("/vault/v1/kv/test_id") body = json.loads(request.content) - assert body["version_check"] == "vault_ver_01EHDAK2BFGWCSZXP9HGZ3VK8C" + assert body["value"] == "test_value" - def test_delete_object(self, workos, httpx_mock): + def test_delete_kv(self, workos, httpx_mock): httpx_mock.add_response(status_code=204) - workos.vault.delete_object(object_id="vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C") + result = workos.vault.delete_kv("test_id") + assert result is None request = httpx_mock.get_request() assert request.method == "DELETE" - assert request.url.path.endswith( - "/vault/v1/kv/vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" - ) + assert request.url.path.endswith("/vault/v1/kv/test_id") - def test_create_data_key(self, workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_data_key.json")) - result = workos.vault.create_data_key(key_context={"tenant": "acme"}) - assert isinstance(result, DataKeyPair) - assert isinstance(result.data_key, DataKey) - assert result.data_key.id == "vault_key_01EHDAK2BFGWCSZXP9HGZ3VK8C" - assert result.context == {"tenant": "acme"} + def test_delete_kv_encodes_query_params(self, workos, httpx_mock): + httpx_mock.add_response(status_code=204) + workos.vault.delete_kv("test_id", version_check="value version_check/test") request = httpx_mock.get_request() - assert request.method == "POST" - assert request.url.path.endswith("/vault/v1/keys/data-key") + assert request.url.params["version_check"] == "value version_check/test" - def test_decrypt_data_key(self, workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_decrypt_key.json")) - result = workos.vault.decrypt_data_key(keys="dGVzdC1lbmNyeXB0ZWQta2V5cw==") - assert isinstance(result, DataKey) - assert result.id == "vault_key_01EHDAK2BFGWCSZXP9HGZ3VK8C" + def test_list_kv_metadata(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("object_without_value.json"), + ) + result = workos.vault.list_kv_metadata("test_id") + assert isinstance(result, ObjectWithoutValue) + assert result.id == "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + assert result.name == "my-secret" request = httpx_mock.get_request() - assert request.method == "POST" - assert request.url.path.endswith("/vault/v1/keys/decrypt") - - def test_encrypt_decrypt_round_trip(self, workos, httpx_mock): - # Mock create_data_key for encrypt - httpx_mock.add_response(json=load_fixture("vault_data_key.json")) - # Mock decrypt_data_key for decrypt - httpx_mock.add_response(json=load_fixture("vault_decrypt_key.json")) + assert request.method == "GET" + assert request.url.path.endswith("/vault/v1/kv/test_id/metadata") - encrypted = workos.vault.encrypt( - data="hello world", key_context={"tenant": "acme"} + def test_list_kv_versions(self, workos, httpx_mock): + httpx_mock.add_response( + json=load_fixture("version_list_response.json"), ) - assert isinstance(encrypted, str) - assert encrypted != "hello world" + result = workos.vault.list_kv_versions("test_id") + assert isinstance(result, VersionListResponse) + request = httpx_mock.get_request() + assert request.method == "GET" + assert request.url.path.endswith("/vault/v1/kv/test_id/versions") - decrypted = workos.vault.decrypt(encrypted_data=encrypted) - assert decrypted == "hello world" + def test_create_data_key_with_request_options(self, workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("create_data_key_response.json")) + workos.vault.create_data_key( + context={}, request_options={"extra_headers": {"X-Custom": "value"}} + ) + request = httpx_mock.get_request() + assert request.headers["X-Custom"] == "value" - def test_read_object_unauthorized(self, workos, httpx_mock): + def test_create_data_key_unauthorized(self, workos, httpx_mock): httpx_mock.add_response( status_code=401, json={"message": "Unauthorized"}, ) with pytest.raises(AuthenticationError): - workos.vault.read_object(object_id="vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C") + workos.vault.create_data_key(context={}) - def test_read_object_not_found(self, httpx_mock): + def test_create_data_key_not_found(self, httpx_mock): workos = WorkOSClient( api_key="sk_test_123", client_id="client_test", max_retries=0 ) try: httpx_mock.add_response(status_code=404, json={"message": "Not found"}) with pytest.raises(NotFoundError): - workos.vault.read_object( - object_id="vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" - ) + workos.vault.create_data_key(context={}) finally: workos.close() - def test_read_object_rate_limited(self, httpx_mock): + def test_create_data_key_rate_limited(self, httpx_mock): workos = WorkOSClient( api_key="sk_test_123", client_id="client_test", max_retries=0 ) @@ -211,167 +242,264 @@ def test_read_object_rate_limited(self, httpx_mock): json={"message": "Slow down"}, ) with pytest.raises(RateLimitExceededError): - workos.vault.read_object( - object_id="vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" - ) + workos.vault.create_data_key(context={}) finally: workos.close() - def test_read_object_server_error(self, httpx_mock): + def test_create_data_key_server_error(self, httpx_mock): workos = WorkOSClient( api_key="sk_test_123", client_id="client_test", max_retries=0 ) try: httpx_mock.add_response(status_code=500, json={"message": "Server error"}) with pytest.raises(ServerError): - workos.vault.read_object( - object_id="vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" - ) + workos.vault.create_data_key(context={}) finally: workos.close() + def test_create_data_key_bad_request(self, httpx_mock): + workos = WorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response(status_code=400, json={"message": "Bad request"}) + with pytest.raises(BadRequestError): + workos.vault.create_data_key(context={}) + finally: + workos.close() -@pytest.mark.asyncio -class TestAsyncVault: - async def test_read_object(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_object.json")) - result = await async_workos.vault.read_object( - object_id="vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" + def test_create_data_key_unprocessable(self, httpx_mock): + workos = WorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 ) - assert isinstance(result, VaultObject) - assert result.id == "vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" - assert result.name == "my-secret" - request = httpx_mock.get_request() - assert request.method == "GET" - assert request.url.path.endswith( - "/vault/v1/kv/vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" + try: + httpx_mock.add_response(status_code=422, json={"message": "Unprocessable"}) + with pytest.raises(UnprocessableEntityError): + workos.vault.create_data_key(context={}) + finally: + workos.close() + + # @oagen-ignore-start — client-side encrypt/decrypt tests (hand-maintained) + + def test_encrypt_decrypt_round_trip(self, workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("vault_data_key.json")) + httpx_mock.add_response(json=load_fixture("vault_decrypt_key.json")) + + encrypted = workos.vault.encrypt( + data="hello world", key_context={"tenant": "acme"} ) + assert isinstance(encrypted, str) + assert encrypted != "hello world" - async def test_read_object_by_name(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_object.json")) - result = await async_workos.vault.read_object_by_name(name="my-secret") - assert isinstance(result, VaultObject) - request = httpx_mock.get_request() - assert request.url.path.endswith("/vault/v1/kv/name/my-secret") + decrypted = workos.vault.decrypt(encrypted_data=encrypted) + assert decrypted == "hello world" - async def test_get_object_metadata(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_object_metadata.json")) - result = await async_workos.vault.get_object_metadata( - object_id="vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" + def test_encrypt_decrypt_with_associated_data(self, workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("vault_data_key.json")) + httpx_mock.add_response(json=load_fixture("vault_decrypt_key.json")) + + encrypted = workos.vault.encrypt( + data="hello world", + key_context={"tenant": "acme"}, + associated_data="context-info", ) - assert isinstance(result, VaultObject) - assert result.value is None - request = httpx_mock.get_request() - assert request.method == "GET" - assert request.url.path.endswith( - "/vault/v1/kv/vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C/metadata" + decrypted = workos.vault.decrypt( + encrypted_data=encrypted, associated_data="context-info" ) + assert decrypted == "hello world" + + # @oagen-ignore-end + - async def test_list_objects(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_list_objects.json")) - result = await async_workos.vault.list_objects() - assert len(result) == 1 - assert isinstance(result[0], ObjectDigest) +class TestAsyncVault: + @pytest.mark.asyncio + async def test_create_data_key(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("create_data_key_response.json")) + result = await async_workos.vault.create_data_key(context={}) + assert isinstance(result, CreateDataKeyResponse) + assert result.data_key == "DR9idtey9MpMrA1VRFrz30HB1yNgL2PoHZyjAkFeWgg=" + assert ( + result.encrypted_keys + == "V09TLkVLTS52MQBiZjUxY2NlYy03OGI0LTUyMDAtYjM4My0zNTczMGU3MWVmNjEBATEBJGJmNjVlMzI2LTQzYTAtNGIyMC04OGM0LTA3ZmYzZGU1NDM0YwF0YmY2NWUzMjYtNDNhMC00YjIwLTg4YzQtMDdmZjNkZTU0MzRj" + ) request = httpx_mock.get_request() - assert request.method == "GET" - assert request.url.path.endswith("/vault/v1/kv") + assert request.method == "POST" + assert request.url.path.endswith("/vault/v1/keys/data-key") - async def test_list_object_versions(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_list_object_versions.json")) - result = await async_workos.vault.list_object_versions( - object_id="vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" + @pytest.mark.asyncio + async def test_create_decrypt(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("decrypt_response.json")) + result = await async_workos.vault.create_decrypt(keys="test_keys") + assert isinstance(result, DecryptResponse) + assert result.data_key == "DR9idtey9MpMrA1VRFrz30HB1yNgL2PoHZyjAkFeWgg=" + assert result.id == "bf51ccec-78b4-5200-b383-35730e71ef61" + request = httpx_mock.get_request() + assert request.method == "POST" + assert request.url.path.endswith("/vault/v1/keys/decrypt") + + @pytest.mark.asyncio + async def test_create_rekey(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("create_data_key_response.json")) + result = await async_workos.vault.create_rekey( + context={}, encrypted_keys="test_encrypted_keys" + ) + assert isinstance(result, CreateDataKeyResponse) + assert result.data_key == "DR9idtey9MpMrA1VRFrz30HB1yNgL2PoHZyjAkFeWgg=" + assert ( + result.encrypted_keys + == "V09TLkVLTS52MQBiZjUxY2NlYy03OGI0LTUyMDAtYjM4My0zNTczMGU3MWVmNjEBATEBJGJmNjVlMzI2LTQzYTAtNGIyMC04OGM0LTA3ZmYzZGU1NDM0YwF0YmY2NWUzMjYtNDNhMC00YjIwLTg4YzQtMDdmZjNkZTU0MzRj" ) - assert len(result) == 1 - assert isinstance(result[0], ObjectVersion) request = httpx_mock.get_request() - assert request.url.path.endswith( - "/vault/v1/kv/vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C/versions" + assert request.method == "POST" + assert request.url.path.endswith("/vault/v1/keys/rekey") + + @pytest.mark.asyncio + async def test_list_kv(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("list_object_summary.json")) + page = await async_workos.vault.list_kv() + assert isinstance(page, AsyncPage) + assert len(page.data) == 1 + assert isinstance(page.data[0], ObjectSummary) + + @pytest.mark.asyncio + async def test_list_kv_empty_page(self, async_workos, httpx_mock): + httpx_mock.add_response(json={"data": [], "list_metadata": {}}) + page = await async_workos.vault.list_kv() + assert isinstance(page, AsyncPage) + assert page.data == [] + + @pytest.mark.asyncio + async def test_list_kv_encodes_query_params(self, async_workos, httpx_mock): + httpx_mock.add_response(json={"data": [], "list_metadata": {}}) + await async_workos.vault.list_kv( + limit=10, + before="cursor before", + after="cursor/after", + order=VaultOrder("asc"), + search="value search/test", + updated_after="value updatedAfter/test", ) - - async def test_create_object(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_create_object.json")) - result = await async_workos.vault.create_object( - name="my-secret", - value="super-secret-value", - key_context={"tenant": "acme"}, + request = httpx_mock.get_request() + assert request.url.params["limit"] == "10" + assert request.url.params["before"] == "cursor before" + assert request.url.params["after"] == "cursor/after" + assert request.url.params["order"] == "asc" + assert request.url.params["search"] == "value search/test" + assert request.url.params["updatedAfter"] == "value updatedAfter/test" + + @pytest.mark.asyncio + async def test_create_kv(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("object_metadata.json")) + result = await async_workos.vault.create_kv( + key_context={}, name="test_name", value="test_value" ) assert isinstance(result, ObjectMetadata) + assert result.environment_id == "environment_01K8ZYT4AWJ6XP0E0S8CTBHE3P" + assert result.id == "a1b2c3d4-e5f6-7890-abcd-ef1234567890" request = httpx_mock.get_request() assert request.method == "POST" assert request.url.path.endswith("/vault/v1/kv") - async def test_update_object(self, async_workos, httpx_mock): + @pytest.mark.asyncio + async def test_get_name(self, async_workos, httpx_mock): httpx_mock.add_response(json=load_fixture("vault_object.json")) - result = await async_workos.vault.update_object( - object_id="vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C", - value="new-secret-value", - ) + result = await async_workos.vault.get_name("test_name") assert isinstance(result, VaultObject) + assert result.id == "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + assert result.name == "my-secret" + request = httpx_mock.get_request() + assert request.method == "GET" + assert request.url.path.endswith("/vault/v1/kv/name/test_name") + + @pytest.mark.asyncio + async def test_get_kv(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("vault_object.json")) + result = await async_workos.vault.get_kv("test_id") + assert isinstance(result, VaultObject) + assert result.id == "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + assert result.name == "my-secret" + request = httpx_mock.get_request() + assert request.method == "GET" + assert request.url.path.endswith("/vault/v1/kv/test_id") + + @pytest.mark.asyncio + async def test_update_kv(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("object_without_value.json")) + result = await async_workos.vault.update_kv("test_id", value="test_value") + assert isinstance(result, ObjectWithoutValue) + assert result.id == "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + assert result.name == "my-secret" request = httpx_mock.get_request() assert request.method == "PUT" + assert request.url.path.endswith("/vault/v1/kv/test_id") - async def test_delete_object(self, async_workos, httpx_mock): + @pytest.mark.asyncio + async def test_delete_kv(self, async_workos, httpx_mock): httpx_mock.add_response(status_code=204) - await async_workos.vault.delete_object( - object_id="vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" - ) + result = await async_workos.vault.delete_kv("test_id") + assert result is None request = httpx_mock.get_request() assert request.method == "DELETE" + assert request.url.path.endswith("/vault/v1/kv/test_id") - async def test_create_data_key(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_data_key.json")) - result = await async_workos.vault.create_data_key( - key_context={"tenant": "acme"} + @pytest.mark.asyncio + async def test_delete_kv_encodes_query_params(self, async_workos, httpx_mock): + httpx_mock.add_response(status_code=204) + await async_workos.vault.delete_kv( + "test_id", version_check="value version_check/test" ) - assert isinstance(result, DataKeyPair) - assert isinstance(result.data_key, DataKey) request = httpx_mock.get_request() - assert request.method == "POST" - assert request.url.path.endswith("/vault/v1/keys/data-key") - - async def test_decrypt_data_key(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_decrypt_key.json")) - result = await async_workos.vault.decrypt_data_key( - keys="dGVzdC1lbmNyeXB0ZWQta2V5cw==" - ) - assert isinstance(result, DataKey) + assert request.url.params["version_check"] == "value version_check/test" + + @pytest.mark.asyncio + async def test_list_kv_metadata(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("object_without_value.json")) + result = await async_workos.vault.list_kv_metadata("test_id") + assert isinstance(result, ObjectWithoutValue) + assert result.id == "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + assert result.name == "my-secret" request = httpx_mock.get_request() - assert request.method == "POST" - assert request.url.path.endswith("/vault/v1/keys/decrypt") + assert request.method == "GET" + assert request.url.path.endswith("/vault/v1/kv/test_id/metadata") - async def test_encrypt_decrypt_round_trip(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("vault_data_key.json")) - httpx_mock.add_response(json=load_fixture("vault_decrypt_key.json")) + @pytest.mark.asyncio + async def test_list_kv_versions(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("version_list_response.json")) + result = await async_workos.vault.list_kv_versions("test_id") + assert isinstance(result, VersionListResponse) + request = httpx_mock.get_request() + assert request.method == "GET" + assert request.url.path.endswith("/vault/v1/kv/test_id/versions") - encrypted = await async_workos.vault.encrypt( - data="hello world", key_context={"tenant": "acme"} + @pytest.mark.asyncio + async def test_create_data_key_with_request_options(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("create_data_key_response.json")) + await async_workos.vault.create_data_key( + context={}, request_options={"extra_headers": {"X-Custom": "value"}} ) - assert isinstance(encrypted, str) - - decrypted = await async_workos.vault.decrypt(encrypted_data=encrypted) - assert decrypted == "hello world" + request = httpx_mock.get_request() + assert request.headers["X-Custom"] == "value" - async def test_read_object_unauthorized(self, async_workos, httpx_mock): + @pytest.mark.asyncio + async def test_create_data_key_unauthorized(self, async_workos, httpx_mock): httpx_mock.add_response(status_code=401, json={"message": "Unauthorized"}) with pytest.raises(AuthenticationError): - await async_workos.vault.read_object( - object_id="vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" - ) + await async_workos.vault.create_data_key(context={}) - async def test_read_object_not_found(self, httpx_mock): + @pytest.mark.asyncio + async def test_create_data_key_not_found(self, httpx_mock): workos = AsyncWorkOSClient( api_key="sk_test_123", client_id="client_test", max_retries=0 ) try: httpx_mock.add_response(status_code=404, json={"message": "Not found"}) with pytest.raises(NotFoundError): - await workos.vault.read_object( - object_id="vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" - ) + await workos.vault.create_data_key(context={}) finally: await workos.close() - async def test_read_object_rate_limited(self, httpx_mock): + @pytest.mark.asyncio + async def test_create_data_key_rate_limited(self, httpx_mock): workos = AsyncWorkOSClient( api_key="sk_test_123", client_id="client_test", max_retries=0 ) @@ -382,21 +510,75 @@ async def test_read_object_rate_limited(self, httpx_mock): json={"message": "Slow down"}, ) with pytest.raises(RateLimitExceededError): - await workos.vault.read_object( - object_id="vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" - ) + await workos.vault.create_data_key(context={}) finally: await workos.close() - async def test_read_object_server_error(self, httpx_mock): + @pytest.mark.asyncio + async def test_create_data_key_server_error(self, httpx_mock): workos = AsyncWorkOSClient( api_key="sk_test_123", client_id="client_test", max_retries=0 ) try: httpx_mock.add_response(status_code=500, json={"message": "Server error"}) with pytest.raises(ServerError): - await workos.vault.read_object( - object_id="vault_obj_01EHDAK2BFGWCSZXP9HGZ3VK8C" - ) + await workos.vault.create_data_key(context={}) + finally: + await workos.close() + + @pytest.mark.asyncio + async def test_create_data_key_bad_request(self, httpx_mock): + workos = AsyncWorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response(status_code=400, json={"message": "Bad request"}) + with pytest.raises(BadRequestError): + await workos.vault.create_data_key(context={}) + finally: + await workos.close() + + @pytest.mark.asyncio + async def test_create_data_key_unprocessable(self, httpx_mock): + workos = AsyncWorkOSClient( + api_key="sk_test_123", client_id="client_test", max_retries=0 + ) + try: + httpx_mock.add_response(status_code=422, json={"message": "Unprocessable"}) + with pytest.raises(UnprocessableEntityError): + await workos.vault.create_data_key(context={}) finally: await workos.close() + + # @oagen-ignore-start — client-side encrypt/decrypt tests (hand-maintained) + + @pytest.mark.asyncio + async def test_encrypt_decrypt_round_trip(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("vault_data_key.json")) + httpx_mock.add_response(json=load_fixture("vault_decrypt_key.json")) + + encrypted = await async_workos.vault.encrypt( + data="hello world", key_context={"tenant": "acme"} + ) + assert isinstance(encrypted, str) + assert encrypted != "hello world" + + decrypted = await async_workos.vault.decrypt(encrypted_data=encrypted) + assert decrypted == "hello world" + + @pytest.mark.asyncio + async def test_encrypt_decrypt_with_associated_data(self, async_workos, httpx_mock): + httpx_mock.add_response(json=load_fixture("vault_data_key.json")) + httpx_mock.add_response(json=load_fixture("vault_decrypt_key.json")) + + encrypted = await async_workos.vault.encrypt( + data="hello world", + key_context={"tenant": "acme"}, + associated_data="context-info", + ) + decrypted = await async_workos.vault.decrypt( + encrypted_data=encrypted, associated_data="context-info" + ) + assert decrypted == "hello world" + + # @oagen-ignore-end diff --git a/tests/test_webhooks.py b/tests/test_webhooks.py index 0f15e748..285aca51 100644 --- a/tests/test_webhooks.py +++ b/tests/test_webhooks.py @@ -7,7 +7,7 @@ from tests.generated_helpers import load_fixture from workos.common.models import PaginationOrder -from workos.webhooks.models import WebhookEndpointJson +from workos.webhooks.models import WebhookEndpoint from workos._pagination import AsyncPage, SyncPage from workos._errors import ( AuthenticationError, @@ -22,12 +22,12 @@ class TestWebhooks: def test_list_webhook_endpoints(self, workos, httpx_mock): httpx_mock.add_response( - json=load_fixture("list_webhook_endpoint_json.json"), + json=load_fixture("list_webhook_endpoint.json"), ) page = workos.webhooks.list_webhook_endpoints() assert isinstance(page, SyncPage) assert len(page.data) == 1 - assert isinstance(page.data[0], WebhookEndpointJson) + assert isinstance(page.data[0], WebhookEndpoint) def test_list_webhook_endpoints_empty_page(self, workos, httpx_mock): httpx_mock.add_response(json={"data": [], "list_metadata": {}}) @@ -51,12 +51,12 @@ def test_list_webhook_endpoints_encodes_query_params(self, workos, httpx_mock): def test_create_webhook_endpoint(self, workos, httpx_mock): httpx_mock.add_response( - json=load_fixture("webhook_endpoint_json.json"), + json=load_fixture("webhook_endpoint.json"), ) result = workos.webhooks.create_webhook_endpoint( endpoint_url="test_endpoint_url", events=[] ) - assert isinstance(result, WebhookEndpointJson) + assert isinstance(result, WebhookEndpoint) assert result.object == "webhook_endpoint" assert result.id == "we_0123456789" request = httpx_mock.get_request() @@ -68,10 +68,10 @@ def test_create_webhook_endpoint(self, workos, httpx_mock): def test_update_webhook_endpoint(self, workos, httpx_mock): httpx_mock.add_response( - json=load_fixture("webhook_endpoint_json.json"), + json=load_fixture("webhook_endpoint.json"), ) result = workos.webhooks.update_webhook_endpoint("test_id") - assert isinstance(result, WebhookEndpointJson) + assert isinstance(result, WebhookEndpoint) assert result.object == "webhook_endpoint" assert result.id == "we_0123456789" request = httpx_mock.get_request() @@ -165,11 +165,11 @@ def test_list_webhook_endpoints_unprocessable(self, httpx_mock): class TestAsyncWebhooks: @pytest.mark.asyncio async def test_list_webhook_endpoints(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("list_webhook_endpoint_json.json")) + httpx_mock.add_response(json=load_fixture("list_webhook_endpoint.json")) page = await async_workos.webhooks.list_webhook_endpoints() assert isinstance(page, AsyncPage) assert len(page.data) == 1 - assert isinstance(page.data[0], WebhookEndpointJson) + assert isinstance(page.data[0], WebhookEndpoint) @pytest.mark.asyncio async def test_list_webhook_endpoints_empty_page(self, async_workos, httpx_mock): @@ -197,11 +197,11 @@ async def test_list_webhook_endpoints_encodes_query_params( @pytest.mark.asyncio async def test_create_webhook_endpoint(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("webhook_endpoint_json.json")) + httpx_mock.add_response(json=load_fixture("webhook_endpoint.json")) result = await async_workos.webhooks.create_webhook_endpoint( endpoint_url="test_endpoint_url", events=[] ) - assert isinstance(result, WebhookEndpointJson) + assert isinstance(result, WebhookEndpoint) assert result.object == "webhook_endpoint" assert result.id == "we_0123456789" request = httpx_mock.get_request() @@ -210,9 +210,9 @@ async def test_create_webhook_endpoint(self, async_workos, httpx_mock): @pytest.mark.asyncio async def test_update_webhook_endpoint(self, async_workos, httpx_mock): - httpx_mock.add_response(json=load_fixture("webhook_endpoint_json.json")) + httpx_mock.add_response(json=load_fixture("webhook_endpoint.json")) result = await async_workos.webhooks.update_webhook_endpoint("test_id") - assert isinstance(result, WebhookEndpointJson) + assert isinstance(result, WebhookEndpoint) assert result.object == "webhook_endpoint" assert result.id == "we_0123456789" request = httpx_mock.get_request()