From 43c4f3141fdf34b70e7b7b939c9e404946fcb0d3 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Wed, 14 Oct 2026 12:22:08 +0100 Subject: [PATCH 1/2] feat: Python SDK update for version 24.4.0 --- CHANGELOG.md | 20 + appwrite/client.py | 12 +- appwrite/encoders/value_class_encoder.py | 80 + appwrite/enums/billing_plan_group.py | 2 + appwrite/enums/build_runtime.py | 2 + appwrite/enums/databases_index_type.py | 1 + appwrite/enums/domain_registration_type.py | 8 + appwrite/enums/domain_transfer_status_enum.py | 12 + appwrite/enums/framework.py | 1 + appwrite/enums/id_token_provider.py | 6 + appwrite/enums/image_gravity.py | 1 + appwrite/enums/o_auth2_auth0_prompt.py | 7 + appwrite/enums/o_auth2_discord_prompt.py | 6 + appwrite/enums/o_auth2_github_prompt.py | 5 + appwrite/enums/o_auth2_kakao_prompt.py | 8 + appwrite/enums/o_auth2_microsoft_prompt.py | 8 + appwrite/enums/o_auth2_okta_prompt.py | 7 + appwrite/enums/o_auth2_salesforce_prompt.py | 6 + appwrite/enums/o_auth2_zoho_prompt.py | 5 + appwrite/enums/o_auth_provider.py | 3 + appwrite/enums/project_email_template_id.py | 2 + appwrite/enums/project_key_scopes.py | 4 + .../enums/project_o_auth2_auth0_prompt.py | 7 + .../enums/project_o_auth2_discord_prompt.py | 6 + .../enums/project_o_auth2_git_hub_prompt.py | 5 + .../enums/project_o_auth2_kakao_prompt.py | 8 + .../enums/project_o_auth2_microsoft_prompt.py | 8 + appwrite/enums/project_o_auth2_okta_prompt.py | 7 + .../project_o_auth2_salesforce_prompt.py | 6 + appwrite/enums/project_o_auth2_zoho_prompt.py | 5 + appwrite/enums/project_o_auth_provider_id.py | 3 + appwrite/enums/project_policy_id.py | 2 + .../proxy_rule_deployment_resource_type.py | 1 + appwrite/enums/runtime.py | 2 + appwrite/enums/tables_db_index_type.py | 1 + appwrite/enums/waf_rule_action.py | 9 + appwrite/models/__init__.py | 40 + appwrite/models/account.py | 98 + appwrite/models/billing_plan.py | 6 + appwrite/models/dedicated_database.py | 9 + .../dedicated_database_specification.py | 12 + appwrite/models/dns_record.py | 50 + appwrite/models/dns_records_list.py | 21 + appwrite/models/domain.py | 55 + appwrite/models/domain_price.py | 38 + appwrite/models/domain_prices_list.py | 21 + appwrite/models/domain_transfer_status.py | 24 + appwrite/models/domains_list.py | 21 + appwrite/models/identity.py | 3 + appwrite/models/o_auth2_apple.py | 6 + appwrite/models/o_auth2_auth0.py | 4 + appwrite/models/o_auth2_discord.py | 4 + appwrite/models/o_auth2_github.py | 4 + appwrite/models/o_auth2_google.py | 6 + appwrite/models/o_auth2_kakao.py | 30 + appwrite/models/o_auth2_microsoft.py | 4 + appwrite/models/o_auth2_okta.py | 4 + appwrite/models/o_auth2_provider_list.py | 8 +- appwrite/models/o_auth2_salesforce.py | 4 + appwrite/models/o_auth2_tik_tok.py | 26 + appwrite/models/o_auth2_webflow.py | 26 + appwrite/models/o_auth2_zoho.py | 4 + appwrite/models/oauth2_introspection.py | 50 + appwrite/models/platform_android.py | 3 + appwrite/models/policy_list.py | 6 +- appwrite/models/policy_password_pwned.py | 26 + appwrite/models/policy_password_rotation.py | 23 + appwrite/models/project.py | 9 + appwrite/models/topic.py | 6 + appwrite/models/user.py | 3 + appwrite/models/waf_rule_bypass.py | 57 + appwrite/models/waf_rule_challenge.py | 66 + appwrite/models/waf_rule_deny.py | 57 + appwrite/models/waf_rule_list.py | 33 + appwrite/models/waf_rule_rate_limit.py | 72 + appwrite/models/waf_rule_redirect.py | 63 + appwrite/services/account.py | 291 +- appwrite/services/avatars.py | 94 +- appwrite/services/databases.py | 5 + appwrite/services/documents_db.py | 5 + appwrite/services/domains.py | 2638 +++++++++++++++++ appwrite/services/functions.py | 13 + appwrite/services/locale.py | 56 + appwrite/services/messaging.py | 173 ++ appwrite/services/oauth2.py | 57 + appwrite/services/organization.py | 266 ++ appwrite/services/project.py | 576 +++- appwrite/services/sites.py | 13 + appwrite/services/tables_db.py | 5 + appwrite/services/teams.py | 5 + appwrite/services/vectors_db.py | 5 + appwrite/services/waf.py | 1039 +++++++ .../account/create-email-password-session.md | 3 +- .../account/create-email-verification-otp.md | 18 + .../account/create-id-token-session.md | 24 + docs/examples/account/create-recovery-otp.md | 19 + docs/examples/account/delete-sessions.md | 4 +- docs/examples/account/list-sessions.md | 4 +- .../account/update-email-verification-otp.md | 19 + docs/examples/account/update-recovery-otp.md | 20 + docs/examples/avatars/delete-photo.md | 13 + docs/examples/avatars/update-photo.md | 19 + docs/examples/databases/list-transactions.md | 3 +- .../examples/documentsdb/list-transactions.md | 3 +- .../domains/create-preset-google-workspace.md | 18 + .../examples/domains/create-preset-i-cloud.md | 18 + .../examples/domains/create-preset-mailgun.md | 18 + .../examples/domains/create-preset-outlook.md | 18 + .../domains/create-preset-proton-mail.md | 18 + docs/examples/domains/create-preset-zoho.md | 18 + docs/examples/domains/create-record-a.md | 22 + docs/examples/domains/create-record-aaaa.md | 22 + docs/examples/domains/create-record-alias.md | 22 + docs/examples/domains/create-record-caa.md | 22 + docs/examples/domains/create-record-cname.md | 22 + docs/examples/domains/create-record-https.md | 22 + docs/examples/domains/create-record-mx.md | 23 + docs/examples/domains/create-record-ns.md | 22 + docs/examples/domains/create-record-srv.md | 25 + docs/examples/domains/create-record-txt.md | 22 + docs/examples/domains/create.md | 19 + docs/examples/domains/delete-record.md | 16 + docs/examples/domains/delete.md | 15 + .../domains/get-preset-google-workspace.md | 18 + docs/examples/domains/get-preset-i-cloud.md | 18 + docs/examples/domains/get-preset-mailgun.md | 18 + docs/examples/domains/get-preset-outlook.md | 18 + .../domains/get-preset-proton-mail.md | 18 + docs/examples/domains/get-preset-zoho.md | 18 + docs/examples/domains/get-price.md | 21 + docs/examples/domains/get-record.md | 19 + docs/examples/domains/get-transfer-status.md | 18 + docs/examples/domains/get-zone.md | 15 + docs/examples/domains/get.md | 18 + docs/examples/domains/list-prices.md | 21 + docs/examples/domains/list-records.md | 19 + docs/examples/domains/list.md | 19 + docs/examples/domains/update-nameservers.md | 19 + docs/examples/domains/update-record-a.md | 23 + docs/examples/domains/update-record-aaaa.md | 23 + docs/examples/domains/update-record-alias.md | 23 + docs/examples/domains/update-record-caa.md | 23 + docs/examples/domains/update-record-cname.md | 23 + docs/examples/domains/update-record-https.md | 23 + docs/examples/domains/update-record-mx.md | 24 + docs/examples/domains/update-record-ns.md | 23 + docs/examples/domains/update-record-srv.md | 26 + docs/examples/domains/update-record-txt.md | 23 + docs/examples/domains/update-team.md | 19 + docs/examples/domains/update-zone.md | 19 + docs/examples/domains/verify-nameservers.md | 18 + docs/examples/functions/list-runtimes.md | 4 +- .../examples/functions/list-specifications.md | 3 +- docs/examples/locale/list-codes.md | 4 +- docs/examples/locale/list-continents.md | 4 +- docs/examples/locale/list-countries-eu.md | 4 +- docs/examples/locale/list-countries-phones.md | 4 +- docs/examples/locale/list-countries.md | 4 +- docs/examples/locale/list-currencies.md | 4 +- docs/examples/locale/list-languages.md | 4 +- .../messaging/create-appwrite-provider.md | 22 + docs/examples/messaging/create-email.md | 4 +- docs/examples/messaging/create-push.md | 3 +- docs/examples/messaging/create-topic.md | 4 +- .../messaging/update-appwrite-provider.md | 22 + docs/examples/messaging/update-email.md | 4 +- docs/examples/messaging/update-push.md | 3 +- docs/examples/messaging/update-topic.md | 4 +- docs/examples/oauth2/introspect.md | 21 + .../create-ephemeral-project-key.md | 21 + .../organization/delete-project-key.md | 16 + docs/examples/organization/get-project-key.md | 19 + .../organization/list-project-keys.md | 20 + .../organization/update-project-key.md | 23 + .../project/create-android-platform.md | 3 +- docs/examples/project/create-environment.md | 19 + docs/examples/project/delete-environment.md | 15 + docs/examples/project/get-environment.md | 18 + .../examples/project/get-o-auth-2-provider.md | 5 +- docs/examples/project/get-policy.md | 4 +- docs/examples/project/list-environments.md | 19 + .../project/update-android-platform.md | 3 +- docs/examples/project/update-environment.md | 19 + .../examples/project/update-o-auth-2-apple.md | 4 +- .../project/update-o-auth-2-auth-0.md | 4 +- .../project/update-o-auth-2-discord.md | 4 +- .../project/update-o-auth-2-git-hub.md | 4 +- .../project/update-o-auth-2-google.md | 4 +- .../examples/project/update-o-auth-2-kakao.md | 22 + .../project/update-o-auth-2-microsoft.md | 4 +- docs/examples/project/update-o-auth-2-okta.md | 4 +- .../project/update-o-auth-2-salesforce.md | 4 +- .../project/update-o-auth-2-tik-tok.md | 20 + .../project/update-o-auth-2-webflow.md | 20 + docs/examples/project/update-o-auth-2-zoho.md | 4 +- .../project/update-password-pwned-policy.md | 20 + .../update-password-rotation-policy.md | 19 + docs/examples/sites/list-frameworks.md | 4 +- docs/examples/sites/list-specifications.md | 3 +- docs/examples/tablesdb/list-transactions.md | 3 +- docs/examples/teams/create-membership.md | 3 +- docs/examples/vectorsdb/list-transactions.md | 3 +- docs/examples/waf/create-bypass-rule.md | 25 + docs/examples/waf/create-challenge-rule.md | 28 + docs/examples/waf/create-deny-rule.md | 25 + docs/examples/waf/create-rate-limit-rule.md | 30 + docs/examples/waf/create-redirect-rule.md | 27 + docs/examples/waf/delete-rule.md | 15 + docs/examples/waf/get-rule.md | 23 + docs/examples/waf/list-rules.md | 20 + docs/examples/waf/update-bypass-rule.md | 25 + docs/examples/waf/update-challenge-rule.md | 28 + docs/examples/waf/update-deny-rule.md | 25 + docs/examples/waf/update-rate-limit-rule.md | 29 + docs/examples/waf/update-redirect-rule.md | 27 + pyproject.toml | 2 +- setup.py | 4 +- test/services/test_account.py | 135 + test/services/test_avatars.py | 45 + test/services/test_domains.py | 1207 ++++++++ test/services/test_messaging.py | 49 + test/services/test_oauth2.py | 17 + test/services/test_organization.py | 115 + test/services/test_project.py | 299 ++ test/services/test_waf.py | 410 +++ 225 files changed, 10653 insertions(+), 53 deletions(-) create mode 100644 appwrite/enums/domain_registration_type.py create mode 100644 appwrite/enums/domain_transfer_status_enum.py create mode 100644 appwrite/enums/id_token_provider.py create mode 100644 appwrite/enums/o_auth2_auth0_prompt.py create mode 100644 appwrite/enums/o_auth2_discord_prompt.py create mode 100644 appwrite/enums/o_auth2_github_prompt.py create mode 100644 appwrite/enums/o_auth2_kakao_prompt.py create mode 100644 appwrite/enums/o_auth2_microsoft_prompt.py create mode 100644 appwrite/enums/o_auth2_okta_prompt.py create mode 100644 appwrite/enums/o_auth2_salesforce_prompt.py create mode 100644 appwrite/enums/o_auth2_zoho_prompt.py create mode 100644 appwrite/enums/project_o_auth2_auth0_prompt.py create mode 100644 appwrite/enums/project_o_auth2_discord_prompt.py create mode 100644 appwrite/enums/project_o_auth2_git_hub_prompt.py create mode 100644 appwrite/enums/project_o_auth2_kakao_prompt.py create mode 100644 appwrite/enums/project_o_auth2_microsoft_prompt.py create mode 100644 appwrite/enums/project_o_auth2_okta_prompt.py create mode 100644 appwrite/enums/project_o_auth2_salesforce_prompt.py create mode 100644 appwrite/enums/project_o_auth2_zoho_prompt.py create mode 100644 appwrite/enums/waf_rule_action.py create mode 100644 appwrite/models/account.py create mode 100644 appwrite/models/dns_record.py create mode 100644 appwrite/models/dns_records_list.py create mode 100644 appwrite/models/domain.py create mode 100644 appwrite/models/domain_price.py create mode 100644 appwrite/models/domain_prices_list.py create mode 100644 appwrite/models/domain_transfer_status.py create mode 100644 appwrite/models/domains_list.py create mode 100644 appwrite/models/o_auth2_kakao.py create mode 100644 appwrite/models/o_auth2_tik_tok.py create mode 100644 appwrite/models/o_auth2_webflow.py create mode 100644 appwrite/models/oauth2_introspection.py create mode 100644 appwrite/models/policy_password_pwned.py create mode 100644 appwrite/models/policy_password_rotation.py create mode 100644 appwrite/models/waf_rule_bypass.py create mode 100644 appwrite/models/waf_rule_challenge.py create mode 100644 appwrite/models/waf_rule_deny.py create mode 100644 appwrite/models/waf_rule_list.py create mode 100644 appwrite/models/waf_rule_rate_limit.py create mode 100644 appwrite/models/waf_rule_redirect.py create mode 100644 appwrite/services/domains.py create mode 100644 appwrite/services/waf.py create mode 100644 docs/examples/account/create-email-verification-otp.md create mode 100644 docs/examples/account/create-id-token-session.md create mode 100644 docs/examples/account/create-recovery-otp.md create mode 100644 docs/examples/account/update-email-verification-otp.md create mode 100644 docs/examples/account/update-recovery-otp.md create mode 100644 docs/examples/avatars/delete-photo.md create mode 100644 docs/examples/avatars/update-photo.md create mode 100644 docs/examples/domains/create-preset-google-workspace.md create mode 100644 docs/examples/domains/create-preset-i-cloud.md create mode 100644 docs/examples/domains/create-preset-mailgun.md create mode 100644 docs/examples/domains/create-preset-outlook.md create mode 100644 docs/examples/domains/create-preset-proton-mail.md create mode 100644 docs/examples/domains/create-preset-zoho.md create mode 100644 docs/examples/domains/create-record-a.md create mode 100644 docs/examples/domains/create-record-aaaa.md create mode 100644 docs/examples/domains/create-record-alias.md create mode 100644 docs/examples/domains/create-record-caa.md create mode 100644 docs/examples/domains/create-record-cname.md create mode 100644 docs/examples/domains/create-record-https.md create mode 100644 docs/examples/domains/create-record-mx.md create mode 100644 docs/examples/domains/create-record-ns.md create mode 100644 docs/examples/domains/create-record-srv.md create mode 100644 docs/examples/domains/create-record-txt.md create mode 100644 docs/examples/domains/create.md create mode 100644 docs/examples/domains/delete-record.md create mode 100644 docs/examples/domains/delete.md create mode 100644 docs/examples/domains/get-preset-google-workspace.md create mode 100644 docs/examples/domains/get-preset-i-cloud.md create mode 100644 docs/examples/domains/get-preset-mailgun.md create mode 100644 docs/examples/domains/get-preset-outlook.md create mode 100644 docs/examples/domains/get-preset-proton-mail.md create mode 100644 docs/examples/domains/get-preset-zoho.md create mode 100644 docs/examples/domains/get-price.md create mode 100644 docs/examples/domains/get-record.md create mode 100644 docs/examples/domains/get-transfer-status.md create mode 100644 docs/examples/domains/get-zone.md create mode 100644 docs/examples/domains/get.md create mode 100644 docs/examples/domains/list-prices.md create mode 100644 docs/examples/domains/list-records.md create mode 100644 docs/examples/domains/list.md create mode 100644 docs/examples/domains/update-nameservers.md create mode 100644 docs/examples/domains/update-record-a.md create mode 100644 docs/examples/domains/update-record-aaaa.md create mode 100644 docs/examples/domains/update-record-alias.md create mode 100644 docs/examples/domains/update-record-caa.md create mode 100644 docs/examples/domains/update-record-cname.md create mode 100644 docs/examples/domains/update-record-https.md create mode 100644 docs/examples/domains/update-record-mx.md create mode 100644 docs/examples/domains/update-record-ns.md create mode 100644 docs/examples/domains/update-record-srv.md create mode 100644 docs/examples/domains/update-record-txt.md create mode 100644 docs/examples/domains/update-team.md create mode 100644 docs/examples/domains/update-zone.md create mode 100644 docs/examples/domains/verify-nameservers.md create mode 100644 docs/examples/messaging/create-appwrite-provider.md create mode 100644 docs/examples/messaging/update-appwrite-provider.md create mode 100644 docs/examples/oauth2/introspect.md create mode 100644 docs/examples/organization/create-ephemeral-project-key.md create mode 100644 docs/examples/organization/delete-project-key.md create mode 100644 docs/examples/organization/get-project-key.md create mode 100644 docs/examples/organization/list-project-keys.md create mode 100644 docs/examples/organization/update-project-key.md create mode 100644 docs/examples/project/create-environment.md create mode 100644 docs/examples/project/delete-environment.md create mode 100644 docs/examples/project/get-environment.md create mode 100644 docs/examples/project/list-environments.md create mode 100644 docs/examples/project/update-environment.md create mode 100644 docs/examples/project/update-o-auth-2-kakao.md create mode 100644 docs/examples/project/update-o-auth-2-tik-tok.md create mode 100644 docs/examples/project/update-o-auth-2-webflow.md create mode 100644 docs/examples/project/update-password-pwned-policy.md create mode 100644 docs/examples/project/update-password-rotation-policy.md create mode 100644 docs/examples/waf/create-bypass-rule.md create mode 100644 docs/examples/waf/create-challenge-rule.md create mode 100644 docs/examples/waf/create-deny-rule.md create mode 100644 docs/examples/waf/create-rate-limit-rule.md create mode 100644 docs/examples/waf/create-redirect-rule.md create mode 100644 docs/examples/waf/delete-rule.md create mode 100644 docs/examples/waf/get-rule.md create mode 100644 docs/examples/waf/list-rules.md create mode 100644 docs/examples/waf/update-bypass-rule.md create mode 100644 docs/examples/waf/update-challenge-rule.md create mode 100644 docs/examples/waf/update-deny-rule.md create mode 100644 docs/examples/waf/update-rate-limit-rule.md create mode 100644 docs/examples/waf/update-redirect-rule.md create mode 100644 test/services/test_domains.py create mode 100644 test/services/test_waf.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 118ce9ea..a9d5f546 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ # Change Log +## 24.4.0 + +* Added: `domains` service to register, transfer and manage domains, DNS records, email presets and zones +* Added: `waf` service with bypass, challenge, deny, rate-limit and redirect rules +* Added: `account.createEmailVerificationOTP`, `updateEmailVerificationOTP`, `createRecoveryOTP` and `updateRecoveryOTP` +* Added: `account.createIdTokenSession` and `Identity.providerIdToken` +* Added: `oauth2.introspect` +* Added: project environments with `project.createEnvironment`, `getEnvironment`, `listEnvironments`, `updateEnvironment` and `deleteEnvironment` +* Added: `organization.createEphemeralProjectKey`, `listProjectKeys`, `getProjectKey`, `updateProjectKey` and `deleteProjectKey` +* Added: Kakao, TikTok and Webflow OAuth2 providers with `project.updateOAuth2Kakao`, `updateOAuth2TikTok` and `updateOAuth2Webflow` +* Added: optional `prompt` on the Auth0, Discord, GitHub, Microsoft, Okta, Salesforce and Zoho OAuth2 settings, and native client IDs on Apple and Google +* Added: `project.updatePasswordPwnedPolicy`, `project.updatePasswordRotationPolicy` and `User.passwordPwned` +* Added: `messaging.createAppwriteProvider` and `messaging.updateAppwriteProvider` +* Added: optional `replyToEmail` and `replyToName` on email messages, `channelId` on push messages, and `qos` and `expiry` on topics +* Added: `avatars.updatePhoto` and `avatars.deletePhoto` +* Added: optional `duration` on `account.createEmailPasswordSession`, `current` on `account.deleteSessions`, `membershipId` on `teams.createMembership` and `fingerprints` on Android platforms +* Added: optional `total` on the locale, transaction, runtime, specification and framework lists +* Added: `dart-3.13` and `flutter-3.47` runtimes, the `jaspr` framework, the `trigram` index type, `auto` image gravity, the `dedicatedDatabase` proxy rule resource type, OTP email templates and new key scopes +* Added: optional fields on `BillingPlan`, `DedicatedDatabase`, `DedicatedDatabaseSpecification`, `Project` and `Topic`, and `free` and `start` in `BillingPlanGroup` + ## 24.3.1 * Fixed: added `ProjectAuthMethodId.PASSKEY`, so `project.updateAuthMethod` can enable passkeys diff --git a/appwrite/client.py b/appwrite/client.py index df31c044..94a60b40 100644 --- a/appwrite/client.py +++ b/appwrite/client.py @@ -18,11 +18,11 @@ def __init__(self): self._endpoint = 'https://cloud.appwrite.io/v1' self._global_headers = { 'content-type': '', - 'user-agent': f'AppwritePythonSDK/24.3.1 ({platform.uname().system}; {platform.uname().version}; {platform.uname().machine})', + 'user-agent': f'AppwritePythonSDK/24.4.0 ({platform.uname().system}; {platform.uname().version}; {platform.uname().machine})', 'x-sdk-name': 'Python', 'x-sdk-platform': 'server', 'x-sdk-language': 'python', - 'x-sdk-version': '24.3.1', + 'x-sdk-version': '24.4.0', 'X-Appwrite-Response-Format': '2.0.0', } self._config = {} @@ -190,6 +190,9 @@ def call(self, method, path='', headers=None, params=None, response_type='json') if response_type == 'location': return response.headers.get('Location') + if response_type == 'text': + return response.content.decode('utf-8') + if content_type.startswith('application/json'): return response.json() @@ -214,6 +217,7 @@ def chunked_upload( param_name='', on_progress=None, upload_id='', + method='post', ): input_file = params[param_name] @@ -230,7 +234,7 @@ def chunked_upload( input_file.data = input.read() params[param_name] = input_file - return self.call('post', path, headers, params) + return self.call(method, path, headers, params) offset = 0 counter = 0 @@ -296,7 +300,7 @@ def upload_chunk(chunk, current_upload_id): chunk_headers["x-appwrite-id"] = current_upload_id return self.call( - 'post', + method, path, chunk_headers, chunk_params, diff --git a/appwrite/encoders/value_class_encoder.py b/appwrite/encoders/value_class_encoder.py index 96f558d2..46727dad 100644 --- a/appwrite/encoders/value_class_encoder.py +++ b/appwrite/encoders/value_class_encoder.py @@ -2,6 +2,7 @@ from ..models.base_model import AppwriteModel from ..enums.authenticator_type import AuthenticatorType from ..enums.authentication_factor import AuthenticationFactor +from ..enums.id_token_provider import IdTokenProvider from ..enums.o_auth_provider import OAuthProvider from ..enums.browser import Browser from ..enums.credit_card import CreditCard @@ -16,6 +17,7 @@ from ..enums.databases_index_type import DatabasesIndexType from ..enums.order_by import OrderBy from ..enums.documents_db_index_type import DocumentsDBIndexType +from ..enums.domain_registration_type import DomainRegistrationType from ..enums.embedding_model import EmbeddingModel from ..enums.runtime import Runtime from ..enums.project_key_scopes import ProjectKeyScopes @@ -28,8 +30,16 @@ from ..enums.organization_key_scopes import OrganizationKeyScopes from ..enums.region import Region from ..enums.project_auth_method_id import ProjectAuthMethodId +from ..enums.project_o_auth2_auth0_prompt import ProjectOAuth2Auth0Prompt +from ..enums.project_o_auth2_discord_prompt import ProjectOAuth2DiscordPrompt +from ..enums.project_o_auth2_git_hub_prompt import ProjectOAuth2GitHubPrompt from ..enums.project_o_auth2_google_prompt import ProjectOAuth2GooglePrompt +from ..enums.project_o_auth2_kakao_prompt import ProjectOAuth2KakaoPrompt +from ..enums.project_o_auth2_microsoft_prompt import ProjectOAuth2MicrosoftPrompt from ..enums.project_o_auth2_oidc_prompt import ProjectOAuth2OidcPrompt +from ..enums.project_o_auth2_okta_prompt import ProjectOAuth2OktaPrompt +from ..enums.project_o_auth2_salesforce_prompt import ProjectOAuth2SalesforcePrompt +from ..enums.project_o_auth2_zoho_prompt import ProjectOAuth2ZohoPrompt from ..enums.project_o_auth_provider_id import ProjectOAuthProviderId from ..enums.project_policy_id import ProjectPolicyId from ..enums.project_protocol_id import ProjectProtocolId @@ -58,13 +68,23 @@ from ..enums.execution_resource_type import ExecutionResourceType from ..enums.execution_trigger import ExecutionTrigger from ..enums.execution_status import ExecutionStatus +from ..enums.o_auth2_github_prompt import OAuth2GithubPrompt +from ..enums.o_auth2_discord_prompt import OAuth2DiscordPrompt from ..enums.o_auth2_google_prompt import OAuth2GooglePrompt +from ..enums.o_auth2_zoho_prompt import OAuth2ZohoPrompt +from ..enums.o_auth2_salesforce_prompt import OAuth2SalesforcePrompt +from ..enums.o_auth2_auth0_prompt import OAuth2Auth0Prompt from ..enums.o_auth2_oidc_prompt import OAuth2OidcPrompt +from ..enums.o_auth2_okta_prompt import OAuth2OktaPrompt +from ..enums.o_auth2_microsoft_prompt import OAuth2MicrosoftPrompt +from ..enums.o_auth2_kakao_prompt import OAuth2KakaoPrompt from ..enums.platform_type import PlatformType from ..enums.proxy_rule_deployment_resource_type import ProxyRuleDeploymentResourceType from ..enums.proxy_rule_status import ProxyRuleStatus from ..enums.message_status import MessageStatus from ..enums.billing_plan_group import BillingPlanGroup +from ..enums.domain_transfer_status_enum import DomainTransferStatusEnum +from ..enums.waf_rule_action import WafRuleAction class ValueClassEncoder(json.JSONEncoder): @@ -78,6 +98,9 @@ def default(self, o): if isinstance(o, AuthenticationFactor): return o.value + if isinstance(o, IdTokenProvider): + return o.value + if isinstance(o, OAuthProvider): return o.value @@ -120,6 +143,9 @@ def default(self, o): if isinstance(o, DocumentsDBIndexType): return o.value + if isinstance(o, DomainRegistrationType): + return o.value + if isinstance(o, EmbeddingModel): return o.value @@ -156,12 +182,36 @@ def default(self, o): if isinstance(o, ProjectAuthMethodId): return o.value + if isinstance(o, ProjectOAuth2Auth0Prompt): + return o.value + + if isinstance(o, ProjectOAuth2DiscordPrompt): + return o.value + + if isinstance(o, ProjectOAuth2GitHubPrompt): + return o.value + if isinstance(o, ProjectOAuth2GooglePrompt): return o.value + if isinstance(o, ProjectOAuth2KakaoPrompt): + return o.value + + if isinstance(o, ProjectOAuth2MicrosoftPrompt): + return o.value + if isinstance(o, ProjectOAuth2OidcPrompt): return o.value + if isinstance(o, ProjectOAuth2OktaPrompt): + return o.value + + if isinstance(o, ProjectOAuth2SalesforcePrompt): + return o.value + + if isinstance(o, ProjectOAuth2ZohoPrompt): + return o.value + if isinstance(o, ProjectOAuthProviderId): return o.value @@ -246,12 +296,36 @@ def default(self, o): if isinstance(o, ExecutionStatus): return o.value + if isinstance(o, OAuth2GithubPrompt): + return o.value + + if isinstance(o, OAuth2DiscordPrompt): + return o.value + if isinstance(o, OAuth2GooglePrompt): return o.value + if isinstance(o, OAuth2ZohoPrompt): + return o.value + + if isinstance(o, OAuth2SalesforcePrompt): + return o.value + + if isinstance(o, OAuth2Auth0Prompt): + return o.value + if isinstance(o, OAuth2OidcPrompt): return o.value + if isinstance(o, OAuth2OktaPrompt): + return o.value + + if isinstance(o, OAuth2MicrosoftPrompt): + return o.value + + if isinstance(o, OAuth2KakaoPrompt): + return o.value + if isinstance(o, PlatformType): return o.value @@ -267,4 +341,10 @@ def default(self, o): if isinstance(o, BillingPlanGroup): return o.value + if isinstance(o, DomainTransferStatusEnum): + return o.value + + if isinstance(o, WafRuleAction): + return o.value + return super().default(o) diff --git a/appwrite/enums/billing_plan_group.py b/appwrite/enums/billing_plan_group.py index 356139e8..e161dd24 100644 --- a/appwrite/enums/billing_plan_group.py +++ b/appwrite/enums/billing_plan_group.py @@ -3,5 +3,7 @@ class BillingPlanGroup(Enum): STARTER = "starter" + FREE = "free" + START = "start" PRO = "pro" SCALE = "scale" diff --git a/appwrite/enums/build_runtime.py b/appwrite/enums/build_runtime.py index 08aacade..4bf67543 100644 --- a/appwrite/enums/build_runtime.py +++ b/appwrite/enums/build_runtime.py @@ -53,6 +53,7 @@ class BuildRuntime(Enum): DART_3_10 = "dart-3.10" DART_3_11 = "dart-3.11" DART_3_12 = "dart-3.12" + DART_3_13 = "dart-3.13" DOTNET_6_0 = "dotnet-6.0" DOTNET_7_0 = "dotnet-7.0" DOTNET_8_0 = "dotnet-8.0" @@ -95,3 +96,4 @@ class BuildRuntime(Enum): FLUTTER_3_38 = "flutter-3.38" FLUTTER_3_41 = "flutter-3.41" FLUTTER_3_44 = "flutter-3.44" + FLUTTER_3_47 = "flutter-3.47" diff --git a/appwrite/enums/databases_index_type.py b/appwrite/enums/databases_index_type.py index 58e52c17..c9aacd09 100644 --- a/appwrite/enums/databases_index_type.py +++ b/appwrite/enums/databases_index_type.py @@ -6,3 +6,4 @@ class DatabasesIndexType(Enum): FULLTEXT = "fulltext" UNIQUE = "unique" SPATIAL = "spatial" + TRIGRAM = "trigram" diff --git a/appwrite/enums/domain_registration_type.py b/appwrite/enums/domain_registration_type.py new file mode 100644 index 00000000..cb6f6e57 --- /dev/null +++ b/appwrite/enums/domain_registration_type.py @@ -0,0 +1,8 @@ +from enum import Enum + + +class DomainRegistrationType(Enum): + NEW = "new" + TRANSFER = "transfer" + RENEWAL = "renewal" + TRADE = "trade" diff --git a/appwrite/enums/domain_transfer_status_enum.py b/appwrite/enums/domain_transfer_status_enum.py new file mode 100644 index 00000000..298de29a --- /dev/null +++ b/appwrite/enums/domain_transfer_status_enum.py @@ -0,0 +1,12 @@ +from enum import Enum + + +class DomainTransferStatusEnum(Enum): + TRANSFERRABLE = "transferrable" + NOT_TRANSFERRABLE = "not_transferrable" + PENDING_OWNER = "pending_owner" + PENDING_ADMIN = "pending_admin" + PENDING_REGISTRY = "pending_registry" + COMPLETED = "completed" + CANCELLED = "cancelled" + SERVICE_UNAVAILABLE = "service_unavailable" diff --git a/appwrite/enums/framework.py b/appwrite/enums/framework.py index 013d71c4..b16cb5d2 100644 --- a/appwrite/enums/framework.py +++ b/appwrite/enums/framework.py @@ -14,6 +14,7 @@ class Framework(Enum): REMIX = "remix" LYNX = "lynx" FLUTTER = "flutter" + JASPR = "jaspr" REACT_NATIVE = "react-native" VITE = "vite" OTHER = "other" diff --git a/appwrite/enums/id_token_provider.py b/appwrite/enums/id_token_provider.py new file mode 100644 index 00000000..707566f4 --- /dev/null +++ b/appwrite/enums/id_token_provider.py @@ -0,0 +1,6 @@ +from enum import Enum + + +class IdTokenProvider(Enum): + APPLE = "apple" + GOOGLE = "google" diff --git a/appwrite/enums/image_gravity.py b/appwrite/enums/image_gravity.py index 57c13887..c34176fa 100644 --- a/appwrite/enums/image_gravity.py +++ b/appwrite/enums/image_gravity.py @@ -2,6 +2,7 @@ class ImageGravity(Enum): + AUTO = "auto" CENTER = "center" TOP_LEFT = "top-left" TOP = "top" diff --git a/appwrite/enums/o_auth2_auth0_prompt.py b/appwrite/enums/o_auth2_auth0_prompt.py new file mode 100644 index 00000000..8acbbfe7 --- /dev/null +++ b/appwrite/enums/o_auth2_auth0_prompt.py @@ -0,0 +1,7 @@ +from enum import Enum + + +class OAuth2Auth0Prompt(Enum): + NONE = "none" + LOGIN = "login" + CONSENT = "consent" diff --git a/appwrite/enums/o_auth2_discord_prompt.py b/appwrite/enums/o_auth2_discord_prompt.py new file mode 100644 index 00000000..38e3725f --- /dev/null +++ b/appwrite/enums/o_auth2_discord_prompt.py @@ -0,0 +1,6 @@ +from enum import Enum + + +class OAuth2DiscordPrompt(Enum): + NONE = "none" + CONSENT = "consent" diff --git a/appwrite/enums/o_auth2_github_prompt.py b/appwrite/enums/o_auth2_github_prompt.py new file mode 100644 index 00000000..1cc47a0b --- /dev/null +++ b/appwrite/enums/o_auth2_github_prompt.py @@ -0,0 +1,5 @@ +from enum import Enum + + +class OAuth2GithubPrompt(Enum): + SELECT_ACCOUNT = "select_account" diff --git a/appwrite/enums/o_auth2_kakao_prompt.py b/appwrite/enums/o_auth2_kakao_prompt.py new file mode 100644 index 00000000..7460a528 --- /dev/null +++ b/appwrite/enums/o_auth2_kakao_prompt.py @@ -0,0 +1,8 @@ +from enum import Enum + + +class OAuth2KakaoPrompt(Enum): + NONE = "none" + LOGIN = "login" + CREATE = "create" + SELECT_ACCOUNT = "select_account" diff --git a/appwrite/enums/o_auth2_microsoft_prompt.py b/appwrite/enums/o_auth2_microsoft_prompt.py new file mode 100644 index 00000000..d237f4ec --- /dev/null +++ b/appwrite/enums/o_auth2_microsoft_prompt.py @@ -0,0 +1,8 @@ +from enum import Enum + + +class OAuth2MicrosoftPrompt(Enum): + NONE = "none" + LOGIN = "login" + CONSENT = "consent" + SELECT_ACCOUNT = "select_account" diff --git a/appwrite/enums/o_auth2_okta_prompt.py b/appwrite/enums/o_auth2_okta_prompt.py new file mode 100644 index 00000000..fb2b16c3 --- /dev/null +++ b/appwrite/enums/o_auth2_okta_prompt.py @@ -0,0 +1,7 @@ +from enum import Enum + + +class OAuth2OktaPrompt(Enum): + NONE = "none" + LOGIN = "login" + CONSENT = "consent" diff --git a/appwrite/enums/o_auth2_salesforce_prompt.py b/appwrite/enums/o_auth2_salesforce_prompt.py new file mode 100644 index 00000000..64833a05 --- /dev/null +++ b/appwrite/enums/o_auth2_salesforce_prompt.py @@ -0,0 +1,6 @@ +from enum import Enum + + +class OAuth2SalesforcePrompt(Enum): + LOGIN = "login" + CONSENT = "consent" diff --git a/appwrite/enums/o_auth2_zoho_prompt.py b/appwrite/enums/o_auth2_zoho_prompt.py new file mode 100644 index 00000000..bd6a30b3 --- /dev/null +++ b/appwrite/enums/o_auth2_zoho_prompt.py @@ -0,0 +1,5 @@ +from enum import Enum + + +class OAuth2ZohoPrompt(Enum): + CONSENT = "consent" diff --git a/appwrite/enums/o_auth_provider.py b/appwrite/enums/o_auth_provider.py index 8656b596..87c6ed02 100644 --- a/appwrite/enums/o_auth_provider.py +++ b/appwrite/enums/o_auth_provider.py @@ -24,6 +24,7 @@ class OAuthProvider(Enum): GITLAB = "gitlab" GOOGLE = "google" HUGGINGFACE = "huggingface" + KAKAO = "kakao" KEYCLOAK = "keycloak" KICK = "kick" LINKEDIN = "linkedin" @@ -39,9 +40,11 @@ class OAuthProvider(Enum): SLACK = "slack" SPOTIFY = "spotify" STRIPE = "stripe" + TIKTOK = "tiktok" TRADESHIFT = "tradeshift" TRADESHIFTBOX = "tradeshiftBox" TWITCH = "twitch" + WEBFLOW = "webflow" WORDPRESS = "wordpress" X = "x" YAHOO = "yahoo" diff --git a/appwrite/enums/project_email_template_id.py b/appwrite/enums/project_email_template_id.py index c2b97a29..c6c940d6 100644 --- a/appwrite/enums/project_email_template_id.py +++ b/appwrite/enums/project_email_template_id.py @@ -9,3 +9,5 @@ class ProjectEmailTemplateId(Enum): MFACHALLENGE = "mfaChallenge" SESSIONALERT = "sessionAlert" OTPSESSION = "otpSession" + OTPVERIFICATION = "otpVerification" + OTPRECOVERY = "otpRecovery" diff --git a/appwrite/enums/project_key_scopes.py b/appwrite/enums/project_key_scopes.py index 57710319..9168740c 100644 --- a/appwrite/enums/project_key_scopes.py +++ b/appwrite/enums/project_key_scopes.py @@ -92,6 +92,7 @@ class ProjectKeyScopes(Enum): WEBHOOKS_WRITE = "webhooks.write" LOCALE_READ = "locale.read" AVATARS_READ = "avatars.read" + AVATARS_WRITE = "avatars.write" HEALTH_READ = "health.read" ASSISTANT_READ = "assistant.read" MIGRATIONS_READ = "migrations.read" @@ -106,6 +107,7 @@ class ProjectKeyScopes(Enum): REPORTS_WRITE = "reports.write" PRESENCES_READ = "presences.read" PRESENCES_WRITE = "presences.write" + DEDICATEDDATABASES_EXECUTE = "dedicatedDatabases.execute" BACKUPS_POLICIES_READ = "backups.policies.read" BACKUPS_POLICIES_WRITE = "backups.policies.write" ARCHIVES_READ = "archives.read" @@ -123,3 +125,5 @@ class ProjectKeyScopes(Enum): OAUTH2_READ = "oauth2.read" OAUTH2_WRITE = "oauth2.write" OAUTH2_INTROSPECT = "oauth2.introspect" + ANALYTICS_READ = "analytics.read" + ANALYTICS_WRITE = "analytics.write" diff --git a/appwrite/enums/project_o_auth2_auth0_prompt.py b/appwrite/enums/project_o_auth2_auth0_prompt.py new file mode 100644 index 00000000..166ec632 --- /dev/null +++ b/appwrite/enums/project_o_auth2_auth0_prompt.py @@ -0,0 +1,7 @@ +from enum import Enum + + +class ProjectOAuth2Auth0Prompt(Enum): + NONE = "none" + LOGIN = "login" + CONSENT = "consent" diff --git a/appwrite/enums/project_o_auth2_discord_prompt.py b/appwrite/enums/project_o_auth2_discord_prompt.py new file mode 100644 index 00000000..7caebc14 --- /dev/null +++ b/appwrite/enums/project_o_auth2_discord_prompt.py @@ -0,0 +1,6 @@ +from enum import Enum + + +class ProjectOAuth2DiscordPrompt(Enum): + NONE = "none" + CONSENT = "consent" diff --git a/appwrite/enums/project_o_auth2_git_hub_prompt.py b/appwrite/enums/project_o_auth2_git_hub_prompt.py new file mode 100644 index 00000000..ba8e9530 --- /dev/null +++ b/appwrite/enums/project_o_auth2_git_hub_prompt.py @@ -0,0 +1,5 @@ +from enum import Enum + + +class ProjectOAuth2GitHubPrompt(Enum): + SELECT_ACCOUNT = "select_account" diff --git a/appwrite/enums/project_o_auth2_kakao_prompt.py b/appwrite/enums/project_o_auth2_kakao_prompt.py new file mode 100644 index 00000000..9805b060 --- /dev/null +++ b/appwrite/enums/project_o_auth2_kakao_prompt.py @@ -0,0 +1,8 @@ +from enum import Enum + + +class ProjectOAuth2KakaoPrompt(Enum): + NONE = "none" + LOGIN = "login" + CREATE = "create" + SELECT_ACCOUNT = "select_account" diff --git a/appwrite/enums/project_o_auth2_microsoft_prompt.py b/appwrite/enums/project_o_auth2_microsoft_prompt.py new file mode 100644 index 00000000..2714e351 --- /dev/null +++ b/appwrite/enums/project_o_auth2_microsoft_prompt.py @@ -0,0 +1,8 @@ +from enum import Enum + + +class ProjectOAuth2MicrosoftPrompt(Enum): + NONE = "none" + LOGIN = "login" + CONSENT = "consent" + SELECT_ACCOUNT = "select_account" diff --git a/appwrite/enums/project_o_auth2_okta_prompt.py b/appwrite/enums/project_o_auth2_okta_prompt.py new file mode 100644 index 00000000..59f35a04 --- /dev/null +++ b/appwrite/enums/project_o_auth2_okta_prompt.py @@ -0,0 +1,7 @@ +from enum import Enum + + +class ProjectOAuth2OktaPrompt(Enum): + NONE = "none" + LOGIN = "login" + CONSENT = "consent" diff --git a/appwrite/enums/project_o_auth2_salesforce_prompt.py b/appwrite/enums/project_o_auth2_salesforce_prompt.py new file mode 100644 index 00000000..f0b43f9a --- /dev/null +++ b/appwrite/enums/project_o_auth2_salesforce_prompt.py @@ -0,0 +1,6 @@ +from enum import Enum + + +class ProjectOAuth2SalesforcePrompt(Enum): + LOGIN = "login" + CONSENT = "consent" diff --git a/appwrite/enums/project_o_auth2_zoho_prompt.py b/appwrite/enums/project_o_auth2_zoho_prompt.py new file mode 100644 index 00000000..c866a245 --- /dev/null +++ b/appwrite/enums/project_o_auth2_zoho_prompt.py @@ -0,0 +1,5 @@ +from enum import Enum + + +class ProjectOAuth2ZohoPrompt(Enum): + CONSENT = "consent" diff --git a/appwrite/enums/project_o_auth_provider_id.py b/appwrite/enums/project_o_auth_provider_id.py index ad47c234..7757a41a 100644 --- a/appwrite/enums/project_o_auth_provider_id.py +++ b/appwrite/enums/project_o_auth_provider_id.py @@ -24,6 +24,7 @@ class ProjectOAuthProviderId(Enum): GITLAB = "gitlab" GOOGLE = "google" HUGGINGFACE = "huggingface" + KAKAO = "kakao" KEYCLOAK = "keycloak" KICK = "kick" LINKEDIN = "linkedin" @@ -39,9 +40,11 @@ class ProjectOAuthProviderId(Enum): SLACK = "slack" SPOTIFY = "spotify" STRIPE = "stripe" + TIKTOK = "tiktok" TRADESHIFT = "tradeshift" TRADESHIFTBOX = "tradeshiftBox" TWITCH = "twitch" + WEBFLOW = "webflow" WORDPRESS = "wordpress" X = "x" YAHOO = "yahoo" diff --git a/appwrite/enums/project_policy_id.py b/appwrite/enums/project_policy_id.py index cdb27f85..bc2ce903 100644 --- a/appwrite/enums/project_policy_id.py +++ b/appwrite/enums/project_policy_id.py @@ -6,6 +6,8 @@ class ProjectPolicyId(Enum): PASSWORD_HISTORY = "password-history" PASSWORD_STRENGTH = "password-strength" PASSWORD_PERSONAL_DATA = "password-personal-data" + PASSWORD_PWNED = "password-pwned" + PASSWORD_ROTATION = "password-rotation" SESSION_ALERT = "session-alert" SESSION_DURATION = "session-duration" SESSION_INVALIDATION = "session-invalidation" diff --git a/appwrite/enums/proxy_rule_deployment_resource_type.py b/appwrite/enums/proxy_rule_deployment_resource_type.py index 8d525d0c..b0589232 100644 --- a/appwrite/enums/proxy_rule_deployment_resource_type.py +++ b/appwrite/enums/proxy_rule_deployment_resource_type.py @@ -4,3 +4,4 @@ class ProxyRuleDeploymentResourceType(Enum): FUNCTION = "function" SITE = "site" + DEDICATEDDATABASE = "dedicatedDatabase" diff --git a/appwrite/enums/runtime.py b/appwrite/enums/runtime.py index e543e3bb..c7f29dd5 100644 --- a/appwrite/enums/runtime.py +++ b/appwrite/enums/runtime.py @@ -53,6 +53,7 @@ class Runtime(Enum): DART_3_10 = "dart-3.10" DART_3_11 = "dart-3.11" DART_3_12 = "dart-3.12" + DART_3_13 = "dart-3.13" DOTNET_6_0 = "dotnet-6.0" DOTNET_7_0 = "dotnet-7.0" DOTNET_8_0 = "dotnet-8.0" @@ -95,3 +96,4 @@ class Runtime(Enum): FLUTTER_3_38 = "flutter-3.38" FLUTTER_3_41 = "flutter-3.41" FLUTTER_3_44 = "flutter-3.44" + FLUTTER_3_47 = "flutter-3.47" diff --git a/appwrite/enums/tables_db_index_type.py b/appwrite/enums/tables_db_index_type.py index 5c0a903c..388f654e 100644 --- a/appwrite/enums/tables_db_index_type.py +++ b/appwrite/enums/tables_db_index_type.py @@ -6,3 +6,4 @@ class TablesDBIndexType(Enum): FULLTEXT = "fulltext" UNIQUE = "unique" SPATIAL = "spatial" + TRIGRAM = "trigram" diff --git a/appwrite/enums/waf_rule_action.py b/appwrite/enums/waf_rule_action.py new file mode 100644 index 00000000..516f60e1 --- /dev/null +++ b/appwrite/enums/waf_rule_action.py @@ -0,0 +1,9 @@ +from enum import Enum + + +class WafRuleAction(Enum): + BYPASS = "bypass" + DENY = "deny" + CHALLENGE = "challenge" + RATELIMIT = "rateLimit" + REDIRECT = "redirect" diff --git a/appwrite/models/__init__.py b/appwrite/models/__init__.py index 2b02e1a0..53aeda55 100644 --- a/appwrite/models/__init__.py +++ b/appwrite/models/__init__.py @@ -106,6 +106,7 @@ from .algo_scrypt import AlgoScrypt from .algo_scrypt_modified import AlgoScryptModified from .algo_argon2 import AlgoArgon2 +from .account import Account from .preferences import Preferences from .session import Session from .identity import Identity @@ -149,6 +150,7 @@ from .o_auth2_yandex import OAuth2Yandex from .o_auth2_x import OAuth2X from .o_auth2_word_press import OAuth2WordPress +from .o_auth2_webflow import OAuth2Webflow from .o_auth2_twitch import OAuth2Twitch from .o_auth2_stripe import OAuth2Stripe from .o_auth2_spotify import OAuth2Spotify @@ -178,11 +180,15 @@ from .o_auth2_apple import OAuth2Apple from .o_auth2_microsoft import OAuth2Microsoft from .o_auth2_resend import OAuth2Resend +from .o_auth2_tik_tok import OAuth2TikTok +from .o_auth2_kakao import OAuth2Kakao from .o_auth2_provider_list import OAuth2ProviderList from .policy_password_dictionary import PolicyPasswordDictionary from .policy_password_history import PolicyPasswordHistory from .policy_password_strength import PolicyPasswordStrength from .policy_password_personal_data import PolicyPasswordPersonalData +from .policy_password_pwned import PolicyPasswordPwned +from .policy_password_rotation import PolicyPasswordRotation from .policy_session_alert import PolicySessionAlert from .policy_session_duration import PolicySessionDuration from .policy_session_invalidation import PolicySessionInvalidation @@ -247,6 +253,10 @@ from .dedicated_database_execution_column import DedicatedDatabaseExecutionColumn from .dedicated_database_restoration import DedicatedDatabaseRestoration from .database_status import DatabaseStatus +from .dns_record import DnsRecord +from .domain import Domain +from .domain_price import DomainPrice +from .domain_transfer_status import DomainTransferStatus from .dedicated_database_extensions import DedicatedDatabaseExtensions from .dedicated_database_member import DedicatedDatabaseMember from .dedicated_database_operation import DedicatedDatabaseOperation @@ -285,8 +295,15 @@ from .oauth2_device_authorization import Oauth2DeviceAuthorization from .oauth2_par import Oauth2PAR from .oauth2_token import Oauth2Token +from .oauth2_introspection import Oauth2Introspection from .oauth2_consent import Oauth2Consent from .oauth2_consent_token import Oauth2ConsentToken +from .waf_rule_bypass import WafRuleBypass +from .waf_rule_deny import WafRuleDeny +from .waf_rule_challenge import WafRuleChallenge +from .waf_rule_rate_limit import WafRuleRateLimit +from .waf_rule_redirect import WafRuleRedirect +from .waf_rule_list import WafRuleList from .oauth2_project import Oauth2Project from .oauth2_organization import Oauth2Organization from .oauth2_project_list import Oauth2ProjectList @@ -299,6 +316,9 @@ from .backup_restoration_list import BackupRestorationList from .database_migration_list import DatabaseMigrationList from .dedicated_database_list import DedicatedDatabaseList +from .dns_records_list import DnsRecordsList +from .domain_prices_list import DomainPricesList +from .domains_list import DomainsList from .apps_list import AppsList from .app_secret_list import AppSecretList from .app_scope_list import AppScopeList @@ -414,6 +434,7 @@ 'AlgoScrypt', 'AlgoScryptModified', 'AlgoArgon2', + 'Account', 'Preferences', 'Session', 'Identity', @@ -457,6 +478,7 @@ 'OAuth2Yandex', 'OAuth2X', 'OAuth2WordPress', + 'OAuth2Webflow', 'OAuth2Twitch', 'OAuth2Stripe', 'OAuth2Spotify', @@ -486,11 +508,15 @@ 'OAuth2Apple', 'OAuth2Microsoft', 'OAuth2Resend', + 'OAuth2TikTok', + 'OAuth2Kakao', 'OAuth2ProviderList', 'PolicyPasswordDictionary', 'PolicyPasswordHistory', 'PolicyPasswordStrength', 'PolicyPasswordPersonalData', + 'PolicyPasswordPwned', + 'PolicyPasswordRotation', 'PolicySessionAlert', 'PolicySessionDuration', 'PolicySessionInvalidation', @@ -555,6 +581,10 @@ 'DedicatedDatabaseExecutionColumn', 'DedicatedDatabaseRestoration', 'DatabaseStatus', + 'DnsRecord', + 'Domain', + 'DomainPrice', + 'DomainTransferStatus', 'DedicatedDatabaseExtensions', 'DedicatedDatabaseMember', 'DedicatedDatabaseOperation', @@ -593,8 +623,15 @@ 'Oauth2DeviceAuthorization', 'Oauth2PAR', 'Oauth2Token', + 'Oauth2Introspection', 'Oauth2Consent', 'Oauth2ConsentToken', + 'WafRuleBypass', + 'WafRuleDeny', + 'WafRuleChallenge', + 'WafRuleRateLimit', + 'WafRuleRedirect', + 'WafRuleList', 'Oauth2Project', 'Oauth2Organization', 'Oauth2ProjectList', @@ -607,6 +644,9 @@ 'BackupRestorationList', 'DatabaseMigrationList', 'DedicatedDatabaseList', + 'DnsRecordsList', + 'DomainPricesList', + 'DomainsList', 'AppsList', 'AppSecretList', 'AppScopeList', diff --git a/appwrite/models/account.py b/appwrite/models/account.py new file mode 100644 index 00000000..669ab5f5 --- /dev/null +++ b/appwrite/models/account.py @@ -0,0 +1,98 @@ +from typing import Any, Dict, List, Optional, Union, cast, Generic, TypeVar, Type +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel +from .preferences import Preferences +from .target import Target + +T = TypeVar('T') + + +class Account(AppwriteModel, Generic[T]): + """ + Account + + Attributes + ---------- + id : str + User ID. + createdat : str + User creation date in ISO 8601 format. + updatedat : str + User update date in ISO 8601 format. + name : str + User name. + registration : str + User registration date in ISO 8601 format. + status : bool + User status. Pass `true` for enabled and `false` for disabled. + labels : List[Any] + Labels for the user. + passwordupdate : str + Password update time in ISO 8601 format. + email : str + User email address. + phone : str + User phone number in E.164 format. + emailverification : bool + Email verification status. + emailcanonical : Optional[str] + Canonical form of the user email address. + emailisfree : Optional[bool] + Whether the user email is from a free email provider. + emailisdisposable : Optional[bool] + Whether the user email is from a disposable email provider. + emailiscorporate : Optional[bool] + Whether the user email is from a corporate domain. + emailiscanonical : Optional[bool] + Whether the user email is in its canonical form. + passwordpwned : Optional[bool] + Whether the password was found in a known data breach the last time it was checked. Null when the password has never been checked. + phoneverification : bool + Phone verification status. + mfa : bool + Multi factor authentication status. + prefs : Preferences[T] + User preferences as a key-value object + targets : List[Target] + A user-owned message receiver. A single user may have multiple e.g. emails, phones, and a browser. Each target is registered with a single provider. + accessedat : str + Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours. + impersonator : Optional[bool] + Whether the user can impersonate other users. + impersonatoruserid : Optional[str] + ID of the original actor performing the impersonation. Present only when the current request is impersonating another user. Internal audit logs attribute the action to this user, while the impersonated target is recorded only in internal audit payload data. + """ + + id: str = Field(..., alias='$id') + createdat: str = Field(..., alias='$createdAt') + updatedat: str = Field(..., alias='$updatedAt') + name: str = Field(..., alias='name') + registration: str = Field(..., alias='registration') + status: bool = Field(..., alias='status') + labels: List[Any] = Field(..., alias='labels') + passwordupdate: str = Field(..., alias='passwordUpdate') + email: str = Field(..., alias='email') + phone: str = Field(..., alias='phone') + emailverification: bool = Field(..., alias='emailVerification') + emailcanonical: Optional[str] = Field(default=None, alias='emailCanonical') + emailisfree: Optional[bool] = Field(default=None, alias='emailIsFree') + emailisdisposable: Optional[bool] = Field(default=None, alias='emailIsDisposable') + emailiscorporate: Optional[bool] = Field(default=None, alias='emailIsCorporate') + emailiscanonical: Optional[bool] = Field(default=None, alias='emailIsCanonical') + passwordpwned: Optional[bool] = Field(default=None, alias='passwordPwned') + phoneverification: bool = Field(..., alias='phoneVerification') + mfa: bool = Field(..., alias='mfa') + prefs: Preferences[T] = Field(..., alias='prefs') + targets: List[Target] = Field(..., alias='targets') + accessedat: str = Field(..., alias='accessedAt') + impersonator: Optional[bool] = Field(default=None, alias='impersonator') + impersonatoruserid: Optional[str] = Field(default=None, alias='impersonatorUserId') + + @classmethod + def with_data(cls, data: Dict[str, Any], model_type: Type[T] = dict) -> 'Account[T]': + """Create Account instance with typed data.""" + instance = cls.model_validate(data) + if 'prefs' in data and data['prefs'] is not None: + instance.prefs = Preferences.with_data(data['prefs'], model_type) + return instance diff --git a/appwrite/models/billing_plan.py b/appwrite/models/billing_plan.py index a167b8e6..e63f0dbf 100644 --- a/appwrite/models/billing_plan.py +++ b/appwrite/models/billing_plan.py @@ -43,6 +43,8 @@ class BillingPlan(AppwriteModel): Webhooks wafrules : float Maximum WAF rules per project + environments : Optional[float] + Maximum environments per project. 0 when the plan does not offer environments. projects : float Projects platforms : float @@ -111,6 +113,8 @@ class BillingPlan(AppwriteModel): Does plan require payment method requiresbillingaddress : bool Does plan require billing address + eligiblecountries : Optional[List[Any]] + ISO country codes eligible for this regional plan. Empty means no restriction. isavailable : bool Is the billing plan available selfservice : bool @@ -178,6 +182,7 @@ class BillingPlan(AppwriteModel): members: Optional[float] = Field(default=None, alias='members') webhooks: float = Field(..., alias='webhooks') wafrules: float = Field(..., alias='wafRules') + environments: Optional[float] = Field(default=None, alias='environments') projects: float = Field(..., alias='projects') platforms: float = Field(..., alias='platforms') users: float = Field(..., alias='users') @@ -212,6 +217,7 @@ class BillingPlan(AppwriteModel): emailbranding: bool = Field(..., alias='emailBranding') requirespaymentmethod: bool = Field(..., alias='requiresPaymentMethod') requiresbillingaddress: bool = Field(..., alias='requiresBillingAddress') + eligiblecountries: Optional[List[Any]] = Field(default=None, alias='eligibleCountries') isavailable: bool = Field(..., alias='isAvailable') selfservice: bool = Field(..., alias='selfService') premiumsupport: bool = Field(..., alias='premiumSupport') diff --git a/appwrite/models/dedicated_database.py b/appwrite/models/dedicated_database.py index 45c49d03..5fbb15bc 100644 --- a/appwrite/models/dedicated_database.py +++ b/appwrite/models/dedicated_database.py @@ -62,6 +62,12 @@ class DedicatedDatabase(AppwriteModel): Memory allocated in MB. storage : float Storage allocated in GB. + storagestatus : Optional[str] + Storage resize status. Possible values: idle (no resize in flight), resizing (the volume is growing towards storageTargetGb). + storagetargetgb : Optional[float] + Size in GB the volume is growing towards while storageStatus is resizing. 0 when no resize is in flight. + storageresizestartedat : Optional[str] + Time the in-flight storage resize started, in ISO 8601 format. storageclass : str Storage class. Currently always 'ssd'; DigitalOcean exposes a single block-storage class. storagemaxgb : float @@ -136,6 +142,9 @@ class DedicatedDatabase(AppwriteModel): cpu: float = Field(..., alias='cpu') memory: float = Field(..., alias='memory') storage: float = Field(..., alias='storage') + storagestatus: Optional[str] = Field(default=None, alias='storageStatus') + storagetargetgb: Optional[float] = Field(default=None, alias='storageTargetGb') + storageresizestartedat: Optional[str] = Field(default=None, alias='storageResizeStartedAt') storageclass: str = Field(..., alias='storageClass') storagemaxgb: float = Field(..., alias='storageMaxGb') nodepool: str = Field(..., alias='nodePool') diff --git a/appwrite/models/dedicated_database_specification.py b/appwrite/models/dedicated_database_specification.py index 71cf58fa..35922431 100644 --- a/appwrite/models/dedicated_database_specification.py +++ b/appwrite/models/dedicated_database_specification.py @@ -16,6 +16,14 @@ class DedicatedDatabaseSpecification(AppwriteModel): Human readable specification name. price : float Monthly price of the specification in USD. + storageoveragerate : Optional[float] + Price per GB of storage above the included amount, per month, in USD. + bandwidthoveragerate : Optional[float] + Price per GB of bandwidth above the included amount, per month, in USD. + replicarate : Optional[float] + High availability replica price as a fraction of the specification price. + pitrrate : Optional[float] + Point-in-time recovery price as a fraction of the specification price. cpu : float Allocated CPU in millicores. memory : float @@ -33,6 +41,10 @@ class DedicatedDatabaseSpecification(AppwriteModel): slug: str = Field(..., alias='slug') name: str = Field(..., alias='name') price: float = Field(..., alias='price') + storageoveragerate: Optional[float] = Field(default=None, alias='storageOverageRate') + bandwidthoveragerate: Optional[float] = Field(default=None, alias='bandwidthOverageRate') + replicarate: Optional[float] = Field(default=None, alias='replicaRate') + pitrrate: Optional[float] = Field(default=None, alias='pitrRate') cpu: float = Field(..., alias='cpu') memory: float = Field(..., alias='memory') maxconnections: float = Field(..., alias='maxConnections') diff --git a/appwrite/models/dns_record.py b/appwrite/models/dns_record.py new file mode 100644 index 00000000..9911c905 --- /dev/null +++ b/appwrite/models/dns_record.py @@ -0,0 +1,50 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel + + +class DnsRecord(AppwriteModel): + """ + DNSRecord + + Attributes + ---------- + id : str + DNS Record ID. + createdat : str + DNS Record creation time in ISO 8601 format. + updatedat : str + DNS Record update date in ISO 8601 format. + type : str + DNS record type (e.g. A, CNAME, MX). + name : str + Record name or subdomain. + value : str + Value of the record (IP address, domain, etc.). + ttl : float + Time to live (in seconds). + priority : float + Record priority (commonly used for MX). + lock : bool + Whether this record is locked (read-only). + weight : float + Record weight (used for SRV records). + port : float + Target port (used for SRV records). + comment : str + Comment for the DNS record. + """ + + id: str = Field(..., alias='$id') + createdat: str = Field(..., alias='$createdAt') + updatedat: str = Field(..., alias='$updatedAt') + type: str = Field(..., alias='type') + name: str = Field(..., alias='name') + value: str = Field(..., alias='value') + ttl: float = Field(..., alias='ttl') + priority: float = Field(..., alias='priority') + lock: bool = Field(..., alias='lock') + weight: float = Field(..., alias='weight') + port: float = Field(..., alias='port') + comment: str = Field(..., alias='comment') diff --git a/appwrite/models/dns_records_list.py b/appwrite/models/dns_records_list.py new file mode 100644 index 00000000..a3948c08 --- /dev/null +++ b/appwrite/models/dns_records_list.py @@ -0,0 +1,21 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel +from .dns_record import DnsRecord + + +class DnsRecordsList(AppwriteModel): + """ + DNS records list + + Attributes + ---------- + total : float + Total number of dnsRecords that matched your query. + dnsrecords : List[DnsRecord] + List of dnsRecords. + """ + + total: float = Field(..., alias='total') + dnsrecords: List[DnsRecord] = Field(..., alias='dnsRecords') diff --git a/appwrite/models/domain.py b/appwrite/models/domain.py new file mode 100644 index 00000000..26e3ee52 --- /dev/null +++ b/appwrite/models/domain.py @@ -0,0 +1,55 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel +from ..enums.domain_transfer_status_enum import DomainTransferStatusEnum +from .dns_record import DnsRecord + + +class Domain(AppwriteModel): + """ + Domain + + Attributes + ---------- + id : str + Domain ID. + createdat : str + Domain creation time in ISO 8601 format. + updatedat : str + Domain update date in ISO 8601 format. + domain : str + Domain name. + registrar : str + Domain registrar (e.g. "appwrite" or "third_party"). + nameservers : str + Nameservers setting. "Appwrite" or empty string. + expire : str + Domain expiry date in ISO 8601 format. + renewal : str + Domain renewal date in ISO 8601 format. + autorenewal : bool + If set to true, the domain will automatically renew. + renewalprice : float + Renewal price (in cents). + transferstatus : Optional[DomainTransferStatusEnum] + Transfer status for domains being transferred in. Null when the domain is not being transferred. + teamid : str + Team ID. + dnsrecords : List[DnsRecord] + Dns records + """ + + id: str = Field(..., alias='$id') + createdat: str = Field(..., alias='$createdAt') + updatedat: str = Field(..., alias='$updatedAt') + domain: str = Field(..., alias='domain') + registrar: str = Field(..., alias='registrar') + nameservers: str = Field(..., alias='nameservers') + expire: str = Field(..., alias='expire') + renewal: str = Field(..., alias='renewal') + autorenewal: bool = Field(..., alias='autoRenewal') + renewalprice: float = Field(..., alias='renewalPrice') + transferstatus: Optional[DomainTransferStatusEnum] = Field(default=None, alias='transferStatus') + teamid: str = Field(..., alias='teamId') + dnsrecords: List[DnsRecord] = Field(..., alias='dnsRecords') diff --git a/appwrite/models/domain_price.py b/appwrite/models/domain_price.py new file mode 100644 index 00000000..298d583c --- /dev/null +++ b/appwrite/models/domain_price.py @@ -0,0 +1,38 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel + + +class DomainPrice(AppwriteModel): + """ + DomainPrice + + Attributes + ---------- + domain : str + Domain name. + tld : str + Top-level domain for the requested domain. + available : bool + Whether the domain is currently available for registration. + price : Optional[float] + Domain registration price. Null when the price could not be resolved, for example for an unsupported TLD. + periodyears : float + Price period in years. + premium : bool + Whether the domain is a premium domain. + renewalprice : Optional[float] + Domain renewal price for the same period. Null when the domain was not priced or the registrar has no renewal price for it. + renewalperiodyears : float + Renewal price period in years. + """ + + domain: str = Field(..., alias='domain') + tld: str = Field(..., alias='tld') + available: bool = Field(..., alias='available') + price: Optional[float] = Field(default=None, alias='price') + periodyears: float = Field(..., alias='periodYears') + premium: bool = Field(..., alias='premium') + renewalprice: Optional[float] = Field(default=None, alias='renewalPrice') + renewalperiodyears: float = Field(..., alias='renewalPeriodYears') diff --git a/appwrite/models/domain_prices_list.py b/appwrite/models/domain_prices_list.py new file mode 100644 index 00000000..773538f4 --- /dev/null +++ b/appwrite/models/domain_prices_list.py @@ -0,0 +1,21 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel +from .domain_price import DomainPrice + + +class DomainPricesList(AppwriteModel): + """ + Domain prices list + + Attributes + ---------- + total : float + Total number of prices that matched your query. + prices : List[DomainPrice] + List of prices. + """ + + total: float = Field(..., alias='total') + prices: List[DomainPrice] = Field(..., alias='prices') diff --git a/appwrite/models/domain_transfer_status.py b/appwrite/models/domain_transfer_status.py new file mode 100644 index 00000000..3a9e9d4c --- /dev/null +++ b/appwrite/models/domain_transfer_status.py @@ -0,0 +1,24 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel +from ..enums.domain_transfer_status_enum import DomainTransferStatusEnum + + +class DomainTransferStatus(AppwriteModel): + """ + domainTransferStatus + + Attributes + ---------- + status : DomainTransferStatusEnum + Transfer status. + reason : str + Additional transfer status information. + timestamp : str + Transfer status timestamp in ISO 8601 format. + """ + + status: DomainTransferStatusEnum = Field(..., alias='status') + reason: str = Field(..., alias='reason') + timestamp: str = Field(..., alias='timestamp') diff --git a/appwrite/models/domains_list.py b/appwrite/models/domains_list.py new file mode 100644 index 00000000..6bde8fba --- /dev/null +++ b/appwrite/models/domains_list.py @@ -0,0 +1,21 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel +from .domain import Domain + + +class DomainsList(AppwriteModel): + """ + Domains list + + Attributes + ---------- + total : float + Total number of domains that matched your query. + domains : List[Domain] + List of domains. + """ + + total: float = Field(..., alias='total') + domains: List[Domain] = Field(..., alias='domains') diff --git a/appwrite/models/identity.py b/appwrite/models/identity.py index c5ff2655..6a72ebc1 100644 --- a/appwrite/models/identity.py +++ b/appwrite/models/identity.py @@ -30,6 +30,8 @@ class Identity(AppwriteModel): The date of when the access token expires in ISO 8601 format. providerrefreshtoken : str Identity Provider Refresh Token. + provideridtoken : Optional[str] + Identity Provider ID token (JWT) from the most recent native sign-in. Empty for identities created through the browser OAuth2 flow. """ id: str = Field(..., alias='$id') @@ -42,3 +44,4 @@ class Identity(AppwriteModel): provideraccesstoken: str = Field(..., alias='providerAccessToken') provideraccesstokenexpiry: str = Field(..., alias='providerAccessTokenExpiry') providerrefreshtoken: str = Field(..., alias='providerRefreshToken') + provideridtoken: Optional[str] = Field(default=None, alias='providerIdToken') diff --git a/appwrite/models/o_auth2_apple.py b/appwrite/models/o_auth2_apple.py index e5f2e488..c31f8062 100644 --- a/appwrite/models/o_auth2_apple.py +++ b/appwrite/models/o_auth2_apple.py @@ -22,6 +22,10 @@ class OAuth2Apple(AppwriteModel): Apple OAuth2 team ID. p8file : str Apple OAuth2 .p8 private key file contents. The secret key wrapped by the PEM markers is 200 characters long. + nativeenabled : Optional[bool] + Native Sign in with Apple is active and can be used to create sessions from an ID token. Independent of enabled, which only controls the browser-based flow. + nativeclientids : Optional[List[Any]] + App bundle IDs accepted as ID token audiences for native Sign in with Apple, next to the Services ID. """ id: str = Field(..., alias='$id') @@ -30,3 +34,5 @@ class OAuth2Apple(AppwriteModel): keyid: str = Field(..., alias='keyId') teamid: str = Field(..., alias='teamId') p8file: str = Field(..., alias='p8File') + nativeenabled: Optional[bool] = Field(default=None, alias='nativeEnabled') + nativeclientids: Optional[List[Any]] = Field(default=None, alias='nativeClientIds') diff --git a/appwrite/models/o_auth2_auth0.py b/appwrite/models/o_auth2_auth0.py index d3d95e2f..776341f7 100644 --- a/appwrite/models/o_auth2_auth0.py +++ b/appwrite/models/o_auth2_auth0.py @@ -2,6 +2,7 @@ from pydantic import Field, PrivateAttr from .base_model import AppwriteModel +from ..enums.o_auth2_auth0_prompt import OAuth2Auth0Prompt class OAuth2Auth0(AppwriteModel): @@ -18,6 +19,8 @@ class OAuth2Auth0(AppwriteModel): Auth0 OAuth2 client ID. clientsecret : str Auth0 OAuth2 client secret. + prompt : Optional[List[OAuth2Auth0Prompt]] + Auth0 OAuth2 prompt values. endpoint : str Auth0 OAuth2 endpoint domain. """ @@ -26,4 +29,5 @@ class OAuth2Auth0(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + prompt: Optional[List[OAuth2Auth0Prompt]] = Field(default=None, alias='prompt') endpoint: str = Field(..., alias='endpoint') diff --git a/appwrite/models/o_auth2_discord.py b/appwrite/models/o_auth2_discord.py index 8516e192..d3f068cb 100644 --- a/appwrite/models/o_auth2_discord.py +++ b/appwrite/models/o_auth2_discord.py @@ -2,6 +2,7 @@ from pydantic import Field, PrivateAttr from .base_model import AppwriteModel +from ..enums.o_auth2_discord_prompt import OAuth2DiscordPrompt class OAuth2Discord(AppwriteModel): @@ -18,9 +19,12 @@ class OAuth2Discord(AppwriteModel): Discord OAuth2 client ID. clientsecret : str Discord OAuth2 client secret. + prompt : Optional[List[OAuth2DiscordPrompt]] + Discord OAuth2 prompt values. """ id: str = Field(..., alias='$id') enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + prompt: Optional[List[OAuth2DiscordPrompt]] = Field(default=None, alias='prompt') diff --git a/appwrite/models/o_auth2_github.py b/appwrite/models/o_auth2_github.py index d436fa70..d326ffe2 100644 --- a/appwrite/models/o_auth2_github.py +++ b/appwrite/models/o_auth2_github.py @@ -2,6 +2,7 @@ from pydantic import Field, PrivateAttr from .base_model import AppwriteModel +from ..enums.o_auth2_github_prompt import OAuth2GithubPrompt class OAuth2Github(AppwriteModel): @@ -18,9 +19,12 @@ class OAuth2Github(AppwriteModel): GitHub OAuth2 client ID. For GitHub Apps, use the "App ID" when both an App ID and client ID are available. clientsecret : str GitHub OAuth2 client secret. + prompt : Optional[List[OAuth2GithubPrompt]] + GitHub OAuth2 prompt values. """ id: str = Field(..., alias='$id') enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + prompt: Optional[List[OAuth2GithubPrompt]] = Field(default=None, alias='prompt') diff --git a/appwrite/models/o_auth2_google.py b/appwrite/models/o_auth2_google.py index 7d815ef2..2bfd961c 100644 --- a/appwrite/models/o_auth2_google.py +++ b/appwrite/models/o_auth2_google.py @@ -21,6 +21,10 @@ class OAuth2Google(AppwriteModel): Google OAuth2 client secret. prompt : List[OAuth2GooglePrompt] Google OAuth2 prompt values. + nativeenabled : Optional[bool] + Native Google sign-in is active and can be used to create sessions from an ID token. Independent of enabled, which only controls the browser-based flow. + nativeclientids : Optional[List[Any]] + Additional OAuth2 client IDs accepted as ID token audiences for native sign-in, next to the client ID. """ id: str = Field(..., alias='$id') @@ -28,3 +32,5 @@ class OAuth2Google(AppwriteModel): clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') prompt: List[OAuth2GooglePrompt] = Field(..., alias='prompt') + nativeenabled: Optional[bool] = Field(default=None, alias='nativeEnabled') + nativeclientids: Optional[List[Any]] = Field(default=None, alias='nativeClientIds') diff --git a/appwrite/models/o_auth2_kakao.py b/appwrite/models/o_auth2_kakao.py new file mode 100644 index 00000000..4918af5c --- /dev/null +++ b/appwrite/models/o_auth2_kakao.py @@ -0,0 +1,30 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel +from ..enums.o_auth2_kakao_prompt import OAuth2KakaoPrompt + + +class OAuth2Kakao(AppwriteModel): + """ + OAuth2Kakao + + Attributes + ---------- + id : str + OAuth2 provider ID. + enabled : bool + OAuth2 provider is active and can be used to create sessions. + clientid : str + Kakao OAuth2 REST API key. + clientsecret : str + Kakao OAuth2 client secret. + prompt : List[OAuth2KakaoPrompt] + Kakao OAuth2 prompt values. + """ + + id: str = Field(..., alias='$id') + enabled: bool = Field(..., alias='enabled') + clientid: str = Field(..., alias='clientId') + clientsecret: str = Field(..., alias='clientSecret') + prompt: List[OAuth2KakaoPrompt] = Field(..., alias='prompt') diff --git a/appwrite/models/o_auth2_microsoft.py b/appwrite/models/o_auth2_microsoft.py index 50cbdd56..622a530d 100644 --- a/appwrite/models/o_auth2_microsoft.py +++ b/appwrite/models/o_auth2_microsoft.py @@ -2,6 +2,7 @@ from pydantic import Field, PrivateAttr from .base_model import AppwriteModel +from ..enums.o_auth2_microsoft_prompt import OAuth2MicrosoftPrompt class OAuth2Microsoft(AppwriteModel): @@ -18,6 +19,8 @@ class OAuth2Microsoft(AppwriteModel): Microsoft OAuth2 application ID. applicationsecret : str Microsoft OAuth2 application secret. + prompt : Optional[List[OAuth2MicrosoftPrompt]] + Microsoft OAuth2 prompt values. tenant : str Microsoft Entra ID tenant identifier. Use 'common', 'organizations', 'consumers' or a specific tenant ID. """ @@ -26,4 +29,5 @@ class OAuth2Microsoft(AppwriteModel): enabled: bool = Field(..., alias='enabled') applicationid: str = Field(..., alias='applicationId') applicationsecret: str = Field(..., alias='applicationSecret') + prompt: Optional[List[OAuth2MicrosoftPrompt]] = Field(default=None, alias='prompt') tenant: str = Field(..., alias='tenant') diff --git a/appwrite/models/o_auth2_okta.py b/appwrite/models/o_auth2_okta.py index 4ecdd0b5..e64c6af1 100644 --- a/appwrite/models/o_auth2_okta.py +++ b/appwrite/models/o_auth2_okta.py @@ -2,6 +2,7 @@ from pydantic import Field, PrivateAttr from .base_model import AppwriteModel +from ..enums.o_auth2_okta_prompt import OAuth2OktaPrompt class OAuth2Okta(AppwriteModel): @@ -18,6 +19,8 @@ class OAuth2Okta(AppwriteModel): Okta OAuth2 client ID. clientsecret : str Okta OAuth2 client secret. + prompt : Optional[List[OAuth2OktaPrompt]] + Okta OAuth2 prompt values. domain : str Okta OAuth2 domain. authorizationserverid : str @@ -28,5 +31,6 @@ class OAuth2Okta(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + prompt: Optional[List[OAuth2OktaPrompt]] = Field(default=None, alias='prompt') domain: str = Field(..., alias='domain') authorizationserverid: str = Field(..., alias='authorizationServerId') diff --git a/appwrite/models/o_auth2_provider_list.py b/appwrite/models/o_auth2_provider_list.py index 09e97009..eaf62fb9 100644 --- a/appwrite/models/o_auth2_provider_list.py +++ b/appwrite/models/o_auth2_provider_list.py @@ -17,6 +17,7 @@ from .o_auth2_yandex import OAuth2Yandex from .o_auth2_x import OAuth2X from .o_auth2_word_press import OAuth2WordPress +from .o_auth2_webflow import OAuth2Webflow from .o_auth2_twitch import OAuth2Twitch from .o_auth2_stripe import OAuth2Stripe from .o_auth2_spotify import OAuth2Spotify @@ -46,6 +47,8 @@ from .o_auth2_hugging_face import OAuth2HuggingFace from .o_auth2_resend import OAuth2Resend from .o_auth2_cloudflare import OAuth2Cloudflare +from .o_auth2_tik_tok import OAuth2TikTok +from .o_auth2_kakao import OAuth2Kakao class OAuth2ProviderList(AppwriteModel): @@ -56,7 +59,7 @@ class OAuth2ProviderList(AppwriteModel): ---------- total : float Total number of OAuth2 providers in the given project. - providers : List[Union[OAuth2Github, OAuth2Discord, OAuth2Figma, OAuth2Dropbox, OAuth2Dailymotion, OAuth2Bitbucket, OAuth2Bitly, OAuth2Box, OAuth2Autodesk, OAuth2Google, OAuth2Zoom, OAuth2Zoho, OAuth2Yandex, OAuth2X, OAuth2WordPress, OAuth2Twitch, OAuth2Stripe, OAuth2Spotify, OAuth2Slack, OAuth2Podio, OAuth2Notion, OAuth2Salesforce, OAuth2Yahoo, OAuth2Linkedin, OAuth2Disqus, OAuth2Amazon, OAuth2Etsy, OAuth2Facebook, OAuth2Tradeshift, OAuth2Paypal, OAuth2Gitlab, OAuth2Appwrite, OAuth2Authentik, OAuth2Auth0, OAuth2FusionAuth, OAuth2Keycloak, OAuth2Oidc, OAuth2Apple, OAuth2Okta, OAuth2Kick, OAuth2Microsoft, OAuth2HuggingFace, OAuth2Resend, OAuth2Cloudflare]] + providers : List[Union[OAuth2Github, OAuth2Discord, OAuth2Figma, OAuth2Dropbox, OAuth2Dailymotion, OAuth2Bitbucket, OAuth2Bitly, OAuth2Box, OAuth2Autodesk, OAuth2Google, OAuth2Zoom, OAuth2Zoho, OAuth2Yandex, OAuth2X, OAuth2WordPress, OAuth2Webflow, OAuth2Twitch, OAuth2Stripe, OAuth2Spotify, OAuth2Slack, OAuth2Podio, OAuth2Notion, OAuth2Salesforce, OAuth2Yahoo, OAuth2Linkedin, OAuth2Disqus, OAuth2Amazon, OAuth2Etsy, OAuth2Facebook, OAuth2Tradeshift, OAuth2Paypal, OAuth2Gitlab, OAuth2Appwrite, OAuth2Authentik, OAuth2Auth0, OAuth2FusionAuth, OAuth2Keycloak, OAuth2Oidc, OAuth2Apple, OAuth2Okta, OAuth2Kick, OAuth2Microsoft, OAuth2HuggingFace, OAuth2Resend, OAuth2Cloudflare, OAuth2TikTok, OAuth2Kakao]] List of OAuth2 providers. """ @@ -78,6 +81,7 @@ class OAuth2ProviderList(AppwriteModel): OAuth2Yandex, OAuth2X, OAuth2WordPress, + OAuth2Webflow, OAuth2Twitch, OAuth2Stripe, OAuth2Spotify, @@ -107,5 +111,7 @@ class OAuth2ProviderList(AppwriteModel): OAuth2HuggingFace, OAuth2Resend, OAuth2Cloudflare, + OAuth2TikTok, + OAuth2Kakao, ] ] = Field(..., alias='providers') diff --git a/appwrite/models/o_auth2_salesforce.py b/appwrite/models/o_auth2_salesforce.py index e1170360..579fb837 100644 --- a/appwrite/models/o_auth2_salesforce.py +++ b/appwrite/models/o_auth2_salesforce.py @@ -2,6 +2,7 @@ from pydantic import Field, PrivateAttr from .base_model import AppwriteModel +from ..enums.o_auth2_salesforce_prompt import OAuth2SalesforcePrompt class OAuth2Salesforce(AppwriteModel): @@ -18,9 +19,12 @@ class OAuth2Salesforce(AppwriteModel): Salesforce OAuth2 consumer key. customersecret : str Salesforce OAuth2 consumer secret. + prompt : Optional[List[OAuth2SalesforcePrompt]] + Salesforce OAuth2 prompt values. """ id: str = Field(..., alias='$id') enabled: bool = Field(..., alias='enabled') customerkey: str = Field(..., alias='customerKey') customersecret: str = Field(..., alias='customerSecret') + prompt: Optional[List[OAuth2SalesforcePrompt]] = Field(default=None, alias='prompt') diff --git a/appwrite/models/o_auth2_tik_tok.py b/appwrite/models/o_auth2_tik_tok.py new file mode 100644 index 00000000..f1d08f68 --- /dev/null +++ b/appwrite/models/o_auth2_tik_tok.py @@ -0,0 +1,26 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel + + +class OAuth2TikTok(AppwriteModel): + """ + OAuth2TikTok + + Attributes + ---------- + id : str + OAuth2 provider ID. + enabled : bool + OAuth2 provider is active and can be used to create sessions. + clientid : str + TikTok OAuth2 client key. + clientsecret : str + TikTok OAuth2 client secret. + """ + + id: str = Field(..., alias='$id') + enabled: bool = Field(..., alias='enabled') + clientid: str = Field(..., alias='clientId') + clientsecret: str = Field(..., alias='clientSecret') diff --git a/appwrite/models/o_auth2_webflow.py b/appwrite/models/o_auth2_webflow.py new file mode 100644 index 00000000..bf6891ab --- /dev/null +++ b/appwrite/models/o_auth2_webflow.py @@ -0,0 +1,26 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel + + +class OAuth2Webflow(AppwriteModel): + """ + OAuth2Webflow + + Attributes + ---------- + id : str + OAuth2 provider ID. + enabled : bool + OAuth2 provider is active and can be used to create sessions. + clientid : str + Webflow OAuth2 client ID. + clientsecret : str + Webflow OAuth2 client secret. + """ + + id: str = Field(..., alias='$id') + enabled: bool = Field(..., alias='enabled') + clientid: str = Field(..., alias='clientId') + clientsecret: str = Field(..., alias='clientSecret') diff --git a/appwrite/models/o_auth2_zoho.py b/appwrite/models/o_auth2_zoho.py index 249420f2..f3ceb99c 100644 --- a/appwrite/models/o_auth2_zoho.py +++ b/appwrite/models/o_auth2_zoho.py @@ -2,6 +2,7 @@ from pydantic import Field, PrivateAttr from .base_model import AppwriteModel +from ..enums.o_auth2_zoho_prompt import OAuth2ZohoPrompt class OAuth2Zoho(AppwriteModel): @@ -18,9 +19,12 @@ class OAuth2Zoho(AppwriteModel): Zoho OAuth2 client ID. clientsecret : str Zoho OAuth2 client secret. + prompt : Optional[List[OAuth2ZohoPrompt]] + Zoho OAuth2 prompt values. """ id: str = Field(..., alias='$id') enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + prompt: Optional[List[OAuth2ZohoPrompt]] = Field(default=None, alias='prompt') diff --git a/appwrite/models/oauth2_introspection.py b/appwrite/models/oauth2_introspection.py new file mode 100644 index 00000000..9fa80c5e --- /dev/null +++ b/appwrite/models/oauth2_introspection.py @@ -0,0 +1,50 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel + + +class Oauth2Introspection(AppwriteModel): + """ + OAuth2 Introspection + + Attributes + ---------- + active : bool + Whether the token is currently active. An inactive token carries no other claims (RFC 7662). + token_use : Optional[str] + Kind of token that was introspected. Can be one of: `access_token` or `refresh_token`. + token_type : Optional[str] + OAuth2 token type. + scope : Optional[str] + Space-separated scopes granted to the token. + client_id : Optional[str] + OAuth2 client ID the token was issued to. + sub : Optional[str] + ID of the user who authorized the token. + aud : Optional[List[Any]] + Audiences the token is intended for. The first entry is the project API base URL; any further entries are the resource indicators requested at authorization time (RFC 8707). + iss : Optional[str] + Issuer URL of the token. + exp : Optional[float] + Expiration time as a Unix timestamp in seconds. + iat : Optional[float] + Issued-at time as a Unix timestamp in seconds. + jti : Optional[str] + Unique identifier of the token. + authorization_details : Optional[List[Any]] + Granted RFC 9396 authorization details, restricted to what the user can currently access. + """ + + active: bool = Field(..., alias='active') + token_use: Optional[str] = Field(default=None, alias='token_use') + token_type: Optional[str] = Field(default=None, alias='token_type') + scope: Optional[str] = Field(default=None, alias='scope') + client_id: Optional[str] = Field(default=None, alias='client_id') + sub: Optional[str] = Field(default=None, alias='sub') + aud: Optional[List[Any]] = Field(default=None, alias='aud') + iss: Optional[str] = Field(default=None, alias='iss') + exp: Optional[float] = Field(default=None, alias='exp') + iat: Optional[float] = Field(default=None, alias='iat') + jti: Optional[str] = Field(default=None, alias='jti') + authorization_details: Optional[List[Any]] = Field(default=None, alias='authorization_details') diff --git a/appwrite/models/platform_android.py b/appwrite/models/platform_android.py index ade36f3f..066c215e 100644 --- a/appwrite/models/platform_android.py +++ b/appwrite/models/platform_android.py @@ -23,6 +23,8 @@ class PlatformAndroid(AppwriteModel): Platform type. Possible values are: windows, apple, android, linux, web. applicationid : str Android application ID. + fingerprints : Optional[List[Any]] + SHA-256 fingerprints of the certificates the app is signed with. Passkeys created in the app are accepted when its signature matches one. """ id: str = Field(..., alias='$id') @@ -31,3 +33,4 @@ class PlatformAndroid(AppwriteModel): name: str = Field(..., alias='name') type: PlatformType = Field(..., alias='type') applicationid: str = Field(..., alias='applicationId') + fingerprints: Optional[List[Any]] = Field(default=None, alias='fingerprints') diff --git a/appwrite/models/policy_list.py b/appwrite/models/policy_list.py index beeb5c95..c2938e49 100644 --- a/appwrite/models/policy_list.py +++ b/appwrite/models/policy_list.py @@ -6,6 +6,8 @@ from .policy_password_history import PolicyPasswordHistory from .policy_password_strength import PolicyPasswordStrength from .policy_password_personal_data import PolicyPasswordPersonalData +from .policy_password_pwned import PolicyPasswordPwned +from .policy_password_rotation import PolicyPasswordRotation from .policy_session_alert import PolicySessionAlert from .policy_session_duration import PolicySessionDuration from .policy_session_invalidation import PolicySessionInvalidation @@ -28,7 +30,7 @@ class PolicyList(AppwriteModel): ---------- total : float Total number of policies in the given project. - policies : List[Union[PolicyPasswordDictionary, PolicyPasswordHistory, PolicyPasswordStrength, PolicyPasswordPersonalData, PolicySessionAlert, PolicySessionDuration, PolicySessionInvalidation, PolicySessionLimit, PolicyUserLimit, PolicyMembershipPrivacy, PolicyMfaFactors, PolicyDenyAliasedEmail, PolicyDenyDisposableEmail, PolicyDenyFreeEmail, PolicyDenyCorporateEmail, PolicyPasskey]] + policies : List[Union[PolicyPasswordDictionary, PolicyPasswordHistory, PolicyPasswordStrength, PolicyPasswordPersonalData, PolicyPasswordPwned, PolicyPasswordRotation, PolicySessionAlert, PolicySessionDuration, PolicySessionInvalidation, PolicySessionLimit, PolicyUserLimit, PolicyMembershipPrivacy, PolicyMfaFactors, PolicyDenyAliasedEmail, PolicyDenyDisposableEmail, PolicyDenyFreeEmail, PolicyDenyCorporateEmail, PolicyPasskey]] List of policies. """ @@ -39,6 +41,8 @@ class PolicyList(AppwriteModel): PolicyPasswordHistory, PolicyPasswordStrength, PolicyPasswordPersonalData, + PolicyPasswordPwned, + PolicyPasswordRotation, PolicySessionAlert, PolicySessionDuration, PolicySessionInvalidation, diff --git a/appwrite/models/policy_password_pwned.py b/appwrite/models/policy_password_pwned.py new file mode 100644 index 00000000..90c58d38 --- /dev/null +++ b/appwrite/models/policy_password_pwned.py @@ -0,0 +1,26 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel + + +class PolicyPasswordPwned(AppwriteModel): + """ + Policy Password Pwned + + Attributes + ---------- + id : str + Policy ID. + enabled : bool + Whether passwords are checked against known data breaches and the result recorded on the user. + sessions : bool + Whether a sign-in with a breached password is refused until the password is reset. + users : bool + Whether a breached password is rejected when a user signs up or sets a new password. + """ + + id: str = Field(..., alias='$id') + enabled: bool = Field(..., alias='enabled') + sessions: bool = Field(..., alias='sessions') + users: bool = Field(..., alias='users') diff --git a/appwrite/models/policy_password_rotation.py b/appwrite/models/policy_password_rotation.py new file mode 100644 index 00000000..080071f5 --- /dev/null +++ b/appwrite/models/policy_password_rotation.py @@ -0,0 +1,23 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel + + +class PolicyPasswordRotation(AppwriteModel): + """ + Policy Password Rotation + + Attributes + ---------- + id : str + Policy ID. + enabled : bool + Whether expired passwords require a reset before email/password sign-in. + maxage : float + Maximum password age in seconds. + """ + + id: str = Field(..., alias='$id') + enabled: bool = Field(..., alias='enabled') + maxage: float = Field(..., alias='maxAge') diff --git a/appwrite/models/project.py b/appwrite/models/project.py index 08721a9b..6b12b5ff 100644 --- a/appwrite/models/project.py +++ b/appwrite/models/project.py @@ -72,8 +72,14 @@ class Project(AppwriteModel): Last time the project was accessed via console. Used with plan's projectInactivityDays to determine if project is paused. wafenabled : Optional[bool] Whether WAF enforcement is enabled for the project. + parentid : Optional[str] + ID of the project this environment belongs to. Null when the project is not an environment. billinglimits : Optional[BillingLimits] Billing limits reached + firstaccessedat : Optional[str] + First time the project received a non-console API request. Empty until the project is used. + mcpaccessedat : Optional[str] + Last time the project was accessed through the MCP server. Empty if it was never accessed via MCP. oauth2serverenabled : Optional[bool] OAuth2 server status oauth2serverauthorizationurl : Optional[str] @@ -138,7 +144,10 @@ class Project(AppwriteModel): blocks: List[Block] = Field(..., alias='blocks') consoleaccessedat: str = Field(..., alias='consoleAccessedAt') wafenabled: Optional[bool] = Field(default=None, alias='wafEnabled') + parentid: Optional[str] = Field(default=None, alias='parentId') billinglimits: Optional[BillingLimits] = Field(default=None, alias='billingLimits') + firstaccessedat: Optional[str] = Field(default=None, alias='firstAccessedAt') + mcpaccessedat: Optional[str] = Field(default=None, alias='mcpAccessedAt') oauth2serverenabled: Optional[bool] = Field(default=None, alias='oAuth2ServerEnabled') oauth2serverauthorizationurl: Optional[str] = Field(default=None, alias='oAuth2ServerAuthorizationUrl') oauth2serverscopes: Optional[List[Any]] = Field(default=None, alias='oAuth2ServerScopes') diff --git a/appwrite/models/topic.py b/appwrite/models/topic.py index ee1005b1..2e494183 100644 --- a/appwrite/models/topic.py +++ b/appwrite/models/topic.py @@ -26,6 +26,10 @@ class Topic(AppwriteModel): Total count of push subscribers subscribed to the topic. subscribe : List[Any] Subscribe permissions. + qos : Optional[float] + MQTT QoS for delivery on this topic. Null lets the subscriber choose their level. + expiry : Optional[float] + Message retention in seconds for offline delivery. """ id: str = Field(..., alias='$id') @@ -36,3 +40,5 @@ class Topic(AppwriteModel): smstotal: float = Field(..., alias='smsTotal') pushtotal: float = Field(..., alias='pushTotal') subscribe: List[Any] = Field(..., alias='subscribe') + qos: Optional[float] = Field(default=None, alias='qos') + expiry: Optional[float] = Field(default=None, alias='expiry') diff --git a/appwrite/models/user.py b/appwrite/models/user.py index c3891c04..a10e5efc 100644 --- a/appwrite/models/user.py +++ b/appwrite/models/user.py @@ -59,6 +59,8 @@ class User(AppwriteModel, Generic[T]): Whether the user email is from a corporate domain. emailiscanonical : Optional[bool] Whether the user email is in its canonical form. + passwordpwned : Optional[bool] + Whether the password was found in a known data breach the last time it was checked. Null when the password has never been checked. phoneverification : bool Phone verification status. mfa : bool @@ -104,6 +106,7 @@ class User(AppwriteModel, Generic[T]): emailisdisposable: Optional[bool] = Field(default=None, alias='emailIsDisposable') emailiscorporate: Optional[bool] = Field(default=None, alias='emailIsCorporate') emailiscanonical: Optional[bool] = Field(default=None, alias='emailIsCanonical') + passwordpwned: Optional[bool] = Field(default=None, alias='passwordPwned') phoneverification: bool = Field(..., alias='phoneVerification') mfa: bool = Field(..., alias='mfa') prefs: Preferences[T] = Field(..., alias='prefs') diff --git a/appwrite/models/waf_rule_bypass.py b/appwrite/models/waf_rule_bypass.py new file mode 100644 index 00000000..fe561556 --- /dev/null +++ b/appwrite/models/waf_rule_bypass.py @@ -0,0 +1,57 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel +from ..enums.waf_rule_action import WafRuleAction + + +class WafRuleBypass(AppwriteModel): + """ + WafRuleBypass + + Attributes + ---------- + id : str + Rule ID. + createdat : str + WAF rule creation time in ISO 8601 format. + updatedat : str + WAF rule last update time in ISO 8601 format. + name : str + Human friendly rule name. + description : str + Optional description for the rule. + teamid : str + Team ID. + projectid : str + Project ID. + resourcetype : str + Resource type the rule is scoped to. + resourceid : str + Resource identifier. Empty for API-wide rules. + action : WafRuleAction + Action performed when the rule matches. + priority : float + Evaluation priority. Lower values execute earlier. + enabled : bool + Whether the rule is active. + conditions : List[Any] + List of conditions evaluated for this rule. + config : Dict[str, Any] + Action specific configuration. + """ + + id: str = Field(..., alias='$id') + createdat: str = Field(..., alias='$createdAt') + updatedat: str = Field(..., alias='$updatedAt') + name: str = Field(..., alias='name') + description: str = Field(..., alias='description') + teamid: str = Field(..., alias='teamId') + projectid: str = Field(..., alias='projectId') + resourcetype: str = Field(..., alias='resourceType') + resourceid: str = Field(..., alias='resourceId') + action: WafRuleAction = Field(..., alias='action') + priority: float = Field(..., alias='priority') + enabled: bool = Field(..., alias='enabled') + conditions: List[Any] = Field(..., alias='conditions') + config: Dict[str, Any] = Field(..., alias='config') diff --git a/appwrite/models/waf_rule_challenge.py b/appwrite/models/waf_rule_challenge.py new file mode 100644 index 00000000..45730853 --- /dev/null +++ b/appwrite/models/waf_rule_challenge.py @@ -0,0 +1,66 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel +from ..enums.waf_rule_action import WafRuleAction + + +class WafRuleChallenge(AppwriteModel): + """ + WafRuleChallenge + + Attributes + ---------- + id : str + Rule ID. + createdat : str + WAF rule creation time in ISO 8601 format. + updatedat : str + WAF rule last update time in ISO 8601 format. + name : str + Human friendly rule name. + description : str + Optional description for the rule. + teamid : str + Team ID. + projectid : str + Project ID. + resourcetype : str + Resource type the rule is scoped to. + resourceid : str + Resource identifier. Empty for API-wide rules. + action : WafRuleAction + Action performed when the rule matches. + priority : float + Evaluation priority. Lower values execute earlier. + enabled : bool + Whether the rule is active. + conditions : List[Any] + List of conditions evaluated for this rule. + config : Dict[str, Any] + Action specific configuration. + challengetype : str + Challenge type enforced when the rule matches. + difficulty : float + Challenge difficulty from 1 (easiest) to 5 (hardest) enforced when the rule matches. + ttl : float + Seconds a visitor stays cleared after passing the challenge before being challenged again. + """ + + id: str = Field(..., alias='$id') + createdat: str = Field(..., alias='$createdAt') + updatedat: str = Field(..., alias='$updatedAt') + name: str = Field(..., alias='name') + description: str = Field(..., alias='description') + teamid: str = Field(..., alias='teamId') + projectid: str = Field(..., alias='projectId') + resourcetype: str = Field(..., alias='resourceType') + resourceid: str = Field(..., alias='resourceId') + action: WafRuleAction = Field(..., alias='action') + priority: float = Field(..., alias='priority') + enabled: bool = Field(..., alias='enabled') + conditions: List[Any] = Field(..., alias='conditions') + config: Dict[str, Any] = Field(..., alias='config') + challengetype: str = Field(..., alias='challengeType') + difficulty: float = Field(..., alias='difficulty') + ttl: float = Field(..., alias='ttl') diff --git a/appwrite/models/waf_rule_deny.py b/appwrite/models/waf_rule_deny.py new file mode 100644 index 00000000..1edafc8b --- /dev/null +++ b/appwrite/models/waf_rule_deny.py @@ -0,0 +1,57 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel +from ..enums.waf_rule_action import WafRuleAction + + +class WafRuleDeny(AppwriteModel): + """ + WafRuleDeny + + Attributes + ---------- + id : str + Rule ID. + createdat : str + WAF rule creation time in ISO 8601 format. + updatedat : str + WAF rule last update time in ISO 8601 format. + name : str + Human friendly rule name. + description : str + Optional description for the rule. + teamid : str + Team ID. + projectid : str + Project ID. + resourcetype : str + Resource type the rule is scoped to. + resourceid : str + Resource identifier. Empty for API-wide rules. + action : WafRuleAction + Action performed when the rule matches. + priority : float + Evaluation priority. Lower values execute earlier. + enabled : bool + Whether the rule is active. + conditions : List[Any] + List of conditions evaluated for this rule. + config : Dict[str, Any] + Action specific configuration. + """ + + id: str = Field(..., alias='$id') + createdat: str = Field(..., alias='$createdAt') + updatedat: str = Field(..., alias='$updatedAt') + name: str = Field(..., alias='name') + description: str = Field(..., alias='description') + teamid: str = Field(..., alias='teamId') + projectid: str = Field(..., alias='projectId') + resourcetype: str = Field(..., alias='resourceType') + resourceid: str = Field(..., alias='resourceId') + action: WafRuleAction = Field(..., alias='action') + priority: float = Field(..., alias='priority') + enabled: bool = Field(..., alias='enabled') + conditions: List[Any] = Field(..., alias='conditions') + config: Dict[str, Any] = Field(..., alias='config') diff --git a/appwrite/models/waf_rule_list.py b/appwrite/models/waf_rule_list.py new file mode 100644 index 00000000..418a8543 --- /dev/null +++ b/appwrite/models/waf_rule_list.py @@ -0,0 +1,33 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel +from .waf_rule_bypass import WafRuleBypass +from .waf_rule_deny import WafRuleDeny +from .waf_rule_challenge import WafRuleChallenge +from .waf_rule_rate_limit import WafRuleRateLimit +from .waf_rule_redirect import WafRuleRedirect + + +class WafRuleList(AppwriteModel): + """ + WAF rule list + + Attributes + ---------- + total : float + Total number of rules that matched your query. + rules : List[Union[WafRuleBypass, WafRuleDeny, WafRuleChallenge, WafRuleRateLimit, WafRuleRedirect]] + List of rules. + """ + + total: float = Field(..., alias='total') + rules: List[ + Union[ + WafRuleBypass, + WafRuleDeny, + WafRuleChallenge, + WafRuleRateLimit, + WafRuleRedirect, + ] + ] = Field(..., alias='rules') diff --git a/appwrite/models/waf_rule_rate_limit.py b/appwrite/models/waf_rule_rate_limit.py new file mode 100644 index 00000000..c05cc13c --- /dev/null +++ b/appwrite/models/waf_rule_rate_limit.py @@ -0,0 +1,72 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel +from ..enums.waf_rule_action import WafRuleAction + + +class WafRuleRateLimit(AppwriteModel): + """ + WafRuleRateLimit + + Attributes + ---------- + id : str + Rule ID. + createdat : str + WAF rule creation time in ISO 8601 format. + updatedat : str + WAF rule last update time in ISO 8601 format. + name : str + Human friendly rule name. + description : str + Optional description for the rule. + teamid : str + Team ID. + projectid : str + Project ID. + resourcetype : str + Resource type the rule is scoped to. + resourceid : str + Resource identifier. Empty for API-wide rules. + action : WafRuleAction + Action performed when the rule matches. + priority : float + Evaluation priority. Lower values execute earlier. + enabled : bool + Whether the rule is active. + conditions : List[Any] + List of conditions evaluated for this rule. + config : Dict[str, Any] + Action specific configuration. + limit : float + Maximum number of matching requests allowed for the given interval. + interval : float + Interval in seconds for the rate limit window. + key : str + Rate limit key: `ip` limits per client IP, `userId` limits per authenticated user. + strategy : str + Rate limit strategy: `fixedWindow`, `slidingWindow`, or `tokenBucket`. + maxbucketsize : float + Maximum burst capacity in tokens, applied by the `tokenBucket` strategy. The sustained refill rate is `limit / interval`. Defaults to `limit`. + """ + + id: str = Field(..., alias='$id') + createdat: str = Field(..., alias='$createdAt') + updatedat: str = Field(..., alias='$updatedAt') + name: str = Field(..., alias='name') + description: str = Field(..., alias='description') + teamid: str = Field(..., alias='teamId') + projectid: str = Field(..., alias='projectId') + resourcetype: str = Field(..., alias='resourceType') + resourceid: str = Field(..., alias='resourceId') + action: WafRuleAction = Field(..., alias='action') + priority: float = Field(..., alias='priority') + enabled: bool = Field(..., alias='enabled') + conditions: List[Any] = Field(..., alias='conditions') + config: Dict[str, Any] = Field(..., alias='config') + limit: float = Field(..., alias='limit') + interval: float = Field(..., alias='interval') + key: str = Field(..., alias='key') + strategy: str = Field(..., alias='strategy') + maxbucketsize: float = Field(..., alias='maxBucketSize') diff --git a/appwrite/models/waf_rule_redirect.py b/appwrite/models/waf_rule_redirect.py new file mode 100644 index 00000000..aba9ffa3 --- /dev/null +++ b/appwrite/models/waf_rule_redirect.py @@ -0,0 +1,63 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel +from ..enums.waf_rule_action import WafRuleAction + + +class WafRuleRedirect(AppwriteModel): + """ + WafRuleRedirect + + Attributes + ---------- + id : str + Rule ID. + createdat : str + WAF rule creation time in ISO 8601 format. + updatedat : str + WAF rule last update time in ISO 8601 format. + name : str + Human friendly rule name. + description : str + Optional description for the rule. + teamid : str + Team ID. + projectid : str + Project ID. + resourcetype : str + Resource type the rule is scoped to. + resourceid : str + Resource identifier. Empty for API-wide rules. + action : WafRuleAction + Action performed when the rule matches. + priority : float + Evaluation priority. Lower values execute earlier. + enabled : bool + Whether the rule is active. + conditions : List[Any] + List of conditions evaluated for this rule. + config : Dict[str, Any] + Action specific configuration. + location : str + Target location for the redirect. + statuscode : float + HTTP status code used for the redirect. + """ + + id: str = Field(..., alias='$id') + createdat: str = Field(..., alias='$createdAt') + updatedat: str = Field(..., alias='$updatedAt') + name: str = Field(..., alias='name') + description: str = Field(..., alias='description') + teamid: str = Field(..., alias='teamId') + projectid: str = Field(..., alias='projectId') + resourcetype: str = Field(..., alias='resourceType') + resourceid: str = Field(..., alias='resourceId') + action: WafRuleAction = Field(..., alias='action') + priority: float = Field(..., alias='priority') + enabled: bool = Field(..., alias='enabled') + conditions: List[Any] = Field(..., alias='conditions') + config: Dict[str, Any] = Field(..., alias='config') + location: str = Field(..., alias='location') + statuscode: float = Field(..., alias='statusCode') diff --git a/appwrite/services/account.py b/appwrite/services/account.py index 65200537..efacbb40 100644 --- a/appwrite/services/account.py +++ b/appwrite/services/account.py @@ -23,6 +23,7 @@ from ..models.preferences import Preferences from ..models.token import Token from ..models.session_list import SessionList +from ..enums.id_token_provider import IdTokenProvider from ..enums.o_auth_provider import OAuthProvider from ..models.token_secret import TokenSecret @@ -1568,11 +1569,118 @@ def update_recovery( return self._parse_response(response, model=Token) + def create_recovery_otp( + self, + email: str, + phrase: Optional[bool] = None, + ) -> Token: + """ + Use this endpoint to send a 6-digit password recovery code to the user's email address. Unlike [createRecovery](https://appwrite.io/docs/references/cloud/client-web/account#createRecovery), this method requires no redirect URL, which makes it suitable for mobile and desktop apps that cannot host a recovery page. Learn more about how to [complete the recovery process](https://appwrite.io/docs/references/cloud/client-web/account#updateRecoveryOTP). The code sent to the user's email address is valid for 15 minutes. + + Enable the **phrase** parameter to include a randomly generated security phrase in both the email and the response. Showing that phrase in your app lets the user confirm the email genuinely came from your request, which helps protect against phishing. + + Parameters + ---------- + email : str + User email. + phrase : Optional[bool] + Toggle for security phrase. If enabled, email will be sent with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow. + Returns + ------- + Token + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/account/recovery/otp' + api_params = {} + if email is None: + raise AppwriteException('Missing required parameter: "email"') + api_params['email'] = self._normalize_value(email) + if phrase is not None: + api_params['phrase'] = self._normalize_value(phrase) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=Token) + + def update_recovery_otp( + self, + user_id: str, + secret: str, + password: str, + ) -> Token: + """ + Use this endpoint to complete the user password recovery process using the 6-digit code that was emailed by [createRecoveryOTP](https://appwrite.io/docs/references/cloud/client-web/account#createRecoveryOTP). Pass the **userId** of the user along with the **secret** code from the email and the new **password** to set. If confirmed, this route will return a 200 status code, the code is consumed and the user's password is updated. + + Parameters + ---------- + user_id : str + User ID. + secret : str + Valid recovery OTP code. + password : str + New user password. Must be between 8 and 256 chars. + Returns + ------- + Token + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/account/recovery/otp' + api_params = {} + if user_id is None: + raise AppwriteException('Missing required parameter: "user_id"') + if secret is None: + raise AppwriteException('Missing required parameter: "secret"') + if password is None: + raise AppwriteException('Missing required parameter: "password"') + api_params['userId'] = self._normalize_value(user_id) + api_params['secret'] = self._normalize_value(secret) + api_params['password'] = self._normalize_value(password) + + response = self.client.call( + 'put', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=Token) + def list_sessions( self, + total: Optional[bool] = None, ) -> SessionList: """ Get the list of active sessions across different devices for the currently logged in user. + + Parameters + ---------- + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. Returns ------- SessionList @@ -1586,6 +1694,8 @@ def list_sessions( api_path = '/account/sessions' api_params = {} + if total is not None: + api_params['total'] = self._normalize_value(total) response = self.client.call( 'get', @@ -1601,9 +1711,15 @@ def list_sessions( def delete_sessions( self, + current: Optional[bool] = None, ) -> Dict[str, Any]: """ - Delete all sessions from the user account and remove any sessions cookies from the end client. + Delete all sessions from the user account and remove any sessions cookies from the end client. Pass `current` as false to keep the session making the request and sign out of every other session. + + Parameters + ---------- + current : Optional[bool] + Delete the current session too. Use false to sign out of every other session while staying signed in on this one. Returns ------- Dict[str, Any] @@ -1617,6 +1733,8 @@ def delete_sessions( api_path = '/account/sessions' api_params = {} + if current is not None: + api_params['current'] = self._normalize_value(current) response = self.client.call( 'delete', @@ -1666,6 +1784,7 @@ def create_email_password_session( self, email: str, password: str, + duration: Optional[float] = None, ) -> Session: """ Allow the user to login into their account by providing a valid email and password combination. This route will create a new session for the user. @@ -1678,6 +1797,8 @@ def create_email_password_session( User email. password : str User password. Must be at least 8 chars. + duration : Optional[float] + Session length in seconds. Minimum is 60 seconds, and it cannot exceed the project maximum session length. Defaults to the project maximum session length. Returns ------- Session @@ -1697,6 +1818,85 @@ def create_email_password_session( raise AppwriteException('Missing required parameter: "password"') api_params['email'] = self._normalize_value(email) api_params['password'] = self._normalize_value(password) + if duration is not None: + api_params['duration'] = self._normalize_value(duration) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=Session) + + def create_id_token_session( + self, + provider: IdTokenProvider, + id_token: str, + nonce: Optional[str] = None, + access_token: Optional[str] = None, + access_token_expiry: Optional[float] = None, + name: Optional[str] = None, + ) -> Session: + """ + Allow the user to login to their account using an OpenID Connect ID token obtained natively from the OAuth2 provider, for example via Google Credential Manager on Android or Sign in with Apple on iOS. No browser or redirect is involved: the ID token is verified against the provider's published signing keys and a session is created in a single request. + + Native sign-in is switched on per provider with its nativeEnabled setting. It is independent of the browser-based flow's enabled setting, which has no effect on this endpoint. The token's audience must match the provider's configured client ID or one of its native client IDs; tokens issued for any other client ID are rejected. For Sign in with Apple, register your app's bundle ID as a native client ID. For Google, the web client ID used by Credential Manager is usually the configured client ID; add your Android and iOS client IDs as native client IDs if your app requests tokens for them. + + Pass the raw nonce used when requesting the ID token so it can be validated against the token's nonce claim. When signing in with Apple, the nonce is required: hash it with SHA-256 before passing it to the Apple SDK, and send the raw value here - Apple tokens requested without a nonce are rejected. For Google the nonce is optional: it is validated whenever the token carries one, and ignored when the provider issued the token without one. Apple only returns the user's name on the first authorization, and never inside the ID token - capture it on the client and pass it via the name parameter. + + If there is already an active session, the new session will be attached to the logged-in account. If there are no active sessions, the server will attempt to look for a user with the same email address as the verified email received from the provider and attach the new session to the existing user. If no matching user is found - the server will create a new user. + + This flow does not return provider refresh tokens. You may pass an access token the provider handed your client, along with its lifetime, to store it on the session - but Appwrite cannot renew it once it expires. If your app needs long-lived access to provider APIs, use the browser-based OAuth2 flow instead. + + A user is limited to 10 active sessions at a time by default. [Learn more about session limits](https://appwrite.io/docs/authentication-security#limits). + + Parameters + ---------- + provider : IdTokenProvider + OAuth2 provider that issued the ID token. Currently, supported providers are: apple, google. + id_token : str + OpenID Connect ID token (JWT) obtained natively from the provider, for example via Google Credential Manager or Sign in with Apple. + nonce : Optional[str] + Raw nonce used when requesting the ID token. Required for Apple, and whenever the token carries a nonce claim, which must match it. Ignored when the provider issued the token without a nonce. + access_token : Optional[str] + Provider access token to store alongside the session for calling provider APIs. Never used for authentication. + access_token_expiry : Optional[float] + Seconds until the provider access token expires, as reported by the provider. Stored so clients can tell when the stored token goes stale. + name : Optional[str] + User name. Only used when creating a new user and the ID token has no name claim, such as on the first Sign in with Apple authorization. + Returns + ------- + Session + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/account/sessions/id-token' + api_params = {} + if provider is None: + raise AppwriteException('Missing required parameter: "provider"') + if id_token is None: + raise AppwriteException('Missing required parameter: "id_token"') + api_params['provider'] = self._normalize_value(provider) + api_params['idToken'] = self._normalize_value(id_token) + if nonce is not None: + api_params['nonce'] = self._normalize_value(nonce) + if access_token is not None: + api_params['accessToken'] = self._normalize_value(access_token) + if access_token_expiry is not None: + api_params['accessTokenExpiry'] = self._normalize_value(access_token_expiry) + if name is not None: + api_params['name'] = self._normalize_value(name) response = self.client.call( 'post', @@ -2510,6 +2710,95 @@ def update_verification( return self._parse_response(response, model=Token) + def create_email_verification_otp( + self, + phrase: Optional[bool] = None, + ) -> Token: + """ + Use this endpoint to send a 6-digit verification code to the currently logged in user's email address. Unlike [createEmailVerification](https://appwrite.io/docs/references/cloud/client-web/account#createEmailVerification), this method requires no redirect URL, which makes it suitable for mobile and desktop apps that cannot host a verification page. Learn more about how to [complete the verification process](https://appwrite.io/docs/references/cloud/client-web/account#updateEmailVerificationOTP). The code sent to the user's email address is valid for 15 minutes. + + Enable the **phrase** parameter to include a randomly generated security phrase in both the email and the response. Showing that phrase in your app lets the user confirm the email genuinely came from your request, which helps protect against phishing. + + Parameters + ---------- + phrase : Optional[bool] + Toggle for security phrase. If enabled, email will be sent with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow. + Returns + ------- + Token + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/account/verifications/email/otp' + api_params = {} + if phrase is not None: + api_params['phrase'] = self._normalize_value(phrase) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=Token) + + def update_email_verification_otp( + self, + user_id: str, + secret: str, + ) -> Token: + """ + Use this endpoint to complete the user email verification process using the 6-digit code that was emailed by [createEmailVerificationOTP](https://appwrite.io/docs/references/cloud/client-web/account#createEmailVerificationOTP). Pass the **userId** of the user being verified along with the **secret** code from the email. If confirmed, this route will return a 200 status code and the code is consumed. + + Parameters + ---------- + user_id : str + User ID. + secret : str + Valid verification OTP code. + Returns + ------- + Token + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/account/verifications/email/otp' + api_params = {} + if user_id is None: + raise AppwriteException('Missing required parameter: "user_id"') + if secret is None: + raise AppwriteException('Missing required parameter: "secret"') + api_params['userId'] = self._normalize_value(user_id) + api_params['secret'] = self._normalize_value(secret) + + response = self.client.call( + 'put', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=Token) + def create_phone_verification( self, ) -> Token: diff --git a/appwrite/services/avatars.py b/appwrite/services/avatars.py index 27d11785..4e735b86 100644 --- a/appwrite/services/avatars.py +++ b/appwrite/services/avatars.py @@ -1,16 +1,20 @@ from ..service import Service from urllib.parse import quote -from typing import Any, Dict, List, Optional, Union +from typing import Any, Dict, List, Optional, Union, Type, TypeVar from ..exception import AppwriteException from appwrite.utils.deprecated import deprecated from ..enums.browser import Browser from ..enums.credit_card import CreditCard from ..enums.flag import Flag +from ..input_file import InputFile +from ..models.account import Account from ..enums.browser_theme import BrowserTheme from ..enums.timezone import Timezone from ..enums.browser_permission import BrowserPermission from ..enums.image_format import ImageFormat +T = TypeVar('T') + class Avatars(Service): @@ -418,6 +422,94 @@ def get_photo( return response + def update_photo( + self, + file: InputFile, + on_progress=None, + model_type: Type[T] = dict, + ) -> Account[T]: + """ + Update the profile photo of the currently authenticated user. The uploaded image takes priority over every other photo source, including OAuth2 identity photos, Gravatar, and Libravatar. Updating an already customized photo replaces it. The image must be at most 5MB and is sent in a single request. + + Parameters + ---------- + file : InputFile + Binary image file of at most 5MB. Allowed file types are png, jpg, jpeg, and webp. + on_progress : callable, optional + Optional callback for upload progress + + model_type : Type[T], optional + Pydantic model class for the user-defined data. Defaults to dict for backward compatibility. + + Returns + ------- + Account[T] + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/avatars/photo' + api_params = {} + if file is None: + raise AppwriteException('Missing required parameter: "file"') + api_params['file'] = self._normalize_value(file) + + param_name = 'file' + + upload_id = '' + + response = self.client.chunked_upload( + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'multipart/form-data', + 'accept': 'application/json', + }, + api_params, + param_name, + on_progress, + upload_id, + method='put', + ) + + return Account.with_data(response, model_type) + + def delete_photo( + self, + ) -> Dict[str, Any]: + """ + Delete the profile photo of the currently authenticated user and store the built-in static placeholder in its place. The placeholder is the user's photo from then on, so it takes priority over every other photo source — OAuth2 identity photos, Gravatar, Libravatar, and initials — until a new photo is uploaded with avatars.updatePhoto. + Returns + ------- + Dict[str, Any] + API response as a dictionary + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/avatars/photo' + api_params = {} + + response = self.client.call( + 'delete', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return response + def get_qr( self, text: str, diff --git a/appwrite/services/databases.py b/appwrite/services/databases.py index dde65c10..83e13410 100644 --- a/appwrite/services/databases.py +++ b/appwrite/services/databases.py @@ -156,6 +156,7 @@ def create( def list_transactions( self, queries: Optional[List[str]] = None, + total: Optional[bool] = None, ) -> TransactionList: """ List transactions across all databases. @@ -166,6 +167,8 @@ def list_transactions( ---------- queries : Optional[List[str]] Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. Returns ------- TransactionList @@ -181,6 +184,8 @@ def list_transactions( api_params = {} if queries is not None: api_params['queries'] = self._normalize_value(queries) + if total is not None: + api_params['total'] = self._normalize_value(total) response = self.client.call( 'get', diff --git a/appwrite/services/documents_db.py b/appwrite/services/documents_db.py index d11632b2..c242c0fb 100644 --- a/appwrite/services/documents_db.py +++ b/appwrite/services/documents_db.py @@ -174,6 +174,7 @@ def list_specifications( def list_transactions( self, queries: Optional[List[str]] = None, + total: Optional[bool] = None, ) -> TransactionList: """ List transactions across all databases. @@ -182,6 +183,8 @@ def list_transactions( ---------- queries : Optional[List[str]] Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. Returns ------- TransactionList @@ -197,6 +200,8 @@ def list_transactions( api_params = {} if queries is not None: api_params['queries'] = self._normalize_value(queries) + if total is not None: + api_params['total'] = self._normalize_value(total) response = self.client.call( 'get', diff --git a/appwrite/services/domains.py b/appwrite/services/domains.py new file mode 100644 index 00000000..6ca12b76 --- /dev/null +++ b/appwrite/services/domains.py @@ -0,0 +1,2638 @@ +from ..service import Service +from urllib.parse import quote +from typing import Any, Dict, List, Optional, Union +from ..exception import AppwriteException +from appwrite.utils.deprecated import deprecated +from ..models.domains_list import DomainsList +from ..models.domain import Domain +from ..enums.domain_registration_type import DomainRegistrationType +from ..models.domain_price import DomainPrice +from ..models.domain_prices_list import DomainPricesList +from ..models.dns_records_list import DnsRecordsList +from ..models.dns_record import DnsRecord +from ..models.domain_transfer_status import DomainTransferStatus + + +class Domains(Service): + + def __init__(self, client) -> None: + super(Domains, self).__init__(client) + + def list( + self, + queries: Optional[List[str]] = None, + search: Optional[str] = None, + ) -> DomainsList: + """ + List all domains registered for this project. This endpoint supports pagination. + + Parameters + ---------- + queries : Optional[List[str]] + Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on attributes such as domain name, teamInternalId, expiration, etc. + search : Optional[str] + Search term to filter your list results. Max length: 256 chars. + Returns + ------- + DomainsList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains' + api_params = {} + if queries is not None: + api_params['queries'] = self._normalize_value(queries) + if search is not None: + api_params['search'] = self._normalize_value(search) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DomainsList) + + def create( + self, + team_id: str, + domain: str, + ) -> Domain: + """ + Create a new domain. Before creating a domain, you need to ensure that your DNS provider is properly configured. After creating the domain, you can use the verification endpoint to check if the domain is ready to be used. + + Parameters + ---------- + team_id : str + Team unique ID. + domain : str + Domain name (e.g. "example.com"). + Returns + ------- + Domain + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains' + api_params = {} + if team_id is None: + raise AppwriteException('Missing required parameter: "team_id"') + if domain is None: + raise AppwriteException('Missing required parameter: "domain"') + api_params['teamId'] = self._normalize_value(team_id) + api_params['domain'] = self._normalize_value(domain) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=Domain) + + @deprecated("This API has been deprecated since 2.0.0. Please use `domains.list_prices` instead.") + def get_price( + self, + domain: str, + period_years: Optional[float] = None, + registration_type: Optional[DomainRegistrationType] = None, + ) -> DomainPrice: + """ + Get the registration price for a domain name. + + .. deprecated::2.0.0 + This API has been deprecated since 2.0.0. Please use `domains.list_prices` instead. + Parameters + ---------- + domain : str + Domain name to get price for. + period_years : Optional[float] + Number of years to calculate the domain price for. Must be at least 1. + registration_type : Optional[DomainRegistrationType] + Type of registration pricing to fetch. Allowed values: new, transfer, renewal, trade. + Returns + ------- + DomainPrice + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/price' + api_params = {} + if domain is None: + raise AppwriteException('Missing required parameter: "domain"') + api_params['domain'] = self._normalize_value(domain) + if period_years is not None: + api_params['periodYears'] = self._normalize_value(period_years) + if registration_type is not None: + api_params['registrationType'] = self._normalize_value(registration_type) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DomainPrice) + + def list_prices( + self, + domains: List[str], + period_years: Optional[float] = None, + registration_type: Optional[DomainRegistrationType] = None, + ) -> DomainPricesList: + """ + Check availability and get the requested registration price for one or more domain names. Availability is resolved for all domains in a single registrar lookup. Unavailable domains have a null price for new registrations, but can still be priced for renewal, transfer, or trade. Every priced domain also carries its renewal price for the same period, so a separate renewal lookup is not needed. A domain whose price could not be resolved, for example because its TLD is not supported, is returned with a null price. + + Parameters + ---------- + domains : List[str] + Domain names to check availability and price for. Maximum of 50 domains per request. + period_years : Optional[float] + Number of years to calculate the domain price for. Must be at least 1. + registration_type : Optional[DomainRegistrationType] + Type of registration pricing to fetch. Allowed values: new, transfer, renewal, trade. + Returns + ------- + DomainPricesList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/prices' + api_params = {} + if domains is None: + raise AppwriteException('Missing required parameter: "domains"') + api_params['domains'] = self._normalize_value(domains) + if period_years is not None: + api_params['periodYears'] = self._normalize_value(period_years) + if registration_type is not None: + api_params['registrationType'] = self._normalize_value(registration_type) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DomainPricesList) + + def get( + self, + domain_id: str, + ) -> Domain: + """ + Get a domain by its unique ID. + + Parameters + ---------- + domain_id : str + Domain unique ID. + Returns + ------- + Domain + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=Domain) + + def delete( + self, + domain_id: str, + ) -> Dict[str, Any]: + """ + Delete a domain by its unique ID. This endpoint can be used to delete a domain from your project. + Once deleted, the domain will no longer be available for use and all associated resources will be removed. + + Parameters + ---------- + domain_id : str + Domain unique ID. + Returns + ------- + Dict[str, Any] + API response as a dictionary + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + + response = self.client.call( + 'delete', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return response + + def update_nameservers( + self, + domain_id: str, + nameservers: Optional[List[str]] = None, + ) -> Domain: + """ + Update the registrar nameservers for the given domain. When nameservers are not provided, + the domain will be updated to use Appwrite nameservers. + + Parameters + ---------- + domain_id : str + Domain unique ID. + nameservers : Optional[List[str]] + Nameservers to set for the domain. Defaults to Appwrite nameservers when omitted. + Returns + ------- + Domain + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/nameservers' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + if nameservers is not None: + api_params['nameservers'] = self._normalize_value(nameservers) + + response = self.client.call( + 'patch', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=Domain) + + def verify_nameservers( + self, + domain_id: str, + ) -> Domain: + """ + Verify which NS records are used and update the domain accordingly. This will check the domain's + nameservers and update the domain's status based on whether the nameservers match the expected + Appwrite nameservers. + + Parameters + ---------- + domain_id : str + Domain unique ID. + Returns + ------- + Domain + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/nameservers/verification' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + + response = self.client.call( + 'patch', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=Domain) + + def get_preset_google_workspace( + self, + domain_id: str, + ) -> DnsRecordsList: + """ + List Google Workspace DNS records. + + Parameters + ---------- + domain_id : str + Domain unique ID. + Returns + ------- + DnsRecordsList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/presets/google-workspace' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecordsList) + + def create_preset_google_workspace( + self, + domain_id: str, + ) -> DnsRecordsList: + """ + Add Google Workspace DNS records to the domain. This will create the required MX records + for Google Workspace email hosting. + + Parameters + ---------- + domain_id : str + Domain unique ID. + Returns + ------- + DnsRecordsList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/presets/google-workspace' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecordsList) + + def get_preset_i_cloud( + self, + domain_id: str, + ) -> DnsRecordsList: + """ + List iCloud DNS records. + + Parameters + ---------- + domain_id : str + Domain unique ID. + Returns + ------- + DnsRecordsList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/presets/icloud' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecordsList) + + def create_preset_i_cloud( + self, + domain_id: str, + ) -> DnsRecordsList: + """ + Add iCloud DNS records to the domain. This will create the required MX and SPF records + for using iCloud email services with your domain. + + Parameters + ---------- + domain_id : str + Domain unique ID. + Returns + ------- + DnsRecordsList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/presets/icloud' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecordsList) + + def get_preset_mailgun( + self, + domain_id: str, + ) -> DnsRecordsList: + """ + List Mailgun DNS records. + + Parameters + ---------- + domain_id : str + Domain unique ID. + Returns + ------- + DnsRecordsList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/presets/mailgun' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecordsList) + + def create_preset_mailgun( + self, + domain_id: str, + ) -> DnsRecordsList: + """ + Add Mailgun DNS records to the domain. This endpoint will create the required DNS records + for Mailgun in the specified domain. + + Parameters + ---------- + domain_id : str + Domain unique ID. + Returns + ------- + DnsRecordsList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/presets/mailgun' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecordsList) + + def get_preset_outlook( + self, + domain_id: str, + ) -> DnsRecordsList: + """ + List Outlook DNS records. + + Parameters + ---------- + domain_id : str + Domain unique ID. + Returns + ------- + DnsRecordsList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/presets/outlook' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecordsList) + + def create_preset_outlook( + self, + domain_id: str, + ) -> DnsRecordsList: + """ + Add Outlook DNS records to the domain. This will create the required MX records + for setting up Outlook email hosting for your domain. + + Parameters + ---------- + domain_id : str + Domain unique ID. + Returns + ------- + DnsRecordsList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/presets/outlook' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecordsList) + + def get_preset_proton_mail( + self, + domain_id: str, + ) -> DnsRecordsList: + """ + List ProtonMail DNS records. + + Parameters + ---------- + domain_id : str + Domain unique ID. + Returns + ------- + DnsRecordsList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/presets/proton-mail' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecordsList) + + def create_preset_proton_mail( + self, + domain_id: str, + ) -> DnsRecordsList: + """ + Add ProtonMail DNS records to the domain. This will create the required MX records + for using ProtonMail with your custom domain. + + Parameters + ---------- + domain_id : str + Domain unique ID. + Returns + ------- + DnsRecordsList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/presets/proton-mail' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecordsList) + + def get_preset_zoho( + self, + domain_id: str, + ) -> DnsRecordsList: + """ + List Zoho DNS records. + + Parameters + ---------- + domain_id : str + Domain unique ID. + Returns + ------- + DnsRecordsList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/presets/zoho' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecordsList) + + def create_preset_zoho( + self, + domain_id: str, + ) -> DnsRecordsList: + """ + Add Zoho Mail DNS records to the domain. This will create the required MX records + for setting up Zoho Mail on your domain. + + Parameters + ---------- + domain_id : str + Domain unique ID. + Returns + ------- + DnsRecordsList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/presets/zoho' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecordsList) + + def list_records( + self, + domain_id: str, + queries: Optional[List[str]] = None, + ) -> DnsRecordsList: + """ + List DNS records for a given domain. You can use this endpoint to list all the DNS records + associated with your domain. + + Parameters + ---------- + domain_id : str + Domain unique ID. + queries : Optional[List[str]] + Array of query strings generated using the Query class provided by the SDK. You may filter on attributes such as type, name, value, etc. Maximum of 100 queries are allowed, each 4096 characters long. + Returns + ------- + DnsRecordsList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + if queries is not None: + api_params['queries'] = self._normalize_value(queries) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecordsList) + + def create_record_a( + self, + domain_id: str, + name: str, + value: str, + ttl: float, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Create a new A record for the given domain. A records are used to point a domain name + to an IPv4 address. The record value should be a valid IPv4 address. + + Parameters + ---------- + domain_id : str + Domain unique ID. + name : str + Record name (subdomain). + value : str + IPv4 address for this A record. + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + comment : Optional[str] + A comment explaining what this record is for. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/a' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if value is None: + raise AppwriteException('Missing required parameter: "value"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_params['name'] = self._normalize_value(name) + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def update_record_a( + self, + domain_id: str, + record_id: str, + name: str, + value: str, + ttl: float, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Update an existing A record for the given domain. This endpoint allows you to modify + the properties of an A record including its name (subdomain), IPv4 address, TTL, + and optional comment. + + Parameters + ---------- + domain_id : str + Domain unique ID. + record_id : str + DNS record unique ID. + name : str + Record name (subdomain). + value : str + IPv4 address for this A record. + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + comment : Optional[str] + A comment explaining what this record is for. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/a/{recordId}' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if record_id is None or record_id == '': + raise AppwriteException('Missing required parameter: "record_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if value is None: + raise AppwriteException('Missing required parameter: "value"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_path = api_path.replace('{recordId}', str(self._normalize_value(record_id))) + api_params['name'] = self._normalize_value(name) + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'put', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def create_record_aaaa( + self, + domain_id: str, + name: str, + value: str, + ttl: float, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Create a new AAAA record for the given domain. This endpoint allows you to add a new IPv6 DNS record + to your domain. The record will be used to point a hostname to an IPv6 address. + + Parameters + ---------- + domain_id : str + Domain unique ID. + name : str + Record name (subdomain). + value : str + IPv6 address for this AAAA record. + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + comment : Optional[str] + A comment explaining what this record is for. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/aaaa' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if value is None: + raise AppwriteException('Missing required parameter: "value"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_params['name'] = self._normalize_value(name) + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def update_record_aaaa( + self, + domain_id: str, + record_id: str, + name: str, + value: str, + ttl: float, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Update an existing AAAA record for the given domain. This endpoint allows you to modify + the properties of an existing AAAA record, including its name (subdomain), IPv6 address, + TTL, and optional comment. + + Parameters + ---------- + domain_id : str + Domain unique ID. + record_id : str + DNS record unique ID. + name : str + Record name (subdomain). + value : str + IPv6 address for this AAAA record. + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + comment : Optional[str] + A comment for this record. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/aaaa/{recordId}' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if record_id is None or record_id == '': + raise AppwriteException('Missing required parameter: "record_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if value is None: + raise AppwriteException('Missing required parameter: "value"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_path = api_path.replace('{recordId}', str(self._normalize_value(record_id))) + api_params['name'] = self._normalize_value(name) + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'put', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def create_record_alias( + self, + domain_id: str, + name: str, + value: str, + ttl: float, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Create a new ALIAS record for the given domain. This record type can be used to point your domain + to another domain name that will serve as an alias. This is particularly useful when you want to + map your domain to a target domain that may change its IP address. + + Parameters + ---------- + domain_id : str + Domain unique ID. + name : str + Record name. + value : str + Target domain for this ALIAS record. + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + comment : Optional[str] + A comment for this record. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/alias' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if value is None: + raise AppwriteException('Missing required parameter: "value"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_params['name'] = self._normalize_value(name) + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def update_record_alias( + self, + domain_id: str, + record_id: str, + name: str, + value: str, + ttl: float, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Update an existing ALIAS record for the specified domain. This endpoint allows you to modify + the properties of an existing ALIAS record including its name, target domain, TTL, and comment. + + The ALIAS record type is similar to a CNAME record but can be used at the zone apex (root domain). + It provides a way to map one domain name to another. + + Parameters + ---------- + domain_id : str + Domain unique ID. + record_id : str + DNS record unique ID. + name : str + Record name. + value : str + Target domain for this ALIAS record. + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + comment : Optional[str] + A comment for this record. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/alias/{recordId}' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if record_id is None or record_id == '': + raise AppwriteException('Missing required parameter: "record_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if value is None: + raise AppwriteException('Missing required parameter: "value"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_path = api_path.replace('{recordId}', str(self._normalize_value(record_id))) + api_params['name'] = self._normalize_value(name) + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'put', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def create_record_caa( + self, + domain_id: str, + name: str, + value: str, + ttl: float, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Create a new CAA record for the given domain. CAA records are used to specify which + Certificate Authorities (CAs) are allowed to issue SSL/TLS certificates for your domain. + + Parameters + ---------- + domain_id : str + Domain unique ID. + name : str + Record name. + value : str + CAA value (e.g. issuer domain). + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + comment : Optional[str] + A comment for this record. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/caa' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if value is None: + raise AppwriteException('Missing required parameter: "value"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_params['name'] = self._normalize_value(name) + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def update_record_caa( + self, + domain_id: str, + record_id: str, + name: str, + value: str, + ttl: float, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Update an existing CAA record for the given domain. A CAA (Certification Authority Authorization) + record is used to specify which certificate authorities (CAs) are authorized to issue certificates + for a domain. + + Parameters + ---------- + domain_id : str + Domain unique ID. + record_id : str + DNS record unique ID. + name : str + Record name. + value : str + CAA value (e.g. issuer domain). + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + comment : Optional[str] + A comment for this record. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/caa/{recordId}' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if record_id is None or record_id == '': + raise AppwriteException('Missing required parameter: "record_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if value is None: + raise AppwriteException('Missing required parameter: "value"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_path = api_path.replace('{recordId}', str(self._normalize_value(record_id))) + api_params['name'] = self._normalize_value(name) + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'put', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def create_record_cname( + self, + domain_id: str, + name: str, + value: str, + ttl: float, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Create a new CNAME record for the given domain. + + A CNAME record maps a subdomain to another domain name, allowing you to create aliases + for your domain. For example, you can create a CNAME record to point 'blog.example.com' + to 'example.wordpress.com'. + + Parameters + ---------- + domain_id : str + Domain unique ID. + name : str + Record name (subdomain). + value : str + Canonical target for this CNAME record. + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + comment : Optional[str] + A comment for this record. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/cname' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if value is None: + raise AppwriteException('Missing required parameter: "value"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_params['name'] = self._normalize_value(name) + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def update_record_cname( + self, + domain_id: str, + record_id: str, + name: str, + value: str, + ttl: float, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Update an existing CNAME record for the given domain. + + Parameters + ---------- + domain_id : str + Domain unique ID. + record_id : str + DNS record unique ID. + name : str + Record name (subdomain). + value : str + Canonical target for this CNAME record. + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + comment : Optional[str] + A comment for this record. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/cname/{recordId}' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if record_id is None or record_id == '': + raise AppwriteException('Missing required parameter: "record_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if value is None: + raise AppwriteException('Missing required parameter: "value"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_path = api_path.replace('{recordId}', str(self._normalize_value(record_id))) + api_params['name'] = self._normalize_value(name) + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'put', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def create_record_https( + self, + domain_id: str, + name: str, + value: str, + ttl: float, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Create a new HTTPS record for the given domain. This record is used to configure HTTPS + settings for your domain, enabling secure communication over SSL/TLS. + + Parameters + ---------- + domain_id : str + Domain unique ID. + name : str + Record name (subdomain). + value : str + Target for the HTTPS record. + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + comment : Optional[str] + A comment for this record. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/https' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if value is None: + raise AppwriteException('Missing required parameter: "value"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_params['name'] = self._normalize_value(name) + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def update_record_https( + self, + domain_id: str, + record_id: str, + name: str, + value: str, + ttl: float, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Update an existing HTTPS record for the given domain. This endpoint allows you to modify + the properties of an HTTPS record associated with your domain, including the name (subdomain), + target value, TTL, and optional comment. + + Parameters + ---------- + domain_id : str + Domain unique ID. + record_id : str + DNS record unique ID. + name : str + Record name (subdomain). + value : str + Target for the HTTPS record. + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + comment : Optional[str] + A comment for this record. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/https/{recordId}' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if record_id is None or record_id == '': + raise AppwriteException('Missing required parameter: "record_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if value is None: + raise AppwriteException('Missing required parameter: "value"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_path = api_path.replace('{recordId}', str(self._normalize_value(record_id))) + api_params['name'] = self._normalize_value(name) + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'put', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def create_record_mx( + self, + domain_id: str, + name: str, + value: str, + ttl: float, + priority: float, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Create a new MX record for the given domain. MX records are used to define the mail servers responsible + for accepting email messages for the domain. Multiple MX records can be created with different priorities. + The priority parameter determines the order in which mail servers are used, with lower values indicating + higher priority. + + Parameters + ---------- + domain_id : str + Domain unique ID. + name : str + Record name (subdomain). + value : str + Mail server domain for this MX record. + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + priority : float + MX priority. Lower values are tried first. + comment : Optional[str] + A comment for this record. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/mx' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if value is None: + raise AppwriteException('Missing required parameter: "value"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + if priority is None: + raise AppwriteException('Missing required parameter: "priority"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_params['name'] = self._normalize_value(name) + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + api_params['priority'] = self._normalize_value(priority) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def update_record_mx( + self, + domain_id: str, + record_id: str, + name: str, + value: str, + ttl: float, + priority: float, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Update an existing MX record for the given domain. + + Parameters + ---------- + domain_id : str + Domain unique ID. + record_id : str + DNS record unique ID. + name : str + Record name (subdomain). + value : str + Mail server domain for this MX record. + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + priority : float + MX priority. Lower values are tried first. + comment : Optional[str] + A comment for this record. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/mx/{recordId}' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if record_id is None or record_id == '': + raise AppwriteException('Missing required parameter: "record_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if value is None: + raise AppwriteException('Missing required parameter: "value"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + if priority is None: + raise AppwriteException('Missing required parameter: "priority"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_path = api_path.replace('{recordId}', str(self._normalize_value(record_id))) + api_params['name'] = self._normalize_value(name) + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + api_params['priority'] = self._normalize_value(priority) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'put', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def create_record_ns( + self, + domain_id: str, + name: str, + value: str, + ttl: float, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Create a new NS record for the given domain. NS records specify the nameservers that are used + to resolve the domain name to IP addresses. Each domain can have multiple NS records. + + Parameters + ---------- + domain_id : str + Domain unique ID. + name : str + Record name (subdomain). + value : str + Nameserver target for this NS record. + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + comment : Optional[str] + A comment for this record. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/ns' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if value is None: + raise AppwriteException('Missing required parameter: "value"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_params['name'] = self._normalize_value(name) + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def update_record_ns( + self, + domain_id: str, + record_id: str, + name: str, + value: str, + ttl: float, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Update an existing NS record for the given domain. This endpoint allows you to modify + the properties of an NS (nameserver) record associated with your domain. You can update + the record name (subdomain), target nameserver value, TTL, and add or modify comments + for better record management. + + Parameters + ---------- + domain_id : str + Domain unique ID. + record_id : str + DNS record unique ID. + name : str + Record name (subdomain). + value : str + Nameserver target for this NS record. + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + comment : Optional[str] + A comment for this record. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/ns/{recordId}' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if record_id is None or record_id == '': + raise AppwriteException('Missing required parameter: "record_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if value is None: + raise AppwriteException('Missing required parameter: "value"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_path = api_path.replace('{recordId}', str(self._normalize_value(record_id))) + api_params['name'] = self._normalize_value(name) + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'put', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def create_record_srv( + self, + domain_id: str, + name: str, + value: str, + ttl: float, + priority: float, + weight: float, + port: float, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Create a new SRV record for the given domain. SRV records are used to define the location + of servers for specific services. For example, they can be used to specify which server + handles a specific service like SIP or XMPP for the domain. + + Parameters + ---------- + domain_id : str + Domain unique ID. + name : str + Record name (service name). + value : str + Target hostname for this SRV record. + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + priority : float + Record priority. Lower values are tried first. + weight : float + Record weight, used to share load between targets of equal priority. + port : float + Port number for the service. + comment : Optional[str] + A comment for this record. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/srv' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if value is None: + raise AppwriteException('Missing required parameter: "value"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + if priority is None: + raise AppwriteException('Missing required parameter: "priority"') + if weight is None: + raise AppwriteException('Missing required parameter: "weight"') + if port is None: + raise AppwriteException('Missing required parameter: "port"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_params['name'] = self._normalize_value(name) + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + api_params['priority'] = self._normalize_value(priority) + api_params['weight'] = self._normalize_value(weight) + api_params['port'] = self._normalize_value(port) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def update_record_srv( + self, + domain_id: str, + record_id: str, + name: str, + value: str, + ttl: float, + priority: float, + weight: float, + port: float, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Update an existing SRV record for the given domain. + + Required parameters: + - domainId: Domain unique ID + - recordId: DNS record unique ID + - name: Record name (service name) + - value: Target hostname for this SRV record + - ttl: Time to live, in seconds + - priority: Record priority + - weight: Record weight + - port: Port number for the service + + Optional parameters: + - comment: A comment for this record + + Parameters + ---------- + domain_id : str + Domain unique ID. + record_id : str + DNS record unique ID. + name : str + Record name (service name). + value : str + Target hostname for this SRV record. + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + priority : float + Record priority. Lower values are tried first. + weight : float + Record weight, used to share load between targets of equal priority. + port : float + Port number for the service. + comment : Optional[str] + A comment for this record. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/srv/{recordId}' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if record_id is None or record_id == '': + raise AppwriteException('Missing required parameter: "record_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if value is None: + raise AppwriteException('Missing required parameter: "value"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + if priority is None: + raise AppwriteException('Missing required parameter: "priority"') + if weight is None: + raise AppwriteException('Missing required parameter: "weight"') + if port is None: + raise AppwriteException('Missing required parameter: "port"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_path = api_path.replace('{recordId}', str(self._normalize_value(record_id))) + api_params['name'] = self._normalize_value(name) + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + api_params['priority'] = self._normalize_value(priority) + api_params['weight'] = self._normalize_value(weight) + api_params['port'] = self._normalize_value(port) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'put', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def create_record_txt( + self, + domain_id: str, + name: str, + ttl: float, + value: Optional[str] = None, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Create a new TXT record for the given domain. TXT records can be used + to provide additional information about your domain, such as domain + verification records, SPF records, or DKIM records. + + Parameters + ---------- + domain_id : str + Domain unique ID. + name : str + Record name (subdomain) for the TXT record. + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + value : Optional[str] + TXT record value. + comment : Optional[str] + A comment for this record. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/txt' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_params['name'] = self._normalize_value(name) + if value is not None: + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def update_record_txt( + self, + domain_id: str, + record_id: str, + name: str, + value: str, + ttl: float, + comment: Optional[str] = None, + ) -> DnsRecord: + """ + Update an existing TXT record for the given domain. + + Update the TXT record details for a specific domain by providing the domain ID, + record ID, and the new record configuration including name, value, TTL, and an optional comment. + + Parameters + ---------- + domain_id : str + Domain unique ID. + record_id : str + DNS record unique ID. + name : str + Record name (subdomain) for the TXT record. + value : str + TXT record value. + ttl : float + Time to live, in seconds. Must be between 1 and 2147483647. + comment : Optional[str] + A comment for this record. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/txt/{recordId}' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if record_id is None or record_id == '': + raise AppwriteException('Missing required parameter: "record_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if value is None: + raise AppwriteException('Missing required parameter: "value"') + if ttl is None: + raise AppwriteException('Missing required parameter: "ttl"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_path = api_path.replace('{recordId}', str(self._normalize_value(record_id))) + api_params['name'] = self._normalize_value(name) + api_params['value'] = self._normalize_value(value) + api_params['ttl'] = self._normalize_value(ttl) + if comment is not None: + api_params['comment'] = self._normalize_value(comment) + + response = self.client.call( + 'put', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def get_record( + self, + domain_id: str, + record_id: str, + ) -> DnsRecord: + """ + Get a single DNS record for a given domain by record ID. + + This endpoint allows you to retrieve a specific DNS record associated with a domain + using its unique identifier. The record contains information about the DNS configuration + such as type, value, and TTL settings. + + Parameters + ---------- + domain_id : str + Domain unique ID. + record_id : str + DNS record unique ID. + Returns + ------- + DnsRecord + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/{recordId}' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if record_id is None or record_id == '': + raise AppwriteException('Missing required parameter: "record_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_path = api_path.replace('{recordId}', str(self._normalize_value(record_id))) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DnsRecord) + + def delete_record( + self, + domain_id: str, + record_id: str, + ) -> Dict[str, Any]: + """ + Delete a DNS record for the given domain. This endpoint allows you to delete an existing DNS record + from a specific domain. + + Parameters + ---------- + domain_id : str + Domain unique ID. + record_id : str + DNS record unique ID. + Returns + ------- + Dict[str, Any] + API response as a dictionary + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/records/{recordId}' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if record_id is None or record_id == '': + raise AppwriteException('Missing required parameter: "record_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_path = api_path.replace('{recordId}', str(self._normalize_value(record_id))) + + response = self.client.call( + 'delete', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return response + + def update_team( + self, + domain_id: str, + team_id: str, + ) -> Domain: + """ + Update the team ID for a specific domain. The caller must administer the current + team and be an owner of the destination team. + + Updating the team ID will transfer ownership and access control of the domain + and all its DNS records to the new team. + + Parameters + ---------- + domain_id : str + Domain unique ID. + team_id : str + New team unique ID. + Returns + ------- + Domain + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/team' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if team_id is None: + raise AppwriteException('Missing required parameter: "team_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_params['teamId'] = self._normalize_value(team_id) + + response = self.client.call( + 'patch', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=Domain) + + def get_transfer_status( + self, + domain_id: str, + ) -> DomainTransferStatus: + """ + Retrieve the current transfer status for a domain. Returns the status, an optional reason, and a timestamp of the last status change. + + Parameters + ---------- + domain_id : str + Domain unique ID. + Returns + ------- + DomainTransferStatus + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/transfers/status' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DomainTransferStatus) + + def get_zone( + self, + domain_id: str, + ) -> str: + """ + Retrieve the DNS zone file for the given domain. This endpoint will return the DNS + zone file in a standardized format that can be used to configure DNS servers. + + Parameters + ---------- + domain_id : str + Domain unique ID. + Returns + ------- + str + Response body as text + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/zone' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'text/plain', + }, + api_params, + response_type='text', + ) + + return response + + def update_zone( + self, + domain_id: str, + content: str, + ) -> Domain: + """ + Update the DNS zone for the given domain using the provided zone file content. + All parsed records are imported and then the main domain document is returned. + + Parameters + ---------- + domain_id : str + Domain unique ID. + content : str + DNS zone file content as a string. + Returns + ------- + Domain + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/domains/{domainId}/zone' + api_params = {} + if domain_id is None or domain_id == '': + raise AppwriteException('Missing required parameter: "domain_id"') + if content is None: + raise AppwriteException('Missing required parameter: "content"') + api_path = api_path.replace('{domainId}', str(self._normalize_value(domain_id))) + api_params['content'] = self._normalize_value(content) + + response = self.client.call( + 'put', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=Domain) diff --git a/appwrite/services/functions.py b/appwrite/services/functions.py index b42734fa..13253dc2 100644 --- a/appwrite/services/functions.py +++ b/appwrite/services/functions.py @@ -231,9 +231,15 @@ def create( def list_runtimes( self, + total: Optional[bool] = None, ) -> RuntimeList: """ Get a list of all runtimes that are currently active on your instance. + + Parameters + ---------- + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. Returns ------- RuntimeList @@ -247,6 +253,8 @@ def list_runtimes( api_path = '/functions/runtimes' api_params = {} + if total is not None: + api_params['total'] = self._normalize_value(total) response = self.client.call( 'get', @@ -263,6 +271,7 @@ def list_runtimes( def list_specifications( self, type: Optional[str] = None, + total: Optional[bool] = None, ) -> SpecificationList: """ List allowed function specifications for this instance. @@ -271,6 +280,8 @@ def list_specifications( ---------- type : Optional[str] Specification type to list. Can be one of: runtimes, builds. Defaults to runtimes. + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. Returns ------- SpecificationList @@ -286,6 +297,8 @@ def list_specifications( api_params = {} if type is not None: api_params['type'] = self._normalize_value(type) + if total is not None: + api_params['total'] = self._normalize_value(total) response = self.client.call( 'get', diff --git a/appwrite/services/locale.py b/appwrite/services/locale.py index 4a3c96f0..e0e69e70 100644 --- a/appwrite/services/locale.py +++ b/appwrite/services/locale.py @@ -52,9 +52,15 @@ def get( def list_codes( self, + total: Optional[bool] = None, ) -> LocaleCodeList: """ List of all locale codes in [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes). + + Parameters + ---------- + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. Returns ------- LocaleCodeList @@ -68,6 +74,8 @@ def list_codes( api_path = '/locale/codes' api_params = {} + if total is not None: + api_params['total'] = self._normalize_value(total) response = self.client.call( 'get', @@ -83,9 +91,15 @@ def list_codes( def list_continents( self, + total: Optional[bool] = None, ) -> ContinentList: """ List of all continents. You can use the locale header to get the data in a supported language. + + Parameters + ---------- + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. Returns ------- ContinentList @@ -99,6 +113,8 @@ def list_continents( api_path = '/locale/continents' api_params = {} + if total is not None: + api_params['total'] = self._normalize_value(total) response = self.client.call( 'get', @@ -114,9 +130,15 @@ def list_continents( def list_countries( self, + total: Optional[bool] = None, ) -> CountryList: """ List of all countries. You can use the locale header to get the data in a supported language. + + Parameters + ---------- + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. Returns ------- CountryList @@ -130,6 +152,8 @@ def list_countries( api_path = '/locale/countries' api_params = {} + if total is not None: + api_params['total'] = self._normalize_value(total) response = self.client.call( 'get', @@ -145,9 +169,15 @@ def list_countries( def list_countries_eu( self, + total: Optional[bool] = None, ) -> CountryList: """ List of all countries that are currently members of the EU. You can use the locale header to get the data in a supported language. + + Parameters + ---------- + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. Returns ------- CountryList @@ -161,6 +191,8 @@ def list_countries_eu( api_path = '/locale/countries/eu' api_params = {} + if total is not None: + api_params['total'] = self._normalize_value(total) response = self.client.call( 'get', @@ -176,9 +208,15 @@ def list_countries_eu( def list_countries_phones( self, + total: Optional[bool] = None, ) -> PhoneList: """ List of all countries phone codes. You can use the locale header to get the data in a supported language. + + Parameters + ---------- + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. Returns ------- PhoneList @@ -192,6 +230,8 @@ def list_countries_phones( api_path = '/locale/countries/phones' api_params = {} + if total is not None: + api_params['total'] = self._normalize_value(total) response = self.client.call( 'get', @@ -207,9 +247,15 @@ def list_countries_phones( def list_currencies( self, + total: Optional[bool] = None, ) -> CurrencyList: """ List of all currencies, including currency symbol, name, plural, and decimal digits for all major and minor currencies. You can use the locale header to get the data in a supported language. + + Parameters + ---------- + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. Returns ------- CurrencyList @@ -223,6 +269,8 @@ def list_currencies( api_path = '/locale/currencies' api_params = {} + if total is not None: + api_params['total'] = self._normalize_value(total) response = self.client.call( 'get', @@ -238,9 +286,15 @@ def list_currencies( def list_languages( self, + total: Optional[bool] = None, ) -> LanguageList: """ List of all languages classified by ISO 639-1 including 2-letter code, name in English, and name in the respective language. + + Parameters + ---------- + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. Returns ------- LanguageList @@ -254,6 +308,8 @@ def list_languages( api_path = '/locale/languages' api_params = {} + if total is not None: + api_params['total'] = self._normalize_value(total) response = self.client.call( 'get', diff --git a/appwrite/services/messaging.py b/appwrite/services/messaging.py index 29a37285..30368cd5 100644 --- a/appwrite/services/messaging.py +++ b/appwrite/services/messaging.py @@ -84,6 +84,8 @@ def create_email( draft: Optional[bool] = None, html: Optional[bool] = None, scheduled_at: Optional[str] = None, + reply_to_email: Optional[str] = None, + reply_to_name: Optional[str] = None, ) -> Message: """ Create a new email message. @@ -114,6 +116,10 @@ def create_email( Is content of type HTML scheduled_at : Optional[str] Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future. + reply_to_email : Optional[str] + Email address to reply to. If not set, defaults to the sender email address. + reply_to_name : Optional[str] + Name of the reply to recipient. If not set, defaults to the sender name. Returns ------- Message @@ -154,6 +160,10 @@ def create_email( api_params['html'] = self._normalize_value(html) if scheduled_at is not None: api_params['scheduledAt'] = self._normalize_value(scheduled_at) + if reply_to_email is not None: + api_params['replyToEmail'] = self._normalize_value(reply_to_email) + if reply_to_name is not None: + api_params['replyToName'] = self._normalize_value(reply_to_name) response = self.client.call( 'post', @@ -182,6 +192,8 @@ def update_email( bcc: Optional[List[str]] = None, scheduled_at: Optional[str] = None, attachments: Optional[List[str]] = None, + reply_to_email: Optional[str] = None, + reply_to_name: Optional[str] = None, ) -> Message: """ Update an email message by its unique ID. This endpoint only works on messages that are in draft status. Messages that are already processing, sent, or failed cannot be updated. @@ -212,6 +224,10 @@ def update_email( Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future. attachments : Optional[List[str]] Array of compound ID strings of bucket IDs and file IDs to be attached to the email. They should be formatted as :. + reply_to_email : Optional[str] + Email address to reply to. Pass an empty string to restore the provider or sender default. + reply_to_name : Optional[str] + Name of the reply to recipient. Pass an empty string to restore the provider or sender default. Returns ------- Message @@ -250,6 +266,10 @@ def update_email( api_params['scheduledAt'] = self._normalize_value(scheduled_at) if attachments is not None: api_params['attachments'] = self._normalize_value(attachments) + if reply_to_email is not None: + api_params['replyToEmail'] = self._normalize_value(reply_to_email) + if reply_to_name is not None: + api_params['replyToName'] = self._normalize_value(reply_to_name) response = self.client.call( 'patch', @@ -285,6 +305,7 @@ def create_push( content_available: Optional[bool] = None, critical: Optional[bool] = None, priority: Optional[MessagePriority] = None, + channel_id: Optional[str] = None, ) -> Message: """ Create a new push notification. @@ -329,6 +350,8 @@ def create_push( If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform. priority : Optional[MessagePriority] Set the notification priority. "normal" will consider device state and may not deliver notifications immediately. "high" will always attempt to immediately deliver the notification. + channel_id : Optional[str] + ID of the notification channel to deliver the notification on. The app must have already created a channel with this ID, otherwise the channel from the app manifest is used. Available only for Android Platform. Returns ------- Message @@ -381,6 +404,8 @@ def create_push( api_params['critical'] = self._normalize_value(critical) if priority is not None: api_params['priority'] = self._normalize_value(priority) + if channel_id is not None: + api_params['channelId'] = self._normalize_value(channel_id) response = self.client.call( 'post', @@ -416,6 +441,7 @@ def update_push( content_available: Optional[bool] = None, critical: Optional[bool] = None, priority: Optional[MessagePriority] = None, + channel_id: Optional[str] = None, ) -> Message: """ Update a push notification by its unique ID. This endpoint only works on messages that are in draft status. Messages that are already processing, sent, or failed cannot be updated. @@ -460,6 +486,8 @@ def update_push( If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform. priority : Optional[MessagePriority] Set the notification priority. "normal" will consider device battery state and may send notifications later. "high" will always attempt to immediately deliver the notification. + channel_id : Optional[str] + ID of the notification channel to deliver the notification on. The app must have already created a channel with this ID, otherwise the channel from the app manifest is used. Pass an empty string to clear it. Available only for Android platforms. Returns ------- Message @@ -512,6 +540,8 @@ def update_push( api_params['critical'] = self._normalize_value(critical) if priority is not None: api_params['priority'] = self._normalize_value(priority) + if channel_id is not None: + api_params['channelId'] = self._normalize_value(channel_id) response = self.client.call( 'patch', @@ -1001,6 +1031,129 @@ def update_apns_provider( return self._parse_response(response, model=Provider) + def create_appwrite_provider( + self, + provider_id: str, + name: str, + enabled: Optional[bool] = None, + qos: Optional[float] = None, + expiry: Optional[float] = None, + ) -> Provider: + """ + Create a new Appwrite push provider. + + Parameters + ---------- + provider_id : str + Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. + name : str + Provider name. + enabled : Optional[bool] + Set as enabled. + qos : Optional[float] + Default QoS for topics on this provider (0 or 1). Null lets the subscriber choose. + expiry : Optional[float] + Default message retention in seconds for offline delivery. Max 7 days (604800). + Returns + ------- + Provider + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/messaging/providers/appwrite' + api_params = {} + if provider_id is None: + raise AppwriteException('Missing required parameter: "provider_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + api_params['providerId'] = self._normalize_value(provider_id) + api_params['name'] = self._normalize_value(name) + if enabled is not None: + api_params['enabled'] = self._normalize_value(enabled) + if qos is not None: + api_params['qos'] = self._normalize_value(qos) + if expiry is not None: + api_params['expiry'] = self._normalize_value(expiry) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=Provider) + + def update_appwrite_provider( + self, + provider_id: str, + name: Optional[str] = None, + enabled: Optional[bool] = None, + qos: Optional[float] = None, + expiry: Optional[float] = None, + ) -> Provider: + """ + Update an Appwrite push provider by its unique ID. + + Parameters + ---------- + provider_id : str + Provider ID. + name : Optional[str] + Provider name. + enabled : Optional[bool] + Set as enabled. + qos : Optional[float] + Default QoS for topics on this provider (0 or 1). Null lets the subscriber choose. + expiry : Optional[float] + Default message retention in seconds for offline delivery. Max 7 days (604800). + Returns + ------- + Provider + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/messaging/providers/appwrite/{providerId}' + api_params = {} + if provider_id is None or provider_id == '': + raise AppwriteException('Missing required parameter: "provider_id"') + api_path = api_path.replace('{providerId}', str(self._normalize_value(provider_id))) + if name is not None: + api_params['name'] = self._normalize_value(name) + if enabled is not None: + api_params['enabled'] = self._normalize_value(enabled) + if qos is not None: + api_params['qos'] = self._normalize_value(qos) + if expiry is not None: + api_params['expiry'] = self._normalize_value(expiry) + + response = self.client.call( + 'patch', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=Provider) + def create_fcm_provider( self, provider_id: str, @@ -2779,6 +2932,8 @@ def create_topic( topic_id: str, name: str, subscribe: Optional[List[str]] = None, + qos: Optional[float] = None, + expiry: Optional[float] = None, ) -> Topic: """ Create a new topic. @@ -2791,6 +2946,10 @@ def create_topic( Topic Name. subscribe : Optional[List[str]] An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https://appwrite.io/docs/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long. + qos : Optional[float] + MQTT delivery quality of service for this topic. 0 is fire-and-forget (delivered only to clients connected at publish time). 1 persists each message and replays it when a client reconnects without having acknowledged it. Null lets the subscriber choose. + expiry : Optional[float] + Message retention in seconds for offline delivery. Max 7 days (604800). Returns ------- Topic @@ -2812,6 +2971,10 @@ def create_topic( api_params['name'] = self._normalize_value(name) if subscribe is not None: api_params['subscribe'] = self._normalize_value(subscribe) + if qos is not None: + api_params['qos'] = self._normalize_value(qos) + if expiry is not None: + api_params['expiry'] = self._normalize_value(expiry) response = self.client.call( 'post', @@ -2871,6 +3034,8 @@ def update_topic( topic_id: str, name: Optional[str] = None, subscribe: Optional[List[str]] = None, + qos: Optional[float] = None, + expiry: Optional[float] = None, ) -> Topic: """ Update a topic by its unique ID. @@ -2883,6 +3048,10 @@ def update_topic( Topic Name. subscribe : Optional[List[str]] An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https://appwrite.io/docs/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long. + qos : Optional[float] + MQTT delivery quality of service for this topic. 0 is fire-and-forget (delivered only to clients connected at publish time). 1 persists each message and replays it when a client reconnects without having acknowledged it. Null lets the subscriber choose. + expiry : Optional[float] + Message retention in seconds for offline delivery. Max 7 days (604800). Returns ------- Topic @@ -2903,6 +3072,10 @@ def update_topic( api_params['name'] = self._normalize_value(name) if subscribe is not None: api_params['subscribe'] = self._normalize_value(subscribe) + if qos is not None: + api_params['qos'] = self._normalize_value(qos) + if expiry is not None: + api_params['expiry'] = self._normalize_value(expiry) response = self.client.call( 'patch', diff --git a/appwrite/services/oauth2.py b/appwrite/services/oauth2.py index 31489fef..de59e3e8 100644 --- a/appwrite/services/oauth2.py +++ b/appwrite/services/oauth2.py @@ -7,6 +7,7 @@ from ..models.oauth2_authorize import Oauth2Authorize from ..models.oauth2_device_authorization import Oauth2DeviceAuthorization from ..models.oauth2_grant import Oauth2Grant +from ..models.oauth2_introspection import Oauth2Introspection from ..models.oauth2_organization_list import Oauth2OrganizationList from ..models.oauth2_par import Oauth2PAR from ..models.oauth2_project_list import Oauth2ProjectList @@ -420,6 +421,62 @@ def get_grant( return self._parse_response(response, model=Oauth2Grant) + def introspect( + self, + token: str, + token_type_hint: Optional[str] = None, + client_id: Optional[str] = None, + client_secret: Optional[str] = None, + ) -> Oauth2Introspection: + """ + Introspect an OAuth2 access token or refresh token. Authenticate with an API key holding the `oauth2.introspect` scope to introspect any token in the project, or with the client credentials of the app the token was issued to. + + Parameters + ---------- + token : str + The access token or refresh token to introspect. + token_type_hint : Optional[str] + Type of token to introspect. Can be one of: `access_token` or `refresh_token`. + client_id : Optional[str] + OAuth2 client ID. Either a registered app ID or an HTTPS client ID metadata document URL. + client_secret : Optional[str] + OAuth2 client secret. + Returns + ------- + Oauth2Introspection + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/oauth2/{project_id}/introspect' + api_params = {} + if token is None: + raise AppwriteException('Missing required parameter: "token"') + api_path = api_path.replace('{project_id}', str(self._normalize_value(self.client.get_config('project')))) + api_params['token'] = self._normalize_value(token) + if token_type_hint is not None: + api_params['token_type_hint'] = self._normalize_value(token_type_hint) + if client_id is not None: + api_params['client_id'] = self._normalize_value(client_id) + if client_secret is not None: + api_params['client_secret'] = self._normalize_value(client_secret) + + response = self.client.call( + 'post', + api_path, + { + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=Oauth2Introspection) + def list_organizations( self, limit: Optional[float] = None, diff --git a/appwrite/services/organization.py b/appwrite/services/organization.py index aa7eed39..0c9e73f6 100644 --- a/appwrite/services/organization.py +++ b/appwrite/services/organization.py @@ -14,6 +14,10 @@ from ..models.project_list import ProjectList from ..enums.region import Region from ..models.project import Project +from ..models.key_list import KeyList +from ..enums.project_key_scopes import ProjectKeyScopes +from ..models.ephemeral_key import EphemeralKey +from ..models.key import Key T = TypeVar('T') @@ -1062,3 +1066,265 @@ def delete_project( ) return response + + def list_project_keys( + self, + project_id: str, + queries: Optional[List[str]] = None, + total: Optional[bool] = None, + ) -> KeyList: + """ + Get a list of all API keys of a project in your organization. + + Parameters + ---------- + project_id : str + Project unique ID. + queries : Optional[List[str]] + Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: expire, accessedAt, name, scopes + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. + Returns + ------- + KeyList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/organization/projects/{projectId}/keys' + api_params = {} + if project_id is None or project_id == '': + raise AppwriteException('Missing required parameter: "project_id"') + api_path = api_path.replace('{projectId}', str(self._normalize_value(project_id))) + if queries is not None: + api_params['queries'] = self._normalize_value(queries) + if total is not None: + api_params['total'] = self._normalize_value(total) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=KeyList) + + def create_ephemeral_project_key( + self, + project_id: str, + scopes: List[ProjectKeyScopes], + duration: float, + ) -> EphemeralKey: + """ + Create a new ephemeral API key for a project in your organization. It's recommended to have multiple API keys with strict scopes for separate functions within your project. + + You can also create a standard API key if you need a longer-lived key instead. + + Parameters + ---------- + project_id : str + Project unique ID. + scopes : List[ProjectKeyScopes] + Key scopes list. Maximum of 200 scopes are allowed. + duration : float + Time in seconds before ephemeral key expires. Maximum duration is 3600 seconds. + Returns + ------- + EphemeralKey + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/organization/projects/{projectId}/keys/ephemeral' + api_params = {} + if project_id is None or project_id == '': + raise AppwriteException('Missing required parameter: "project_id"') + if scopes is None: + raise AppwriteException('Missing required parameter: "scopes"') + if duration is None: + raise AppwriteException('Missing required parameter: "duration"') + api_path = api_path.replace('{projectId}', str(self._normalize_value(project_id))) + api_params['scopes'] = self._normalize_value(scopes) + api_params['duration'] = self._normalize_value(duration) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=EphemeralKey) + + def get_project_key( + self, + project_id: str, + key_id: str, + ) -> Key: + """ + Get a project key by its unique ID. + + Parameters + ---------- + project_id : str + Project unique ID. + key_id : str + Key ID. + Returns + ------- + Key + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/organization/projects/{projectId}/keys/{keyId}' + api_params = {} + if project_id is None or project_id == '': + raise AppwriteException('Missing required parameter: "project_id"') + if key_id is None or key_id == '': + raise AppwriteException('Missing required parameter: "key_id"') + api_path = api_path.replace('{projectId}', str(self._normalize_value(project_id))) + api_path = api_path.replace('{keyId}', str(self._normalize_value(key_id))) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=Key) + + def update_project_key( + self, + project_id: str, + key_id: str, + name: str, + scopes: List[ProjectKeyScopes], + expire: Optional[str] = None, + ) -> Key: + """ + Update a project key by its unique ID. Use this endpoint to update the name, scopes, or expiration time of an API key. + + Parameters + ---------- + project_id : str + Project unique ID. + key_id : str + Key ID. + name : str + Key name. Max length: 128 chars. + scopes : List[ProjectKeyScopes] + Key scopes list. Maximum of 200 scopes are allowed. + expire : Optional[str] + Expiration time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Use null for unlimited expiration. + Returns + ------- + Key + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/organization/projects/{projectId}/keys/{keyId}' + api_params = {} + if project_id is None or project_id == '': + raise AppwriteException('Missing required parameter: "project_id"') + if key_id is None or key_id == '': + raise AppwriteException('Missing required parameter: "key_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if scopes is None: + raise AppwriteException('Missing required parameter: "scopes"') + api_path = api_path.replace('{projectId}', str(self._normalize_value(project_id))) + api_path = api_path.replace('{keyId}', str(self._normalize_value(key_id))) + api_params['name'] = self._normalize_value(name) + api_params['scopes'] = self._normalize_value(scopes) + if expire is not None: + api_params['expire'] = self._normalize_value(expire) + + response = self.client.call( + 'put', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=Key) + + def delete_project_key( + self, + project_id: str, + key_id: str, + ) -> Dict[str, Any]: + """ + Delete a project key by its unique ID. Once deleted, the key can no longer be used to authenticate API calls. + + Parameters + ---------- + project_id : str + Project unique ID. + key_id : str + Key ID. + Returns + ------- + Dict[str, Any] + API response as a dictionary + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/organization/projects/{projectId}/keys/{keyId}' + api_params = {} + if project_id is None or project_id == '': + raise AppwriteException('Missing required parameter: "project_id"') + if key_id is None or key_id == '': + raise AppwriteException('Missing required parameter: "key_id"') + api_path = api_path.replace('{projectId}', str(self._normalize_value(project_id))) + api_path = api_path.replace('{keyId}', str(self._normalize_value(key_id))) + + response = self.client.call( + 'delete', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return response diff --git a/appwrite/services/project.py b/appwrite/services/project.py index 84737c41..d049fcbd 100644 --- a/appwrite/services/project.py +++ b/appwrite/services/project.py @@ -5,6 +5,7 @@ from appwrite.utils.deprecated import deprecated from ..models.project import Project as ProjectModel from ..enums.project_auth_method_id import ProjectAuthMethodId +from ..models.project_list import ProjectList from ..models.key_list import KeyList from ..enums.project_key_scopes import ProjectKeyScopes from ..models.ephemeral_key import EphemeralKey @@ -15,6 +16,7 @@ from ..models.o_auth2_amazon import OAuth2Amazon from ..models.o_auth2_apple import OAuth2Apple from ..models.o_auth2_appwrite import OAuth2Appwrite +from ..enums.project_o_auth2_auth0_prompt import ProjectOAuth2Auth0Prompt from ..models.o_auth2_auth0 import OAuth2Auth0 from ..models.o_auth2_authentik import OAuth2Authentik from ..models.o_auth2_autodesk import OAuth2Autodesk @@ -23,6 +25,7 @@ from ..models.o_auth2_box import OAuth2Box from ..models.o_auth2_cloudflare import OAuth2Cloudflare from ..models.o_auth2_dailymotion import OAuth2Dailymotion +from ..enums.project_o_auth2_discord_prompt import ProjectOAuth2DiscordPrompt from ..models.o_auth2_discord import OAuth2Discord from ..models.o_auth2_disqus import OAuth2Disqus from ..models.o_auth2_dropbox import OAuth2Dropbox @@ -30,32 +33,41 @@ from ..models.o_auth2_facebook import OAuth2Facebook from ..models.o_auth2_figma import OAuth2Figma from ..models.o_auth2_fusion_auth import OAuth2FusionAuth +from ..enums.project_o_auth2_git_hub_prompt import ProjectOAuth2GitHubPrompt from ..models.o_auth2_github import OAuth2Github from ..models.o_auth2_gitlab import OAuth2Gitlab from ..enums.project_o_auth2_google_prompt import ProjectOAuth2GooglePrompt from ..models.o_auth2_google import OAuth2Google from ..models.o_auth2_hugging_face import OAuth2HuggingFace +from ..enums.project_o_auth2_kakao_prompt import ProjectOAuth2KakaoPrompt +from ..models.o_auth2_kakao import OAuth2Kakao from ..models.o_auth2_keycloak import OAuth2Keycloak from ..models.o_auth2_kick import OAuth2Kick from ..models.o_auth2_linkedin import OAuth2Linkedin +from ..enums.project_o_auth2_microsoft_prompt import ProjectOAuth2MicrosoftPrompt from ..models.o_auth2_microsoft import OAuth2Microsoft from ..models.o_auth2_notion import OAuth2Notion from ..enums.project_o_auth2_oidc_prompt import ProjectOAuth2OidcPrompt from ..models.o_auth2_oidc import OAuth2Oidc +from ..enums.project_o_auth2_okta_prompt import ProjectOAuth2OktaPrompt from ..models.o_auth2_okta import OAuth2Okta from ..models.o_auth2_paypal import OAuth2Paypal from ..models.o_auth2_podio import OAuth2Podio from ..models.o_auth2_resend import OAuth2Resend +from ..enums.project_o_auth2_salesforce_prompt import ProjectOAuth2SalesforcePrompt from ..models.o_auth2_salesforce import OAuth2Salesforce from ..models.o_auth2_slack import OAuth2Slack from ..models.o_auth2_spotify import OAuth2Spotify from ..models.o_auth2_stripe import OAuth2Stripe +from ..models.o_auth2_tik_tok import OAuth2TikTok from ..models.o_auth2_tradeshift import OAuth2Tradeshift from ..models.o_auth2_twitch import OAuth2Twitch +from ..models.o_auth2_webflow import OAuth2Webflow from ..models.o_auth2_word_press import OAuth2WordPress from ..models.o_auth2_x import OAuth2X from ..models.o_auth2_yahoo import OAuth2Yahoo from ..models.o_auth2_yandex import OAuth2Yandex +from ..enums.project_o_auth2_zoho_prompt import ProjectOAuth2ZohoPrompt from ..models.o_auth2_zoho import OAuth2Zoho from ..models.o_auth2_zoom import OAuth2Zoom from ..enums.project_o_auth_provider_id import ProjectOAuthProviderId @@ -71,6 +83,8 @@ from ..models.policy_password_dictionary import PolicyPasswordDictionary from ..models.policy_password_history import PolicyPasswordHistory from ..models.policy_password_personal_data import PolicyPasswordPersonalData +from ..models.policy_password_pwned import PolicyPasswordPwned +from ..models.policy_password_rotation import PolicyPasswordRotation from ..models.policy_session_alert import PolicySessionAlert from ..models.policy_session_duration import PolicySessionDuration from ..models.policy_session_invalidation import PolicySessionInvalidation @@ -207,6 +221,225 @@ def update_auth_method( return self._parse_response(response, model=ProjectModel) + def list_environments( + self, + queries: Optional[List[str]] = None, + total: Optional[bool] = None, + ) -> ProjectList: + """ + Get a list of all environments of the project. You can use the query params to filter your results. + + Parameters + ---------- + queries : Optional[List[str]] + Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, teamId, labels, search, accessedAt, status, parentId + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. + Returns + ------- + ProjectList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/project/environments' + api_params = {} + if queries is not None: + api_params['queries'] = self._normalize_value(queries) + if total is not None: + api_params['total'] = self._normalize_value(total) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=ProjectList) + + def create_environment( + self, + environment_id: str, + name: str, + ) -> ProjectModel: + """ + Create a new environment of the project. An environment is a separate project in the same organization and region, with its own resources and users. Its usage is billed under the project it belongs to. + + Parameters + ---------- + environment_id : str + Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, and hyphen. Can't start with a special char. Max length is 36 chars. + name : str + Environment name. Max length: 128 chars. + Returns + ------- + ProjectModel + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/project/environments' + api_params = {} + if environment_id is None: + raise AppwriteException('Missing required parameter: "environment_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + api_params['environmentId'] = self._normalize_value(environment_id) + api_params['name'] = self._normalize_value(name) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=ProjectModel) + + def get_environment( + self, + environment_id: str, + ) -> ProjectModel: + """ + Get an environment of the project by its unique ID. + + Parameters + ---------- + environment_id : str + Environment unique ID. + Returns + ------- + ProjectModel + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/project/environments/{environmentId}' + api_params = {} + if environment_id is None or environment_id == '': + raise AppwriteException('Missing required parameter: "environment_id"') + api_path = api_path.replace('{environmentId}', str(self._normalize_value(environment_id))) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=ProjectModel) + + def update_environment( + self, + environment_id: str, + name: str, + ) -> ProjectModel: + """ + Update the name of an environment of the project. + + Parameters + ---------- + environment_id : str + Environment unique ID. + name : str + Environment name. Max length: 128 chars. + Returns + ------- + ProjectModel + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/project/environments/{environmentId}' + api_params = {} + if environment_id is None or environment_id == '': + raise AppwriteException('Missing required parameter: "environment_id"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + api_path = api_path.replace('{environmentId}', str(self._normalize_value(environment_id))) + api_params['name'] = self._normalize_value(name) + + response = self.client.call( + 'patch', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=ProjectModel) + + def delete_environment( + self, + environment_id: str, + ) -> Dict[str, Any]: + """ + Delete an environment of the project, with all of its resources and users. + + Parameters + ---------- + environment_id : str + Environment unique ID. + Returns + ------- + Dict[str, Any] + API response as a dictionary + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/project/environments/{environmentId}' + api_params = {} + if environment_id is None or environment_id == '': + raise AppwriteException('Missing required parameter: "environment_id"') + api_path = api_path.replace('{environmentId}', str(self._normalize_value(environment_id))) + + response = self.client.call( + 'delete', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return response + def list_keys( self, queries: Optional[List[str]] = None, @@ -915,6 +1148,8 @@ def update_o_auth2_apple( team_id: Optional[str] = None, p8_file: Optional[str] = None, enabled: Optional[bool] = None, + native_client_ids: Optional[List[str]] = None, + native_enabled: Optional[bool] = None, ) -> OAuth2Apple: """ Update the project OAuth2 Apple configuration. @@ -930,7 +1165,11 @@ def update_o_auth2_apple( p8_file : Optional[str] Contents of the Apple OAuth2 app .p8 private key file. The secret key wrapped by the PEM markers is 200 characters long. For example: -----BEGIN PRIVATE KEY-----MIGTAg...jy2Xbna-----END PRIVATE KEY----- enabled : Optional[bool] - OAuth2 sign-in method status. Set to true to enable new session creation. Setting to true will trigger end-to-end credentials validation, and will throw if the credentials are invalid. + Browser-based OAuth2 sign-in status. Set to true to enable new session creation through the redirect flow. Setting to true will trigger end-to-end credentials validation, and will throw if the credentials are invalid. Has no effect on native sign-in, which is controlled by nativeEnabled only. + native_client_ids : Optional[List[str]] + App bundle IDs accepted as ID token audiences for native Sign in with Apple. For example: com.example.app. Together with the Services ID, these are the only client IDs whose tokens are trusted. Pass an empty array to clear the list. + native_enabled : Optional[bool] + Native Sign in with Apple status. This is the only switch for creating sessions from ID tokens obtained on device and is independent of enabled. Needs a Services ID or at least one native client ID to match tokens against, but no key or team ID: this method verifies a signature rather than redeeming an authorization code. Returns ------- OAuth2Apple @@ -954,6 +1193,10 @@ def update_o_auth2_apple( api_params['p8File'] = self._normalize_value(p8_file) if enabled is not None: api_params['enabled'] = self._normalize_value(enabled) + if native_client_ids is not None: + api_params['nativeClientIds'] = self._normalize_value(native_client_ids) + if native_enabled is not None: + api_params['nativeEnabled'] = self._normalize_value(native_enabled) response = self.client.call( 'patch', @@ -1024,6 +1267,7 @@ def update_o_auth2_auth0( client_secret: Optional[str] = None, endpoint: Optional[str] = None, enabled: Optional[bool] = None, + prompt: Optional[List[ProjectOAuth2Auth0Prompt]] = None, ) -> OAuth2Auth0: """ Update the project OAuth2 Auth0 configuration. @@ -1038,6 +1282,8 @@ def update_o_auth2_auth0( Domain of Auth0 instance. For example: example.us.auth0.com enabled : Optional[bool] OAuth2 sign-in method status. Set to true to enable new session creation. Setting to true will trigger end-to-end credentials validation, and will throw if the credentials are invalid. + prompt : Optional[List[ProjectOAuth2Auth0Prompt]] + Array of Auth0 OAuth2 prompt values. If "none" is included, it must be the only element. "none" means: don't display any authentication or consent screens. "login" means: prompt the user to re-authenticate. "consent" means: prompt the user for consent. Pass an empty array to use the Auth0 default. Returns ------- OAuth2Auth0 @@ -1059,6 +1305,8 @@ def update_o_auth2_auth0( api_params['endpoint'] = self._normalize_value(endpoint) if enabled is not None: api_params['enabled'] = self._normalize_value(enabled) + if prompt is not None: + api_params['prompt'] = self._normalize_value(prompt) response = self.client.call( 'patch', @@ -1433,6 +1681,7 @@ def update_o_auth2_discord( client_id: Optional[str] = None, client_secret: Optional[str] = None, enabled: Optional[bool] = None, + prompt: Optional[List[ProjectOAuth2DiscordPrompt]] = None, ) -> OAuth2Discord: """ Update the project OAuth2 Discord configuration. @@ -1445,6 +1694,8 @@ def update_o_auth2_discord( 'Client Secret' of Discord OAuth2 app. For example: YmPXnM000000000000000000002zFg5D enabled : Optional[bool] OAuth2 sign-in method status. Set to true to enable new session creation. Setting to true will trigger end-to-end credentials validation, and will throw if the credentials are invalid. + prompt : Optional[List[ProjectOAuth2DiscordPrompt]] + Array with at most one Discord OAuth2 prompt value. "none" means: skip the authorization screen for users who already authorized the app with the requested scopes. "consent" means: ask users who already authorized the app to approve it again. Pass an empty array to use the Discord default. Returns ------- OAuth2Discord @@ -1464,6 +1715,8 @@ def update_o_auth2_discord( api_params['clientSecret'] = self._normalize_value(client_secret) if enabled is not None: api_params['enabled'] = self._normalize_value(enabled) + if prompt is not None: + api_params['prompt'] = self._normalize_value(prompt) response = self.client.call( 'patch', @@ -1788,6 +2041,7 @@ def update_o_auth2_git_hub( client_id: Optional[str] = None, client_secret: Optional[str] = None, enabled: Optional[bool] = None, + prompt: Optional[List[ProjectOAuth2GitHubPrompt]] = None, ) -> OAuth2Github: """ Update the project OAuth2 GitHub configuration. @@ -1800,6 +2054,8 @@ def update_o_auth2_git_hub( 'Client Secret' of GitHub OAuth2 app. For example: 5e07c00000000000000000000000000000198bcc enabled : Optional[bool] OAuth2 sign-in method status. Set to true to enable new session creation. Setting to true will trigger end-to-end credentials validation, and will throw if the credentials are invalid. + prompt : Optional[List[ProjectOAuth2GitHubPrompt]] + Array of GitHub OAuth2 prompt values. "select_account" means: prompt the user to select an account. Pass an empty array to use the GitHub default. Returns ------- OAuth2Github @@ -1819,6 +2075,8 @@ def update_o_auth2_git_hub( api_params['clientSecret'] = self._normalize_value(client_secret) if enabled is not None: api_params['enabled'] = self._normalize_value(enabled) + if prompt is not None: + api_params['prompt'] = self._normalize_value(prompt) response = self.client.call( 'patch', @@ -1894,6 +2152,8 @@ def update_o_auth2_google( client_secret: Optional[str] = None, prompt: Optional[List[ProjectOAuth2GooglePrompt]] = None, enabled: Optional[bool] = None, + native_client_ids: Optional[List[str]] = None, + native_enabled: Optional[bool] = None, ) -> OAuth2Google: """ Update the project OAuth2 Google configuration. @@ -1907,7 +2167,11 @@ def update_o_auth2_google( prompt : Optional[List[ProjectOAuth2GooglePrompt]] Array of Google OAuth2 prompt values. If "none" is included, it must be the only element. "none" means: don't display any authentication or consent screens. Must not be specified with other values. "consent" means: prompt the user for consent. "select_account" means: prompt the user to select an account. enabled : Optional[bool] - OAuth2 sign-in method status. Set to true to enable new session creation. Setting to true will trigger end-to-end credentials validation, and will throw if the credentials are invalid. + Browser-based OAuth2 sign-in status. Set to true to enable new session creation through the redirect flow. Setting to true will trigger end-to-end credentials validation, and will throw if the credentials are invalid. Has no effect on native sign-in, which is controlled by nativeEnabled only. + native_client_ids : Optional[List[str]] + Additional OAuth2 client IDs accepted as ID token audiences for native sign-in (Android and iOS client IDs). Together with the client ID, which is always accepted, these are the only client IDs whose tokens are trusted. Pass an empty array to clear the list. + native_enabled : Optional[bool] + Native Google sign-in status. This is the only switch for creating sessions from ID tokens obtained on device and is independent of enabled. Needs a client ID or at least one native client ID to match tokens against, but no client secret: this method verifies a signature rather than redeeming an authorization code. Returns ------- OAuth2Google @@ -1929,6 +2193,10 @@ def update_o_auth2_google( api_params['prompt'] = self._normalize_value(prompt) if enabled is not None: api_params['enabled'] = self._normalize_value(enabled) + if native_client_ids is not None: + api_params['nativeClientIds'] = self._normalize_value(native_client_ids) + if native_enabled is not None: + api_params['nativeEnabled'] = self._normalize_value(native_enabled) response = self.client.call( 'patch', @@ -1993,6 +2261,61 @@ def update_o_auth2_hugging_face( return self._parse_response(response, model=OAuth2HuggingFace) + def update_o_auth2_kakao( + self, + client_id: Optional[str] = None, + client_secret: Optional[str] = None, + prompt: Optional[List[ProjectOAuth2KakaoPrompt]] = None, + enabled: Optional[bool] = None, + ) -> OAuth2Kakao: + """ + Update the project OAuth2 Kakao configuration. + + Parameters + ---------- + client_id : Optional[str] + 'REST API key' of Kakao OAuth2 app. For example: 839ff5000000000000000000013206de + client_secret : Optional[str] + 'Client Secret' of Kakao OAuth2 app. For example: jLNVOK00000000000000000000yJebea. Generate it under Kakao Login > Security and set its status to enabled + prompt : Optional[List[ProjectOAuth2KakaoPrompt]] + Array of Kakao OAuth2 prompt values. If "none" is included, it must be the only element. "none" means: don't display any authentication or consent screens. "login" means: prompt the user to re-authenticate. "create" means: prompt the user to sign up. "select_account" means: prompt the user to select an account. Pass an empty array to use the Kakao default. + enabled : Optional[bool] + OAuth2 sign-in method status. Set to true to enable new session creation. Setting to true will trigger end-to-end credentials validation, and will throw if the credentials are invalid. + Returns + ------- + OAuth2Kakao + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/project/oauth2/kakao' + api_params = {} + if client_id is not None: + api_params['clientId'] = self._normalize_value(client_id) + if client_secret is not None: + api_params['clientSecret'] = self._normalize_value(client_secret) + if prompt is not None: + api_params['prompt'] = self._normalize_value(prompt) + if enabled is not None: + api_params['enabled'] = self._normalize_value(enabled) + + response = self.client.call( + 'patch', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=OAuth2Kakao) + def update_o_auth2_keycloak( self, client_id: Optional[str] = None, @@ -2159,6 +2482,7 @@ def update_o_auth2_microsoft( application_secret: Optional[str] = None, tenant: Optional[str] = None, enabled: Optional[bool] = None, + prompt: Optional[List[ProjectOAuth2MicrosoftPrompt]] = None, ) -> OAuth2Microsoft: """ Update the project OAuth2 Microsoft configuration. @@ -2173,6 +2497,8 @@ def update_o_auth2_microsoft( Microsoft Entra ID tenant identifier. Use 'common', 'organizations', 'consumers' or a specific tenant ID. For example: common enabled : Optional[bool] OAuth2 sign-in method status. Set to true to enable new session creation. Setting to true will trigger end-to-end credentials validation, and will throw if the credentials are invalid. + prompt : Optional[List[ProjectOAuth2MicrosoftPrompt]] + Array of Microsoft OAuth2 prompt values. "none" means: don't display any authentication or consent screens. "login" means: prompt the user to re-authenticate. "consent" means: prompt the user for consent. "select_account" means: prompt the user to select an account. Pass an empty array to use the Microsoft default. Returns ------- OAuth2Microsoft @@ -2194,6 +2520,8 @@ def update_o_auth2_microsoft( api_params['tenant'] = self._normalize_value(tenant) if enabled is not None: api_params['enabled'] = self._normalize_value(enabled) + if prompt is not None: + api_params['prompt'] = self._normalize_value(prompt) response = self.client.call( 'patch', @@ -2345,6 +2673,7 @@ def update_o_auth2_okta( domain: Optional[str] = None, authorization_server_id: Optional[str] = None, enabled: Optional[bool] = None, + prompt: Optional[List[ProjectOAuth2OktaPrompt]] = None, ) -> OAuth2Okta: """ Update the project OAuth2 Okta configuration. @@ -2361,6 +2690,8 @@ def update_o_auth2_okta( Custom Authorization Servers. Optional, can be left empty or unconfigured. For example: aus000000000000000h7z enabled : Optional[bool] OAuth2 sign-in method status. Set to true to enable new session creation. Setting to true will trigger end-to-end credentials validation, and will throw if the credentials are invalid. + prompt : Optional[List[ProjectOAuth2OktaPrompt]] + Array of Okta OAuth2 prompt values. If "none" is included, it must be the only element. "none" means: don't display any authentication or consent screens. "login" means: prompt the user to re-authenticate. "consent" means: prompt the user for consent. Pass an empty array to use the Okta default. Returns ------- OAuth2Okta @@ -2384,6 +2715,8 @@ def update_o_auth2_okta( api_params['authorizationServerId'] = self._normalize_value(authorization_server_id) if enabled is not None: api_params['enabled'] = self._normalize_value(enabled) + if prompt is not None: + api_params['prompt'] = self._normalize_value(prompt) response = self.client.call( 'patch', @@ -2603,6 +2936,7 @@ def update_o_auth2_salesforce( customer_key: Optional[str] = None, customer_secret: Optional[str] = None, enabled: Optional[bool] = None, + prompt: Optional[List[ProjectOAuth2SalesforcePrompt]] = None, ) -> OAuth2Salesforce: """ Update the project OAuth2 Salesforce configuration. @@ -2615,6 +2949,8 @@ def update_o_auth2_salesforce( 'Consumer Secret' of Salesforce OAuth2 app. For example: 3w000000000000e2 enabled : Optional[bool] OAuth2 sign-in method status. Set to true to enable new session creation. Setting to true will trigger end-to-end credentials validation, and will throw if the credentials are invalid. + prompt : Optional[List[ProjectOAuth2SalesforcePrompt]] + Array of Salesforce OAuth2 prompt values. "login" means: prompt the user to re-authenticate. "consent" means: prompt the user for consent. Pass an empty array to use the Salesforce default. Returns ------- OAuth2Salesforce @@ -2634,6 +2970,8 @@ def update_o_auth2_salesforce( api_params['customerSecret'] = self._normalize_value(customer_secret) if enabled is not None: api_params['enabled'] = self._normalize_value(enabled) + if prompt is not None: + api_params['prompt'] = self._normalize_value(prompt) response = self.client.call( 'patch', @@ -2798,6 +3136,56 @@ def update_o_auth2_stripe( return self._parse_response(response, model=OAuth2Stripe) + def update_o_auth2_tik_tok( + self, + client_id: Optional[str] = None, + client_secret: Optional[str] = None, + enabled: Optional[bool] = None, + ) -> OAuth2TikTok: + """ + Update the project OAuth2 TikTok configuration. + + Parameters + ---------- + client_id : Optional[str] + 'Client key' of TikTok OAuth2 app. For example: awz000000000tyw0 + client_secret : Optional[str] + 'Client secret' of TikTok OAuth2 app. For example: 6wXewM00000000000000000000yXnite + enabled : Optional[bool] + OAuth2 sign-in method status. Set to true to enable new session creation. Setting to true will trigger end-to-end credentials validation, and will throw if the credentials are invalid. + Returns + ------- + OAuth2TikTok + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/project/oauth2/tiktok' + api_params = {} + if client_id is not None: + api_params['clientId'] = self._normalize_value(client_id) + if client_secret is not None: + api_params['clientSecret'] = self._normalize_value(client_secret) + if enabled is not None: + api_params['enabled'] = self._normalize_value(enabled) + + response = self.client.call( + 'patch', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=OAuth2TikTok) + def update_o_auth2_tradeshift( self, oauth2_client_id: Optional[str] = None, @@ -2948,6 +3336,56 @@ def update_o_auth2_twitch( return self._parse_response(response, model=OAuth2Twitch) + def update_o_auth2_webflow( + self, + client_id: Optional[str] = None, + client_secret: Optional[str] = None, + enabled: Optional[bool] = None, + ) -> OAuth2Webflow: + """ + Update the project OAuth2 Webflow configuration. + + Parameters + ---------- + client_id : Optional[str] + 'Client ID' of Webflow OAuth2 app. For example: 8bb20000000000000000000000000000000000000000000000000000000040dd + client_secret : Optional[str] + 'Client Secret' of Webflow OAuth2 app. For example: 59bf00000000000000000000000000000000000000000000000000000000fe59 + enabled : Optional[bool] + OAuth2 sign-in method status. Set to true to enable new session creation. Setting to true will trigger end-to-end credentials validation, and will throw if the credentials are invalid. + Returns + ------- + OAuth2Webflow + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/project/oauth2/webflow' + api_params = {} + if client_id is not None: + api_params['clientId'] = self._normalize_value(client_id) + if client_secret is not None: + api_params['clientSecret'] = self._normalize_value(client_secret) + if enabled is not None: + api_params['enabled'] = self._normalize_value(enabled) + + response = self.client.call( + 'patch', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=OAuth2Webflow) + def update_o_auth2_word_press( self, client_id: Optional[str] = None, @@ -3153,6 +3591,7 @@ def update_o_auth2_zoho( client_id: Optional[str] = None, client_secret: Optional[str] = None, enabled: Optional[bool] = None, + prompt: Optional[List[ProjectOAuth2ZohoPrompt]] = None, ) -> OAuth2Zoho: """ Update the project OAuth2 Zoho configuration. @@ -3165,6 +3604,8 @@ def update_o_auth2_zoho( 'Client Secret' of Zoho OAuth2 app. For example: fb5cac000000000000000000000000000000a68f6e enabled : Optional[bool] OAuth2 sign-in method status. Set to true to enable new session creation. Setting to true will trigger end-to-end credentials validation, and will throw if the credentials are invalid. + prompt : Optional[List[ProjectOAuth2ZohoPrompt]] + Array of Zoho OAuth2 prompt values. "consent" means: prompt the user for consent. Pass an empty array to use the Zoho default. Returns ------- OAuth2Zoho @@ -3184,6 +3625,8 @@ def update_o_auth2_zoho( api_params['clientSecret'] = self._normalize_value(client_secret) if enabled is not None: api_params['enabled'] = self._normalize_value(enabled) + if prompt is not None: + api_params['prompt'] = self._normalize_value(prompt) response = self.client.call( 'patch', @@ -3267,6 +3710,7 @@ def get_o_auth2_provider( OAuth2Yandex, OAuth2X, OAuth2WordPress, + OAuth2Webflow, OAuth2Twitch, OAuth2Stripe, OAuth2Spotify, @@ -3295,6 +3739,8 @@ def get_o_auth2_provider( OAuth2Okta, OAuth2Kick, OAuth2Microsoft, + OAuth2TikTok, + OAuth2Kakao, ]: """ Get a single OAuth2 provider configuration. Credential fields (client secret, p8 file, key/team IDs) are write-only and always returned empty. @@ -3305,7 +3751,7 @@ def get_o_auth2_provider( OAuth2 provider key. For example: github, google, apple. Returns ------- - Union[OAuth2Github, OAuth2Discord, OAuth2Figma, OAuth2Dropbox, OAuth2Dailymotion, OAuth2Bitbucket, OAuth2Bitly, OAuth2Box, OAuth2Autodesk, OAuth2Google, OAuth2Zoom, OAuth2Zoho, OAuth2Yandex, OAuth2X, OAuth2WordPress, OAuth2Twitch, OAuth2Stripe, OAuth2Spotify, OAuth2Slack, OAuth2Podio, OAuth2Notion, OAuth2Salesforce, OAuth2Yahoo, OAuth2HuggingFace, OAuth2Resend, OAuth2Cloudflare, OAuth2Linkedin, OAuth2Disqus, OAuth2Amazon, OAuth2Etsy, OAuth2Facebook, OAuth2Tradeshift, OAuth2Paypal, OAuth2Gitlab, OAuth2Authentik, OAuth2Auth0, OAuth2FusionAuth, OAuth2Keycloak, OAuth2Oidc, OAuth2Apple, OAuth2Okta, OAuth2Kick, OAuth2Microsoft] + Union[OAuth2Github, OAuth2Discord, OAuth2Figma, OAuth2Dropbox, OAuth2Dailymotion, OAuth2Bitbucket, OAuth2Bitly, OAuth2Box, OAuth2Autodesk, OAuth2Google, OAuth2Zoom, OAuth2Zoho, OAuth2Yandex, OAuth2X, OAuth2WordPress, OAuth2Webflow, OAuth2Twitch, OAuth2Stripe, OAuth2Spotify, OAuth2Slack, OAuth2Podio, OAuth2Notion, OAuth2Salesforce, OAuth2Yahoo, OAuth2HuggingFace, OAuth2Resend, OAuth2Cloudflare, OAuth2Linkedin, OAuth2Disqus, OAuth2Amazon, OAuth2Etsy, OAuth2Facebook, OAuth2Tradeshift, OAuth2Paypal, OAuth2Gitlab, OAuth2Authentik, OAuth2Auth0, OAuth2FusionAuth, OAuth2Keycloak, OAuth2Oidc, OAuth2Apple, OAuth2Okta, OAuth2Kick, OAuth2Microsoft, OAuth2TikTok, OAuth2Kakao] API response as one of the typed response models Raises @@ -3377,6 +3823,9 @@ def get_o_auth2_provider( if response.get('$id') == 'wordpress': return self._parse_response(response, model=OAuth2WordPress) + if response.get('$id') == 'webflow': + return self._parse_response(response, model=OAuth2Webflow) + if response.get('$id') == 'twitch': return self._parse_response(response, model=OAuth2Twitch) @@ -3461,6 +3910,12 @@ def get_o_auth2_provider( if response.get('$id') == 'microsoft': return self._parse_response(response, model=OAuth2Microsoft) + if response.get('$id') == 'tiktok': + return self._parse_response(response, model=OAuth2TikTok) + + if response.get('$id') == 'kakao': + return self._parse_response(response, model=OAuth2Kakao) + raise AppwriteException('Unable to match response to any known model') def list_platforms( @@ -3512,6 +3967,7 @@ def create_android_platform( platform_id: str, name: str, application_id: str, + fingerprints: Optional[List[str]] = None, ) -> PlatformAndroid: """ Create a new Android platform for your project. Use this endpoint to register a new Android platform where your users will run your application which will interact with the Appwrite API. @@ -3524,6 +3980,8 @@ def create_android_platform( Platform name. Max length: 128 chars. application_id : str Android application ID. Max length: 256 chars. + fingerprints : Optional[List[str]] + SHA-256 fingerprints of the certificates your app is signed with, such as "14:6D:E9:...:2B:6A". Passkeys created in the app are accepted when its signature matches one. Find them under App signing in Play Console, or with `./gradlew signingReport`. Returns ------- PlatformAndroid @@ -3546,6 +4004,8 @@ def create_android_platform( api_params['platformId'] = self._normalize_value(platform_id) api_params['name'] = self._normalize_value(name) api_params['applicationId'] = self._normalize_value(application_id) + if fingerprints is not None: + api_params['fingerprints'] = self._normalize_value(fingerprints) response = self.client.call( 'post', @@ -3565,6 +4025,7 @@ def update_android_platform( platform_id: str, name: str, application_id: str, + fingerprints: Optional[List[str]] = None, ) -> PlatformAndroid: """ Update an Android platform by its unique ID. Use this endpoint to update the platform's name or application ID. @@ -3577,6 +4038,8 @@ def update_android_platform( Platform name. Max length: 128 chars. application_id : str Android application ID. Max length: 256 chars. + fingerprints : Optional[List[str]] + SHA-256 fingerprints of the certificates your app is signed with, such as "14:6D:E9:...:2B:6A". Passkeys created in the app are accepted when its signature matches one. Find them under App signing in Play Console, or with `./gradlew signingReport`. Omit to keep the current list, or pass an empty array to clear it. Returns ------- PlatformAndroid @@ -3599,6 +4062,8 @@ def update_android_platform( api_path = api_path.replace('{platformId}', str(self._normalize_value(platform_id))) api_params['name'] = self._normalize_value(name) api_params['applicationId'] = self._normalize_value(application_id) + if fingerprints is not None: + api_params['fingerprints'] = self._normalize_value(fingerprints) response = self.client.call( 'put', @@ -4632,6 +5097,101 @@ def update_password_personal_data_policy( return self._parse_response(response, model=ProjectModel) + def update_password_pwned_policy( + self, + enabled: Optional[bool] = None, + sessions: Optional[bool] = None, + users: Optional[bool] = None, + ) -> ProjectModel: + """ + Updating this policy allows you to control if passwords are checked against the Have I Been Pwned breach database. When enabled, every password a user signs up, signs in or resets with is checked and the result is recorded on the user as `passwordPwned`. On its own the policy only records. Enable `users` to reject a breached password when a user signs up or sets a new password, and `sessions` to refuse a sign-in with a breached password until it is reset. Only the first five characters of the password hash are ever shared with the service. Options left out keep their current value. + + Parameters + ---------- + enabled : Optional[bool] + Toggle password pwned policy. Set to true to check passwords against known data breaches and record the result on the user, or false to never check. Default is true. On its own this only records; use `users` and `sessions` to block. When changing this policy, existing passwords remain valid. + sessions : Optional[bool] + Whether a sign-in with a breached password is refused until the password is reset. Default is false, which allows the sign-in and only records the result. + users : Optional[bool] + Whether a breached password is rejected when a user signs up or sets a new password. Default is false, which allows the password and only records the result. + Returns + ------- + ProjectModel + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/project/policies/password-pwned' + api_params = {} + if enabled is not None: + api_params['enabled'] = self._normalize_value(enabled) + if sessions is not None: + api_params['sessions'] = self._normalize_value(sessions) + if users is not None: + api_params['users'] = self._normalize_value(users) + + response = self.client.call( + 'patch', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=ProjectModel) + + def update_password_rotation_policy( + self, + enabled: Optional[bool] = None, + max_age: Optional[float] = None, + ) -> ProjectModel: + """ + Require a password reset when an email/password sign-in uses a password older than the configured maximum age. Options left out keep their current value. + + Parameters + ---------- + enabled : Optional[bool] + Enable password rotation. Disabled by default. + max_age : Optional[float] + Maximum password age in seconds. Minimum allowed value is 86400 seconds (1 day), and maximum is 10 years, which is 315360000 seconds. Defaults to 1 year, which is 31536000 seconds. + Returns + ------- + ProjectModel + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/project/policies/password-rotation' + api_params = {} + if enabled is not None: + api_params['enabled'] = self._normalize_value(enabled) + if max_age is not None: + api_params['maxAge'] = self._normalize_value(max_age) + + response = self.client.call( + 'patch', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=ProjectModel) + def update_password_strength_policy( self, min: Optional[float] = None, @@ -4903,6 +5463,8 @@ def get_policy( PolicyPasswordHistory, PolicyPasswordStrength, PolicyPasswordPersonalData, + PolicyPasswordPwned, + PolicyPasswordRotation, PolicySessionAlert, PolicySessionDuration, PolicySessionInvalidation, @@ -4925,7 +5487,7 @@ def get_policy( Policy ID. Can be one of: password-dictionary, password-history, password-strength, password-personal-data, session-alert, session-duration, session-invalidation, session-limit, user-limit, membership-privacy, mfa-factors, deny-aliased-email, deny-disposable-email, deny-free-email, deny-corporate-email. Returns ------- - Union[PolicyPasswordDictionary, PolicyPasswordHistory, PolicyPasswordStrength, PolicyPasswordPersonalData, PolicySessionAlert, PolicySessionDuration, PolicySessionInvalidation, PolicySessionLimit, PolicyUserLimit, PolicyMembershipPrivacy, PolicyMfaFactors, PolicyDenyAliasedEmail, PolicyDenyDisposableEmail, PolicyDenyFreeEmail, PolicyDenyCorporateEmail, PolicyPasskey] + Union[PolicyPasswordDictionary, PolicyPasswordHistory, PolicyPasswordStrength, PolicyPasswordPersonalData, PolicyPasswordPwned, PolicyPasswordRotation, PolicySessionAlert, PolicySessionDuration, PolicySessionInvalidation, PolicySessionLimit, PolicyUserLimit, PolicyMembershipPrivacy, PolicyMfaFactors, PolicyDenyAliasedEmail, PolicyDenyDisposableEmail, PolicyDenyFreeEmail, PolicyDenyCorporateEmail, PolicyPasskey] API response as one of the typed response models Raises @@ -4964,6 +5526,12 @@ def get_policy( if response.get('$id') == 'password-personal-data': return self._parse_response(response, model=PolicyPasswordPersonalData) + if response.get('$id') == 'password-pwned': + return self._parse_response(response, model=PolicyPasswordPwned) + + if response.get('$id') == 'password-rotation': + return self._parse_response(response, model=PolicyPasswordRotation) + if response.get('$id') == 'session-alert': return self._parse_response(response, model=PolicySessionAlert) diff --git a/appwrite/services/sites.py b/appwrite/services/sites.py index 36a29462..3766cce7 100644 --- a/appwrite/services/sites.py +++ b/appwrite/services/sites.py @@ -238,9 +238,15 @@ def create( def list_frameworks( self, + total: Optional[bool] = None, ) -> FrameworkList: """ Get a list of all frameworks that are currently available on the server instance. + + Parameters + ---------- + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. Returns ------- FrameworkList @@ -254,6 +260,8 @@ def list_frameworks( api_path = '/sites/frameworks' api_params = {} + if total is not None: + api_params['total'] = self._normalize_value(total) response = self.client.call( 'get', @@ -270,6 +278,7 @@ def list_frameworks( def list_specifications( self, type: Optional[str] = None, + total: Optional[bool] = None, ) -> SpecificationList: """ List allowed site specifications for this instance. @@ -278,6 +287,8 @@ def list_specifications( ---------- type : Optional[str] Specification type to list. Can be one of: runtimes, builds. Defaults to runtimes. + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. Returns ------- SpecificationList @@ -293,6 +304,8 @@ def list_specifications( api_params = {} if type is not None: api_params['type'] = self._normalize_value(type) + if total is not None: + api_params['total'] = self._normalize_value(total) response = self.client.call( 'get', diff --git a/appwrite/services/tables_db.py b/appwrite/services/tables_db.py index f7e8ed2e..17ed9f8d 100644 --- a/appwrite/services/tables_db.py +++ b/appwrite/services/tables_db.py @@ -202,6 +202,7 @@ def list_specifications( def list_transactions( self, queries: Optional[List[str]] = None, + total: Optional[bool] = None, ) -> TransactionList: """ List transactions across all databases. @@ -210,6 +211,8 @@ def list_transactions( ---------- queries : Optional[List[str]] Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. Returns ------- TransactionList @@ -225,6 +228,8 @@ def list_transactions( api_params = {} if queries is not None: api_params['queries'] = self._normalize_value(queries) + if total is not None: + api_params['total'] = self._normalize_value(total) response = self.client.call( 'get', diff --git a/appwrite/services/teams.py b/appwrite/services/teams.py index 9df2eb7e..48092675 100644 --- a/appwrite/services/teams.py +++ b/appwrite/services/teams.py @@ -574,6 +574,7 @@ def create_membership( phone: Optional[str] = None, url: Optional[str] = None, name: Optional[str] = None, + membership_id: Optional[str] = None, ) -> Membership: """ Invite a new member to join your team. Provide an ID for existing users, or invite unregistered users using an email or phone number. If initiated from a Client SDK, Appwrite will send an email or sms with a link to join the team to the invited user, and an account will be created for them if one doesn't exist. If initiated from a Server SDK, the new member will be added automatically to the team. @@ -600,6 +601,8 @@ def create_membership( URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API. name : Optional[str] Name of the new team member. Max length: 128 chars. + membership_id : Optional[str] + Membership ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. Returns ------- Membership @@ -629,6 +632,8 @@ def create_membership( api_params['url'] = self._normalize_value(url) if name is not None: api_params['name'] = self._normalize_value(name) + if membership_id is not None: + api_params['membershipId'] = self._normalize_value(membership_id) response = self.client.call( 'post', diff --git a/appwrite/services/vectors_db.py b/appwrite/services/vectors_db.py index eede5fa1..a23ccb29 100644 --- a/appwrite/services/vectors_db.py +++ b/appwrite/services/vectors_db.py @@ -174,6 +174,7 @@ def list_specifications( def list_transactions( self, queries: Optional[List[str]] = None, + total: Optional[bool] = None, ) -> TransactionList: """ List transactions across all databases. @@ -182,6 +183,8 @@ def list_transactions( ---------- queries : Optional[List[str]] Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. Returns ------- TransactionList @@ -197,6 +200,8 @@ def list_transactions( api_params = {} if queries is not None: api_params['queries'] = self._normalize_value(queries) + if total is not None: + api_params['total'] = self._normalize_value(total) response = self.client.call( 'get', diff --git a/appwrite/services/waf.py b/appwrite/services/waf.py new file mode 100644 index 00000000..8aaa3ebc --- /dev/null +++ b/appwrite/services/waf.py @@ -0,0 +1,1039 @@ +from ..service import Service +from urllib.parse import quote +from typing import Any, Dict, List, Optional, Union +from ..exception import AppwriteException +from appwrite.utils.deprecated import deprecated +from ..models.waf_rule_list import WafRuleList +from ..models.waf_rule_bypass import WafRuleBypass +from ..models.waf_rule_challenge import WafRuleChallenge +from ..models.waf_rule_deny import WafRuleDeny +from ..models.waf_rule_rate_limit import WafRuleRateLimit +from ..models.waf_rule_redirect import WafRuleRedirect + + +class Waf(Service): + + def __init__(self, client) -> None: + super(Waf, self).__init__(client) + + def list_rules( + self, + queries: Optional[List[str]] = None, + search: Optional[str] = None, + total: Optional[bool] = None, + ) -> WafRuleList: + """ + List WAF rules for the current project. + + Parameters + ---------- + queries : Optional[List[str]] + Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of 100 queries are allowed, each 4096 characters long. + search : Optional[str] + Search term to filter your list results. Max length: 256 chars. + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. + Returns + ------- + WafRuleList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/waf/rules' + api_params = {} + if queries is not None: + api_params['queries'] = self._normalize_value(queries) + if search is not None: + api_params['search'] = self._normalize_value(search) + if total is not None: + api_params['total'] = self._normalize_value(total) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=WafRuleList) + + def create_bypass_rule( + self, + rule_id: str, + resource_type: str, + name: str, + resource_id: Optional[str] = None, + description: Optional[str] = None, + priority: Optional[float] = None, + enabled: Optional[bool] = None, + conditions: Optional[List[str]] = None, + ) -> WafRuleBypass: + """ + Create a bypass WAF rule. Conditions can match request attributes including `ip` (plain IPs or CIDR blocks like `10.0.0.0/8`), `method`, `path`, `host`, `country`, `continent`, `headers.`, `query.`, `queryKeys`, `userAgent`, `os`, `osVersion`, `browser`, and `browserVersion`. Conditions on `city` and `state` require the premium Geo DB addon. + + Parameters + ---------- + rule_id : str + Rule ID. Choose a custom ID or pass `ID.unique()` to generate a unique one. + resource_type : str + Resource type the rule applies to. + name : str + Rule name. + resource_id : Optional[str] + Resource identifier. Leave empty for the API resource type. + description : Optional[str] + Optional description for the rule. + priority : Optional[float] + Evaluation priority. Lower numbers run earlier. + enabled : Optional[bool] + Set to false to create the rule in a disabled state. + conditions : Optional[List[str]] + Array of condition strings generated using the WAF Condition builder. Maximum of 100 conditions are allowed, each 4096 characters long. + Returns + ------- + WafRuleBypass + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/waf/rules/bypass' + api_params = {} + if rule_id is None: + raise AppwriteException('Missing required parameter: "rule_id"') + if resource_type is None: + raise AppwriteException('Missing required parameter: "resource_type"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + api_params['ruleId'] = self._normalize_value(rule_id) + api_params['resourceType'] = self._normalize_value(resource_type) + if resource_id is not None: + api_params['resourceId'] = self._normalize_value(resource_id) + api_params['name'] = self._normalize_value(name) + if description is not None: + api_params['description'] = self._normalize_value(description) + if priority is not None: + api_params['priority'] = self._normalize_value(priority) + if enabled is not None: + api_params['enabled'] = self._normalize_value(enabled) + if conditions is not None: + api_params['conditions'] = self._normalize_value(conditions) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=WafRuleBypass) + + def update_bypass_rule( + self, + rule_id: str, + resource_type: Optional[str] = None, + resource_id: Optional[str] = None, + name: Optional[str] = None, + description: Optional[str] = None, + priority: Optional[float] = None, + enabled: Optional[bool] = None, + conditions: Optional[List[str]] = None, + ) -> WafRuleBypass: + """ + Update a bypass WAF rule. Conditions can match request attributes including `ip` (plain IPs or CIDR blocks like `10.0.0.0/8`), `method`, `path`, `host`, `country`, `continent`, `headers.`, `query.`, `queryKeys`, `userAgent`, `os`, `osVersion`, `browser`, and `browserVersion`. Conditions on `city` and `state` require the premium Geo DB addon. + + Parameters + ---------- + rule_id : str + Rule ID. + resource_type : Optional[str] + Resource type the rule applies to. + resource_id : Optional[str] + Resource identifier. Required for functions and sites. + name : Optional[str] + Rule name. + description : Optional[str] + Optional description for the rule. + priority : Optional[float] + Evaluation priority. Lower numbers run earlier. + enabled : Optional[bool] + Set to false to disable the rule. + conditions : Optional[List[str]] + Array of condition strings generated using the WAF Condition builder. Maximum of 100 conditions are allowed, each 4096 characters long. + Returns + ------- + WafRuleBypass + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/waf/rules/bypass/{ruleId}' + api_params = {} + if rule_id is None or rule_id == '': + raise AppwriteException('Missing required parameter: "rule_id"') + api_path = api_path.replace('{ruleId}', str(self._normalize_value(rule_id))) + if resource_type is not None: + api_params['resourceType'] = self._normalize_value(resource_type) + if resource_id is not None: + api_params['resourceId'] = self._normalize_value(resource_id) + if name is not None: + api_params['name'] = self._normalize_value(name) + if description is not None: + api_params['description'] = self._normalize_value(description) + if priority is not None: + api_params['priority'] = self._normalize_value(priority) + if enabled is not None: + api_params['enabled'] = self._normalize_value(enabled) + if conditions is not None: + api_params['conditions'] = self._normalize_value(conditions) + + response = self.client.call( + 'patch', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=WafRuleBypass) + + def create_challenge_rule( + self, + rule_id: str, + resource_type: str, + name: str, + resource_id: Optional[str] = None, + description: Optional[str] = None, + challenge_type: Optional[str] = None, + priority: Optional[float] = None, + enabled: Optional[bool] = None, + conditions: Optional[List[str]] = None, + difficulty: Optional[float] = None, + ttl: Optional[float] = None, + ) -> WafRuleChallenge: + """ + Create a challenge WAF rule. Use `difficulty` (1 easiest to 5 hardest) to tune the client-side proof-of-work cost, and `ttl` to control how long, in seconds, a visitor stays cleared after passing the challenge before being challenged again. Conditions can match request attributes including `ip` (plain IPs or CIDR blocks like `10.0.0.0/8`), `method`, `path`, `host`, `country`, `continent`, `headers.`, `query.`, `queryKeys`, `userAgent`, `os`, `osVersion`, `browser`, and `browserVersion`. Conditions on `city` and `state` require the premium Geo DB addon. + + Parameters + ---------- + rule_id : str + Rule ID. Choose a custom ID or pass `ID.unique()` to generate a unique one. + resource_type : str + Resource type the rule applies to. + name : str + Rule name. + resource_id : Optional[str] + Resource identifier. Required for functions and sites. + description : Optional[str] + Optional description for the rule. + challenge_type : Optional[str] + Challenge type enforced by the rule. + priority : Optional[float] + Evaluation priority. Lower numbers run earlier. + enabled : Optional[bool] + Set to false to create the rule in a disabled state. + conditions : Optional[List[str]] + Array of condition strings generated using the WAF Condition builder. Maximum of 100 conditions are allowed, each 4096 characters long. + difficulty : Optional[float] + Challenge difficulty from 1 (easiest) to 5 (hardest). Higher values demand more client-side proof-of-work. + ttl : Optional[float] + How long, in seconds, a visitor stays cleared after passing the challenge before being challenged again. + Returns + ------- + WafRuleChallenge + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/waf/rules/challenge' + api_params = {} + if rule_id is None: + raise AppwriteException('Missing required parameter: "rule_id"') + if resource_type is None: + raise AppwriteException('Missing required parameter: "resource_type"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + api_params['ruleId'] = self._normalize_value(rule_id) + api_params['resourceType'] = self._normalize_value(resource_type) + if resource_id is not None: + api_params['resourceId'] = self._normalize_value(resource_id) + api_params['name'] = self._normalize_value(name) + if description is not None: + api_params['description'] = self._normalize_value(description) + if challenge_type is not None: + api_params['challengeType'] = self._normalize_value(challenge_type) + if priority is not None: + api_params['priority'] = self._normalize_value(priority) + if enabled is not None: + api_params['enabled'] = self._normalize_value(enabled) + if conditions is not None: + api_params['conditions'] = self._normalize_value(conditions) + if difficulty is not None: + api_params['difficulty'] = self._normalize_value(difficulty) + if ttl is not None: + api_params['ttl'] = self._normalize_value(ttl) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=WafRuleChallenge) + + def update_challenge_rule( + self, + rule_id: str, + resource_type: Optional[str] = None, + resource_id: Optional[str] = None, + name: Optional[str] = None, + description: Optional[str] = None, + challenge_type: Optional[str] = None, + priority: Optional[float] = None, + enabled: Optional[bool] = None, + conditions: Optional[List[str]] = None, + difficulty: Optional[float] = None, + ttl: Optional[float] = None, + ) -> WafRuleChallenge: + """ + Update a challenge WAF rule. Use `difficulty` (1 easiest to 5 hardest) to tune the client-side proof-of-work cost, and `ttl` to control how long, in seconds, a visitor stays cleared after passing the challenge before being challenged again. Conditions can match request attributes including `ip` (plain IPs or CIDR blocks like `10.0.0.0/8`), `method`, `path`, `host`, `country`, `continent`, `headers.`, `query.`, `queryKeys`, `userAgent`, `os`, `osVersion`, `browser`, and `browserVersion`. Conditions on `city` and `state` require the premium Geo DB addon. + + Parameters + ---------- + rule_id : str + Rule ID. + resource_type : Optional[str] + Resource type the rule applies to. + resource_id : Optional[str] + Resource identifier. Required for functions and sites. + name : Optional[str] + Rule name. + description : Optional[str] + Optional description for the rule. + challenge_type : Optional[str] + Challenge type enforced by the rule. + priority : Optional[float] + Evaluation priority. Lower numbers run earlier. + enabled : Optional[bool] + Set to false to disable the rule. + conditions : Optional[List[str]] + Array of condition strings generated using the WAF Condition builder. Maximum of 100 conditions are allowed, each 4096 characters long. + difficulty : Optional[float] + Challenge difficulty from 1 (easiest) to 5 (hardest). Higher values demand more client-side proof-of-work. + ttl : Optional[float] + How long, in seconds, a visitor stays cleared after passing the challenge before being challenged again. + Returns + ------- + WafRuleChallenge + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/waf/rules/challenge/{ruleId}' + api_params = {} + if rule_id is None or rule_id == '': + raise AppwriteException('Missing required parameter: "rule_id"') + api_path = api_path.replace('{ruleId}', str(self._normalize_value(rule_id))) + if resource_type is not None: + api_params['resourceType'] = self._normalize_value(resource_type) + if resource_id is not None: + api_params['resourceId'] = self._normalize_value(resource_id) + if name is not None: + api_params['name'] = self._normalize_value(name) + if description is not None: + api_params['description'] = self._normalize_value(description) + if challenge_type is not None: + api_params['challengeType'] = self._normalize_value(challenge_type) + if priority is not None: + api_params['priority'] = self._normalize_value(priority) + if enabled is not None: + api_params['enabled'] = self._normalize_value(enabled) + if conditions is not None: + api_params['conditions'] = self._normalize_value(conditions) + if difficulty is not None: + api_params['difficulty'] = self._normalize_value(difficulty) + if ttl is not None: + api_params['ttl'] = self._normalize_value(ttl) + + response = self.client.call( + 'patch', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=WafRuleChallenge) + + def create_deny_rule( + self, + rule_id: str, + resource_type: str, + name: str, + resource_id: Optional[str] = None, + description: Optional[str] = None, + priority: Optional[float] = None, + enabled: Optional[bool] = None, + conditions: Optional[List[str]] = None, + ) -> WafRuleDeny: + """ + Create a deny WAF rule. Conditions can match request attributes including `ip` (plain IPs or CIDR blocks like `10.0.0.0/8`), `method`, `path`, `host`, `country`, `continent`, `headers.`, `query.`, `queryKeys`, `userAgent`, `os`, `osVersion`, `browser`, and `browserVersion`. Conditions on `city` and `state` require the premium Geo DB addon. + + Parameters + ---------- + rule_id : str + Rule ID. Choose a custom ID or pass `ID.unique()` to generate a unique one. + resource_type : str + Resource type the rule applies to. + name : str + Rule name. + resource_id : Optional[str] + Resource identifier. Required for functions and sites. + description : Optional[str] + Optional description for the rule. + priority : Optional[float] + Evaluation priority. Lower numbers run earlier. + enabled : Optional[bool] + Set to false to create the rule in a disabled state. + conditions : Optional[List[str]] + Array of condition strings generated using the WAF Condition builder. Maximum of 100 conditions are allowed, each 4096 characters long. + Returns + ------- + WafRuleDeny + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/waf/rules/deny' + api_params = {} + if rule_id is None: + raise AppwriteException('Missing required parameter: "rule_id"') + if resource_type is None: + raise AppwriteException('Missing required parameter: "resource_type"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + api_params['ruleId'] = self._normalize_value(rule_id) + api_params['resourceType'] = self._normalize_value(resource_type) + if resource_id is not None: + api_params['resourceId'] = self._normalize_value(resource_id) + api_params['name'] = self._normalize_value(name) + if description is not None: + api_params['description'] = self._normalize_value(description) + if priority is not None: + api_params['priority'] = self._normalize_value(priority) + if enabled is not None: + api_params['enabled'] = self._normalize_value(enabled) + if conditions is not None: + api_params['conditions'] = self._normalize_value(conditions) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=WafRuleDeny) + + def update_deny_rule( + self, + rule_id: str, + resource_type: Optional[str] = None, + resource_id: Optional[str] = None, + name: Optional[str] = None, + description: Optional[str] = None, + priority: Optional[float] = None, + enabled: Optional[bool] = None, + conditions: Optional[List[str]] = None, + ) -> WafRuleDeny: + """ + Update a deny WAF rule. Conditions can match request attributes including `ip` (plain IPs or CIDR blocks like `10.0.0.0/8`), `method`, `path`, `host`, `country`, `continent`, `headers.`, `query.`, `queryKeys`, `userAgent`, `os`, `osVersion`, `browser`, and `browserVersion`. Conditions on `city` and `state` require the premium Geo DB addon. + + Parameters + ---------- + rule_id : str + Rule ID. + resource_type : Optional[str] + Resource type the rule applies to. + resource_id : Optional[str] + Resource identifier. Required for functions and sites. + name : Optional[str] + Rule name. + description : Optional[str] + Optional description for the rule. + priority : Optional[float] + Evaluation priority. Lower numbers run earlier. + enabled : Optional[bool] + Set to false to disable the rule. + conditions : Optional[List[str]] + Array of condition strings generated using the WAF Condition builder. Maximum of 100 conditions are allowed, each 4096 characters long. + Returns + ------- + WafRuleDeny + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/waf/rules/deny/{ruleId}' + api_params = {} + if rule_id is None or rule_id == '': + raise AppwriteException('Missing required parameter: "rule_id"') + api_path = api_path.replace('{ruleId}', str(self._normalize_value(rule_id))) + if resource_type is not None: + api_params['resourceType'] = self._normalize_value(resource_type) + if resource_id is not None: + api_params['resourceId'] = self._normalize_value(resource_id) + if name is not None: + api_params['name'] = self._normalize_value(name) + if description is not None: + api_params['description'] = self._normalize_value(description) + if priority is not None: + api_params['priority'] = self._normalize_value(priority) + if enabled is not None: + api_params['enabled'] = self._normalize_value(enabled) + if conditions is not None: + api_params['conditions'] = self._normalize_value(conditions) + + response = self.client.call( + 'patch', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=WafRuleDeny) + + def create_rate_limit_rule( + self, + rule_id: str, + resource_type: str, + name: str, + limit: float, + interval: float, + resource_id: Optional[str] = None, + description: Optional[str] = None, + key: Optional[str] = None, + strategy: Optional[str] = None, + max_bucket_size: Optional[float] = None, + priority: Optional[float] = None, + enabled: Optional[bool] = None, + conditions: Optional[List[str]] = None, + ) -> WafRuleRateLimit: + """ + Create a rate limit WAF rule. Use `key` to choose the counter: `ip` limits per client IP, while `userId` limits per authenticated user (requests without an authenticated user skip `userId` rules). Conditions can match request attributes including `ip` (plain IPs or CIDR blocks like `10.0.0.0/8`), `method`, `path`, `host`, `country`, `continent`, `headers.`, `query.`, `queryKeys`, `userAgent`, `os`, `osVersion`, `browser`, and `browserVersion`. Conditions on `city` and `state` require the premium Geo DB addon. + + Parameters + ---------- + rule_id : str + Rule ID. Choose a custom ID or pass `ID.unique()` to generate a unique one. + resource_type : str + Resource type the rule applies to. + name : str + Rule name. + limit : float + Maximum number of matching requests allowed in the configured interval. + interval : float + Interval in seconds used for rate limiting. + resource_id : Optional[str] + Resource identifier. Required for functions and sites. + description : Optional[str] + Optional description for the rule. + key : Optional[str] + Rate limit key. Use `ip` to limit per client IP or `userId` to limit per authenticated user. Requests without an authenticated user skip `userId` rules. + strategy : Optional[str] + Rate limit strategy. `fixedWindow` counts requests in discrete intervals, `slidingWindow` weights the previous interval for smoother limiting, and `tokenBucket` refills allowance continuously to permit short bursts. + max_bucket_size : Optional[float] + Maximum number of tokens the bucket can hold for the `tokenBucket` strategy, controlling how large a burst is allowed. The sustained refill rate is `limit / interval`. Defaults to `limit` when omitted. Ignored by other strategies. + priority : Optional[float] + Evaluation priority. Lower numbers run earlier. + enabled : Optional[bool] + Set to false to create the rule in a disabled state. + conditions : Optional[List[str]] + Array of condition strings generated using the WAF Condition builder. Maximum of 100 conditions are allowed, each 4096 characters long. + Returns + ------- + WafRuleRateLimit + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/waf/rules/rate-limit' + api_params = {} + if rule_id is None: + raise AppwriteException('Missing required parameter: "rule_id"') + if resource_type is None: + raise AppwriteException('Missing required parameter: "resource_type"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if limit is None: + raise AppwriteException('Missing required parameter: "limit"') + if interval is None: + raise AppwriteException('Missing required parameter: "interval"') + api_params['ruleId'] = self._normalize_value(rule_id) + api_params['resourceType'] = self._normalize_value(resource_type) + if resource_id is not None: + api_params['resourceId'] = self._normalize_value(resource_id) + api_params['name'] = self._normalize_value(name) + if description is not None: + api_params['description'] = self._normalize_value(description) + api_params['limit'] = self._normalize_value(limit) + api_params['interval'] = self._normalize_value(interval) + if key is not None: + api_params['key'] = self._normalize_value(key) + if strategy is not None: + api_params['strategy'] = self._normalize_value(strategy) + if max_bucket_size is not None: + api_params['maxBucketSize'] = self._normalize_value(max_bucket_size) + if priority is not None: + api_params['priority'] = self._normalize_value(priority) + if enabled is not None: + api_params['enabled'] = self._normalize_value(enabled) + if conditions is not None: + api_params['conditions'] = self._normalize_value(conditions) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=WafRuleRateLimit) + + def update_rate_limit_rule( + self, + rule_id: str, + resource_type: Optional[str] = None, + resource_id: Optional[str] = None, + name: Optional[str] = None, + description: Optional[str] = None, + limit: Optional[float] = None, + interval: Optional[float] = None, + key: Optional[str] = None, + max_bucket_size: Optional[float] = None, + priority: Optional[float] = None, + enabled: Optional[bool] = None, + conditions: Optional[List[str]] = None, + ) -> WafRuleRateLimit: + """ + Update a rate limit WAF rule. Use `key` to choose the counter: `ip` limits per client IP, while `userId` limits per authenticated user (requests without an authenticated user skip `userId` rules). Conditions can match request attributes including `ip` (plain IPs or CIDR blocks like `10.0.0.0/8`), `method`, `path`, `host`, `country`, `continent`, `headers.`, `query.`, `queryKeys`, `userAgent`, `os`, `osVersion`, `browser`, and `browserVersion`. Conditions on `city` and `state` require the premium Geo DB addon. + + Parameters + ---------- + rule_id : str + Rule ID. + resource_type : Optional[str] + Resource type the rule applies to. + resource_id : Optional[str] + Resource identifier. Required for functions and sites. + name : Optional[str] + Rule name. + description : Optional[str] + Optional description for the rule. + limit : Optional[float] + Maximum number of matching requests allowed in the configured interval. + interval : Optional[float] + Interval in seconds used for rate limiting. + key : Optional[str] + Rate limit key. Use `ip` to limit per client IP or `userId` to limit per authenticated user. Requests without an authenticated user skip `userId` rules. + max_bucket_size : Optional[float] + Maximum number of tokens the bucket can hold for the `tokenBucket` strategy, controlling how large a burst is allowed. The sustained refill rate is `limit / interval`. Ignored by other strategies. The strategy itself cannot be changed after creation. + priority : Optional[float] + Evaluation priority. Lower numbers run earlier. + enabled : Optional[bool] + Set to false to disable the rule. + conditions : Optional[List[str]] + Array of condition strings generated using the WAF Condition builder. Maximum of 100 conditions are allowed, each 4096 characters long. + Returns + ------- + WafRuleRateLimit + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/waf/rules/rate-limit/{ruleId}' + api_params = {} + if rule_id is None or rule_id == '': + raise AppwriteException('Missing required parameter: "rule_id"') + api_path = api_path.replace('{ruleId}', str(self._normalize_value(rule_id))) + if resource_type is not None: + api_params['resourceType'] = self._normalize_value(resource_type) + if resource_id is not None: + api_params['resourceId'] = self._normalize_value(resource_id) + if name is not None: + api_params['name'] = self._normalize_value(name) + if description is not None: + api_params['description'] = self._normalize_value(description) + if limit is not None: + api_params['limit'] = self._normalize_value(limit) + if interval is not None: + api_params['interval'] = self._normalize_value(interval) + if key is not None: + api_params['key'] = self._normalize_value(key) + if max_bucket_size is not None: + api_params['maxBucketSize'] = self._normalize_value(max_bucket_size) + if priority is not None: + api_params['priority'] = self._normalize_value(priority) + if enabled is not None: + api_params['enabled'] = self._normalize_value(enabled) + if conditions is not None: + api_params['conditions'] = self._normalize_value(conditions) + + response = self.client.call( + 'patch', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=WafRuleRateLimit) + + def create_redirect_rule( + self, + rule_id: str, + resource_type: str, + name: str, + location: str, + status_code: float, + resource_id: Optional[str] = None, + description: Optional[str] = None, + priority: Optional[float] = None, + enabled: Optional[bool] = None, + conditions: Optional[List[str]] = None, + ) -> WafRuleRedirect: + """ + Create a redirect WAF rule. Conditions can match request attributes including `ip` (plain IPs or CIDR blocks like `10.0.0.0/8`), `method`, `path`, `host`, `country`, `continent`, `headers.`, `query.`, `queryKeys`, `userAgent`, `os`, `osVersion`, `browser`, and `browserVersion`. Conditions on `city` and `state` require the premium Geo DB addon. + + Parameters + ---------- + rule_id : str + Rule ID. Choose a custom ID or pass `ID.unique()` to generate a unique one. + resource_type : str + Resource type the rule applies to. + name : str + Rule name. + location : str + Location used for redirect responses. + status_code : float + Integer status code used for redirect responses. + resource_id : Optional[str] + Resource identifier. Required for functions and sites. + description : Optional[str] + Optional description for the rule. + priority : Optional[float] + Evaluation priority. Lower numbers run earlier. + enabled : Optional[bool] + Set to false to create the rule in a disabled state. + conditions : Optional[List[str]] + Array of condition strings generated using the WAF Condition builder. Maximum of 100 conditions are allowed, each 4096 characters long. + Returns + ------- + WafRuleRedirect + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/waf/rules/redirect' + api_params = {} + if rule_id is None: + raise AppwriteException('Missing required parameter: "rule_id"') + if resource_type is None: + raise AppwriteException('Missing required parameter: "resource_type"') + if name is None: + raise AppwriteException('Missing required parameter: "name"') + if location is None: + raise AppwriteException('Missing required parameter: "location"') + if status_code is None: + raise AppwriteException('Missing required parameter: "status_code"') + api_params['ruleId'] = self._normalize_value(rule_id) + api_params['resourceType'] = self._normalize_value(resource_type) + if resource_id is not None: + api_params['resourceId'] = self._normalize_value(resource_id) + api_params['name'] = self._normalize_value(name) + if description is not None: + api_params['description'] = self._normalize_value(description) + api_params['location'] = self._normalize_value(location) + api_params['statusCode'] = self._normalize_value(status_code) + if priority is not None: + api_params['priority'] = self._normalize_value(priority) + if enabled is not None: + api_params['enabled'] = self._normalize_value(enabled) + if conditions is not None: + api_params['conditions'] = self._normalize_value(conditions) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=WafRuleRedirect) + + def update_redirect_rule( + self, + rule_id: str, + resource_type: Optional[str] = None, + resource_id: Optional[str] = None, + name: Optional[str] = None, + description: Optional[str] = None, + location: Optional[str] = None, + status_code: Optional[float] = None, + priority: Optional[float] = None, + enabled: Optional[bool] = None, + conditions: Optional[List[str]] = None, + ) -> WafRuleRedirect: + """ + Update a redirect WAF rule. Conditions can match request attributes including `ip` (plain IPs or CIDR blocks like `10.0.0.0/8`), `method`, `path`, `host`, `country`, `continent`, `headers.`, `query.`, `queryKeys`, `userAgent`, `os`, `osVersion`, `browser`, and `browserVersion`. Conditions on `city` and `state` require the premium Geo DB addon. + + Parameters + ---------- + rule_id : str + Rule ID. + resource_type : Optional[str] + Resource type the rule applies to. + resource_id : Optional[str] + Resource identifier. Required for functions and sites. + name : Optional[str] + Rule name. + description : Optional[str] + Optional description for the rule. + location : Optional[str] + Location used for redirect responses. + status_code : Optional[float] + Integer status code used for redirect responses. + priority : Optional[float] + Evaluation priority. Lower numbers run earlier. + enabled : Optional[bool] + Set to false to disable the rule. + conditions : Optional[List[str]] + Array of condition strings generated using the WAF Condition builder. Maximum of 100 conditions are allowed, each 4096 characters long. + Returns + ------- + WafRuleRedirect + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/waf/rules/redirect/{ruleId}' + api_params = {} + if rule_id is None or rule_id == '': + raise AppwriteException('Missing required parameter: "rule_id"') + api_path = api_path.replace('{ruleId}', str(self._normalize_value(rule_id))) + if resource_type is not None: + api_params['resourceType'] = self._normalize_value(resource_type) + if resource_id is not None: + api_params['resourceId'] = self._normalize_value(resource_id) + if name is not None: + api_params['name'] = self._normalize_value(name) + if description is not None: + api_params['description'] = self._normalize_value(description) + if location is not None: + api_params['location'] = self._normalize_value(location) + if status_code is not None: + api_params['statusCode'] = self._normalize_value(status_code) + if priority is not None: + api_params['priority'] = self._normalize_value(priority) + if enabled is not None: + api_params['enabled'] = self._normalize_value(enabled) + if conditions is not None: + api_params['conditions'] = self._normalize_value(conditions) + + response = self.client.call( + 'patch', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=WafRuleRedirect) + + def get_rule( + self, + rule_id: str, + ) -> Union[ + WafRuleBypass, + WafRuleDeny, + WafRuleChallenge, + WafRuleRateLimit, + WafRuleRedirect, + ]: + """ + Get a WAF rule by its ID. + + Parameters + ---------- + rule_id : str + Rule ID. + Returns + ------- + Union[WafRuleBypass, WafRuleDeny, WafRuleChallenge, WafRuleRateLimit, WafRuleRedirect] + API response as one of the typed response models + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/waf/rules/{ruleId}' + api_params = {} + if rule_id is None or rule_id == '': + raise AppwriteException('Missing required parameter: "rule_id"') + api_path = api_path.replace('{ruleId}', str(self._normalize_value(rule_id))) + + response = self.client.call( + 'get', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', + }, + api_params, + ) + if not isinstance(response, dict): + raise AppwriteException('Expected object response when hydrating a response model') + + if response.get('action') == 'bypass': + return self._parse_response(response, model=WafRuleBypass) + + if response.get('action') == 'deny': + return self._parse_response(response, model=WafRuleDeny) + + if response.get('action') == 'challenge': + return self._parse_response(response, model=WafRuleChallenge) + + if response.get('action') == 'rateLimit': + return self._parse_response(response, model=WafRuleRateLimit) + + if response.get('action') == 'redirect': + return self._parse_response(response, model=WafRuleRedirect) + + raise AppwriteException('Unable to match response to any known model') + + def delete_rule( + self, + rule_id: str, + ) -> Dict[str, Any]: + """ + Delete a WAF rule. + + Parameters + ---------- + rule_id : str + Rule ID. + Returns + ------- + Dict[str, Any] + API response as a dictionary + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/waf/rules/{ruleId}' + api_params = {} + if rule_id is None or rule_id == '': + raise AppwriteException('Missing required parameter: "rule_id"') + api_path = api_path.replace('{ruleId}', str(self._normalize_value(rule_id))) + + response = self.client.call( + 'delete', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return response diff --git a/docs/examples/account/create-email-password-session.md b/docs/examples/account/create-email-password-session.md index 292074db..7e016dab 100644 --- a/docs/examples/account/create-email-password-session.md +++ b/docs/examples/account/create-email-password-session.md @@ -12,7 +12,8 @@ account = Account(client) result: Session = account.create_email_password_session( email = 'email@example.com', - password = 'password' + password = 'password', + duration = 60 # optional ) print(result.model_dump()) diff --git a/docs/examples/account/create-email-verification-otp.md b/docs/examples/account/create-email-verification-otp.md new file mode 100644 index 00000000..92de90e8 --- /dev/null +++ b/docs/examples/account/create-email-verification-otp.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.account import Account +from appwrite.models import Token + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_session('') # The user session to authenticate with + +account = Account(client) + +result: Token = account.create_email_verification_otp( + phrase = False # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/account/create-id-token-session.md b/docs/examples/account/create-id-token-session.md new file mode 100644 index 00000000..b076d40c --- /dev/null +++ b/docs/examples/account/create-id-token-session.md @@ -0,0 +1,24 @@ +```python +from appwrite.client import Client +from appwrite.services.account import Account +from appwrite.models import Session +from appwrite.enums.id_token_provider import IdTokenProvider + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_session('') # The user session to authenticate with + +account = Account(client) + +result: Session = account.create_id_token_session( + provider = IdTokenProvider.APPLE, + id_token = '', + nonce = '', # optional + access_token = '', # optional + access_token_expiry = 0, # optional + name = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/account/create-recovery-otp.md b/docs/examples/account/create-recovery-otp.md new file mode 100644 index 00000000..02240e31 --- /dev/null +++ b/docs/examples/account/create-recovery-otp.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.account import Account +from appwrite.models import Token + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_session('') # The user session to authenticate with + +account = Account(client) + +result: Token = account.create_recovery_otp( + email = 'email@example.com', + phrase = False # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/account/delete-sessions.md b/docs/examples/account/delete-sessions.md index 4db5c1ec..ae380854 100644 --- a/docs/examples/account/delete-sessions.md +++ b/docs/examples/account/delete-sessions.md @@ -9,5 +9,7 @@ client.set_session('') # The user session to authenticate with account = Account(client) -result = account.delete_sessions() +result = account.delete_sessions( + current = False # optional +) ``` diff --git a/docs/examples/account/list-sessions.md b/docs/examples/account/list-sessions.md index d9df7a71..828aad6f 100644 --- a/docs/examples/account/list-sessions.md +++ b/docs/examples/account/list-sessions.md @@ -10,7 +10,9 @@ client.set_session('') # The user session to authenticate with account = Account(client) -result: SessionList = account.list_sessions() +result: SessionList = account.list_sessions( + total = False # optional +) print(result.model_dump()) ``` diff --git a/docs/examples/account/update-email-verification-otp.md b/docs/examples/account/update-email-verification-otp.md new file mode 100644 index 00000000..b112871f --- /dev/null +++ b/docs/examples/account/update-email-verification-otp.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.account import Account +from appwrite.models import Token + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_session('') # The user session to authenticate with + +account = Account(client) + +result: Token = account.update_email_verification_otp( + user_id = '', + secret = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/account/update-recovery-otp.md b/docs/examples/account/update-recovery-otp.md new file mode 100644 index 00000000..e34e5808 --- /dev/null +++ b/docs/examples/account/update-recovery-otp.md @@ -0,0 +1,20 @@ +```python +from appwrite.client import Client +from appwrite.services.account import Account +from appwrite.models import Token + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_session('') # The user session to authenticate with + +account = Account(client) + +result: Token = account.update_recovery_otp( + user_id = '', + secret = '', + password = 'password' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/avatars/delete-photo.md b/docs/examples/avatars/delete-photo.md new file mode 100644 index 00000000..0851c0c5 --- /dev/null +++ b/docs/examples/avatars/delete-photo.md @@ -0,0 +1,13 @@ +```python +from appwrite.client import Client +from appwrite.services.avatars import Avatars + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_session('') # The user session to authenticate with + +avatars = Avatars(client) + +result = avatars.delete_photo() +``` diff --git a/docs/examples/avatars/update-photo.md b/docs/examples/avatars/update-photo.md new file mode 100644 index 00000000..cdd605a0 --- /dev/null +++ b/docs/examples/avatars/update-photo.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.avatars import Avatars +from appwrite.input_file import InputFile +from appwrite.models import Account + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_session('') # The user session to authenticate with + +avatars = Avatars(client) + +result: Account = avatars.update_photo( + file = InputFile.from_path('file.png') +) + +print(result.model_dump()) +``` diff --git a/docs/examples/databases/list-transactions.md b/docs/examples/databases/list-transactions.md index bd099314..d382cb93 100644 --- a/docs/examples/databases/list-transactions.md +++ b/docs/examples/databases/list-transactions.md @@ -11,7 +11,8 @@ client.set_key('') # Your secret API key databases = Databases(client) result: TransactionList = databases.list_transactions( - queries = [] # optional + queries = [], # optional + total = False # optional ) print(result.model_dump()) diff --git a/docs/examples/documentsdb/list-transactions.md b/docs/examples/documentsdb/list-transactions.md index 6dc7aae2..7128d9b5 100644 --- a/docs/examples/documentsdb/list-transactions.md +++ b/docs/examples/documentsdb/list-transactions.md @@ -11,7 +11,8 @@ client.set_key('') # Your secret API key documents_db = DocumentsDB(client) result: TransactionList = documents_db.list_transactions( - queries = [] # optional + queries = [], # optional + total = False # optional ) print(result.model_dump()) diff --git a/docs/examples/domains/create-preset-google-workspace.md b/docs/examples/domains/create-preset-google-workspace.md new file mode 100644 index 00000000..73c5594e --- /dev/null +++ b/docs/examples/domains/create-preset-google-workspace.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecordsList + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecordsList = domains.create_preset_google_workspace( + domain_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/create-preset-i-cloud.md b/docs/examples/domains/create-preset-i-cloud.md new file mode 100644 index 00000000..d9a957aa --- /dev/null +++ b/docs/examples/domains/create-preset-i-cloud.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecordsList + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecordsList = domains.create_preset_i_cloud( + domain_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/create-preset-mailgun.md b/docs/examples/domains/create-preset-mailgun.md new file mode 100644 index 00000000..89012267 --- /dev/null +++ b/docs/examples/domains/create-preset-mailgun.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecordsList + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecordsList = domains.create_preset_mailgun( + domain_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/create-preset-outlook.md b/docs/examples/domains/create-preset-outlook.md new file mode 100644 index 00000000..b8e0f790 --- /dev/null +++ b/docs/examples/domains/create-preset-outlook.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecordsList + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecordsList = domains.create_preset_outlook( + domain_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/create-preset-proton-mail.md b/docs/examples/domains/create-preset-proton-mail.md new file mode 100644 index 00000000..1caf9d5d --- /dev/null +++ b/docs/examples/domains/create-preset-proton-mail.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecordsList + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecordsList = domains.create_preset_proton_mail( + domain_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/create-preset-zoho.md b/docs/examples/domains/create-preset-zoho.md new file mode 100644 index 00000000..bc5a7c2a --- /dev/null +++ b/docs/examples/domains/create-preset-zoho.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecordsList + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecordsList = domains.create_preset_zoho( + domain_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/create-record-a.md b/docs/examples/domains/create-record-a.md new file mode 100644 index 00000000..17be375e --- /dev/null +++ b/docs/examples/domains/create-record-a.md @@ -0,0 +1,22 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.create_record_a( + domain_id = '', + name = '', + value = '', + ttl = 1, + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/create-record-aaaa.md b/docs/examples/domains/create-record-aaaa.md new file mode 100644 index 00000000..c02fff65 --- /dev/null +++ b/docs/examples/domains/create-record-aaaa.md @@ -0,0 +1,22 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.create_record_aaaa( + domain_id = '', + name = '', + value = '', + ttl = 1, + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/create-record-alias.md b/docs/examples/domains/create-record-alias.md new file mode 100644 index 00000000..a5c9f167 --- /dev/null +++ b/docs/examples/domains/create-record-alias.md @@ -0,0 +1,22 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.create_record_alias( + domain_id = '', + name = '', + value = '', + ttl = 1, + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/create-record-caa.md b/docs/examples/domains/create-record-caa.md new file mode 100644 index 00000000..5e0ee5d8 --- /dev/null +++ b/docs/examples/domains/create-record-caa.md @@ -0,0 +1,22 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.create_record_caa( + domain_id = '', + name = '', + value = '', + ttl = 1, + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/create-record-cname.md b/docs/examples/domains/create-record-cname.md new file mode 100644 index 00000000..8afe96a2 --- /dev/null +++ b/docs/examples/domains/create-record-cname.md @@ -0,0 +1,22 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.create_record_cname( + domain_id = '', + name = '', + value = '', + ttl = 1, + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/create-record-https.md b/docs/examples/domains/create-record-https.md new file mode 100644 index 00000000..2448b64c --- /dev/null +++ b/docs/examples/domains/create-record-https.md @@ -0,0 +1,22 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.create_record_https( + domain_id = '', + name = '', + value = '', + ttl = 1, + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/create-record-mx.md b/docs/examples/domains/create-record-mx.md new file mode 100644 index 00000000..ef492fe1 --- /dev/null +++ b/docs/examples/domains/create-record-mx.md @@ -0,0 +1,23 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.create_record_mx( + domain_id = '', + name = '', + value = '', + ttl = 1, + priority = 0, + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/create-record-ns.md b/docs/examples/domains/create-record-ns.md new file mode 100644 index 00000000..bc2e4187 --- /dev/null +++ b/docs/examples/domains/create-record-ns.md @@ -0,0 +1,22 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.create_record_ns( + domain_id = '', + name = '', + value = '', + ttl = 1, + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/create-record-srv.md b/docs/examples/domains/create-record-srv.md new file mode 100644 index 00000000..04071b34 --- /dev/null +++ b/docs/examples/domains/create-record-srv.md @@ -0,0 +1,25 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.create_record_srv( + domain_id = '', + name = '', + value = '', + ttl = 1, + priority = 0, + weight = 0, + port = 0, + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/create-record-txt.md b/docs/examples/domains/create-record-txt.md new file mode 100644 index 00000000..4a66afd0 --- /dev/null +++ b/docs/examples/domains/create-record-txt.md @@ -0,0 +1,22 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.create_record_txt( + domain_id = '', + name = '', + ttl = 1, + value = '', # optional + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/create.md b/docs/examples/domains/create.md new file mode 100644 index 00000000..01c02414 --- /dev/null +++ b/docs/examples/domains/create.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import Domain + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: Domain = domains.create( + team_id = '', + domain = 'example.com' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/delete-record.md b/docs/examples/domains/delete-record.md new file mode 100644 index 00000000..40b12e83 --- /dev/null +++ b/docs/examples/domains/delete-record.md @@ -0,0 +1,16 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result = domains.delete_record( + domain_id = '', + record_id = '' +) +``` diff --git a/docs/examples/domains/delete.md b/docs/examples/domains/delete.md new file mode 100644 index 00000000..f9cb3c43 --- /dev/null +++ b/docs/examples/domains/delete.md @@ -0,0 +1,15 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result = domains.delete( + domain_id = '' +) +``` diff --git a/docs/examples/domains/get-preset-google-workspace.md b/docs/examples/domains/get-preset-google-workspace.md new file mode 100644 index 00000000..e228af7c --- /dev/null +++ b/docs/examples/domains/get-preset-google-workspace.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecordsList + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecordsList = domains.get_preset_google_workspace( + domain_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/get-preset-i-cloud.md b/docs/examples/domains/get-preset-i-cloud.md new file mode 100644 index 00000000..5b0169c2 --- /dev/null +++ b/docs/examples/domains/get-preset-i-cloud.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecordsList + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecordsList = domains.get_preset_i_cloud( + domain_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/get-preset-mailgun.md b/docs/examples/domains/get-preset-mailgun.md new file mode 100644 index 00000000..494f42a5 --- /dev/null +++ b/docs/examples/domains/get-preset-mailgun.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecordsList + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecordsList = domains.get_preset_mailgun( + domain_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/get-preset-outlook.md b/docs/examples/domains/get-preset-outlook.md new file mode 100644 index 00000000..5daf056d --- /dev/null +++ b/docs/examples/domains/get-preset-outlook.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecordsList + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecordsList = domains.get_preset_outlook( + domain_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/get-preset-proton-mail.md b/docs/examples/domains/get-preset-proton-mail.md new file mode 100644 index 00000000..5dff2d5b --- /dev/null +++ b/docs/examples/domains/get-preset-proton-mail.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecordsList + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecordsList = domains.get_preset_proton_mail( + domain_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/get-preset-zoho.md b/docs/examples/domains/get-preset-zoho.md new file mode 100644 index 00000000..b9f6e1ab --- /dev/null +++ b/docs/examples/domains/get-preset-zoho.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecordsList + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecordsList = domains.get_preset_zoho( + domain_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/get-price.md b/docs/examples/domains/get-price.md new file mode 100644 index 00000000..648998d5 --- /dev/null +++ b/docs/examples/domains/get-price.md @@ -0,0 +1,21 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DomainPrice +from appwrite.enums.domain_registration_type import DomainRegistrationType + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DomainPrice = domains.get_price( + domain = 'example.com', + period_years = None, # optional + registration_type = DomainRegistrationType.NEW # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/get-record.md b/docs/examples/domains/get-record.md new file mode 100644 index 00000000..e923cd6c --- /dev/null +++ b/docs/examples/domains/get-record.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.get_record( + domain_id = '', + record_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/get-transfer-status.md b/docs/examples/domains/get-transfer-status.md new file mode 100644 index 00000000..ca10cf7a --- /dev/null +++ b/docs/examples/domains/get-transfer-status.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DomainTransferStatus + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DomainTransferStatus = domains.get_transfer_status( + domain_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/get-zone.md b/docs/examples/domains/get-zone.md new file mode 100644 index 00000000..ad17f2dc --- /dev/null +++ b/docs/examples/domains/get-zone.md @@ -0,0 +1,15 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result = domains.get_zone( + domain_id = '' +) +``` diff --git a/docs/examples/domains/get.md b/docs/examples/domains/get.md new file mode 100644 index 00000000..c1d772d4 --- /dev/null +++ b/docs/examples/domains/get.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import Domain + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: Domain = domains.get( + domain_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/list-prices.md b/docs/examples/domains/list-prices.md new file mode 100644 index 00000000..ea6907e7 --- /dev/null +++ b/docs/examples/domains/list-prices.md @@ -0,0 +1,21 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DomainPricesList +from appwrite.enums.domain_registration_type import DomainRegistrationType + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DomainPricesList = domains.list_prices( + domains = [], + period_years = None, # optional + registration_type = DomainRegistrationType.NEW # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/list-records.md b/docs/examples/domains/list-records.md new file mode 100644 index 00000000..9d40d255 --- /dev/null +++ b/docs/examples/domains/list-records.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecordsList + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecordsList = domains.list_records( + domain_id = '', + queries = [] # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/list.md b/docs/examples/domains/list.md new file mode 100644 index 00000000..f0d15a75 --- /dev/null +++ b/docs/examples/domains/list.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DomainsList + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DomainsList = domains.list( + queries = [], # optional + search = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/update-nameservers.md b/docs/examples/domains/update-nameservers.md new file mode 100644 index 00000000..0e5ed4be --- /dev/null +++ b/docs/examples/domains/update-nameservers.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import Domain + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: Domain = domains.update_nameservers( + domain_id = '', + nameservers = [] # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/update-record-a.md b/docs/examples/domains/update-record-a.md new file mode 100644 index 00000000..516e273b --- /dev/null +++ b/docs/examples/domains/update-record-a.md @@ -0,0 +1,23 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.update_record_a( + domain_id = '', + record_id = '', + name = '', + value = '', + ttl = 1, + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/update-record-aaaa.md b/docs/examples/domains/update-record-aaaa.md new file mode 100644 index 00000000..1d36e41f --- /dev/null +++ b/docs/examples/domains/update-record-aaaa.md @@ -0,0 +1,23 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.update_record_aaaa( + domain_id = '', + record_id = '', + name = '', + value = '', + ttl = 1, + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/update-record-alias.md b/docs/examples/domains/update-record-alias.md new file mode 100644 index 00000000..9dc96784 --- /dev/null +++ b/docs/examples/domains/update-record-alias.md @@ -0,0 +1,23 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.update_record_alias( + domain_id = '', + record_id = '', + name = '', + value = '', + ttl = 1, + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/update-record-caa.md b/docs/examples/domains/update-record-caa.md new file mode 100644 index 00000000..e1c74e35 --- /dev/null +++ b/docs/examples/domains/update-record-caa.md @@ -0,0 +1,23 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.update_record_caa( + domain_id = '', + record_id = '', + name = '', + value = '', + ttl = 1, + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/update-record-cname.md b/docs/examples/domains/update-record-cname.md new file mode 100644 index 00000000..35e12cd6 --- /dev/null +++ b/docs/examples/domains/update-record-cname.md @@ -0,0 +1,23 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.update_record_cname( + domain_id = '', + record_id = '', + name = '', + value = '', + ttl = 1, + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/update-record-https.md b/docs/examples/domains/update-record-https.md new file mode 100644 index 00000000..c31e963d --- /dev/null +++ b/docs/examples/domains/update-record-https.md @@ -0,0 +1,23 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.update_record_https( + domain_id = '', + record_id = '', + name = '', + value = '', + ttl = 1, + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/update-record-mx.md b/docs/examples/domains/update-record-mx.md new file mode 100644 index 00000000..bd96398a --- /dev/null +++ b/docs/examples/domains/update-record-mx.md @@ -0,0 +1,24 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.update_record_mx( + domain_id = '', + record_id = '', + name = '', + value = '', + ttl = 1, + priority = 0, + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/update-record-ns.md b/docs/examples/domains/update-record-ns.md new file mode 100644 index 00000000..3ca42be8 --- /dev/null +++ b/docs/examples/domains/update-record-ns.md @@ -0,0 +1,23 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.update_record_ns( + domain_id = '', + record_id = '', + name = '', + value = '', + ttl = 1, + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/update-record-srv.md b/docs/examples/domains/update-record-srv.md new file mode 100644 index 00000000..c47f9f2c --- /dev/null +++ b/docs/examples/domains/update-record-srv.md @@ -0,0 +1,26 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.update_record_srv( + domain_id = '', + record_id = '', + name = '', + value = '', + ttl = 1, + priority = 0, + weight = 0, + port = 0, + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/update-record-txt.md b/docs/examples/domains/update-record-txt.md new file mode 100644 index 00000000..b6461701 --- /dev/null +++ b/docs/examples/domains/update-record-txt.md @@ -0,0 +1,23 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import DnsRecord + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: DnsRecord = domains.update_record_txt( + domain_id = '', + record_id = '', + name = '', + value = '', + ttl = 1, + comment = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/update-team.md b/docs/examples/domains/update-team.md new file mode 100644 index 00000000..3963e778 --- /dev/null +++ b/docs/examples/domains/update-team.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import Domain + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: Domain = domains.update_team( + domain_id = '', + team_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/update-zone.md b/docs/examples/domains/update-zone.md new file mode 100644 index 00000000..89e9011a --- /dev/null +++ b/docs/examples/domains/update-zone.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import Domain + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: Domain = domains.update_zone( + domain_id = '', + content = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/domains/verify-nameservers.md b/docs/examples/domains/verify-nameservers.md new file mode 100644 index 00000000..13caac7f --- /dev/null +++ b/docs/examples/domains/verify-nameservers.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.domains import Domains +from appwrite.models import Domain + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +domains = Domains(client) + +result: Domain = domains.verify_nameservers( + domain_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/functions/list-runtimes.md b/docs/examples/functions/list-runtimes.md index ee75c80e..a33db3ad 100644 --- a/docs/examples/functions/list-runtimes.md +++ b/docs/examples/functions/list-runtimes.md @@ -10,7 +10,9 @@ client.set_key('') # Your secret API key functions = Functions(client) -result: RuntimeList = functions.list_runtimes() +result: RuntimeList = functions.list_runtimes( + total = False # optional +) print(result.model_dump()) ``` diff --git a/docs/examples/functions/list-specifications.md b/docs/examples/functions/list-specifications.md index 7cf529a9..ff71a1be 100644 --- a/docs/examples/functions/list-specifications.md +++ b/docs/examples/functions/list-specifications.md @@ -11,7 +11,8 @@ client.set_key('') # Your secret API key functions = Functions(client) result: SpecificationList = functions.list_specifications( - type = 'runtimes' # optional + type = 'runtimes', # optional + total = False # optional ) print(result.model_dump()) diff --git a/docs/examples/locale/list-codes.md b/docs/examples/locale/list-codes.md index adc29396..66079411 100644 --- a/docs/examples/locale/list-codes.md +++ b/docs/examples/locale/list-codes.md @@ -10,7 +10,9 @@ client.set_session('') # The user session to authenticate with locale = Locale(client) -result: LocaleCodeList = locale.list_codes() +result: LocaleCodeList = locale.list_codes( + total = False # optional +) print(result.model_dump()) ``` diff --git a/docs/examples/locale/list-continents.md b/docs/examples/locale/list-continents.md index fcf05e6e..cc7c3fd7 100644 --- a/docs/examples/locale/list-continents.md +++ b/docs/examples/locale/list-continents.md @@ -10,7 +10,9 @@ client.set_session('') # The user session to authenticate with locale = Locale(client) -result: ContinentList = locale.list_continents() +result: ContinentList = locale.list_continents( + total = False # optional +) print(result.model_dump()) ``` diff --git a/docs/examples/locale/list-countries-eu.md b/docs/examples/locale/list-countries-eu.md index 374cc9a3..d7bebd5a 100644 --- a/docs/examples/locale/list-countries-eu.md +++ b/docs/examples/locale/list-countries-eu.md @@ -10,7 +10,9 @@ client.set_session('') # The user session to authenticate with locale = Locale(client) -result: CountryList = locale.list_countries_eu() +result: CountryList = locale.list_countries_eu( + total = False # optional +) print(result.model_dump()) ``` diff --git a/docs/examples/locale/list-countries-phones.md b/docs/examples/locale/list-countries-phones.md index 8b36a1f9..cf23539b 100644 --- a/docs/examples/locale/list-countries-phones.md +++ b/docs/examples/locale/list-countries-phones.md @@ -10,7 +10,9 @@ client.set_session('') # The user session to authenticate with locale = Locale(client) -result: PhoneList = locale.list_countries_phones() +result: PhoneList = locale.list_countries_phones( + total = False # optional +) print(result.model_dump()) ``` diff --git a/docs/examples/locale/list-countries.md b/docs/examples/locale/list-countries.md index 5c45a766..73cb699f 100644 --- a/docs/examples/locale/list-countries.md +++ b/docs/examples/locale/list-countries.md @@ -10,7 +10,9 @@ client.set_session('') # The user session to authenticate with locale = Locale(client) -result: CountryList = locale.list_countries() +result: CountryList = locale.list_countries( + total = False # optional +) print(result.model_dump()) ``` diff --git a/docs/examples/locale/list-currencies.md b/docs/examples/locale/list-currencies.md index 07f061c9..6d4d2628 100644 --- a/docs/examples/locale/list-currencies.md +++ b/docs/examples/locale/list-currencies.md @@ -10,7 +10,9 @@ client.set_session('') # The user session to authenticate with locale = Locale(client) -result: CurrencyList = locale.list_currencies() +result: CurrencyList = locale.list_currencies( + total = False # optional +) print(result.model_dump()) ``` diff --git a/docs/examples/locale/list-languages.md b/docs/examples/locale/list-languages.md index 3fb0c82c..ea1f75f2 100644 --- a/docs/examples/locale/list-languages.md +++ b/docs/examples/locale/list-languages.md @@ -10,7 +10,9 @@ client.set_session('') # The user session to authenticate with locale = Locale(client) -result: LanguageList = locale.list_languages() +result: LanguageList = locale.list_languages( + total = False # optional +) print(result.model_dump()) ``` diff --git a/docs/examples/messaging/create-appwrite-provider.md b/docs/examples/messaging/create-appwrite-provider.md new file mode 100644 index 00000000..c17c582e --- /dev/null +++ b/docs/examples/messaging/create-appwrite-provider.md @@ -0,0 +1,22 @@ +```python +from appwrite.client import Client +from appwrite.services.messaging import Messaging +from appwrite.models import Provider + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +messaging = Messaging(client) + +result: Provider = messaging.create_appwrite_provider( + provider_id = '', + name = '', + enabled = False, # optional + qos = 0, # optional + expiry = 0 # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/messaging/create-email.md b/docs/examples/messaging/create-email.md index a6454e49..c8f278dd 100644 --- a/docs/examples/messaging/create-email.md +++ b/docs/examples/messaging/create-email.md @@ -22,7 +22,9 @@ result: Message = messaging.create_email( attachments = [], # optional draft = False, # optional html = False, # optional - scheduled_at = '2020-10-15T06:38:00.000+00:00' # optional + scheduled_at = '2020-10-15T06:38:00.000+00:00', # optional + reply_to_email = 'email@example.com', # optional + reply_to_name = '' # optional ) print(result.model_dump()) diff --git a/docs/examples/messaging/create-push.md b/docs/examples/messaging/create-push.md index 155128a0..0b169447 100644 --- a/docs/examples/messaging/create-push.md +++ b/docs/examples/messaging/create-push.md @@ -30,7 +30,8 @@ result: Message = messaging.create_push( scheduled_at = '2020-10-15T06:38:00.000+00:00', # optional content_available = False, # optional critical = False, # optional - priority = MessagePriority.NORMAL # optional + priority = MessagePriority.NORMAL, # optional + channel_id = '' # optional ) print(result.model_dump()) diff --git a/docs/examples/messaging/create-topic.md b/docs/examples/messaging/create-topic.md index 3a6547eb..93388456 100644 --- a/docs/examples/messaging/create-topic.md +++ b/docs/examples/messaging/create-topic.md @@ -13,7 +13,9 @@ messaging = Messaging(client) result: Topic = messaging.create_topic( topic_id = '', name = '', - subscribe = ["any"] # optional + subscribe = ["any"], # optional + qos = 0, # optional + expiry = 0 # optional ) print(result.model_dump()) diff --git a/docs/examples/messaging/update-appwrite-provider.md b/docs/examples/messaging/update-appwrite-provider.md new file mode 100644 index 00000000..6b931ab6 --- /dev/null +++ b/docs/examples/messaging/update-appwrite-provider.md @@ -0,0 +1,22 @@ +```python +from appwrite.client import Client +from appwrite.services.messaging import Messaging +from appwrite.models import Provider + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +messaging = Messaging(client) + +result: Provider = messaging.update_appwrite_provider( + provider_id = '', + name = '', # optional + enabled = False, # optional + qos = 0, # optional + expiry = 0 # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/messaging/update-email.md b/docs/examples/messaging/update-email.md index 94d2d407..bf8c5ba8 100644 --- a/docs/examples/messaging/update-email.md +++ b/docs/examples/messaging/update-email.md @@ -22,7 +22,9 @@ result: Message = messaging.update_email( cc = [], # optional bcc = [], # optional scheduled_at = '2020-10-15T06:38:00.000+00:00', # optional - attachments = [] # optional + attachments = [], # optional + reply_to_email = 'email@example.com', # optional + reply_to_name = '' # optional ) print(result.model_dump()) diff --git a/docs/examples/messaging/update-push.md b/docs/examples/messaging/update-push.md index 0c592d6c..cc87614a 100644 --- a/docs/examples/messaging/update-push.md +++ b/docs/examples/messaging/update-push.md @@ -30,7 +30,8 @@ result: Message = messaging.update_push( scheduled_at = '2020-10-15T06:38:00.000+00:00', # optional content_available = False, # optional critical = False, # optional - priority = MessagePriority.NORMAL # optional + priority = MessagePriority.NORMAL, # optional + channel_id = '' # optional ) print(result.model_dump()) diff --git a/docs/examples/messaging/update-topic.md b/docs/examples/messaging/update-topic.md index d7936aa6..4870903a 100644 --- a/docs/examples/messaging/update-topic.md +++ b/docs/examples/messaging/update-topic.md @@ -13,7 +13,9 @@ messaging = Messaging(client) result: Topic = messaging.update_topic( topic_id = '', name = '', # optional - subscribe = ["any"] # optional + subscribe = ["any"], # optional + qos = 0, # optional + expiry = 0 # optional ) print(result.model_dump()) diff --git a/docs/examples/oauth2/introspect.md b/docs/examples/oauth2/introspect.md new file mode 100644 index 00000000..bde9da87 --- /dev/null +++ b/docs/examples/oauth2/introspect.md @@ -0,0 +1,21 @@ +```python +from appwrite.client import Client +from appwrite.services.oauth2 import Oauth2 +from appwrite.models import Oauth2Introspection + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +oauth2 = Oauth2(client) + +result: Oauth2Introspection = oauth2.introspect( + token = '', + token_type_hint = 'access_token', # optional + client_id = '', # optional + client_secret = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/organization/create-ephemeral-project-key.md b/docs/examples/organization/create-ephemeral-project-key.md new file mode 100644 index 00000000..1762acd3 --- /dev/null +++ b/docs/examples/organization/create-ephemeral-project-key.md @@ -0,0 +1,21 @@ +```python +from appwrite.client import Client +from appwrite.services.organization import Organization +from appwrite.models import EphemeralKey +from appwrite.enums.project_key_scopes import ProjectKeyScopes + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +organization = Organization(client) + +result: EphemeralKey = organization.create_ephemeral_project_key( + project_id = '', + scopes = [ProjectKeyScopes.USERS_READ], + duration = 600 +) + +print(result.model_dump()) +``` diff --git a/docs/examples/organization/delete-project-key.md b/docs/examples/organization/delete-project-key.md new file mode 100644 index 00000000..060c6fd4 --- /dev/null +++ b/docs/examples/organization/delete-project-key.md @@ -0,0 +1,16 @@ +```python +from appwrite.client import Client +from appwrite.services.organization import Organization + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +organization = Organization(client) + +result = organization.delete_project_key( + project_id = '', + key_id = '' +) +``` diff --git a/docs/examples/organization/get-project-key.md b/docs/examples/organization/get-project-key.md new file mode 100644 index 00000000..841e3817 --- /dev/null +++ b/docs/examples/organization/get-project-key.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.organization import Organization +from appwrite.models import Key + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +organization = Organization(client) + +result: Key = organization.get_project_key( + project_id = '', + key_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/organization/list-project-keys.md b/docs/examples/organization/list-project-keys.md new file mode 100644 index 00000000..c09c02cd --- /dev/null +++ b/docs/examples/organization/list-project-keys.md @@ -0,0 +1,20 @@ +```python +from appwrite.client import Client +from appwrite.services.organization import Organization +from appwrite.models import KeyList + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +organization = Organization(client) + +result: KeyList = organization.list_project_keys( + project_id = '', + queries = [], # optional + total = False # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/organization/update-project-key.md b/docs/examples/organization/update-project-key.md new file mode 100644 index 00000000..7f01ddf5 --- /dev/null +++ b/docs/examples/organization/update-project-key.md @@ -0,0 +1,23 @@ +```python +from appwrite.client import Client +from appwrite.services.organization import Organization +from appwrite.models import Key +from appwrite.enums.project_key_scopes import ProjectKeyScopes + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +organization = Organization(client) + +result: Key = organization.update_project_key( + project_id = '', + key_id = '', + name = '', + scopes = [ProjectKeyScopes.USERS_READ], + expire = '2020-10-15T06:38:00.000+00:00' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/project/create-android-platform.md b/docs/examples/project/create-android-platform.md index 092376e0..60e7f73d 100644 --- a/docs/examples/project/create-android-platform.md +++ b/docs/examples/project/create-android-platform.md @@ -13,7 +13,8 @@ project = Project(client) result: PlatformAndroid = project.create_android_platform( platform_id = '', name = '', - application_id = '' + application_id = '', + fingerprints = [] # optional ) print(result.model_dump()) diff --git a/docs/examples/project/create-environment.md b/docs/examples/project/create-environment.md new file mode 100644 index 00000000..41dc4bcd --- /dev/null +++ b/docs/examples/project/create-environment.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.project import Project +from appwrite.models import Project as ProjectModel + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +project = Project(client) + +result: ProjectModel = project.create_environment( + environment_id = '', + name = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/project/delete-environment.md b/docs/examples/project/delete-environment.md new file mode 100644 index 00000000..123c2834 --- /dev/null +++ b/docs/examples/project/delete-environment.md @@ -0,0 +1,15 @@ +```python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +project = Project(client) + +result = project.delete_environment( + environment_id = '' +) +``` diff --git a/docs/examples/project/get-environment.md b/docs/examples/project/get-environment.md new file mode 100644 index 00000000..82082dfb --- /dev/null +++ b/docs/examples/project/get-environment.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.project import Project +from appwrite.models import Project as ProjectModel + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +project = Project(client) + +result: ProjectModel = project.get_environment( + environment_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/project/get-o-auth-2-provider.md b/docs/examples/project/get-o-auth-2-provider.md index e2e8f9e9..792ef765 100644 --- a/docs/examples/project/get-o-auth-2-provider.md +++ b/docs/examples/project/get-o-auth-2-provider.md @@ -16,6 +16,7 @@ from appwrite.models import OAuth2Zoho from appwrite.models import OAuth2Yandex from appwrite.models import OAuth2X from appwrite.models import OAuth2WordPress +from appwrite.models import OAuth2Webflow from appwrite.models import OAuth2Twitch from appwrite.models import OAuth2Stripe from appwrite.models import OAuth2Spotify @@ -44,6 +45,8 @@ from appwrite.models import OAuth2Apple from appwrite.models import OAuth2Okta from appwrite.models import OAuth2Kick from appwrite.models import OAuth2Microsoft +from appwrite.models import OAuth2TikTok +from appwrite.models import OAuth2Kakao from typing import Union from appwrite.enums import ProjectOAuthProviderId @@ -54,7 +57,7 @@ client.set_key('') # Your secret API key project = Project(client) -result: Union[OAuth2Github, OAuth2Discord, OAuth2Figma, OAuth2Dropbox, OAuth2Dailymotion, OAuth2Bitbucket, OAuth2Bitly, OAuth2Box, OAuth2Autodesk, OAuth2Google, OAuth2Zoom, OAuth2Zoho, OAuth2Yandex, OAuth2X, OAuth2WordPress, OAuth2Twitch, OAuth2Stripe, OAuth2Spotify, OAuth2Slack, OAuth2Podio, OAuth2Notion, OAuth2Salesforce, OAuth2Yahoo, OAuth2HuggingFace, OAuth2Resend, OAuth2Cloudflare, OAuth2Linkedin, OAuth2Disqus, OAuth2Amazon, OAuth2Etsy, OAuth2Facebook, OAuth2Tradeshift, OAuth2Paypal, OAuth2Gitlab, OAuth2Authentik, OAuth2Auth0, OAuth2FusionAuth, OAuth2Keycloak, OAuth2Oidc, OAuth2Apple, OAuth2Okta, OAuth2Kick, OAuth2Microsoft] = project.get_o_auth2_provider( +result: Union[OAuth2Github, OAuth2Discord, OAuth2Figma, OAuth2Dropbox, OAuth2Dailymotion, OAuth2Bitbucket, OAuth2Bitly, OAuth2Box, OAuth2Autodesk, OAuth2Google, OAuth2Zoom, OAuth2Zoho, OAuth2Yandex, OAuth2X, OAuth2WordPress, OAuth2Webflow, OAuth2Twitch, OAuth2Stripe, OAuth2Spotify, OAuth2Slack, OAuth2Podio, OAuth2Notion, OAuth2Salesforce, OAuth2Yahoo, OAuth2HuggingFace, OAuth2Resend, OAuth2Cloudflare, OAuth2Linkedin, OAuth2Disqus, OAuth2Amazon, OAuth2Etsy, OAuth2Facebook, OAuth2Tradeshift, OAuth2Paypal, OAuth2Gitlab, OAuth2Authentik, OAuth2Auth0, OAuth2FusionAuth, OAuth2Keycloak, OAuth2Oidc, OAuth2Apple, OAuth2Okta, OAuth2Kick, OAuth2Microsoft, OAuth2TikTok, OAuth2Kakao] = project.get_o_auth2_provider( provider_id = ProjectOAuthProviderId.AMAZON ) diff --git a/docs/examples/project/get-policy.md b/docs/examples/project/get-policy.md index 90e71597..e5d3e405 100644 --- a/docs/examples/project/get-policy.md +++ b/docs/examples/project/get-policy.md @@ -5,6 +5,8 @@ from appwrite.models import PolicyPasswordDictionary from appwrite.models import PolicyPasswordHistory from appwrite.models import PolicyPasswordStrength from appwrite.models import PolicyPasswordPersonalData +from appwrite.models import PolicyPasswordPwned +from appwrite.models import PolicyPasswordRotation from appwrite.models import PolicySessionAlert from appwrite.models import PolicySessionDuration from appwrite.models import PolicySessionInvalidation @@ -27,7 +29,7 @@ client.set_key('') # Your secret API key project = Project(client) -result: Union[PolicyPasswordDictionary, PolicyPasswordHistory, PolicyPasswordStrength, PolicyPasswordPersonalData, PolicySessionAlert, PolicySessionDuration, PolicySessionInvalidation, PolicySessionLimit, PolicyUserLimit, PolicyMembershipPrivacy, PolicyMfaFactors, PolicyDenyAliasedEmail, PolicyDenyDisposableEmail, PolicyDenyFreeEmail, PolicyDenyCorporateEmail, PolicyPasskey] = project.get_policy( +result: Union[PolicyPasswordDictionary, PolicyPasswordHistory, PolicyPasswordStrength, PolicyPasswordPersonalData, PolicyPasswordPwned, PolicyPasswordRotation, PolicySessionAlert, PolicySessionDuration, PolicySessionInvalidation, PolicySessionLimit, PolicyUserLimit, PolicyMembershipPrivacy, PolicyMfaFactors, PolicyDenyAliasedEmail, PolicyDenyDisposableEmail, PolicyDenyFreeEmail, PolicyDenyCorporateEmail, PolicyPasskey] = project.get_policy( policy_id = ProjectPolicyId.PASSWORD_DICTIONARY ) diff --git a/docs/examples/project/list-environments.md b/docs/examples/project/list-environments.md new file mode 100644 index 00000000..f414fbea --- /dev/null +++ b/docs/examples/project/list-environments.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.project import Project +from appwrite.models import ProjectList + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +project = Project(client) + +result: ProjectList = project.list_environments( + queries = [], # optional + total = False # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/project/update-android-platform.md b/docs/examples/project/update-android-platform.md index 1c915ac4..70e179c7 100644 --- a/docs/examples/project/update-android-platform.md +++ b/docs/examples/project/update-android-platform.md @@ -13,7 +13,8 @@ project = Project(client) result: PlatformAndroid = project.update_android_platform( platform_id = '', name = '', - application_id = '' + application_id = '', + fingerprints = [] # optional ) print(result.model_dump()) diff --git a/docs/examples/project/update-environment.md b/docs/examples/project/update-environment.md new file mode 100644 index 00000000..e4db2999 --- /dev/null +++ b/docs/examples/project/update-environment.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.project import Project +from appwrite.models import Project as ProjectModel + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +project = Project(client) + +result: ProjectModel = project.update_environment( + environment_id = '', + name = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/project/update-o-auth-2-apple.md b/docs/examples/project/update-o-auth-2-apple.md index 2619115e..6e1a1efb 100644 --- a/docs/examples/project/update-o-auth-2-apple.md +++ b/docs/examples/project/update-o-auth-2-apple.md @@ -15,7 +15,9 @@ result: OAuth2Apple = project.update_o_auth2_apple( key_id = '', # optional team_id = '', # optional p8_file = '', # optional - enabled = False # optional + enabled = False, # optional + native_client_ids = [], # optional + native_enabled = False # optional ) print(result.model_dump()) diff --git a/docs/examples/project/update-o-auth-2-auth-0.md b/docs/examples/project/update-o-auth-2-auth-0.md index 568bb9bb..632286f8 100644 --- a/docs/examples/project/update-o-auth-2-auth-0.md +++ b/docs/examples/project/update-o-auth-2-auth-0.md @@ -2,6 +2,7 @@ from appwrite.client import Client from appwrite.services.project import Project from appwrite.models import OAuth2Auth0 +from appwrite.enums.project_o_auth2_auth0_prompt import ProjectOAuth2Auth0Prompt client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -14,7 +15,8 @@ result: OAuth2Auth0 = project.update_o_auth2_auth0( client_id = '', # optional client_secret = '', # optional endpoint = '', # optional - enabled = False # optional + enabled = False, # optional + prompt = [ProjectOAuth2Auth0Prompt.NONE] # optional ) print(result.model_dump()) diff --git a/docs/examples/project/update-o-auth-2-discord.md b/docs/examples/project/update-o-auth-2-discord.md index a95cc496..9b89515d 100644 --- a/docs/examples/project/update-o-auth-2-discord.md +++ b/docs/examples/project/update-o-auth-2-discord.md @@ -2,6 +2,7 @@ from appwrite.client import Client from appwrite.services.project import Project from appwrite.models import OAuth2Discord +from appwrite.enums.project_o_auth2_discord_prompt import ProjectOAuth2DiscordPrompt client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -13,7 +14,8 @@ project = Project(client) result: OAuth2Discord = project.update_o_auth2_discord( client_id = '', # optional client_secret = '', # optional - enabled = False # optional + enabled = False, # optional + prompt = [ProjectOAuth2DiscordPrompt.NONE] # optional ) print(result.model_dump()) diff --git a/docs/examples/project/update-o-auth-2-git-hub.md b/docs/examples/project/update-o-auth-2-git-hub.md index 36664b85..1df4ea59 100644 --- a/docs/examples/project/update-o-auth-2-git-hub.md +++ b/docs/examples/project/update-o-auth-2-git-hub.md @@ -2,6 +2,7 @@ from appwrite.client import Client from appwrite.services.project import Project from appwrite.models import OAuth2Github +from appwrite.enums.project_o_auth2_git_hub_prompt import ProjectOAuth2GitHubPrompt client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -13,7 +14,8 @@ project = Project(client) result: OAuth2Github = project.update_o_auth2_git_hub( client_id = '', # optional client_secret = '', # optional - enabled = False # optional + enabled = False, # optional + prompt = [ProjectOAuth2GitHubPrompt.SELECT_ACCOUNT] # optional ) print(result.model_dump()) diff --git a/docs/examples/project/update-o-auth-2-google.md b/docs/examples/project/update-o-auth-2-google.md index b1cc1eca..28fc11e6 100644 --- a/docs/examples/project/update-o-auth-2-google.md +++ b/docs/examples/project/update-o-auth-2-google.md @@ -15,7 +15,9 @@ result: OAuth2Google = project.update_o_auth2_google( client_id = '', # optional client_secret = '', # optional prompt = [ProjectOAuth2GooglePrompt.NONE], # optional - enabled = False # optional + enabled = False, # optional + native_client_ids = [], # optional + native_enabled = False # optional ) print(result.model_dump()) diff --git a/docs/examples/project/update-o-auth-2-kakao.md b/docs/examples/project/update-o-auth-2-kakao.md new file mode 100644 index 00000000..b67c6e49 --- /dev/null +++ b/docs/examples/project/update-o-auth-2-kakao.md @@ -0,0 +1,22 @@ +```python +from appwrite.client import Client +from appwrite.services.project import Project +from appwrite.models import OAuth2Kakao +from appwrite.enums.project_o_auth2_kakao_prompt import ProjectOAuth2KakaoPrompt + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +project = Project(client) + +result: OAuth2Kakao = project.update_o_auth2_kakao( + client_id = '', # optional + client_secret = '', # optional + prompt = [ProjectOAuth2KakaoPrompt.NONE], # optional + enabled = False # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/project/update-o-auth-2-microsoft.md b/docs/examples/project/update-o-auth-2-microsoft.md index aeeefa9e..c681a42f 100644 --- a/docs/examples/project/update-o-auth-2-microsoft.md +++ b/docs/examples/project/update-o-auth-2-microsoft.md @@ -2,6 +2,7 @@ from appwrite.client import Client from appwrite.services.project import Project from appwrite.models import OAuth2Microsoft +from appwrite.enums.project_o_auth2_microsoft_prompt import ProjectOAuth2MicrosoftPrompt client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -14,7 +15,8 @@ result: OAuth2Microsoft = project.update_o_auth2_microsoft( application_id = '', # optional application_secret = '', # optional tenant = '', # optional - enabled = False # optional + enabled = False, # optional + prompt = [ProjectOAuth2MicrosoftPrompt.NONE] # optional ) print(result.model_dump()) diff --git a/docs/examples/project/update-o-auth-2-okta.md b/docs/examples/project/update-o-auth-2-okta.md index 0b4fc532..05cb4529 100644 --- a/docs/examples/project/update-o-auth-2-okta.md +++ b/docs/examples/project/update-o-auth-2-okta.md @@ -2,6 +2,7 @@ from appwrite.client import Client from appwrite.services.project import Project from appwrite.models import OAuth2Okta +from appwrite.enums.project_o_auth2_okta_prompt import ProjectOAuth2OktaPrompt client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -15,7 +16,8 @@ result: OAuth2Okta = project.update_o_auth2_okta( client_secret = '', # optional domain = 'example.com', # optional authorization_server_id = '', # optional - enabled = False # optional + enabled = False, # optional + prompt = [ProjectOAuth2OktaPrompt.NONE] # optional ) print(result.model_dump()) diff --git a/docs/examples/project/update-o-auth-2-salesforce.md b/docs/examples/project/update-o-auth-2-salesforce.md index a3cb6377..275462ef 100644 --- a/docs/examples/project/update-o-auth-2-salesforce.md +++ b/docs/examples/project/update-o-auth-2-salesforce.md @@ -2,6 +2,7 @@ from appwrite.client import Client from appwrite.services.project import Project from appwrite.models import OAuth2Salesforce +from appwrite.enums.project_o_auth2_salesforce_prompt import ProjectOAuth2SalesforcePrompt client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -13,7 +14,8 @@ project = Project(client) result: OAuth2Salesforce = project.update_o_auth2_salesforce( customer_key = '', # optional customer_secret = '', # optional - enabled = False # optional + enabled = False, # optional + prompt = [ProjectOAuth2SalesforcePrompt.LOGIN] # optional ) print(result.model_dump()) diff --git a/docs/examples/project/update-o-auth-2-tik-tok.md b/docs/examples/project/update-o-auth-2-tik-tok.md new file mode 100644 index 00000000..3a7c9cb7 --- /dev/null +++ b/docs/examples/project/update-o-auth-2-tik-tok.md @@ -0,0 +1,20 @@ +```python +from appwrite.client import Client +from appwrite.services.project import Project +from appwrite.models import OAuth2TikTok + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +project = Project(client) + +result: OAuth2TikTok = project.update_o_auth2_tik_tok( + client_id = '', # optional + client_secret = '', # optional + enabled = False # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/project/update-o-auth-2-webflow.md b/docs/examples/project/update-o-auth-2-webflow.md new file mode 100644 index 00000000..5edfea64 --- /dev/null +++ b/docs/examples/project/update-o-auth-2-webflow.md @@ -0,0 +1,20 @@ +```python +from appwrite.client import Client +from appwrite.services.project import Project +from appwrite.models import OAuth2Webflow + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +project = Project(client) + +result: OAuth2Webflow = project.update_o_auth2_webflow( + client_id = '', # optional + client_secret = '', # optional + enabled = False # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/project/update-o-auth-2-zoho.md b/docs/examples/project/update-o-auth-2-zoho.md index 069a9645..712bcd96 100644 --- a/docs/examples/project/update-o-auth-2-zoho.md +++ b/docs/examples/project/update-o-auth-2-zoho.md @@ -2,6 +2,7 @@ from appwrite.client import Client from appwrite.services.project import Project from appwrite.models import OAuth2Zoho +from appwrite.enums.project_o_auth2_zoho_prompt import ProjectOAuth2ZohoPrompt client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -13,7 +14,8 @@ project = Project(client) result: OAuth2Zoho = project.update_o_auth2_zoho( client_id = '', # optional client_secret = '', # optional - enabled = False # optional + enabled = False, # optional + prompt = [ProjectOAuth2ZohoPrompt.CONSENT] # optional ) print(result.model_dump()) diff --git a/docs/examples/project/update-password-pwned-policy.md b/docs/examples/project/update-password-pwned-policy.md new file mode 100644 index 00000000..53d2130c --- /dev/null +++ b/docs/examples/project/update-password-pwned-policy.md @@ -0,0 +1,20 @@ +```python +from appwrite.client import Client +from appwrite.services.project import Project +from appwrite.models import Project as ProjectModel + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +project = Project(client) + +result: ProjectModel = project.update_password_pwned_policy( + enabled = False, # optional + sessions = False, # optional + users = False # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/project/update-password-rotation-policy.md b/docs/examples/project/update-password-rotation-policy.md new file mode 100644 index 00000000..68d69221 --- /dev/null +++ b/docs/examples/project/update-password-rotation-policy.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.project import Project +from appwrite.models import Project as ProjectModel + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +project = Project(client) + +result: ProjectModel = project.update_password_rotation_policy( + enabled = False, # optional + max_age = 86400 # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/sites/list-frameworks.md b/docs/examples/sites/list-frameworks.md index 84996b3f..2edd3b35 100644 --- a/docs/examples/sites/list-frameworks.md +++ b/docs/examples/sites/list-frameworks.md @@ -10,7 +10,9 @@ client.set_key('') # Your secret API key sites = Sites(client) -result: FrameworkList = sites.list_frameworks() +result: FrameworkList = sites.list_frameworks( + total = False # optional +) print(result.model_dump()) ``` diff --git a/docs/examples/sites/list-specifications.md b/docs/examples/sites/list-specifications.md index 2f04ddf4..88c3402b 100644 --- a/docs/examples/sites/list-specifications.md +++ b/docs/examples/sites/list-specifications.md @@ -11,7 +11,8 @@ client.set_key('') # Your secret API key sites = Sites(client) result: SpecificationList = sites.list_specifications( - type = 'runtimes' # optional + type = 'runtimes', # optional + total = False # optional ) print(result.model_dump()) diff --git a/docs/examples/tablesdb/list-transactions.md b/docs/examples/tablesdb/list-transactions.md index b4384e67..ded73360 100644 --- a/docs/examples/tablesdb/list-transactions.md +++ b/docs/examples/tablesdb/list-transactions.md @@ -11,7 +11,8 @@ client.set_key('') # Your secret API key tables_db = TablesDB(client) result: TransactionList = tables_db.list_transactions( - queries = [] # optional + queries = [], # optional + total = False # optional ) print(result.model_dump()) diff --git a/docs/examples/teams/create-membership.md b/docs/examples/teams/create-membership.md index 313bf5f6..5e63bc02 100644 --- a/docs/examples/teams/create-membership.md +++ b/docs/examples/teams/create-membership.md @@ -17,7 +17,8 @@ result: Membership = teams.create_membership( user_id = '', # optional phone = '+12065550100', # optional url = 'https://example.com', # optional - name = '' # optional + name = '', # optional + membership_id = '' # optional ) print(result.model_dump()) diff --git a/docs/examples/vectorsdb/list-transactions.md b/docs/examples/vectorsdb/list-transactions.md index d21db012..6ff6cdaa 100644 --- a/docs/examples/vectorsdb/list-transactions.md +++ b/docs/examples/vectorsdb/list-transactions.md @@ -11,7 +11,8 @@ client.set_key('') # Your secret API key vectors_db = VectorsDB(client) result: TransactionList = vectors_db.list_transactions( - queries = [] # optional + queries = [], # optional + total = False # optional ) print(result.model_dump()) diff --git a/docs/examples/waf/create-bypass-rule.md b/docs/examples/waf/create-bypass-rule.md new file mode 100644 index 00000000..70ed9061 --- /dev/null +++ b/docs/examples/waf/create-bypass-rule.md @@ -0,0 +1,25 @@ +```python +from appwrite.client import Client +from appwrite.services.waf import Waf +from appwrite.models import WafRuleBypass + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +waf = Waf(client) + +result: WafRuleBypass = waf.create_bypass_rule( + rule_id = '', + resource_type = 'api', + name = '', + resource_id = '', # optional + description = '', # optional + priority = -100000, # optional + enabled = False, # optional + conditions = [] # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/waf/create-challenge-rule.md b/docs/examples/waf/create-challenge-rule.md new file mode 100644 index 00000000..e3d2fea2 --- /dev/null +++ b/docs/examples/waf/create-challenge-rule.md @@ -0,0 +1,28 @@ +```python +from appwrite.client import Client +from appwrite.services.waf import Waf +from appwrite.models import WafRuleChallenge + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +waf = Waf(client) + +result: WafRuleChallenge = waf.create_challenge_rule( + rule_id = '', + resource_type = 'api', + name = '', + resource_id = '', # optional + description = '', # optional + challenge_type = 'compute', # optional + priority = -100000, # optional + enabled = False, # optional + conditions = [], # optional + difficulty = 1, # optional + ttl = 900 # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/waf/create-deny-rule.md b/docs/examples/waf/create-deny-rule.md new file mode 100644 index 00000000..a23ae249 --- /dev/null +++ b/docs/examples/waf/create-deny-rule.md @@ -0,0 +1,25 @@ +```python +from appwrite.client import Client +from appwrite.services.waf import Waf +from appwrite.models import WafRuleDeny + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +waf = Waf(client) + +result: WafRuleDeny = waf.create_deny_rule( + rule_id = '', + resource_type = 'api', + name = '', + resource_id = '', # optional + description = '', # optional + priority = -100000, # optional + enabled = False, # optional + conditions = [] # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/waf/create-rate-limit-rule.md b/docs/examples/waf/create-rate-limit-rule.md new file mode 100644 index 00000000..e76605f8 --- /dev/null +++ b/docs/examples/waf/create-rate-limit-rule.md @@ -0,0 +1,30 @@ +```python +from appwrite.client import Client +from appwrite.services.waf import Waf +from appwrite.models import WafRuleRateLimit + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +waf = Waf(client) + +result: WafRuleRateLimit = waf.create_rate_limit_rule( + rule_id = '', + resource_type = 'api', + name = '', + limit = 1, + interval = 1, + resource_id = '', # optional + description = '', # optional + key = 'ip', # optional + strategy = 'fixedWindow', # optional + max_bucket_size = 1, # optional + priority = -100000, # optional + enabled = False, # optional + conditions = [] # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/waf/create-redirect-rule.md b/docs/examples/waf/create-redirect-rule.md new file mode 100644 index 00000000..a33a1e6c --- /dev/null +++ b/docs/examples/waf/create-redirect-rule.md @@ -0,0 +1,27 @@ +```python +from appwrite.client import Client +from appwrite.services.waf import Waf +from appwrite.models import WafRuleRedirect + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +waf = Waf(client) + +result: WafRuleRedirect = waf.create_redirect_rule( + rule_id = '', + resource_type = 'api', + name = '', + location = '', + status_code = 300, + resource_id = '', # optional + description = '', # optional + priority = -100000, # optional + enabled = False, # optional + conditions = [] # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/waf/delete-rule.md b/docs/examples/waf/delete-rule.md new file mode 100644 index 00000000..a2fbe6d8 --- /dev/null +++ b/docs/examples/waf/delete-rule.md @@ -0,0 +1,15 @@ +```python +from appwrite.client import Client +from appwrite.services.waf import Waf + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +waf = Waf(client) + +result = waf.delete_rule( + rule_id = '' +) +``` diff --git a/docs/examples/waf/get-rule.md b/docs/examples/waf/get-rule.md new file mode 100644 index 00000000..3168d309 --- /dev/null +++ b/docs/examples/waf/get-rule.md @@ -0,0 +1,23 @@ +```python +from appwrite.client import Client +from appwrite.services.waf import Waf +from appwrite.models import WafRuleBypass +from appwrite.models import WafRuleDeny +from appwrite.models import WafRuleChallenge +from appwrite.models import WafRuleRateLimit +from appwrite.models import WafRuleRedirect +from typing import Union + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +waf = Waf(client) + +result: Union[WafRuleBypass, WafRuleDeny, WafRuleChallenge, WafRuleRateLimit, WafRuleRedirect] = waf.get_rule( + rule_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/waf/list-rules.md b/docs/examples/waf/list-rules.md new file mode 100644 index 00000000..d06a509e --- /dev/null +++ b/docs/examples/waf/list-rules.md @@ -0,0 +1,20 @@ +```python +from appwrite.client import Client +from appwrite.services.waf import Waf +from appwrite.models import WafRuleList + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +waf = Waf(client) + +result: WafRuleList = waf.list_rules( + queries = [], # optional + search = '', # optional + total = False # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/waf/update-bypass-rule.md b/docs/examples/waf/update-bypass-rule.md new file mode 100644 index 00000000..39ceb7f4 --- /dev/null +++ b/docs/examples/waf/update-bypass-rule.md @@ -0,0 +1,25 @@ +```python +from appwrite.client import Client +from appwrite.services.waf import Waf +from appwrite.models import WafRuleBypass + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +waf = Waf(client) + +result: WafRuleBypass = waf.update_bypass_rule( + rule_id = '', + resource_type = 'api', # optional + resource_id = '', # optional + name = '', # optional + description = '', # optional + priority = -100000, # optional + enabled = False, # optional + conditions = [] # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/waf/update-challenge-rule.md b/docs/examples/waf/update-challenge-rule.md new file mode 100644 index 00000000..30afcd7f --- /dev/null +++ b/docs/examples/waf/update-challenge-rule.md @@ -0,0 +1,28 @@ +```python +from appwrite.client import Client +from appwrite.services.waf import Waf +from appwrite.models import WafRuleChallenge + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +waf = Waf(client) + +result: WafRuleChallenge = waf.update_challenge_rule( + rule_id = '', + resource_type = 'api', # optional + resource_id = '', # optional + name = '', # optional + description = '', # optional + challenge_type = 'compute', # optional + priority = -100000, # optional + enabled = False, # optional + conditions = [], # optional + difficulty = 1, # optional + ttl = 900 # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/waf/update-deny-rule.md b/docs/examples/waf/update-deny-rule.md new file mode 100644 index 00000000..2253e2b7 --- /dev/null +++ b/docs/examples/waf/update-deny-rule.md @@ -0,0 +1,25 @@ +```python +from appwrite.client import Client +from appwrite.services.waf import Waf +from appwrite.models import WafRuleDeny + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +waf = Waf(client) + +result: WafRuleDeny = waf.update_deny_rule( + rule_id = '', + resource_type = 'api', # optional + resource_id = '', # optional + name = '', # optional + description = '', # optional + priority = -100000, # optional + enabled = False, # optional + conditions = [] # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/waf/update-rate-limit-rule.md b/docs/examples/waf/update-rate-limit-rule.md new file mode 100644 index 00000000..e413cef8 --- /dev/null +++ b/docs/examples/waf/update-rate-limit-rule.md @@ -0,0 +1,29 @@ +```python +from appwrite.client import Client +from appwrite.services.waf import Waf +from appwrite.models import WafRuleRateLimit + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +waf = Waf(client) + +result: WafRuleRateLimit = waf.update_rate_limit_rule( + rule_id = '', + resource_type = 'api', # optional + resource_id = '', # optional + name = '', # optional + description = '', # optional + limit = 1, # optional + interval = 1, # optional + key = 'ip', # optional + max_bucket_size = 1, # optional + priority = -100000, # optional + enabled = False, # optional + conditions = [] # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/waf/update-redirect-rule.md b/docs/examples/waf/update-redirect-rule.md new file mode 100644 index 00000000..7e294f8c --- /dev/null +++ b/docs/examples/waf/update-redirect-rule.md @@ -0,0 +1,27 @@ +```python +from appwrite.client import Client +from appwrite.services.waf import Waf +from appwrite.models import WafRuleRedirect + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +waf = Waf(client) + +result: WafRuleRedirect = waf.update_redirect_rule( + rule_id = '', + resource_type = 'api', # optional + resource_id = '', # optional + name = '', # optional + description = '', # optional + location = '', # optional + status_code = 300, # optional + priority = -100000, # optional + enabled = False, # optional + conditions = [] # optional +) + +print(result.model_dump()) +``` diff --git a/pyproject.toml b/pyproject.toml index 0698c715..805fd42f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "appwrite" -version = "24.3.1" +version = "24.4.0" description = "Appwrite is an open-source self-hosted backend server that abstracts and simplifies complex and repetitive development tasks behind a very simple REST API" readme = "README.md" requires-python = ">=3.9" diff --git a/setup.py b/setup.py index cee81d46..859b5862 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ setuptools.setup( name='appwrite', packages=setuptools.find_packages(), - version='24.3.1', + version='24.4.0', license='BSD-3-Clause', description='Appwrite is an open-source self-hosted backend server that abstracts and simplifies complex and repetitive development tasks behind a very simple REST API', long_description=long_description, @@ -18,7 +18,7 @@ maintainer='Appwrite Team', maintainer_email='team@appwrite.io', url='https://appwrite.io/support', - download_url='https://github.com/appwrite/sdk-for-python/archive/24.3.1.tar.gz', + download_url='https://github.com/appwrite/sdk-for-python/archive/24.4.0.tar.gz', install_requires=[ 'requests', 'pydantic>=2,<3', diff --git a/test/services/test_account.py b/test/services/test_account.py index 45da64b2..04c3068a 100644 --- a/test/services/test_account.py +++ b/test/services/test_account.py @@ -1005,6 +1005,52 @@ def test_update_recovery(self, m): ) self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() + def test_create_recovery_otp(self, m): + data = { + "$id": "bb8ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "userId": "5e5ea5c168bb8", + "secret": "", + "expire": "2020-10-15T06:38:00.000+00:00", + "phrase": "Golden Fox", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.account.create_recovery_otp( + 'email@example.com', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_recovery_otp(self, m): + data = { + "$id": "bb8ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "userId": "5e5ea5c168bb8", + "secret": "", + "expire": "2020-10-15T06:38:00.000+00:00", + "phrase": "Golden Fox", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.account.update_recovery_otp( + '', + '', + 'password', + ) + self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() def test_list_sessions(self, m): data = { @@ -1123,6 +1169,52 @@ def test_create_email_password_session(self, m): ) self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() + def test_create_id_token_session(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "userId": "5e5bb8c16897e", + "expire": "2020-10-15T06:38:00.000+00:00", + "provider": "email", + "providerUid": "user@example.com", + "providerAccessToken": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3", + "providerAccessTokenExpiry": "2020-10-15T06:38:00.000+00:00", + "providerRefreshToken": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3", + "ip": "127.0.0.1", + "osCode": "Mac", + "osName": "Mac", + "osVersion": "Mac", + "clientType": "browser", + "clientCode": "CM", + "clientName": "Chrome Mobile iOS", + "clientVersion": "84.0", + "clientEngine": "WebKit", + "clientEngineVersion": "605.1.15", + "deviceName": "smartphone", + "deviceBrand": "Google", + "deviceModel": "Nexus 5", + "countryCode": "US", + "countryName": "United States", + "current": True, + "factors": [], + "secret": "5e5bb8c16897e", + "mfaUpdatedAt": "2020-10-15T06:38:00.000+00:00", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.account.create_id_token_session( + 'apple', + '', + ) + self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() def test_update_magic_url_session(self, m): data = { @@ -1612,6 +1704,49 @@ def test_update_verification(self, m): ) self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() + def test_create_email_verification_otp(self, m): + data = { + "$id": "bb8ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "userId": "5e5ea5c168bb8", + "secret": "", + "expire": "2020-10-15T06:38:00.000+00:00", + "phrase": "Golden Fox", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.account.create_email_verification_otp() + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_email_verification_otp(self, m): + data = { + "$id": "bb8ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "userId": "5e5ea5c168bb8", + "secret": "", + "expire": "2020-10-15T06:38:00.000+00:00", + "phrase": "Golden Fox", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.account.update_email_verification_otp( + '', + '', + ) + self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() def test_create_phone_verification(self, m): data = { diff --git a/test/services/test_avatars.py b/test/services/test_avatars.py index b6fc5fbb..c54fe183 100644 --- a/test/services/test_avatars.py +++ b/test/services/test_avatars.py @@ -115,6 +115,51 @@ def test_get_photo(self, m): response = self.avatars.get_photo() self.assertEqual(response, data) + @requests_mock.Mocker() + def test_update_photo(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "John Doe", + "registration": "2020-10-15T06:38:00.000+00:00", + "status": True, + "labels": [], + "passwordUpdate": "2020-10-15T06:38:00.000+00:00", + "email": "john@appwrite.io", + "phone": "+4930901820", + "emailVerification": True, + "phoneVerification": True, + "mfa": True, + "prefs": {}, + "targets": [], + "accessedAt": "2020-10-15T06:38:00.000+00:00", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.avatars.update_photo( + InputFile.from_bytes(bytearray(), "example.file"), + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_delete_photo(self, m): + data = '' + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.avatars.delete_photo() + self.assertEqual(response, data) + @requests_mock.Mocker() def test_get_qr(self, m): data = bytearray() diff --git a/test/services/test_domains.py b/test/services/test_domains.py new file mode 100644 index 00000000..8ae6d3c4 --- /dev/null +++ b/test/services/test_domains.py @@ -0,0 +1,1207 @@ +import json +import requests_mock +import unittest + +from appwrite.client import Client +from appwrite.input_file import InputFile +from appwrite.models import * +from appwrite.services.domains import Domains + + +class DomainsServiceTest(unittest.TestCase): + + def setUp(self): + self.client = Client() + self.domains = Domains(self.client) + + @requests_mock.Mocker() + def test_list(self, m): + data = { + "total": 5.0, + "domains": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.list() + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "domain": "example.com", + "registrar": "appwrite", + "nameservers": "Appwrite", + "expire": "2020-10-15T06:38:00.000+00:00", + "renewal": "2020-10-15T06:38:00.000+00:00", + "autoRenewal": True, + "renewalPrice": 2599.0, + "teamId": "5e5ea5c16897e", + "dnsRecords": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.create( + '', + 'example.com', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_get_price(self, m): + data = { + "domain": "example.com", + "tld": "com", + "available": True, + "periodYears": 1.0, + "premium": True, + "renewalPeriodYears": 1.0, + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.get_price( + 'example.com', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_list_prices(self, m): + data = { + "total": 5.0, + "prices": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.list_prices( + [], + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_get(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "domain": "example.com", + "registrar": "appwrite", + "nameservers": "Appwrite", + "expire": "2020-10-15T06:38:00.000+00:00", + "renewal": "2020-10-15T06:38:00.000+00:00", + "autoRenewal": True, + "renewalPrice": 2599.0, + "teamId": "5e5ea5c16897e", + "dnsRecords": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.get( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_delete(self, m): + data = '' + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.delete( + '', + ) + self.assertEqual(response, data) + + @requests_mock.Mocker() + def test_update_nameservers(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "domain": "example.com", + "registrar": "appwrite", + "nameservers": "Appwrite", + "expire": "2020-10-15T06:38:00.000+00:00", + "renewal": "2020-10-15T06:38:00.000+00:00", + "autoRenewal": True, + "renewalPrice": 2599.0, + "teamId": "5e5ea5c16897e", + "dnsRecords": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.update_nameservers( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_verify_nameservers(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "domain": "example.com", + "registrar": "appwrite", + "nameservers": "Appwrite", + "expire": "2020-10-15T06:38:00.000+00:00", + "renewal": "2020-10-15T06:38:00.000+00:00", + "autoRenewal": True, + "renewalPrice": 2599.0, + "teamId": "5e5ea5c16897e", + "dnsRecords": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.verify_nameservers( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_get_preset_google_workspace(self, m): + data = { + "total": 5.0, + "dnsRecords": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.get_preset_google_workspace( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_preset_google_workspace(self, m): + data = { + "total": 5.0, + "dnsRecords": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.create_preset_google_workspace( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_get_preset_i_cloud(self, m): + data = { + "total": 5.0, + "dnsRecords": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.get_preset_i_cloud( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_preset_i_cloud(self, m): + data = { + "total": 5.0, + "dnsRecords": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.create_preset_i_cloud( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_get_preset_mailgun(self, m): + data = { + "total": 5.0, + "dnsRecords": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.get_preset_mailgun( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_preset_mailgun(self, m): + data = { + "total": 5.0, + "dnsRecords": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.create_preset_mailgun( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_get_preset_outlook(self, m): + data = { + "total": 5.0, + "dnsRecords": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.get_preset_outlook( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_preset_outlook(self, m): + data = { + "total": 5.0, + "dnsRecords": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.create_preset_outlook( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_get_preset_proton_mail(self, m): + data = { + "total": 5.0, + "dnsRecords": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.get_preset_proton_mail( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_preset_proton_mail(self, m): + data = { + "total": 5.0, + "dnsRecords": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.create_preset_proton_mail( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_get_preset_zoho(self, m): + data = { + "total": 5.0, + "dnsRecords": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.get_preset_zoho( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_preset_zoho(self, m): + data = { + "total": 5.0, + "dnsRecords": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.create_preset_zoho( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_list_records(self, m): + data = { + "total": 5.0, + "dnsRecords": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.list_records( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_record_a(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.create_record_a( + '', + 'name', + 'value', + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_record_a(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.update_record_a( + '', + '', + 'name', + 'value', + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_record_aaaa(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.create_record_aaaa( + '', + 'name', + 'value', + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_record_aaaa(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.update_record_aaaa( + '', + '', + 'name', + 'value', + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_record_alias(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.create_record_alias( + '', + 'name', + '', + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_record_alias(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.update_record_alias( + '', + '', + 'name', + '', + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_record_caa(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.create_record_caa( + '', + 'name', + 'value', + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_record_caa(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.update_record_caa( + '', + '', + 'name', + 'value', + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_record_cname(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.create_record_cname( + '', + 'name', + '', + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_record_cname(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.update_record_cname( + '', + '', + 'name', + '', + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_record_https(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.create_record_https( + '', + 'name', + '', + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_record_https(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.update_record_https( + '', + '', + 'name', + '', + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_record_mx(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.create_record_mx( + '', + 'name', + '', + 1, + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_record_mx(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.update_record_mx( + '', + '', + 'name', + '', + 1, + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_record_ns(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.create_record_ns( + '', + 'name', + '', + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_record_ns(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.update_record_ns( + '', + '', + 'name', + '', + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_record_srv(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.create_record_srv( + '', + 'name', + '', + 1, + 1, + 1, + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_record_srv(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.update_record_srv( + '', + '', + 'name', + '', + 1, + 1, + 1, + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_record_txt(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.create_record_txt( + '', + 'name', + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_record_txt(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.update_record_txt( + '', + '', + 'name', + '', + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_get_record(self, m): + data = { + "$id": "5f40a6e10c65e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "type": "A", + "name": "mail", + "value": "192.0.2.1", + "ttl": 86400.0, + "priority": 10.0, + "lock": True, + "weight": 10.0, + "port": 443.0, + "comment": "Mail server record", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.get_record( + '', + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_delete_record(self, m): + data = '' + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.delete_record( + '', + '', + ) + self.assertEqual(response, data) + + @requests_mock.Mocker() + def test_update_team(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "domain": "example.com", + "registrar": "appwrite", + "nameservers": "Appwrite", + "expire": "2020-10-15T06:38:00.000+00:00", + "renewal": "2020-10-15T06:38:00.000+00:00", + "autoRenewal": True, + "renewalPrice": 2599.0, + "teamId": "5e5ea5c16897e", + "dnsRecords": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.update_team( + '', + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_get_transfer_status(self, m): + data = { + "status": "pending_registry", + "reason": "Transfer in progress", + "timestamp": "2020-10-15T06:38:00.000+00:00", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.get_transfer_status( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_get_zone(self, m): + data = '; café zone\nwww 3600 IN A 192.0.2.1\n' + headers = {'Content-Type': 'text/plain; charset=utf-8'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=data, + headers=headers, + ) + response = self.domains.get_zone( + '', + ) + self.assertEqual(response, data) + + @requests_mock.Mocker() + def test_update_zone(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "domain": "example.com", + "registrar": "appwrite", + "nameservers": "Appwrite", + "expire": "2020-10-15T06:38:00.000+00:00", + "renewal": "2020-10-15T06:38:00.000+00:00", + "autoRenewal": True, + "renewalPrice": 2599.0, + "teamId": "5e5ea5c16897e", + "dnsRecords": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.domains.update_zone( + '', + '', + ) + self.assertEqual(response.to_dict(), data) diff --git a/test/services/test_messaging.py b/test/services/test_messaging.py index ad69b926..03c86ea6 100644 --- a/test/services/test_messaging.py +++ b/test/services/test_messaging.py @@ -415,6 +415,55 @@ def test_update_apns_provider(self, m): ) self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() + def test_create_appwrite_provider(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "Mailgun", + "provider": "mailgun", + "enabled": True, + "type": "sms", + "credentials": {}, + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.messaging.create_appwrite_provider( + '', + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_appwrite_provider(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "Mailgun", + "provider": "mailgun", + "enabled": True, + "type": "sms", + "credentials": {}, + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.messaging.update_appwrite_provider( + '', + ) + self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() def test_create_fcm_provider(self, m): data = { diff --git a/test/services/test_oauth2.py b/test/services/test_oauth2.py index 5365456d..c71e41aa 100644 --- a/test/services/test_oauth2.py +++ b/test/services/test_oauth2.py @@ -139,6 +139,23 @@ def test_get_grant(self, m): ) self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() + def test_introspect(self, m): + data = { + "active": True, + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.oauth2.introspect( + '', + ) + self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() def test_list_organizations(self, m): data = { diff --git a/test/services/test_organization.py b/test/services/test_organization.py index 5a7df9dc..e7237111 100644 --- a/test/services/test_organization.py +++ b/test/services/test_organization.py @@ -871,3 +871,118 @@ def test_delete_project(self, m): '', ) self.assertEqual(response, data) + + @requests_mock.Mocker() + def test_list_project_keys(self, m): + data = { + "total": 5.0, + "keys": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.organization.list_project_keys( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_ephemeral_project_key(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "My API Key", + "expire": "2020-10-15T06:38:00.000+00:00", + "scopes": [], + "secret": "919c2d18fb5d4...a2ae413da83346ad2", + "accessedAt": "2020-10-15T06:38:00.000+00:00", + "sdks": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.organization.create_ephemeral_project_key( + '', + [], + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_get_project_key(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "My API Key", + "expire": "2020-10-15T06:38:00.000+00:00", + "scopes": [], + "secret": "919c2d18fb5d4...a2ae413da83346ad2", + "accessedAt": "2020-10-15T06:38:00.000+00:00", + "sdks": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.organization.get_project_key( + '', + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_project_key(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "My API Key", + "expire": "2020-10-15T06:38:00.000+00:00", + "scopes": [], + "secret": "919c2d18fb5d4...a2ae413da83346ad2", + "accessedAt": "2020-10-15T06:38:00.000+00:00", + "sdks": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.organization.update_project_key( + '', + '', + '', + [], + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_delete_project_key(self, m): + data = '' + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.organization.delete_project_key( + '', + '', + ) + self.assertEqual(response, data) diff --git a/test/services/test_project.py b/test/services/test_project.py index f2a11008..0d5d0b3d 100644 --- a/test/services/test_project.py +++ b/test/services/test_project.py @@ -112,6 +112,168 @@ def test_update_auth_method(self, m): ) self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() + def test_list_environments(self, m): + data = { + "total": 5.0, + "projects": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.project.list_environments() + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_environment(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "New Project", + "teamId": "1592981250", + "region": "fra", + "devKeys": [], + "smtpEnabled": True, + "smtpSenderName": "John Appwrite", + "smtpSenderEmail": "john@appwrite.io", + "smtpReplyToName": "Support Team", + "smtpReplyToEmail": "support@appwrite.io", + "smtpHost": "mail.appwrite.io", + "smtpPort": 25.0, + "smtpUsername": "emailuser", + "smtpPassword": "smtp-password", + "smtpSecure": "tls", + "pingCount": 1.0, + "pingedAt": "2020-10-15T06:38:00.000+00:00", + "labels": [], + "status": "active", + "onboarding": {}, + "authMethods": [], + "services": [], + "protocols": [], + "blocks": [], + "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.project.create_environment( + '', + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_get_environment(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "New Project", + "teamId": "1592981250", + "region": "fra", + "devKeys": [], + "smtpEnabled": True, + "smtpSenderName": "John Appwrite", + "smtpSenderEmail": "john@appwrite.io", + "smtpReplyToName": "Support Team", + "smtpReplyToEmail": "support@appwrite.io", + "smtpHost": "mail.appwrite.io", + "smtpPort": 25.0, + "smtpUsername": "emailuser", + "smtpPassword": "smtp-password", + "smtpSecure": "tls", + "pingCount": 1.0, + "pingedAt": "2020-10-15T06:38:00.000+00:00", + "labels": [], + "status": "active", + "onboarding": {}, + "authMethods": [], + "services": [], + "protocols": [], + "blocks": [], + "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.project.get_environment( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_environment(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "New Project", + "teamId": "1592981250", + "region": "fra", + "devKeys": [], + "smtpEnabled": True, + "smtpSenderName": "John Appwrite", + "smtpSenderEmail": "john@appwrite.io", + "smtpReplyToName": "Support Team", + "smtpReplyToEmail": "support@appwrite.io", + "smtpHost": "mail.appwrite.io", + "smtpPort": 25.0, + "smtpUsername": "emailuser", + "smtpPassword": "smtp-password", + "smtpSecure": "tls", + "pingCount": 1.0, + "pingedAt": "2020-10-15T06:38:00.000+00:00", + "labels": [], + "status": "active", + "onboarding": {}, + "authMethods": [], + "services": [], + "protocols": [], + "blocks": [], + "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.project.update_environment( + '', + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_delete_environment(self, m): + data = '' + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.project.delete_environment( + '', + ) + self.assertEqual(response, data) + @requests_mock.Mocker() def test_list_keys(self, m): data = { @@ -820,6 +982,25 @@ def test_update_o_auth2_hugging_face(self, m): response = self.project.update_o_auth2_hugging_face() self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() + def test_update_o_auth2_kakao(self, m): + data = { + "$id": "github", + "enabled": True, + "clientId": "839ff5000000000000000000013206de", + "clientSecret": "jLNVOK00000000000000000000yJebea", + "prompt": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.project.update_o_auth2_kakao() + self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() def test_update_o_auth2_keycloak(self, m): data = { @@ -1100,6 +1281,24 @@ def test_update_o_auth2_stripe(self, m): response = self.project.update_o_auth2_stripe() self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() + def test_update_o_auth2_tik_tok(self, m): + data = { + "$id": "github", + "enabled": True, + "clientId": "awz000000000tyw0", + "clientSecret": "6wXewM00000000000000000000yXnite", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.project.update_o_auth2_tik_tok() + self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() def test_update_o_auth2_tradeshift(self, m): data = { @@ -1154,6 +1353,24 @@ def test_update_o_auth2_twitch(self, m): response = self.project.update_o_auth2_twitch() self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() + def test_update_o_auth2_webflow(self, m): + data = { + "$id": "github", + "enabled": True, + "clientId": "8bb20000000000000000000000000000000000000000000000000000000040dd", + "clientSecret": "59bf00000000000000000000000000000000000000000000000000000000fe59", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.project.update_o_auth2_webflow() + self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() def test_update_o_auth2_word_press(self, m): data = { @@ -2017,6 +2234,88 @@ def test_update_password_personal_data_policy(self, m): ) self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() + def test_update_password_pwned_policy(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "New Project", + "teamId": "1592981250", + "region": "fra", + "devKeys": [], + "smtpEnabled": True, + "smtpSenderName": "John Appwrite", + "smtpSenderEmail": "john@appwrite.io", + "smtpReplyToName": "Support Team", + "smtpReplyToEmail": "support@appwrite.io", + "smtpHost": "mail.appwrite.io", + "smtpPort": 25.0, + "smtpUsername": "emailuser", + "smtpPassword": "smtp-password", + "smtpSecure": "tls", + "pingCount": 1.0, + "pingedAt": "2020-10-15T06:38:00.000+00:00", + "labels": [], + "status": "active", + "onboarding": {}, + "authMethods": [], + "services": [], + "protocols": [], + "blocks": [], + "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.project.update_password_pwned_policy() + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_password_rotation_policy(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "New Project", + "teamId": "1592981250", + "region": "fra", + "devKeys": [], + "smtpEnabled": True, + "smtpSenderName": "John Appwrite", + "smtpSenderEmail": "john@appwrite.io", + "smtpReplyToName": "Support Team", + "smtpReplyToEmail": "support@appwrite.io", + "smtpHost": "mail.appwrite.io", + "smtpPort": 25.0, + "smtpUsername": "emailuser", + "smtpPassword": "smtp-password", + "smtpSecure": "tls", + "pingCount": 1.0, + "pingedAt": "2020-10-15T06:38:00.000+00:00", + "labels": [], + "status": "active", + "onboarding": {}, + "authMethods": [], + "services": [], + "protocols": [], + "blocks": [], + "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.project.update_password_rotation_policy() + self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() def test_update_password_strength_policy(self, m): data = { diff --git a/test/services/test_waf.py b/test/services/test_waf.py new file mode 100644 index 00000000..8c9e8bec --- /dev/null +++ b/test/services/test_waf.py @@ -0,0 +1,410 @@ +import json +import requests_mock +import unittest + +from appwrite.client import Client +from appwrite.input_file import InputFile +from appwrite.models import * +from appwrite.services.waf import Waf + + +class WafServiceTest(unittest.TestCase): + + def setUp(self): + self.client = Client() + self.waf = Waf(self.client) + + @requests_mock.Mocker() + def test_list_rules(self, m): + data = { + "total": 5.0, + "rules": [], + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.waf.list_rules() + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_bypass_rule(self, m): + data = { + "$id": "wafRule1", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "Block anonymous POST traffic", + "description": "Blocks anonymous POST calls to \/v1\/graphql", + "teamId": "5e5ea5c16897e", + "projectId": "cloudConsole", + "resourceType": "functions", + "resourceId": "functionId", + "action": "deny", + "priority": 100.0, + "enabled": True, + "conditions": [], + "config": {}, + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.waf.create_bypass_rule( + '', + 'api', + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_bypass_rule(self, m): + data = { + "$id": "wafRule1", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "Block anonymous POST traffic", + "description": "Blocks anonymous POST calls to \/v1\/graphql", + "teamId": "5e5ea5c16897e", + "projectId": "cloudConsole", + "resourceType": "functions", + "resourceId": "functionId", + "action": "deny", + "priority": 100.0, + "enabled": True, + "conditions": [], + "config": {}, + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.waf.update_bypass_rule( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_challenge_rule(self, m): + data = { + "$id": "wafRule1", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "Block anonymous POST traffic", + "description": "Blocks anonymous POST calls to \/v1\/graphql", + "teamId": "5e5ea5c16897e", + "projectId": "cloudConsole", + "resourceType": "functions", + "resourceId": "functionId", + "action": "deny", + "priority": 100.0, + "enabled": True, + "conditions": [], + "config": {}, + "challengeType": "compute", + "difficulty": 3.0, + "ttl": 1800.0, + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.waf.create_challenge_rule( + '', + 'api', + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_challenge_rule(self, m): + data = { + "$id": "wafRule1", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "Block anonymous POST traffic", + "description": "Blocks anonymous POST calls to \/v1\/graphql", + "teamId": "5e5ea5c16897e", + "projectId": "cloudConsole", + "resourceType": "functions", + "resourceId": "functionId", + "action": "deny", + "priority": 100.0, + "enabled": True, + "conditions": [], + "config": {}, + "challengeType": "compute", + "difficulty": 3.0, + "ttl": 1800.0, + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.waf.update_challenge_rule( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_deny_rule(self, m): + data = { + "$id": "wafRule1", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "Block anonymous POST traffic", + "description": "Blocks anonymous POST calls to \/v1\/graphql", + "teamId": "5e5ea5c16897e", + "projectId": "cloudConsole", + "resourceType": "functions", + "resourceId": "functionId", + "action": "deny", + "priority": 100.0, + "enabled": True, + "conditions": [], + "config": {}, + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.waf.create_deny_rule( + '', + 'api', + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_deny_rule(self, m): + data = { + "$id": "wafRule1", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "Block anonymous POST traffic", + "description": "Blocks anonymous POST calls to \/v1\/graphql", + "teamId": "5e5ea5c16897e", + "projectId": "cloudConsole", + "resourceType": "functions", + "resourceId": "functionId", + "action": "deny", + "priority": 100.0, + "enabled": True, + "conditions": [], + "config": {}, + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.waf.update_deny_rule( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_rate_limit_rule(self, m): + data = { + "$id": "wafRule1", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "Block anonymous POST traffic", + "description": "Blocks anonymous POST calls to \/v1\/graphql", + "teamId": "5e5ea5c16897e", + "projectId": "cloudConsole", + "resourceType": "functions", + "resourceId": "functionId", + "action": "deny", + "priority": 100.0, + "enabled": True, + "conditions": [], + "config": {}, + "limit": 1000.0, + "interval": 60.0, + "key": "userId", + "strategy": "slidingWindow", + "maxBucketSize": 200.0, + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.waf.create_rate_limit_rule( + '', + 'api', + '', + 1, + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_rate_limit_rule(self, m): + data = { + "$id": "wafRule1", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "Block anonymous POST traffic", + "description": "Blocks anonymous POST calls to \/v1\/graphql", + "teamId": "5e5ea5c16897e", + "projectId": "cloudConsole", + "resourceType": "functions", + "resourceId": "functionId", + "action": "deny", + "priority": 100.0, + "enabled": True, + "conditions": [], + "config": {}, + "limit": 1000.0, + "interval": 60.0, + "key": "userId", + "strategy": "slidingWindow", + "maxBucketSize": 200.0, + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.waf.update_rate_limit_rule( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_redirect_rule(self, m): + data = { + "$id": "wafRule1", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "Block anonymous POST traffic", + "description": "Blocks anonymous POST calls to \/v1\/graphql", + "teamId": "5e5ea5c16897e", + "projectId": "cloudConsole", + "resourceType": "functions", + "resourceId": "functionId", + "action": "deny", + "priority": 100.0, + "enabled": True, + "conditions": [], + "config": {}, + "location": "\/maintenance", + "statusCode": 301.0, + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.waf.create_redirect_rule( + '', + 'api', + '', + '', + 1, + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update_redirect_rule(self, m): + data = { + "$id": "wafRule1", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "Block anonymous POST traffic", + "description": "Blocks anonymous POST calls to \/v1\/graphql", + "teamId": "5e5ea5c16897e", + "projectId": "cloudConsole", + "resourceType": "functions", + "resourceId": "functionId", + "action": "deny", + "priority": 100.0, + "enabled": True, + "conditions": [], + "config": {}, + "location": "\/maintenance", + "statusCode": 301.0, + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.waf.update_redirect_rule( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_get_rule(self, m): + data = { + "$id": "wafRule1", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "name": "Block anonymous POST traffic", + "description": "Blocks anonymous POST calls to \/v1\/graphql", + "teamId": "5e5ea5c16897e", + "projectId": "cloudConsole", + "resourceType": "functions", + "resourceId": "functionId", + "action": "deny", + "priority": 100.0, + "enabled": True, + "conditions": [], + "config": {}, + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.waf.get_rule( + '', + ) + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_delete_rule(self, m): + data = '' + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.waf.delete_rule( + '', + ) + self.assertEqual(response, data) From a596bd0bb678afc8ebc1aa9b2062ad3ca3b35918 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Wed, 14 Oct 2026 12:56:34 +0100 Subject: [PATCH 2/2] docs: correct the domains changelog entry The domains service reads transfer status; it does not start transfers. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9d5f546..462f7d1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## 24.4.0 -* Added: `domains` service to register, transfer and manage domains, DNS records, email presets and zones +* Added: `domains` service to manage domains, DNS records, email presets, prices, transfer status and zones * Added: `waf` service with bypass, challenge, deny, rate-limit and redirect rules * Added: `account.createEmailVerificationOTP`, `updateEmailVerificationOTP`, `createRecoveryOTP` and `updateRecoveryOTP` * Added: `account.createIdTokenSession` and `Identity.providerIdToken`