From 6d99a66b1a799c5ca01f64a74bce1c0974238019 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Mon, 22 Jun 2026 18:40:46 +0530 Subject: [PATCH] chore: update Python SDK to 21.0.0 --- CHANGELOG.md | 14 + appwrite/client.py | 10 +- appwrite/enums/project_key_scopes.py | 1 + appwrite/enums/project_policy_id.py | 1 + appwrite/enums/project_service_id.py | 1 + appwrite/models/__init__.py | 40 +- appwrite/models/activity_event.py | 36 - appwrite/models/app.py | 82 +++ appwrite/models/app_secret.py | 39 + appwrite/models/app_secret_list.py | 19 + appwrite/models/app_secret_plaintext.py | 39 + appwrite/models/apps_list.py | 19 + appwrite/models/backup_policy.py | 3 + appwrite/models/membership.py | 3 + appwrite/models/oauth2_approve.py | 15 + appwrite/models/oauth2_authorize.py | 18 + .../models/oauth2_device_authorization.py | 30 + appwrite/models/oauth2_grant.py | 45 ++ appwrite/models/oauth2_reject.py | 15 + appwrite/models/oauth2_token.py | 33 + .../models/policy_deny_corporate_email.py | 18 + appwrite/models/policy_list.py | 5 +- appwrite/models/policy_membership_privacy.py | 3 + appwrite/models/project.py | 51 +- appwrite/models/usage_data_point.py | 60 ++ appwrite/models/usage_event.py | 42 -- appwrite/models/usage_event_list.py | 16 +- appwrite/models/usage_gauge.py | 27 - appwrite/models/usage_gauge_list.py | 16 +- appwrite/models/usage_metric.py | 19 + appwrite/models/user.py | 15 + appwrite/services/account.py | 41 ++ appwrite/services/activities.py | 2 + appwrite/services/advisor.py | 4 + appwrite/services/apps.py | 666 ++++++++++++++++++ appwrite/services/avatars.py | 8 + appwrite/services/backups.py | 12 + appwrite/services/databases.py | 137 +++- appwrite/services/functions.py | 22 + appwrite/services/graphql.py | 2 + appwrite/services/health.py | 25 + appwrite/services/locale.py | 8 + appwrite/services/messaging.py | 46 ++ appwrite/services/oauth2.py | 453 ++++++++++++ appwrite/services/organization.py | 7 + appwrite/services/presences.py | 4 + appwrite/services/project.py | 177 ++++- appwrite/services/proxy.py | 7 + appwrite/services/sites.py | 22 + appwrite/services/storage.py | 11 + appwrite/services/tables_db.py | 102 ++- appwrite/services/teams.py | 11 + appwrite/services/tokens.py | 4 + appwrite/services/usage.py | 156 +++- appwrite/services/users.py | 37 + appwrite/services/webhooks.py | 5 + docs/examples/account/create.md | 2 +- docs/examples/account/update-password.md | 4 +- docs/examples/account/update-recovery.md | 2 +- docs/examples/apps/create-secret.md | 18 + docs/examples/apps/create.md | 36 + docs/examples/apps/delete-secret.md | 16 + docs/examples/apps/delete-tokens.md | 15 + docs/examples/apps/delete.md | 15 + docs/examples/apps/get-secret.md | 19 + docs/examples/apps/get.md | 18 + docs/examples/apps/list-secrets.md | 20 + docs/examples/apps/list.md | 19 + docs/examples/apps/update-team.md | 19 + docs/examples/apps/update.md | 35 + .../messaging/create-smtp-provider.md | 2 +- .../messaging/update-smtp-provider.md | 2 +- docs/examples/oauth2/approve.md | 19 + docs/examples/oauth2/authorize.md | 28 + .../oauth2/create-device-authorization.md | 20 + docs/examples/oauth2/create-grant.md | 18 + docs/examples/oauth2/create-token.md | 25 + docs/examples/oauth2/get-grant.md | 18 + docs/examples/oauth2/reject.md | 18 + docs/examples/oauth2/revoke.md | 18 + docs/examples/project/get-policy.md | 3 +- .../update-deny-corporate-email-policy.md | 18 + .../update-membership-privacy-policy.md | 3 +- .../project/update-o-auth-2-server.md | 7 +- docs/examples/project/update-smtp.md | 2 +- docs/examples/tablesdb/create.md | 3 +- docs/examples/usage/list-events.md | 13 +- docs/examples/usage/list-gauges.md | 13 +- docs/examples/users/create.md | 2 +- docs/examples/users/update-password.md | 2 +- docs/examples/webhooks/create.md | 2 +- docs/examples/webhooks/update.md | 2 +- pyproject.toml | 2 +- setup.py | 4 +- test/services/test_account.py | 6 +- test/services/test_activities.py | 12 - test/services/test_apps.py | 272 +++++++ test/services/test_backups.py | 3 + test/services/test_oauth2.py | 157 +++++ test/services/test_organization.py | 39 +- test/services/test_project.py | 286 ++------ test/services/test_teams.py | 4 + test/services/test_usage.py | 10 +- test/services/test_users.py | 2 +- test/services/test_webhooks.py | 8 +- 105 files changed, 3484 insertions(+), 501 deletions(-) create mode 100644 appwrite/models/app.py create mode 100644 appwrite/models/app_secret.py create mode 100644 appwrite/models/app_secret_list.py create mode 100644 appwrite/models/app_secret_plaintext.py create mode 100644 appwrite/models/apps_list.py create mode 100644 appwrite/models/oauth2_approve.py create mode 100644 appwrite/models/oauth2_authorize.py create mode 100644 appwrite/models/oauth2_device_authorization.py create mode 100644 appwrite/models/oauth2_grant.py create mode 100644 appwrite/models/oauth2_reject.py create mode 100644 appwrite/models/oauth2_token.py create mode 100644 appwrite/models/policy_deny_corporate_email.py create mode 100644 appwrite/models/usage_data_point.py delete mode 100644 appwrite/models/usage_event.py delete mode 100644 appwrite/models/usage_gauge.py create mode 100644 appwrite/models/usage_metric.py create mode 100644 appwrite/services/apps.py create mode 100644 appwrite/services/oauth2.py create mode 100644 docs/examples/apps/create-secret.md create mode 100644 docs/examples/apps/create.md create mode 100644 docs/examples/apps/delete-secret.md create mode 100644 docs/examples/apps/delete-tokens.md create mode 100644 docs/examples/apps/delete.md create mode 100644 docs/examples/apps/get-secret.md create mode 100644 docs/examples/apps/get.md create mode 100644 docs/examples/apps/list-secrets.md create mode 100644 docs/examples/apps/list.md create mode 100644 docs/examples/apps/update-team.md create mode 100644 docs/examples/apps/update.md create mode 100644 docs/examples/oauth2/approve.md create mode 100644 docs/examples/oauth2/authorize.md create mode 100644 docs/examples/oauth2/create-device-authorization.md create mode 100644 docs/examples/oauth2/create-grant.md create mode 100644 docs/examples/oauth2/create-token.md create mode 100644 docs/examples/oauth2/get-grant.md create mode 100644 docs/examples/oauth2/reject.md create mode 100644 docs/examples/oauth2/revoke.md create mode 100644 docs/examples/project/update-deny-corporate-email-policy.md create mode 100644 test/services/test_apps.py create mode 100644 test/services/test_oauth2.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e20b2d2..c8e7a93d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Change Log +## 21.0.0 + +* Added: `apps` service for managing apps and app secrets +* Added: `oauth2` service for the OAuth2 authorization, device, and token flows +* Added: device authorization grant parameters (`verificationUrl`, `userCodeLength`, `userCodeFormat`, `deviceCodeDuration`) to `updateOAuth2Server` +* Added: `emailCanonical`, `emailIsFree`, `emailIsDisposable`, `emailIsCorporate`, and `emailIsCanonical` to the `User` model +* Added: `userAccessedAt` to the `Membership` model +* Added: `PolicyDenyCorporateEmail` and `deny-corporate-email` to `ProjectPolicyId` +* Added: `dedicatedDatabases.execute` to `ProjectKeyScopes` +* Breaking: `usage.listEvents` now takes a required `metrics` array with `resource`, `interval`, and `dimensions` instead of `queries` and `total` +* Breaking: Replaced `UsageEvent` and `UsageGauge` models with `UsageDataPoint` and `UsageMetric` +* Updated: Send an `Accept: application/json` header on all requests + + ## 20.1.0 * Added: `createSesProvider` and `updateSesProvider` to `messaging` diff --git a/appwrite/client.py b/appwrite/client.py index c81b6f65..baafb0e7 100644 --- a/appwrite/client.py +++ b/appwrite/client.py @@ -17,11 +17,11 @@ def __init__(self): self._endpoint = 'https://cloud.appwrite.io/v1' self._global_headers = { 'content-type': '', - 'user-agent' : f'AppwritePythonSDK/20.1.0 ({platform.uname().system}; {platform.uname().version}; {platform.uname().machine})', + 'user-agent' : f'AppwritePythonSDK/21.0.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': '20.1.0', + 'x-sdk-version': '21.0.0', 'X-Appwrite-Response-Format' : '1.9.5', } self._config = {} @@ -101,21 +101,21 @@ def set_cookie(self, value): return self def set_impersonate_user_id(self, value): - """Impersonate a user by ID on an already user-authenticated request. Requires the current request to be authenticated as a user with impersonator capability; X-Appwrite-Key alone is not sufficient. Impersonator users are intentionally granted users.read so they can discover a target before impersonation begins. Internal audit logs still attribute actions to the original impersonator and record the impersonated target only in internal audit payload data.""" + """Impersonate a user by ID""" self._global_headers['x-appwrite-impersonate-user-id'] = value self._config['impersonateuserid'] = value return self def set_impersonate_user_email(self, value): - """Impersonate a user by email on an already user-authenticated request. Requires the current request to be authenticated as a user with impersonator capability; X-Appwrite-Key alone is not sufficient. Impersonator users are intentionally granted users.read so they can discover a target before impersonation begins. Internal audit logs still attribute actions to the original impersonator and record the impersonated target only in internal audit payload data.""" + """Impersonate a user by email""" self._global_headers['x-appwrite-impersonate-user-email'] = value self._config['impersonateuseremail'] = value return self def set_impersonate_user_phone(self, value): - """Impersonate a user by phone on an already user-authenticated request. Requires the current request to be authenticated as a user with impersonator capability; X-Appwrite-Key alone is not sufficient. Impersonator users are intentionally granted users.read so they can discover a target before impersonation begins. Internal audit logs still attribute actions to the original impersonator and record the impersonated target only in internal audit payload data.""" + """Impersonate a user by phone""" self._global_headers['x-appwrite-impersonate-user-phone'] = value self._config['impersonateuserphone'] = value diff --git a/appwrite/enums/project_key_scopes.py b/appwrite/enums/project_key_scopes.py index 54e5ff58..a0356058 100644 --- a/appwrite/enums/project_key_scopes.py +++ b/appwrite/enums/project_key_scopes.py @@ -91,6 +91,7 @@ class ProjectKeyScopes(Enum): ARCHIVES_WRITE = "archives.write" RESTORATIONS_READ = "restorations.read" RESTORATIONS_WRITE = "restorations.write" + DEDICATEDDATABASES_EXECUTE = "dedicatedDatabases.execute" DOMAINS_READ = "domains.read" DOMAINS_WRITE = "domains.write" EVENTS_READ = "events.read" diff --git a/appwrite/enums/project_policy_id.py b/appwrite/enums/project_policy_id.py index fb1714c0..56ca022b 100644 --- a/appwrite/enums/project_policy_id.py +++ b/appwrite/enums/project_policy_id.py @@ -14,3 +14,4 @@ class ProjectPolicyId(Enum): DENY_ALIASED_EMAIL = "deny-aliased-email" DENY_DISPOSABLE_EMAIL = "deny-disposable-email" DENY_FREE_EMAIL = "deny-free-email" + DENY_CORPORATE_EMAIL = "deny-corporate-email" diff --git a/appwrite/enums/project_service_id.py b/appwrite/enums/project_service_id.py index 2ab5a4b8..322e6d6c 100644 --- a/appwrite/enums/project_service_id.py +++ b/appwrite/enums/project_service_id.py @@ -19,3 +19,4 @@ class ProjectServiceId(Enum): MIGRATIONS = "migrations" MESSAGING = "messaging" ADVISOR = "advisor" + OAUTH2 = "oauth2" diff --git a/appwrite/models/__init__.py b/appwrite/models/__init__.py index e1b177b7..e8267dd9 100644 --- a/appwrite/models/__init__.py +++ b/appwrite/models/__init__.py @@ -222,15 +222,27 @@ from .policy_deny_aliased_email import PolicyDenyAliasedEmail from .policy_deny_disposable_email import PolicyDenyDisposableEmail from .policy_deny_free_email import PolicyDenyFreeEmail +from .policy_deny_corporate_email import PolicyDenyCorporateEmail from .backup_restoration import BackupRestoration -from .usage_event import UsageEvent -from .usage_gauge import UsageGauge +from .usage_data_point import UsageDataPoint +from .usage_event_list import UsageEventList +from .usage_gauge_list import UsageGaugeList +from .usage_metric import UsageMetric +from .app import App +from .app_secret import AppSecret +from .app_secret_plaintext import AppSecretPlaintext +from .oauth2_authorize import Oauth2Authorize +from .oauth2_approve import Oauth2Approve +from .oauth2_reject import Oauth2Reject +from .oauth2_grant import Oauth2Grant +from .oauth2_device_authorization import Oauth2DeviceAuthorization +from .oauth2_token import Oauth2Token from .activity_event_list import ActivityEventList from .backup_archive_list import BackupArchiveList from .backup_policy_list import BackupPolicyList from .backup_restoration_list import BackupRestorationList -from .usage_event_list import UsageEventList -from .usage_gauge_list import UsageGaugeList +from .apps_list import AppsList +from .app_secret_list import AppSecretList __all__ = [ 'AppwriteModel', @@ -457,13 +469,25 @@ 'PolicyDenyAliasedEmail', 'PolicyDenyDisposableEmail', 'PolicyDenyFreeEmail', + 'PolicyDenyCorporateEmail', 'BackupRestoration', - 'UsageEvent', - 'UsageGauge', + 'UsageDataPoint', + 'UsageEventList', + 'UsageGaugeList', + 'UsageMetric', + 'App', + 'AppSecret', + 'AppSecretPlaintext', + 'Oauth2Authorize', + 'Oauth2Approve', + 'Oauth2Reject', + 'Oauth2Grant', + 'Oauth2DeviceAuthorization', + 'Oauth2Token', 'ActivityEventList', 'BackupArchiveList', 'BackupPolicyList', 'BackupRestorationList', - 'UsageEventList', - 'UsageGaugeList', + 'AppsList', + 'AppSecretList', ] diff --git a/appwrite/models/activity_event.py b/appwrite/models/activity_event.py index c3146494..9e2b6313 100644 --- a/appwrite/models/activity_event.py +++ b/appwrite/models/activity_event.py @@ -45,30 +45,6 @@ class ActivityEvent(AppwriteModel): Team ID. hostname : str Hostname. - oscode : str - Operating system code name. View list of [available options](https://github.com/appwrite/appwrite/blob/master/docs/lists/os.json). - osname : str - Operating system name. - osversion : str - Operating system version. - clienttype : str - Client type. - clientcode : str - Client code name. View list of [available options](https://github.com/appwrite/appwrite/blob/master/docs/lists/clients.json). - clientname : str - Client name. - clientversion : str - Client version. - clientengine : str - Client engine name. - clientengineversion : str - Client engine name. - devicename : str - Device name. - devicebrand : str - Device brand name. - devicemodel : str - Device model name. countrycode : str Country two-character ISO 3166-1 alpha code. countryname : str @@ -92,17 +68,5 @@ class ActivityEvent(AppwriteModel): projectid: str = Field(..., alias='projectId') teamid: str = Field(..., alias='teamId') hostname: str = Field(..., alias='hostname') - oscode: str = Field(..., alias='osCode') - osname: str = Field(..., alias='osName') - osversion: str = Field(..., alias='osVersion') - clienttype: str = Field(..., alias='clientType') - clientcode: str = Field(..., alias='clientCode') - clientname: str = Field(..., alias='clientName') - clientversion: str = Field(..., alias='clientVersion') - clientengine: str = Field(..., alias='clientEngine') - clientengineversion: str = Field(..., alias='clientEngineVersion') - devicename: str = Field(..., alias='deviceName') - devicebrand: str = Field(..., alias='deviceBrand') - devicemodel: str = Field(..., alias='deviceModel') countrycode: str = Field(..., alias='countryCode') countryname: str = Field(..., alias='countryName') diff --git a/appwrite/models/app.py b/appwrite/models/app.py new file mode 100644 index 00000000..189910d2 --- /dev/null +++ b/appwrite/models/app.py @@ -0,0 +1,82 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel +from .app_secret import AppSecret + +class App(AppwriteModel): + """ + App + + Attributes + ---------- + id : str + App ID. + createdat : str + App creation time in ISO 8601 format. + updatedat : str + App update date in ISO 8601 format. + name : str + Application name. + description : str + Application description shown to users during OAuth2 consent. + clienturi : str + Application homepage URL shown to users during OAuth2 consent. + logouri : str + Application logo URL shown to users during OAuth2 consent. + privacypolicyurl : str + Application privacy policy URL shown to users during OAuth2 consent. + termsurl : str + Application terms of service URL shown to users during OAuth2 consent. + contacts : List[Any] + Application support or security contact emails. + tagline : str + Application tagline shown to users during OAuth2 consent. + tags : List[Any] + Application tags shown to users during OAuth2 consent. + images : List[Any] + Application image URLs shown to users during OAuth2 consent. + supporturl : str + Application support URL shown to users during OAuth2 consent. + datadeletionurl : str + Application data deletion URL shown to users during OAuth2 consent. + redirecturis : List[Any] + List of authorized redirect URIs. These URIs can be used to redirect users after they authenticate. + postlogoutredirecturis : List[Any] + List of authorized post-logout redirect URIs for OpenID Connect RP-Initiated Logout. The logout endpoint only redirects users to URIs in this list after ending their session. + enabled : bool + Whether the app is enabled or not. + type : str + OAuth2 client type. `public` for SPAs, mobile, and native apps that cannot keep a client secret (PKCE required); `confidential` for server-side clients that authenticate with a client secret. + deviceflow : bool + Whether this client may use the OAuth2 Device Authorization Grant (RFC 8628). + teamid : str + ID of team that owns the application, if owned by team. Otherwise, user ID will be used. + userid : str + ID of user who owns the application, if owned by user. Otherwise, team ID will be used. + secrets : List[AppSecret] + List of application secrets. + """ + 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') + clienturi: str = Field(..., alias='clientUri') + logouri: str = Field(..., alias='logoUri') + privacypolicyurl: str = Field(..., alias='privacyPolicyUrl') + termsurl: str = Field(..., alias='termsUrl') + contacts: List[Any] = Field(..., alias='contacts') + tagline: str = Field(..., alias='tagline') + tags: List[Any] = Field(..., alias='tags') + images: List[Any] = Field(..., alias='images') + supporturl: str = Field(..., alias='supportUrl') + datadeletionurl: str = Field(..., alias='dataDeletionUrl') + redirecturis: List[Any] = Field(..., alias='redirectUris') + postlogoutredirecturis: List[Any] = Field(..., alias='postLogoutRedirectUris') + enabled: bool = Field(..., alias='enabled') + type: str = Field(..., alias='type') + deviceflow: bool = Field(..., alias='deviceFlow') + teamid: str = Field(..., alias='teamId') + userid: str = Field(..., alias='userId') + secrets: List[AppSecret] = Field(..., alias='secrets') diff --git a/appwrite/models/app_secret.py b/appwrite/models/app_secret.py new file mode 100644 index 00000000..dc7def83 --- /dev/null +++ b/appwrite/models/app_secret.py @@ -0,0 +1,39 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel + +class AppSecret(AppwriteModel): + """ + AppSecret + + Attributes + ---------- + id : str + Secret ID. + createdat : str + Secret creation time in ISO 8601 format. + updatedat : str + Secret update time in ISO 8601 format. + appid : str + Application ID this secret belongs to. + secret : str + Hashed application client secret. + hint : str + Last few characters of the client secret, used to help identify it. + createdbyid : str + ID of the user who created the secret. + createdbyname : str + Name of the user who created the secret. + lastaccessedat : Optional[str] + Time the secret was last used for authentication in ISO 8601 format. Null if never used. + """ + id: str = Field(..., alias='$id') + createdat: str = Field(..., alias='$createdAt') + updatedat: str = Field(..., alias='$updatedAt') + appid: str = Field(..., alias='appId') + secret: str = Field(..., alias='secret') + hint: str = Field(..., alias='hint') + createdbyid: str = Field(..., alias='createdById') + createdbyname: str = Field(..., alias='createdByName') + lastaccessedat: Optional[str] = Field(default=None, alias='lastAccessedAt') diff --git a/appwrite/models/app_secret_list.py b/appwrite/models/app_secret_list.py new file mode 100644 index 00000000..c5e84728 --- /dev/null +++ b/appwrite/models/app_secret_list.py @@ -0,0 +1,19 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel +from .app_secret import AppSecret + +class AppSecretList(AppwriteModel): + """ + App secrets list + + Attributes + ---------- + total : float + Total number of secrets that matched your query. + secrets : List[AppSecret] + List of secrets. + """ + total: float = Field(..., alias='total') + secrets: List[AppSecret] = Field(..., alias='secrets') diff --git a/appwrite/models/app_secret_plaintext.py b/appwrite/models/app_secret_plaintext.py new file mode 100644 index 00000000..ec6d9ae5 --- /dev/null +++ b/appwrite/models/app_secret_plaintext.py @@ -0,0 +1,39 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel + +class AppSecretPlaintext(AppwriteModel): + """ + AppSecretPlaintext + + Attributes + ---------- + id : str + Secret ID. + createdat : str + Secret creation time in ISO 8601 format. + updatedat : str + Secret update time in ISO 8601 format. + appid : str + Application ID this secret belongs to. + secret : str + Application client secret. Returned in full only when the secret is created; subsequent reads return a masked value. + hint : str + Last few characters of the client secret, used to help identify it. + createdbyid : str + ID of the user who created the secret. + createdbyname : str + Name of the user who created the secret. + lastaccessedat : Optional[str] + Time the secret was last used for authentication in ISO 8601 format. Null if never used. + """ + id: str = Field(..., alias='$id') + createdat: str = Field(..., alias='$createdAt') + updatedat: str = Field(..., alias='$updatedAt') + appid: str = Field(..., alias='appId') + secret: str = Field(..., alias='secret') + hint: str = Field(..., alias='hint') + createdbyid: str = Field(..., alias='createdById') + createdbyname: str = Field(..., alias='createdByName') + lastaccessedat: Optional[str] = Field(default=None, alias='lastAccessedAt') diff --git a/appwrite/models/apps_list.py b/appwrite/models/apps_list.py new file mode 100644 index 00000000..dd11e26d --- /dev/null +++ b/appwrite/models/apps_list.py @@ -0,0 +1,19 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel +from .app import App + +class AppsList(AppwriteModel): + """ + Apps list + + Attributes + ---------- + total : float + Total number of apps that matched your query. + apps : List[App] + List of apps. + """ + total: float = Field(..., alias='total') + apps: List[App] = Field(..., alias='apps') diff --git a/appwrite/models/backup_policy.py b/appwrite/models/backup_policy.py index 8b67ca7a..be27b567 100644 --- a/appwrite/models/backup_policy.py +++ b/appwrite/models/backup_policy.py @@ -29,6 +29,8 @@ class BackupPolicy(AppwriteModel): How many days to keep the backup before it will be automatically deleted. schedule : str Policy backup schedule in CRON format. + type : str + Backup type. Possible values: full (complete database snapshot), incremental (changes since last backup). enabled : bool Is this policy enabled. """ @@ -42,4 +44,5 @@ class BackupPolicy(AppwriteModel): resourcetype: Optional[str] = Field(default=None, alias='resourceType') retention: float = Field(..., alias='retention') schedule: str = Field(..., alias='schedule') + type: str = Field(..., alias='type') enabled: bool = Field(..., alias='enabled') diff --git a/appwrite/models/membership.py b/appwrite/models/membership.py index 822c8a6a..83b276cc 100644 --- a/appwrite/models/membership.py +++ b/appwrite/models/membership.py @@ -35,6 +35,8 @@ class Membership(AppwriteModel): User confirmation status, true if the user has joined the team or false otherwise. mfa : bool Multi factor authentication status, true if the user has MFA enabled or false otherwise. Hide this attribute by toggling membership privacy in the Console. + useraccessedat : str + Most recent access date in ISO 8601 format. Show this attribute by toggling membership privacy in the Console. roles : List[Any] User list of roles """ @@ -51,4 +53,5 @@ class Membership(AppwriteModel): joined: str = Field(..., alias='joined') confirm: bool = Field(..., alias='confirm') mfa: bool = Field(..., alias='mfa') + useraccessedat: str = Field(..., alias='userAccessedAt') roles: List[Any] = Field(..., alias='roles') diff --git a/appwrite/models/oauth2_approve.py b/appwrite/models/oauth2_approve.py new file mode 100644 index 00000000..4e7d6fab --- /dev/null +++ b/appwrite/models/oauth2_approve.py @@ -0,0 +1,15 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel + +class Oauth2Approve(AppwriteModel): + """ + OAuth2 Approve + + Attributes + ---------- + redirecturl : str + URL the end user should be redirected to after the grant is approved, carrying the authorization `code` and/or `id_token` along with the original `state`. + """ + redirecturl: str = Field(..., alias='redirectUrl') diff --git a/appwrite/models/oauth2_authorize.py b/appwrite/models/oauth2_authorize.py new file mode 100644 index 00000000..8afb4749 --- /dev/null +++ b/appwrite/models/oauth2_authorize.py @@ -0,0 +1,18 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel + +class Oauth2Authorize(AppwriteModel): + """ + OAuth2 Authorize + + Attributes + ---------- + grantid : str + OAuth2 grant ID. Set when the user must give explicit consent; pass it to the approve or reject endpoint. Empty when a redirect URL is returned instead. + redirecturl : str + URL the end user should be redirected to when the flow can complete without consent. Empty when consent is still required. + """ + grantid: str = Field(..., alias='grantId') + redirecturl: str = Field(..., alias='redirectUrl') diff --git a/appwrite/models/oauth2_device_authorization.py b/appwrite/models/oauth2_device_authorization.py new file mode 100644 index 00000000..66413a71 --- /dev/null +++ b/appwrite/models/oauth2_device_authorization.py @@ -0,0 +1,30 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel + +class Oauth2DeviceAuthorization(AppwriteModel): + """ + OAuth2 Device Authorization + + Attributes + ---------- + device_code : str + Device verification code used by the client to poll the token endpoint. + user_code : str + Short code the end user enters on the verification page. + verification_uri : str + URL where the end user enters the user code. + verification_uri_complete : str + Verification URL with the user code prefilled as a query parameter. + expires_in : float + Lifetime of the device code and user code in seconds. + interval : float + Minimum polling interval for the token endpoint in seconds. + """ + device_code: str = Field(..., alias='device_code') + user_code: str = Field(..., alias='user_code') + verification_uri: str = Field(..., alias='verification_uri') + verification_uri_complete: str = Field(..., alias='verification_uri_complete') + expires_in: float = Field(..., alias='expires_in') + interval: float = Field(..., alias='interval') diff --git a/appwrite/models/oauth2_grant.py b/appwrite/models/oauth2_grant.py new file mode 100644 index 00000000..a17a74fd --- /dev/null +++ b/appwrite/models/oauth2_grant.py @@ -0,0 +1,45 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel + +class Oauth2Grant(AppwriteModel): + """ + OAuth2 Grant + + Attributes + ---------- + id : str + Grant ID. + createdat : str + Grant creation time in ISO 8601 format. + updatedat : str + Grant update date in ISO 8601 format. + userid : str + ID of the user the grant belongs to. + appid : str + ID of the OAuth2 client (app) the grant was requested for. + scopes : List[Any] + Requested OAuth2 scopes the user is being asked to consent to. + authorizationdetails : str + Requested authorization_details the user is being asked to consent to, as a JSON string. Each entry has a `type` plus project-defined fields. + prompt : str + OIDC prompt directive the consent screen should honor. Space-separated list of: login, consent, select_account. + redirecturi : str + Redirect URI the user will be sent to after the flow completes. + authtime : float + Unix timestamp of when the user last authenticated. + expire : str + Grant expiration time in ISO 8601 format. + """ + id: str = Field(..., alias='$id') + createdat: str = Field(..., alias='$createdAt') + updatedat: str = Field(..., alias='$updatedAt') + userid: str = Field(..., alias='userId') + appid: str = Field(..., alias='appId') + scopes: List[Any] = Field(..., alias='scopes') + authorizationdetails: str = Field(..., alias='authorizationDetails') + prompt: str = Field(..., alias='prompt') + redirecturi: str = Field(..., alias='redirectUri') + authtime: float = Field(..., alias='authTime') + expire: str = Field(..., alias='expire') diff --git a/appwrite/models/oauth2_reject.py b/appwrite/models/oauth2_reject.py new file mode 100644 index 00000000..b76c5073 --- /dev/null +++ b/appwrite/models/oauth2_reject.py @@ -0,0 +1,15 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel + +class Oauth2Reject(AppwriteModel): + """ + OAuth2 Reject + + Attributes + ---------- + redirecturl : str + URL the end user should be redirected to after the grant is rejected, carrying an `access_denied` error. + """ + redirecturl: str = Field(..., alias='redirectUrl') diff --git a/appwrite/models/oauth2_token.py b/appwrite/models/oauth2_token.py new file mode 100644 index 00000000..83d6dc99 --- /dev/null +++ b/appwrite/models/oauth2_token.py @@ -0,0 +1,33 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel + +class Oauth2Token(AppwriteModel): + """ + OAuth2 Token + + Attributes + ---------- + access_token : str + OAuth2 access token. + token_type : str + OAuth2 token type. + expires_in : float + Access token lifetime in seconds. + refresh_token : str + OAuth2 refresh token. + scope : str + Space-separated scopes granted to the access token. + authorization_details : Optional[str] + Granted RFC 9396 authorization details as a JSON string. + id_token : Optional[str] + OpenID Connect ID token. Returned when the `openid` scope is granted. + """ + access_token: str = Field(..., alias='access_token') + token_type: str = Field(..., alias='token_type') + expires_in: float = Field(..., alias='expires_in') + refresh_token: str = Field(..., alias='refresh_token') + scope: str = Field(..., alias='scope') + authorization_details: Optional[str] = Field(default=None, alias='authorization_details') + id_token: Optional[str] = Field(default=None, alias='id_token') diff --git a/appwrite/models/policy_deny_corporate_email.py b/appwrite/models/policy_deny_corporate_email.py new file mode 100644 index 00000000..af00e330 --- /dev/null +++ b/appwrite/models/policy_deny_corporate_email.py @@ -0,0 +1,18 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel + +class PolicyDenyCorporateEmail(AppwriteModel): + """ + Policy Deny Corporate Email + + Attributes + ---------- + id : str + Policy ID. + enabled : bool + Whether the deny non-corporate email policy is enabled. + """ + id: str = Field(..., alias='$id') + enabled: bool = Field(..., alias='enabled') diff --git a/appwrite/models/policy_list.py b/appwrite/models/policy_list.py index 97399089..3e579817 100644 --- a/appwrite/models/policy_list.py +++ b/appwrite/models/policy_list.py @@ -15,6 +15,7 @@ from .policy_deny_aliased_email import PolicyDenyAliasedEmail from .policy_deny_disposable_email import PolicyDenyDisposableEmail from .policy_deny_free_email import PolicyDenyFreeEmail +from .policy_deny_corporate_email import PolicyDenyCorporateEmail class PolicyList(AppwriteModel): """ @@ -24,8 +25,8 @@ 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, PolicyDenyAliasedEmail, PolicyDenyDisposableEmail, PolicyDenyFreeEmail]] + policies : List[Union[PolicyPasswordDictionary, PolicyPasswordHistory, PolicyPasswordStrength, PolicyPasswordPersonalData, PolicySessionAlert, PolicySessionDuration, PolicySessionInvalidation, PolicySessionLimit, PolicyUserLimit, PolicyMembershipPrivacy, PolicyDenyAliasedEmail, PolicyDenyDisposableEmail, PolicyDenyFreeEmail, PolicyDenyCorporateEmail]] List of policies. """ total: float = Field(..., alias='total') - policies: List[Union[PolicyPasswordDictionary, PolicyPasswordHistory, PolicyPasswordStrength, PolicyPasswordPersonalData, PolicySessionAlert, PolicySessionDuration, PolicySessionInvalidation, PolicySessionLimit, PolicyUserLimit, PolicyMembershipPrivacy, PolicyDenyAliasedEmail, PolicyDenyDisposableEmail, PolicyDenyFreeEmail]] = Field(..., alias='policies') + policies: List[Union[PolicyPasswordDictionary, PolicyPasswordHistory, PolicyPasswordStrength, PolicyPasswordPersonalData, PolicySessionAlert, PolicySessionDuration, PolicySessionInvalidation, PolicySessionLimit, PolicyUserLimit, PolicyMembershipPrivacy, PolicyDenyAliasedEmail, PolicyDenyDisposableEmail, PolicyDenyFreeEmail, PolicyDenyCorporateEmail]] = Field(..., alias='policies') diff --git a/appwrite/models/policy_membership_privacy.py b/appwrite/models/policy_membership_privacy.py index ca73ec98..e3e2a5bc 100644 --- a/appwrite/models/policy_membership_privacy.py +++ b/appwrite/models/policy_membership_privacy.py @@ -21,6 +21,8 @@ class PolicyMembershipPrivacy(AppwriteModel): Whether user name is visible in memberships. usermfa : bool Whether user MFA status is visible in memberships. + useraccessedat : bool + Whether user last access time is visible in memberships. """ id: str = Field(..., alias='$id') userid: bool = Field(..., alias='userId') @@ -28,3 +30,4 @@ class PolicyMembershipPrivacy(AppwriteModel): userphone: bool = Field(..., alias='userPhone') username: bool = Field(..., alias='userName') usermfa: bool = Field(..., alias='userMFA') + useraccessedat: bool = Field(..., alias='userAccessedAt') diff --git a/appwrite/models/project.py b/appwrite/models/project.py index 701823ff..afd4b5a5 100644 --- a/appwrite/models/project.py +++ b/appwrite/models/project.py @@ -69,23 +69,33 @@ class Project(AppwriteModel): Last time the project was accessed via console. Used with plan's projectInactivityDays to determine if project is paused. billinglimits : Optional[BillingLimits] Billing limits reached - oauth2serverenabled : bool + oauth2serverenabled : Optional[bool] OAuth2 server status - oauth2serverauthorizationurl : str + oauth2serverauthorizationurl : Optional[str] OAuth2 server authorization URL - oauth2serverscopes : List[Any] + oauth2serverscopes : Optional[List[Any]] OAuth2 server allowed scopes - oauth2serveraccesstokenduration : float + oauth2serverauthorizationdetailstypes : Optional[List[Any]] + OAuth2 server accepted RFC 9396 authorization_details types + oauth2serveraccesstokenduration : Optional[float] OAuth2 server access token duration in seconds for confidential clients - oauth2serverrefreshtokenduration : float + oauth2serverrefreshtokenduration : Optional[float] OAuth2 server refresh token duration in seconds for confidential clients - oauth2serverpublicaccesstokenduration : float + oauth2serverpublicaccesstokenduration : Optional[float] OAuth2 server access token duration in seconds for public clients (SPAs, mobile, native) - oauth2serverpublicrefreshtokenduration : float + oauth2serverpublicrefreshtokenduration : Optional[float] OAuth2 server refresh token duration in seconds for public clients (SPAs, mobile, native) - oauth2serverconfidentialpkce : bool + oauth2serverconfidentialpkce : Optional[bool] When enabled, PKCE is required for confidential clients (server-side flows using client_secret). PKCE is always required for public clients regardless of this setting. - oauth2serverdiscoveryurl : str + oauth2serververificationurl : Optional[str] + URL to your application page where users enter the device flow user code. Empty when the Device Authorization Grant is not configured. + oauth2serverusercodelength : Optional[float] + Number of characters in the device flow user code, excluding the formatting separator. + oauth2serverusercodeformat : Optional[str] + Character set for device flow user codes: `numeric`, `alphabetic`, or `alphanumeric`. + oauth2serverdevicecodeduration : Optional[float] + Lifetime in seconds of device flow device codes and user codes. + oauth2serverdiscoveryurl : Optional[str] OAuth2 server discovery URL """ id: str = Field(..., alias='$id') @@ -115,12 +125,17 @@ class Project(AppwriteModel): blocks: List[Block] = Field(..., alias='blocks') consoleaccessedat: str = Field(..., alias='consoleAccessedAt') billinglimits: Optional[BillingLimits] = Field(default=None, alias='billingLimits') - oauth2serverenabled: bool = Field(..., alias='oAuth2ServerEnabled') - oauth2serverauthorizationurl: str = Field(..., alias='oAuth2ServerAuthorizationUrl') - oauth2serverscopes: List[Any] = Field(..., alias='oAuth2ServerScopes') - oauth2serveraccesstokenduration: float = Field(..., alias='oAuth2ServerAccessTokenDuration') - oauth2serverrefreshtokenduration: float = Field(..., alias='oAuth2ServerRefreshTokenDuration') - oauth2serverpublicaccesstokenduration: float = Field(..., alias='oAuth2ServerPublicAccessTokenDuration') - oauth2serverpublicrefreshtokenduration: float = Field(..., alias='oAuth2ServerPublicRefreshTokenDuration') - oauth2serverconfidentialpkce: bool = Field(..., alias='oAuth2ServerConfidentialPkce') - oauth2serverdiscoveryurl: str = Field(..., alias='oAuth2ServerDiscoveryUrl') + 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') + oauth2serverauthorizationdetailstypes: Optional[List[Any]] = Field(default=None, alias='oAuth2ServerAuthorizationDetailsTypes') + oauth2serveraccesstokenduration: Optional[float] = Field(default=None, alias='oAuth2ServerAccessTokenDuration') + oauth2serverrefreshtokenduration: Optional[float] = Field(default=None, alias='oAuth2ServerRefreshTokenDuration') + oauth2serverpublicaccesstokenduration: Optional[float] = Field(default=None, alias='oAuth2ServerPublicAccessTokenDuration') + oauth2serverpublicrefreshtokenduration: Optional[float] = Field(default=None, alias='oAuth2ServerPublicRefreshTokenDuration') + oauth2serverconfidentialpkce: Optional[bool] = Field(default=None, alias='oAuth2ServerConfidentialPkce') + oauth2serververificationurl: Optional[str] = Field(default=None, alias='oAuth2ServerVerificationUrl') + oauth2serverusercodelength: Optional[float] = Field(default=None, alias='oAuth2ServerUserCodeLength') + oauth2serverusercodeformat: Optional[str] = Field(default=None, alias='oAuth2ServerUserCodeFormat') + oauth2serverdevicecodeduration: Optional[float] = Field(default=None, alias='oAuth2ServerDeviceCodeDuration') + oauth2serverdiscoveryurl: Optional[str] = Field(default=None, alias='oAuth2ServerDiscoveryUrl') diff --git a/appwrite/models/usage_data_point.py b/appwrite/models/usage_data_point.py new file mode 100644 index 00000000..a314956c --- /dev/null +++ b/appwrite/models/usage_data_point.py @@ -0,0 +1,60 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel + +class UsageDataPoint(AppwriteModel): + """ + usageDataPoint + + Attributes + ---------- + time : str + Bucket start timestamp (ISO 8601). When `interval` is omitted this is the request end time, marking the aggregate as-of moment. + value : float + Aggregated value for the bucket. + path : Optional[str] + API endpoint path when broken down by `path`. + method : Optional[str] + HTTP method when broken down by `method`. + status : Optional[str] + HTTP status code when broken down by `status`. + service : Optional[str] + API service segment when broken down by `service`. + country : Optional[str] + Country code when broken down by `country`. + region : Optional[str] + Appwrite region when broken down by `region`. + hostname : Optional[str] + Caller origin hostname when broken down by `hostname`. + osname : Optional[str] + Operating system name when broken down by `osName`. + clienttype : Optional[str] + Client type when broken down by `clientType`. + clientname : Optional[str] + Client name when broken down by `clientName`. + devicename : Optional[str] + Device classification when broken down by `deviceName`. + teamid : Optional[str] + Owning team ID when broken down by `teamId`. + resourceid : Optional[str] + External resource ID when broken down by `resourceId`. + resource : Optional[str] + Resource type when broken down by `resource` (gauges only). + """ + time: str = Field(..., alias='time') + value: float = Field(..., alias='value') + path: Optional[str] = Field(default=None, alias='path') + method: Optional[str] = Field(default=None, alias='method') + status: Optional[str] = Field(default=None, alias='status') + service: Optional[str] = Field(default=None, alias='service') + country: Optional[str] = Field(default=None, alias='country') + region: Optional[str] = Field(default=None, alias='region') + hostname: Optional[str] = Field(default=None, alias='hostname') + osname: Optional[str] = Field(default=None, alias='osName') + clienttype: Optional[str] = Field(default=None, alias='clientType') + clientname: Optional[str] = Field(default=None, alias='clientName') + devicename: Optional[str] = Field(default=None, alias='deviceName') + teamid: Optional[str] = Field(default=None, alias='teamId') + resourceid: Optional[str] = Field(default=None, alias='resourceId') + resource: Optional[str] = Field(default=None, alias='resource') diff --git a/appwrite/models/usage_event.py b/appwrite/models/usage_event.py deleted file mode 100644 index 81d05834..00000000 --- a/appwrite/models/usage_event.py +++ /dev/null @@ -1,42 +0,0 @@ -from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr - -from .base_model import AppwriteModel - -class UsageEvent(AppwriteModel): - """ - usageEvent - - Attributes - ---------- - metric : str - The metric key. - value : float - The metric value. - time : str - The event timestamp. - path : str - The API endpoint path. - method : str - The HTTP method. - status : str - HTTP status code. Stored as string to preserve unset state (empty string = not available). - resourcetype : str - The resource type. - resourceid : str - The resource ID. - countrycode : str - Country code in [ISO 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1) two-character format. - useragent : str - The user agent string. - """ - metric: str = Field(..., alias='metric') - value: float = Field(..., alias='value') - time: str = Field(..., alias='time') - path: str = Field(..., alias='path') - method: str = Field(..., alias='method') - status: str = Field(..., alias='status') - resourcetype: str = Field(..., alias='resourceType') - resourceid: str = Field(..., alias='resourceId') - countrycode: str = Field(..., alias='countryCode') - useragent: str = Field(..., alias='userAgent') diff --git a/appwrite/models/usage_event_list.py b/appwrite/models/usage_event_list.py index 4845b7c6..c183c3e4 100644 --- a/appwrite/models/usage_event_list.py +++ b/appwrite/models/usage_event_list.py @@ -2,18 +2,18 @@ from pydantic import Field, PrivateAttr from .base_model import AppwriteModel -from .usage_event import UsageEvent +from .usage_metric import UsageMetric class UsageEventList(AppwriteModel): """ - Usage events list + usageEventList Attributes ---------- - total : float - Total number of events that matched your query. - events : List[UsageEvent] - List of events. + interval : str + Time interval size (1h or 1d). Empty when the request omits `interval` — points then carry the request end time as their as-of marker. + metrics : List[UsageMetric] + One entry per requested metric, each carrying its own points[] time series (sums per bucket / dimension over time). """ - total: float = Field(..., alias='total') - events: List[UsageEvent] = Field(..., alias='events') + interval: str = Field(..., alias='interval') + metrics: List[UsageMetric] = Field(..., alias='metrics') diff --git a/appwrite/models/usage_gauge.py b/appwrite/models/usage_gauge.py deleted file mode 100644 index dd56e10e..00000000 --- a/appwrite/models/usage_gauge.py +++ /dev/null @@ -1,27 +0,0 @@ -from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr - -from .base_model import AppwriteModel - -class UsageGauge(AppwriteModel): - """ - usageGauge - - Attributes - ---------- - metric : str - The metric key. - value : float - The current snapshot value. - time : str - The snapshot timestamp. - resourcetype : str - The resource type. - resourceid : str - The resource ID. - """ - metric: str = Field(..., alias='metric') - value: float = Field(..., alias='value') - time: str = Field(..., alias='time') - resourcetype: str = Field(..., alias='resourceType') - resourceid: str = Field(..., alias='resourceId') diff --git a/appwrite/models/usage_gauge_list.py b/appwrite/models/usage_gauge_list.py index a0f2df72..ee3727ae 100644 --- a/appwrite/models/usage_gauge_list.py +++ b/appwrite/models/usage_gauge_list.py @@ -2,18 +2,18 @@ from pydantic import Field, PrivateAttr from .base_model import AppwriteModel -from .usage_gauge import UsageGauge +from .usage_metric import UsageMetric class UsageGaugeList(AppwriteModel): """ - Usage gauges list + usageGaugeList Attributes ---------- - total : float - Total number of gauges that matched your query. - gauges : List[UsageGauge] - List of gauges. + interval : str + Time interval size (1h or 1d). Empty when the request omits `interval` — points then carry the request end time as their as-of marker. + metrics : List[UsageMetric] + One entry per requested metric, each carrying its own points[] time series (latest-snapshot per bucket / dimension via argMax over time). """ - total: float = Field(..., alias='total') - gauges: List[UsageGauge] = Field(..., alias='gauges') + interval: str = Field(..., alias='interval') + metrics: List[UsageMetric] = Field(..., alias='metrics') diff --git a/appwrite/models/usage_metric.py b/appwrite/models/usage_metric.py new file mode 100644 index 00000000..3cd15d47 --- /dev/null +++ b/appwrite/models/usage_metric.py @@ -0,0 +1,19 @@ +from typing import Any, Dict, List, Optional, Union, cast +from pydantic import Field, PrivateAttr + +from .base_model import AppwriteModel +from .usage_data_point import UsageDataPoint + +class UsageMetric(AppwriteModel): + """ + usageMetric + + Attributes + ---------- + metric : str + Metric key this series describes. + points : List[UsageDataPoint] + Data points for this metric, ordered by time ascending. With `interval`, each entry is one bucket; without, each entry is one row of the dimensional or aggregate breakdown. + """ + metric: str = Field(..., alias='metric') + points: List[UsageDataPoint] = Field(..., alias='points') diff --git a/appwrite/models/user.py b/appwrite/models/user.py index 58c5080d..034c0052 100644 --- a/appwrite/models/user.py +++ b/appwrite/models/user.py @@ -48,6 +48,16 @@ class User(AppwriteModel, Generic[T]): 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. phoneverification : bool Phone verification status. mfa : bool @@ -77,6 +87,11 @@ class User(AppwriteModel, Generic[T]): 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') phoneverification: bool = Field(..., alias='phoneVerification') mfa: bool = Field(..., alias='mfa') prefs: Preferences[T] = Field(..., alias='prefs') diff --git a/appwrite/services/account.py b/appwrite/services/account.py index 4f7d5f60..21b734d1 100644 --- a/appwrite/services/account.py +++ b/appwrite/services/account.py @@ -55,6 +55,7 @@ def get( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', }, api_params) return User.with_data(response, model_type) @@ -117,6 +118,7 @@ def create( 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 User.with_data(response, model_type) @@ -169,6 +171,7 @@ def update_email( 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 User.with_data(response, model_type) @@ -210,6 +213,7 @@ def list_identities( 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=IdentityList) @@ -286,6 +290,7 @@ def create_jwt( 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=Jwt) @@ -327,6 +332,7 @@ def list_logs( 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=LogList) @@ -370,6 +376,7 @@ def update_mfa( 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 User.with_data(response, model_type) @@ -409,6 +416,7 @@ def create_mfa_authenticator( 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=MfaType) @@ -459,6 +467,7 @@ def update_mfa_authenticator( 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 User.with_data(response, model_type) @@ -537,6 +546,7 @@ def create_mfa_challenge( 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=MfaChallenge) @@ -583,6 +593,7 @@ def update_mfa_challenge( 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=Session) @@ -610,6 +621,7 @@ def list_mfa_factors( 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=MfaFactors) @@ -637,6 +649,7 @@ def get_mfa_recovery_codes( 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=MfaRecoveryCodes) @@ -665,6 +678,7 @@ def create_mfa_recovery_codes( 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=MfaRecoveryCodes) @@ -693,6 +707,7 @@ def update_mfa_recovery_codes( 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=MfaRecoveryCodes) @@ -736,6 +751,7 @@ def update_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 User.with_data(response, model_type) @@ -784,6 +800,7 @@ def update_password( 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 User.with_data(response, model_type) @@ -834,6 +851,7 @@ def update_phone( 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 User.with_data(response, model_type) @@ -868,6 +886,7 @@ def get_prefs( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', }, api_params) return Preferences.with_data(response, model_type) @@ -911,6 +930,7 @@ def update_prefs( 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 User.with_data(response, model_type) @@ -957,6 +977,7 @@ def create_recovery( 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) @@ -1012,6 +1033,7 @@ def update_recovery( 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) @@ -1039,6 +1061,7 @@ def list_sessions( 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=SessionList) @@ -1095,6 +1118,7 @@ def create_anonymous_session( 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) @@ -1143,6 +1167,7 @@ def create_email_password_session( 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) @@ -1192,6 +1217,7 @@ def update_magic_url_session( 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=Session) @@ -1241,6 +1267,7 @@ def update_phone_session( 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=Session) @@ -1287,6 +1314,7 @@ def create_session( 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) @@ -1325,6 +1353,7 @@ def get_session( 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=Session) @@ -1364,6 +1393,7 @@ def update_session( 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=Session) @@ -1438,6 +1468,7 @@ def update_status( 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 User.with_data(response, model_type) @@ -1492,6 +1523,7 @@ def create_email_token( 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) @@ -1551,6 +1583,7 @@ def create_magic_url_token( 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) @@ -1608,6 +1641,7 @@ def create_o_auth2_token( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'text/html', }, api_params, response_type='location') return response @@ -1656,6 +1690,7 @@ def create_phone_token( 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) @@ -1698,6 +1733,7 @@ def create_email_verification( 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) @@ -1743,6 +1779,7 @@ def create_verification( 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) @@ -1789,6 +1826,7 @@ def update_email_verification( 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) @@ -1838,6 +1876,7 @@ def update_verification( 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) @@ -1866,6 +1905,7 @@ def create_phone_verification( 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) @@ -1912,6 +1952,7 @@ def update_phone_verification( 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) diff --git a/appwrite/services/activities.py b/appwrite/services/activities.py index 63c8a3f5..0d1e5b5b 100644 --- a/appwrite/services/activities.py +++ b/appwrite/services/activities.py @@ -42,6 +42,7 @@ def list_events( 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=ActivityEventList) @@ -81,6 +82,7 @@ def get_event( 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=ActivityEvent) diff --git a/appwrite/services/advisor.py b/appwrite/services/advisor.py index 3176193d..249e3b76 100644 --- a/appwrite/services/advisor.py +++ b/appwrite/services/advisor.py @@ -50,6 +50,7 @@ def list_reports( 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=ReportList) @@ -89,6 +90,7 @@ def get_report( 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=Report) @@ -178,6 +180,7 @@ def list_insights( 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=InsightList) @@ -224,6 +227,7 @@ def get_insight( 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=Insight) diff --git a/appwrite/services/apps.py b/appwrite/services/apps.py new file mode 100644 index 00000000..da3c25d3 --- /dev/null +++ b/appwrite/services/apps.py @@ -0,0 +1,666 @@ +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.apps_list import AppsList +from ..models.app import App +from ..models.app_secret_list import AppSecretList +from ..models.app_secret_plaintext import AppSecretPlaintext +from ..models.app_secret import AppSecret + +class Apps(Service): + + def __init__(self, client) -> None: + super(Apps, self).__init__(client) + + def list( + self, + queries: Optional[List[str]] = None, + total: Optional[bool] = None + ) -> AppsList: + """ + List applications. + + 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. + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. + + Returns + ------- + AppsList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/apps' + 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=AppsList) + + + def create( + self, + app_id: str, + name: str, + redirect_uris: List[str], + description: Optional[str] = None, + client_uri: Optional[str] = None, + logo_uri: Optional[str] = None, + privacy_policy_url: Optional[str] = None, + terms_url: Optional[str] = None, + contacts: Optional[List[str]] = None, + tagline: Optional[str] = None, + tags: Optional[List[str]] = None, + images: Optional[List[str]] = None, + support_url: Optional[str] = None, + data_deletion_url: Optional[str] = None, + post_logout_redirect_uris: Optional[List[str]] = None, + enabled: Optional[bool] = None, + type: Optional[str] = None, + device_flow: Optional[bool] = None, + team_id: Optional[str] = None + ) -> App: + """ + Create a new application. + + Parameters + ---------- + app_id : str + Application 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 + Application name. + redirect_uris : List[str] + Redirect URIs (array of valid URLs). + description : Optional[str] + Application description shown to users during OAuth2 consent. + client_uri : Optional[str] + Application homepage URL shown to users during OAuth2 consent. + logo_uri : Optional[str] + Application logo URL shown to users during OAuth2 consent. + privacy_policy_url : Optional[str] + Application privacy policy URL shown to users during OAuth2 consent. + terms_url : Optional[str] + Application terms of service URL shown to users during OAuth2 consent. + contacts : Optional[List[str]] + Application support or security contact emails. Maximum of 100 contacts are allowed. + tagline : Optional[str] + Application tagline shown to users during OAuth2 consent. + tags : Optional[List[str]] + Application tags shown to users during OAuth2 consent. Maximum of 100 tags are allowed, each up to 64 characters long. + images : Optional[List[str]] + Application image URLs shown to users during OAuth2 consent. Maximum of 100 images are allowed. + support_url : Optional[str] + Application support URL shown to users during OAuth2 consent. + data_deletion_url : Optional[str] + Application data deletion URL shown to users during OAuth2 consent. + post_logout_redirect_uris : Optional[List[str]] + Post-logout redirect URIs for OpenID Connect RP-Initiated Logout (array of valid URLs). After ending the user session, the logout endpoint only redirects to URIs in this list. + enabled : Optional[bool] + Is application enabled? + type : Optional[str] + OAuth2 client type. Use `public` for SPAs, mobile, and native apps that cannot keep a `client_secret` — PKCE is then required at the token endpoint. Use `confidential` for server-side clients that present a `client_secret`. Defaults to `confidential`. + device_flow : Optional[bool] + Allow this client to use the OAuth2 Device Authorization Grant (RFC 8628) for input-constrained devices such as TVs and CLIs. Defaults to false. + team_id : Optional[str] + Team unique ID. + + Returns + ------- + App + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/apps' + api_params = {} + if app_id is None: + raise AppwriteException('Missing required parameter: "app_id"') + + if name is None: + raise AppwriteException('Missing required parameter: "name"') + + if redirect_uris is None: + raise AppwriteException('Missing required parameter: "redirect_uris"') + + + api_params['appId'] = self._normalize_value(app_id) + api_params['name'] = self._normalize_value(name) + if description is not None: + api_params['description'] = self._normalize_value(description) + if client_uri is not None: + api_params['clientUri'] = self._normalize_value(client_uri) + if logo_uri is not None: + api_params['logoUri'] = self._normalize_value(logo_uri) + if privacy_policy_url is not None: + api_params['privacyPolicyUrl'] = self._normalize_value(privacy_policy_url) + if terms_url is not None: + api_params['termsUrl'] = self._normalize_value(terms_url) + if contacts is not None: + api_params['contacts'] = self._normalize_value(contacts) + if tagline is not None: + api_params['tagline'] = self._normalize_value(tagline) + if tags is not None: + api_params['tags'] = self._normalize_value(tags) + if images is not None: + api_params['images'] = self._normalize_value(images) + if support_url is not None: + api_params['supportUrl'] = self._normalize_value(support_url) + if data_deletion_url is not None: + api_params['dataDeletionUrl'] = self._normalize_value(data_deletion_url) + api_params['redirectUris'] = self._normalize_value(redirect_uris) + if post_logout_redirect_uris is not None: + api_params['postLogoutRedirectUris'] = self._normalize_value(post_logout_redirect_uris) + if enabled is not None: + api_params['enabled'] = self._normalize_value(enabled) + if type is not None: + api_params['type'] = self._normalize_value(type) + if device_flow is not None: + api_params['deviceFlow'] = self._normalize_value(device_flow) + if team_id is not None: + api_params['teamId'] = self._normalize_value(team_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=App) + + + def get( + self, + app_id: str + ) -> App: + """ + Get an application by its unique ID. + + Parameters + ---------- + app_id : str + Application unique ID. + + Returns + ------- + App + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/apps/{appId}' + api_params = {} + if app_id is None: + raise AppwriteException('Missing required parameter: "app_id"') + + api_path = api_path.replace('{appId}', str(self._normalize_value(app_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=App) + + + def update( + self, + app_id: str, + name: str, + description: Optional[str] = None, + client_uri: Optional[str] = None, + logo_uri: Optional[str] = None, + privacy_policy_url: Optional[str] = None, + terms_url: Optional[str] = None, + contacts: Optional[List[str]] = None, + tagline: Optional[str] = None, + tags: Optional[List[str]] = None, + images: Optional[List[str]] = None, + support_url: Optional[str] = None, + data_deletion_url: Optional[str] = None, + enabled: Optional[bool] = None, + redirect_uris: Optional[List[str]] = None, + post_logout_redirect_uris: Optional[List[str]] = None, + type: Optional[str] = None, + device_flow: Optional[bool] = None + ) -> App: + """ + Update an application by its unique ID. + + Parameters + ---------- + app_id : str + Application unique ID. + name : str + Application name. + description : Optional[str] + Application description shown to users during OAuth2 consent. + client_uri : Optional[str] + Application homepage URL shown to users during OAuth2 consent. + logo_uri : Optional[str] + Application logo URL shown to users during OAuth2 consent. + privacy_policy_url : Optional[str] + Application privacy policy URL shown to users during OAuth2 consent. + terms_url : Optional[str] + Application terms of service URL shown to users during OAuth2 consent. + contacts : Optional[List[str]] + Application support or security contact emails. Maximum of 100 contacts are allowed. + tagline : Optional[str] + Application tagline shown to users during OAuth2 consent. + tags : Optional[List[str]] + Application tags shown to users during OAuth2 consent. Maximum of 100 tags are allowed, each up to 64 characters long. + images : Optional[List[str]] + Application image URLs shown to users during OAuth2 consent. Maximum of 100 images are allowed. + support_url : Optional[str] + Application support URL shown to users during OAuth2 consent. + data_deletion_url : Optional[str] + Application data deletion URL shown to users during OAuth2 consent. + enabled : Optional[bool] + Is application enabled? + redirect_uris : Optional[List[str]] + Redirect URIs (array of valid URLs). + post_logout_redirect_uris : Optional[List[str]] + Post-logout redirect URIs for OpenID Connect RP-Initiated Logout (array of valid URLs). After ending the user session, the logout endpoint only redirects to URIs in this list. + type : Optional[str] + OAuth2 client type. Use `public` for SPAs, mobile, and native apps that cannot keep a `client_secret` — PKCE is then required at the token endpoint. Use `confidential` for server-side clients that present a `client_secret`. Defaults to `confidential`. + device_flow : Optional[bool] + Allow this client to use the OAuth2 Device Authorization Grant (RFC 8628) for input-constrained devices such as TVs and CLIs. Defaults to false. + + Returns + ------- + App + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/apps/{appId}' + api_params = {} + if app_id is None: + raise AppwriteException('Missing required parameter: "app_id"') + + if name is None: + raise AppwriteException('Missing required parameter: "name"') + + api_path = api_path.replace('{appId}', str(self._normalize_value(app_id))) + + api_params['name'] = self._normalize_value(name) + if description is not None: + api_params['description'] = self._normalize_value(description) + if client_uri is not None: + api_params['clientUri'] = self._normalize_value(client_uri) + if logo_uri is not None: + api_params['logoUri'] = self._normalize_value(logo_uri) + if privacy_policy_url is not None: + api_params['privacyPolicyUrl'] = self._normalize_value(privacy_policy_url) + if terms_url is not None: + api_params['termsUrl'] = self._normalize_value(terms_url) + if contacts is not None: + api_params['contacts'] = self._normalize_value(contacts) + if tagline is not None: + api_params['tagline'] = self._normalize_value(tagline) + if tags is not None: + api_params['tags'] = self._normalize_value(tags) + if images is not None: + api_params['images'] = self._normalize_value(images) + if support_url is not None: + api_params['supportUrl'] = self._normalize_value(support_url) + if data_deletion_url is not None: + api_params['dataDeletionUrl'] = self._normalize_value(data_deletion_url) + if enabled is not None: + api_params['enabled'] = self._normalize_value(enabled) + if redirect_uris is not None: + api_params['redirectUris'] = self._normalize_value(redirect_uris) + if post_logout_redirect_uris is not None: + api_params['postLogoutRedirectUris'] = self._normalize_value(post_logout_redirect_uris) + if type is not None: + api_params['type'] = self._normalize_value(type) + if device_flow is not None: + api_params['deviceFlow'] = self._normalize_value(device_flow) + + 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=App) + + + def delete( + self, + app_id: str + ) -> Dict[str, Any]: + """ + Delete an application by its unique ID. + + Parameters + ---------- + app_id : str + Application unique ID. + + Returns + ------- + Dict[str, Any] + API response as a dictionary + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/apps/{appId}' + api_params = {} + if app_id is None: + raise AppwriteException('Missing required parameter: "app_id"') + + api_path = api_path.replace('{appId}', str(self._normalize_value(app_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_secrets( + self, + app_id: str, + queries: Optional[List[str]] = None, + total: Optional[bool] = None + ) -> AppSecretList: + """ + List client secrets for an application. + + Parameters + ---------- + app_id : str + Application 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. + total : Optional[bool] + When set to false, the total count returned will be 0 and will not be calculated. + + Returns + ------- + AppSecretList + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/apps/{appId}/secrets' + api_params = {} + if app_id is None: + raise AppwriteException('Missing required parameter: "app_id"') + + api_path = api_path.replace('{appId}', str(self._normalize_value(app_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=AppSecretList) + + + def create_secret( + self, + app_id: str + ) -> AppSecretPlaintext: + """ + Create a new client secret for an application. + + Parameters + ---------- + app_id : str + Application unique ID. + + Returns + ------- + AppSecretPlaintext + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/apps/{appId}/secrets' + api_params = {} + if app_id is None: + raise AppwriteException('Missing required parameter: "app_id"') + + api_path = api_path.replace('{appId}', str(self._normalize_value(app_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=AppSecretPlaintext) + + + def get_secret( + self, + app_id: str, + secret_id: str + ) -> AppSecret: + """ + Get an application client secret by its unique ID. + + Parameters + ---------- + app_id : str + Application unique ID. + secret_id : str + Secret unique ID. + + Returns + ------- + AppSecret + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/apps/{appId}/secrets/{secretId}' + api_params = {} + if app_id is None: + raise AppwriteException('Missing required parameter: "app_id"') + + if secret_id is None: + raise AppwriteException('Missing required parameter: "secret_id"') + + api_path = api_path.replace('{appId}', str(self._normalize_value(app_id))) + api_path = api_path.replace('{secretId}', str(self._normalize_value(secret_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=AppSecret) + + + def delete_secret( + self, + app_id: str, + secret_id: str + ) -> Dict[str, Any]: + """ + Delete an application client secret by its unique ID. + + Parameters + ---------- + app_id : str + Application unique ID. + secret_id : str + Secret unique ID. + + Returns + ------- + Dict[str, Any] + API response as a dictionary + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/apps/{appId}/secrets/{secretId}' + api_params = {} + if app_id is None: + raise AppwriteException('Missing required parameter: "app_id"') + + if secret_id is None: + raise AppwriteException('Missing required parameter: "secret_id"') + + api_path = api_path.replace('{appId}', str(self._normalize_value(app_id))) + api_path = api_path.replace('{secretId}', str(self._normalize_value(secret_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, + app_id: str, + team_id: str + ) -> App: + """ + Transfer an application to another team by its unique ID. + + Parameters + ---------- + app_id : str + Application unique ID. + team_id : str + Team ID of the team to transfer application to. + + Returns + ------- + App + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/apps/{appId}/team' + api_params = {} + if app_id is None: + raise AppwriteException('Missing required parameter: "app_id"') + + if team_id is None: + raise AppwriteException('Missing required parameter: "team_id"') + + api_path = api_path.replace('{appId}', str(self._normalize_value(app_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=App) + + + def delete_tokens( + self, + app_id: str + ) -> Dict[str, Any]: + """ + Revoke all tokens for an application by its unique ID. + + Parameters + ---------- + app_id : str + Application unique ID. + + Returns + ------- + Dict[str, Any] + API response as a dictionary + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/apps/{appId}/tokens' + api_params = {} + if app_id is None: + raise AppwriteException('Missing required parameter: "app_id"') + + api_path = api_path.replace('{appId}', str(self._normalize_value(app_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/avatars.py b/appwrite/services/avatars.py index f04535bc..5200f9dd 100644 --- a/appwrite/services/avatars.py +++ b/appwrite/services/avatars.py @@ -66,6 +66,7 @@ def get_browser( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'image/png', }, api_params) return response @@ -122,6 +123,7 @@ def get_credit_card( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'image/png', }, api_params) return response @@ -162,6 +164,7 @@ def get_favicon( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'image/*', }, api_params) return response @@ -218,6 +221,7 @@ def get_flag( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'image/png', }, api_params) return response @@ -270,6 +274,7 @@ def get_image( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'image/*', }, api_params) return response @@ -326,6 +331,7 @@ def get_initials( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'image/png', }, api_params) return response @@ -380,6 +386,7 @@ def get_qr( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'image/png', }, api_params) return response @@ -517,6 +524,7 @@ def get_screenshot( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'image/png', }, api_params) return response diff --git a/appwrite/services/backups.py b/appwrite/services/backups.py index 38dd52a4..a13743d6 100644 --- a/appwrite/services/backups.py +++ b/appwrite/services/backups.py @@ -47,6 +47,7 @@ def list_archives( 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=BackupArchiveList) @@ -90,6 +91,7 @@ def create_archive( 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=BackupArchive) @@ -128,6 +130,7 @@ def get_archive( 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=BackupArchive) @@ -167,6 +170,7 @@ def delete_archive( 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 @@ -203,6 +207,7 @@ def list_policies( 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=BackupPolicyList) @@ -277,6 +282,7 @@ def create_policy( 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=BackupPolicy) @@ -315,6 +321,7 @@ def get_policy( 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=BackupPolicy) @@ -371,6 +378,7 @@ def update_policy( 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=BackupPolicy) @@ -410,6 +418,7 @@ def delete_policy( 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 @@ -466,6 +475,7 @@ def create_restoration( 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=BackupRestoration) @@ -502,6 +512,7 @@ def list_restorations( 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=BackupRestorationList) @@ -540,6 +551,7 @@ def get_restoration( 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=BackupRestoration) diff --git a/appwrite/services/databases.py b/appwrite/services/databases.py index 9ee228f7..fdc30428 100644 --- a/appwrite/services/databases.py +++ b/appwrite/services/databases.py @@ -88,6 +88,7 @@ def list( 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=DatabaseList) @@ -143,11 +144,13 @@ def create( 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=Database) + @deprecated("This API has been deprecated since 1.8.0. Please use `tablesDB.list_transactions` instead.") def list_transactions( self, queries: Optional[List[str]] = None @@ -155,6 +158,8 @@ def list_transactions( """ List transactions across all databases. + .. deprecated::1.8.0 + This API has been deprecated since 1.8.0. Please use `tablesDB.list_transactions` instead. Parameters ---------- queries : Optional[List[str]] @@ -179,11 +184,13 @@ def list_transactions( 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=TransactionList) + @deprecated("This API has been deprecated since 1.8.0. Please use `tablesDB.create_transaction` instead.") def create_transaction( self, ttl: Optional[float] = None @@ -191,6 +198,8 @@ def create_transaction( """ Create a new transaction. + .. deprecated::1.8.0 + This API has been deprecated since 1.8.0. Please use `tablesDB.create_transaction` instead. Parameters ---------- ttl : Optional[float] @@ -216,11 +225,13 @@ def create_transaction( 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=Transaction) + @deprecated("This API has been deprecated since 1.8.0. Please use `tablesDB.get_transaction` instead.") def get_transaction( self, transaction_id: str @@ -228,6 +239,8 @@ def get_transaction( """ Get a transaction by its unique ID. + .. deprecated::1.8.0 + This API has been deprecated since 1.8.0. Please use `tablesDB.get_transaction` instead. Parameters ---------- transaction_id : str @@ -254,11 +267,13 @@ def get_transaction( 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=Transaction) + @deprecated("This API has been deprecated since 1.8.0. Please use `tablesDB.update_transaction` instead.") def update_transaction( self, transaction_id: str, @@ -268,6 +283,8 @@ def update_transaction( """ Update a transaction, to either commit or roll back its operations. + .. deprecated::1.8.0 + This API has been deprecated since 1.8.0. Please use `tablesDB.update_transaction` instead. Parameters ---------- transaction_id : str @@ -303,11 +320,13 @@ def update_transaction( 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=Transaction) + @deprecated("This API has been deprecated since 1.8.0. Please use `tablesDB.delete_transaction` instead.") def delete_transaction( self, transaction_id: str @@ -315,6 +334,8 @@ def delete_transaction( """ Delete a transaction by its unique ID. + .. deprecated::1.8.0 + This API has been deprecated since 1.8.0. Please use `tablesDB.delete_transaction` instead. Parameters ---------- transaction_id : str @@ -347,6 +368,7 @@ def delete_transaction( return response + @deprecated("This API has been deprecated since 1.8.0. Please use `tablesDB.create_operations` instead.") def create_operations( self, transaction_id: str, @@ -355,6 +377,8 @@ def create_operations( """ Create multiple operations in a single transaction. + .. deprecated::1.8.0 + This API has been deprecated since 1.8.0. Please use `tablesDB.create_operations` instead. Parameters ---------- transaction_id : str @@ -386,6 +410,7 @@ def create_operations( 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=Transaction) @@ -427,6 +452,7 @@ def get( 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=Database) @@ -479,6 +505,7 @@ def update( 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=Database) @@ -577,6 +604,7 @@ def list_collections( 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=CollectionList) @@ -657,6 +685,7 @@ def create_collection( 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=Collection) @@ -705,6 +734,7 @@ def get_collection( 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=Collection) @@ -778,6 +808,7 @@ def update_collection( 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=Collection) @@ -885,6 +916,7 @@ def list_attributes( 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=AttributeList) @@ -966,6 +998,7 @@ def create_big_int_attribute( 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=AttributeBigint) @@ -1046,6 +1079,7 @@ def update_big_int_attribute( 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=AttributeBigint) @@ -1119,6 +1153,7 @@ def create_boolean_attribute( 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=AttributeBoolean) @@ -1190,6 +1225,7 @@ def update_boolean_attribute( 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=AttributeBoolean) @@ -1262,6 +1298,7 @@ def create_datetime_attribute( 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=AttributeDatetime) @@ -1333,6 +1370,7 @@ def update_datetime_attribute( 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=AttributeDatetime) @@ -1406,6 +1444,7 @@ def create_email_attribute( 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=AttributeEmail) @@ -1478,6 +1517,7 @@ def update_email_attribute( 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=AttributeEmail) @@ -1558,6 +1598,7 @@ def create_enum_attribute( 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=AttributeEnum) @@ -1637,6 +1678,7 @@ def update_enum_attribute( 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=AttributeEnum) @@ -1718,6 +1760,7 @@ def create_float_attribute( 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=AttributeFloat) @@ -1798,6 +1841,7 @@ def update_float_attribute( 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=AttributeFloat) @@ -1879,6 +1923,7 @@ def create_integer_attribute( 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=AttributeInteger) @@ -1959,6 +2004,7 @@ def update_integer_attribute( 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=AttributeInteger) @@ -2032,6 +2078,7 @@ def create_ip_attribute( 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=AttributeIp) @@ -2104,6 +2151,7 @@ def update_ip_attribute( 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=AttributeIp) @@ -2116,7 +2164,7 @@ def create_line_attribute( collection_id: str, key: str, required: bool, - default: Optional[List[Any]] = None + default: Optional[List[List[Any]]] = None ) -> AttributeLine: """ Create a geometric line attribute. @@ -2133,7 +2181,7 @@ def create_line_attribute( Attribute Key. required : bool Is attribute required? - default : Optional[List[Any]] + default : Optional[List[List[Any]]] Default value for attribute when not provided, two-dimensional array of coordinate pairs, [[longitude, latitude], [longitude, latitude], …], listing the vertices of the line in order. Cannot be set when attribute is required. Returns @@ -2171,6 +2219,7 @@ def create_line_attribute( 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=AttributeLine) @@ -2183,7 +2232,7 @@ def update_line_attribute( collection_id: str, key: str, required: bool, - default: Optional[List[Any]] = None, + default: Optional[List[List[Any]]] = None, new_key: Optional[str] = None ) -> AttributeLine: """ @@ -2201,7 +2250,7 @@ def update_line_attribute( Attribute Key. required : bool Is attribute required? - default : Optional[List[Any]] + default : Optional[List[List[Any]]] Default value for attribute when not provided, two-dimensional array of coordinate pairs, [[longitude, latitude], [longitude, latitude], …], listing the vertices of the line in order. Cannot be set when attribute is required. new_key : Optional[str] New attribute key. @@ -2242,11 +2291,13 @@ def update_line_attribute( 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=AttributeLine) + @deprecated("This API has been deprecated since 1.8.0. Please use `tablesDB.create_longtext_column` instead.") def create_longtext_attribute( self, database_id: str, @@ -2261,6 +2312,8 @@ def create_longtext_attribute( Create a longtext attribute. + .. deprecated::1.8.0 + This API has been deprecated since 1.8.0. Please use `tablesDB.create_longtext_column` instead. Parameters ---------- database_id : str @@ -2317,11 +2370,13 @@ def create_longtext_attribute( 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=AttributeLongtext) + @deprecated("This API has been deprecated since 1.8.0. Please use `tablesDB.update_longtext_column` instead.") def update_longtext_attribute( self, database_id: str, @@ -2335,6 +2390,8 @@ def update_longtext_attribute( Update a longtext attribute. Changing the `default` value will not update already existing documents. + .. deprecated::1.8.0 + This API has been deprecated since 1.8.0. Please use `tablesDB.update_longtext_column` instead. Parameters ---------- database_id : str @@ -2386,11 +2443,13 @@ def update_longtext_attribute( 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=AttributeLongtext) + @deprecated("This API has been deprecated since 1.8.0. Please use `tablesDB.create_mediumtext_column` instead.") def create_mediumtext_attribute( self, database_id: str, @@ -2405,6 +2464,8 @@ def create_mediumtext_attribute( Create a mediumtext attribute. + .. deprecated::1.8.0 + This API has been deprecated since 1.8.0. Please use `tablesDB.create_mediumtext_column` instead. Parameters ---------- database_id : str @@ -2461,11 +2522,13 @@ def create_mediumtext_attribute( 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=AttributeMediumtext) + @deprecated("This API has been deprecated since 1.8.0. Please use `tablesDB.update_mediumtext_column` instead.") def update_mediumtext_attribute( self, database_id: str, @@ -2479,6 +2542,8 @@ def update_mediumtext_attribute( Update a mediumtext attribute. Changing the `default` value will not update already existing documents. + .. deprecated::1.8.0 + This API has been deprecated since 1.8.0. Please use `tablesDB.update_mediumtext_column` instead. Parameters ---------- database_id : str @@ -2530,6 +2595,7 @@ def update_mediumtext_attribute( 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=AttributeMediumtext) @@ -2542,7 +2608,7 @@ def create_point_attribute( collection_id: str, key: str, required: bool, - default: Optional[List[Any]] = None + default: Optional[List[float]] = None ) -> AttributePoint: """ Create a geometric point attribute. @@ -2559,7 +2625,7 @@ def create_point_attribute( Attribute Key. required : bool Is attribute required? - default : Optional[List[Any]] + default : Optional[List[float]] Default value for attribute when not provided, array of two numbers [longitude, latitude], representing a single coordinate. Cannot be set when attribute is required. Returns @@ -2597,6 +2663,7 @@ def create_point_attribute( 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=AttributePoint) @@ -2609,7 +2676,7 @@ def update_point_attribute( collection_id: str, key: str, required: bool, - default: Optional[List[Any]] = None, + default: Optional[List[float]] = None, new_key: Optional[str] = None ) -> AttributePoint: """ @@ -2627,7 +2694,7 @@ def update_point_attribute( Attribute Key. required : bool Is attribute required? - default : Optional[List[Any]] + default : Optional[List[float]] Default value for attribute when not provided, array of two numbers [longitude, latitude], representing a single coordinate. Cannot be set when attribute is required. new_key : Optional[str] New attribute key. @@ -2668,6 +2735,7 @@ def update_point_attribute( 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=AttributePoint) @@ -2680,7 +2748,7 @@ def create_polygon_attribute( collection_id: str, key: str, required: bool, - default: Optional[List[Any]] = None + default: Optional[List[List[Any]]] = None ) -> AttributePolygon: """ Create a geometric polygon attribute. @@ -2697,7 +2765,7 @@ def create_polygon_attribute( Attribute Key. required : bool Is attribute required? - default : Optional[List[Any]] + default : Optional[List[List[Any]]] Default value for attribute when not provided, three-dimensional array where the outer array holds one or more linear rings, [[[longitude, latitude], …], …], the first ring is the exterior boundary, any additional rings are interior holes, and each ring must start and end with the same coordinate pair. Cannot be set when attribute is required. Returns @@ -2735,6 +2803,7 @@ def create_polygon_attribute( 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=AttributePolygon) @@ -2747,7 +2816,7 @@ def update_polygon_attribute( collection_id: str, key: str, required: bool, - default: Optional[List[Any]] = None, + default: Optional[List[List[Any]]] = None, new_key: Optional[str] = None ) -> AttributePolygon: """ @@ -2765,7 +2834,7 @@ def update_polygon_attribute( Attribute Key. required : bool Is attribute required? - default : Optional[List[Any]] + default : Optional[List[List[Any]]] Default value for attribute when not provided, three-dimensional array where the outer array holds one or more linear rings, [[[longitude, latitude], …], …], the first ring is the exterior boundary, any additional rings are interior holes, and each ring must start and end with the same coordinate pair. Cannot be set when attribute is required. new_key : Optional[str] New attribute key. @@ -2806,6 +2875,7 @@ def update_polygon_attribute( 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=AttributePolygon) @@ -2888,6 +2958,7 @@ def create_relationship_attribute( 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=AttributeRelationship) @@ -2954,6 +3025,7 @@ def update_relationship_attribute( 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=AttributeRelationship) @@ -3039,6 +3111,7 @@ def create_string_attribute( 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=AttributeString) @@ -3115,11 +3188,13 @@ def update_string_attribute( 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=AttributeString) + @deprecated("This API has been deprecated since 1.8.0. Please use `tablesDB.create_text_column` instead.") def create_text_attribute( self, database_id: str, @@ -3134,6 +3209,8 @@ def create_text_attribute( Create a text attribute. + .. deprecated::1.8.0 + This API has been deprecated since 1.8.0. Please use `tablesDB.create_text_column` instead. Parameters ---------- database_id : str @@ -3190,11 +3267,13 @@ def create_text_attribute( 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=AttributeText) + @deprecated("This API has been deprecated since 1.8.0. Please use `tablesDB.update_text_column` instead.") def update_text_attribute( self, database_id: str, @@ -3208,6 +3287,8 @@ def update_text_attribute( Update a text attribute. Changing the `default` value will not update already existing documents. + .. deprecated::1.8.0 + This API has been deprecated since 1.8.0. Please use `tablesDB.update_text_column` instead. Parameters ---------- database_id : str @@ -3259,6 +3340,7 @@ def update_text_attribute( 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=AttributeText) @@ -3332,6 +3414,7 @@ def create_url_attribute( 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=AttributeUrl) @@ -3404,11 +3487,13 @@ def update_url_attribute( 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=AttributeUrl) + @deprecated("This API has been deprecated since 1.8.0. Please use `tablesDB.create_varchar_column` instead.") def create_varchar_attribute( self, database_id: str, @@ -3424,6 +3509,8 @@ def create_varchar_attribute( Create a varchar attribute. + .. deprecated::1.8.0 + This API has been deprecated since 1.8.0. Please use `tablesDB.create_varchar_column` instead. Parameters ---------- database_id : str @@ -3486,11 +3573,13 @@ def create_varchar_attribute( 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=AttributeVarchar) + @deprecated("This API has been deprecated since 1.8.0. Please use `tablesDB.update_varchar_column` instead.") def update_varchar_attribute( self, database_id: str, @@ -3505,6 +3594,8 @@ def update_varchar_attribute( Update a varchar attribute. Changing the `default` value will not update already existing documents. + .. deprecated::1.8.0 + This API has been deprecated since 1.8.0. Please use `tablesDB.update_varchar_column` instead. Parameters ---------- database_id : str @@ -3559,6 +3650,7 @@ def update_varchar_attribute( 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=AttributeVarchar) @@ -3614,6 +3706,7 @@ def get_attribute( 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') @@ -3774,6 +3867,7 @@ def list_documents( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', }, api_params) return DocumentList.with_data(response, model_type) @@ -3849,6 +3943,7 @@ def create_document( 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 Document.with_data(response, model_type) @@ -3913,6 +4008,7 @@ def create_documents( 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 DocumentList.with_data(response, model_type) @@ -3978,6 +4074,7 @@ def upsert_documents( 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 DocumentList.with_data(response, model_type) @@ -4045,6 +4142,7 @@ def update_documents( 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 DocumentList.with_data(response, model_type) @@ -4102,11 +4200,13 @@ def delete_documents( if queries is not None: api_params['queries'] = self._normalize_value(queries) - api_params['transactionId'] = self._normalize_value(transaction_id) + if transaction_id is not None: + api_params['transactionId'] = self._normalize_value(transaction_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 DocumentList.with_data(response, model_type) @@ -4176,6 +4276,7 @@ def get_document( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', }, api_params) return Document.with_data(response, model_type) @@ -4249,6 +4350,7 @@ def upsert_document( 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 Document.with_data(response, model_type) @@ -4322,6 +4424,7 @@ def update_document( 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 Document.with_data(response, model_type) @@ -4377,7 +4480,8 @@ def delete_document( api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) api_path = api_path.replace('{documentId}', str(self._normalize_value(document_id))) - api_params['transactionId'] = self._normalize_value(transaction_id) + if transaction_id is not None: + api_params['transactionId'] = self._normalize_value(transaction_id) response = self.client.call('delete', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), @@ -4462,6 +4566,7 @@ def decrement_document_attribute( 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 Document.with_data(response, model_type) @@ -4542,6 +4647,7 @@ def increment_document_attribute( 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 Document.with_data(response, model_type) @@ -4600,6 +4706,7 @@ def list_indexes( 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=IndexList) @@ -4681,6 +4788,7 @@ def create_index( 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=Index) @@ -4736,6 +4844,7 @@ def get_index( 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=Index) diff --git a/appwrite/services/functions.py b/appwrite/services/functions.py index 07b42865..7d9a0f14 100644 --- a/appwrite/services/functions.py +++ b/appwrite/services/functions.py @@ -67,6 +67,7 @@ def list( 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=FunctionList) @@ -215,6 +216,7 @@ def create( 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=Function) @@ -242,6 +244,7 @@ def list_runtimes( 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=RuntimeList) @@ -269,6 +272,7 @@ def list_specifications( 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=SpecificationList) @@ -307,6 +311,7 @@ def get( 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=Function) @@ -450,6 +455,7 @@ def update( 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=Function) @@ -535,6 +541,7 @@ def update_function_deployment( 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=Function) @@ -588,6 +595,7 @@ def list_deployments( 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=DeploymentList) @@ -663,6 +671,7 @@ def create_deployment( 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) return self._parse_response(response, model=Deployment) @@ -714,6 +723,7 @@ def create_duplicate_deployment( 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=Deployment) @@ -795,6 +805,7 @@ def create_template_deployment( 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=Deployment) @@ -855,6 +866,7 @@ def create_vcs_deployment( 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=Deployment) @@ -900,6 +912,7 @@ def get_deployment( 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=Deployment) @@ -996,6 +1009,7 @@ def get_deployment_download( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': '*/*', }, api_params) return response @@ -1042,6 +1056,7 @@ def update_deployment_status( 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=Deployment) @@ -1090,6 +1105,7 @@ def list_executions( 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=ExecutionList) @@ -1158,6 +1174,7 @@ def create_execution( 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=Execution) @@ -1203,6 +1220,7 @@ def get_execution( 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=Execution) @@ -1297,6 +1315,7 @@ def list_variables( 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=VariableList) @@ -1362,6 +1381,7 @@ def create_variable( 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=Variable) @@ -1407,6 +1427,7 @@ def get_variable( 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=Variable) @@ -1465,6 +1486,7 @@ def update_variable( 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=Variable) diff --git a/appwrite/services/graphql.py b/appwrite/services/graphql.py index f1756b48..e0fce562 100644 --- a/appwrite/services/graphql.py +++ b/appwrite/services/graphql.py @@ -44,6 +44,7 @@ def query( 'X-Appwrite-Project': self.client.get_config('project'), 'x-sdk-graphql': 'true', 'content-type': 'application/json', + 'accept': 'application/json', }, api_params) return response @@ -84,6 +85,7 @@ def mutation( 'X-Appwrite-Project': self.client.get_config('project'), 'x-sdk-graphql': 'true', 'content-type': 'application/json', + 'accept': 'application/json', }, api_params) return response diff --git a/appwrite/services/health.py b/appwrite/services/health.py index a455158d..bbf93903 100644 --- a/appwrite/services/health.py +++ b/appwrite/services/health.py @@ -38,6 +38,7 @@ def get( 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=HealthStatus) @@ -65,6 +66,7 @@ def get_antivirus( 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=HealthAntivirus) @@ -93,6 +95,7 @@ def get_audits_db( 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=HealthStatusList) @@ -120,6 +123,7 @@ def get_cache( 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=HealthStatusList) @@ -156,6 +160,7 @@ def get_certificate( 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=HealthCertificate) @@ -198,6 +203,7 @@ def get_console_pausing( 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=HealthStatus) @@ -225,6 +231,7 @@ def get_db( 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=HealthStatusList) @@ -252,6 +259,7 @@ def get_pub_sub( 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=HealthStatusList) @@ -289,6 +297,7 @@ def get_queue_audits( 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=HealthQueue) @@ -325,6 +334,7 @@ def get_queue_builds( 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=HealthQueue) @@ -361,6 +371,7 @@ def get_queue_certificates( 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=HealthQueue) @@ -402,6 +413,7 @@ def get_queue_databases( 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=HealthQueue) @@ -438,6 +450,7 @@ def get_queue_deletes( 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=HealthQueue) @@ -482,6 +495,7 @@ def get_failed_jobs( 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=HealthQueue) @@ -518,6 +532,7 @@ def get_queue_functions( 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=HealthQueue) @@ -554,6 +569,7 @@ def get_queue_logs( 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=HealthQueue) @@ -590,6 +606,7 @@ def get_queue_mails( 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=HealthQueue) @@ -626,6 +643,7 @@ def get_queue_messaging( 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=HealthQueue) @@ -662,6 +680,7 @@ def get_queue_migrations( 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=HealthQueue) @@ -698,6 +717,7 @@ def get_queue_stats_resources( 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=HealthQueue) @@ -734,6 +754,7 @@ def get_queue_usage( 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=HealthQueue) @@ -770,6 +791,7 @@ def get_queue_webhooks( 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=HealthQueue) @@ -797,6 +819,7 @@ def get_storage( 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=HealthStatus) @@ -824,6 +847,7 @@ def get_storage_local( 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=HealthStatus) @@ -851,6 +875,7 @@ def get_time( 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=HealthTime) diff --git a/appwrite/services/locale.py b/appwrite/services/locale.py index 5dbfe1ad..678511e5 100644 --- a/appwrite/services/locale.py +++ b/appwrite/services/locale.py @@ -40,6 +40,7 @@ def get( 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=LocaleModel) @@ -67,6 +68,7 @@ def list_codes( 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=LocaleCodeList) @@ -94,6 +96,7 @@ def list_continents( 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=ContinentList) @@ -121,6 +124,7 @@ def list_countries( 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=CountryList) @@ -148,6 +152,7 @@ def list_countries_eu( 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=CountryList) @@ -175,6 +180,7 @@ def list_countries_phones( 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=PhoneList) @@ -202,6 +208,7 @@ def list_currencies( 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=CurrencyList) @@ -229,6 +236,7 @@ def list_languages( 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=LanguageList) diff --git a/appwrite/services/messaging.py b/appwrite/services/messaging.py index 2614e43b..065a9537 100644 --- a/appwrite/services/messaging.py +++ b/appwrite/services/messaging.py @@ -62,6 +62,7 @@ def list_messages( 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=MessageList) @@ -159,6 +160,7 @@ def create_email( 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=Message) @@ -243,6 +245,7 @@ def update_email( 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=Message) @@ -370,6 +373,7 @@ def create_push( 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=Message) @@ -482,6 +486,7 @@ def update_push( 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=Message) @@ -552,6 +557,7 @@ def create_sms( 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=Message) @@ -616,6 +622,7 @@ def update_sms( 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=Message) @@ -655,6 +662,7 @@ def get_message( 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=Message) @@ -742,6 +750,7 @@ def list_message_logs( 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=LogList) @@ -790,6 +799,7 @@ def list_targets( 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=TargetList) @@ -836,6 +846,7 @@ def list_providers( 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=ProviderList) @@ -911,6 +922,7 @@ def create_apns_provider( 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) @@ -983,6 +995,7 @@ def update_apns_provider( 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) @@ -1037,6 +1050,7 @@ def create_fcm_provider( 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) @@ -1089,6 +1103,7 @@ def update_fcm_provider( 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) @@ -1173,6 +1188,7 @@ def create_mailgun_provider( 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) @@ -1255,6 +1271,7 @@ def update_mailgun_provider( 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) @@ -1320,6 +1337,7 @@ def create_msg91_provider( 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) @@ -1383,6 +1401,7 @@ def update_msg91_provider( 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) @@ -1458,6 +1477,7 @@ def create_resend_provider( 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) @@ -1531,6 +1551,7 @@ def update_resend_provider( 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) @@ -1606,6 +1627,7 @@ def create_sendgrid_provider( 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) @@ -1679,6 +1701,7 @@ def update_sendgrid_provider( 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) @@ -1764,6 +1787,7 @@ def create_ses_provider( 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) @@ -1847,6 +1871,7 @@ def update_ses_provider( 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) @@ -1954,6 +1979,7 @@ def create_smtp_provider( 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) @@ -2055,6 +2081,7 @@ def update_smtp_provider( 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) @@ -2120,6 +2147,7 @@ def create_telesign_provider( 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) @@ -2183,6 +2211,7 @@ def update_telesign_provider( 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) @@ -2248,6 +2277,7 @@ def create_textmagic_provider( 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) @@ -2311,6 +2341,7 @@ def update_textmagic_provider( 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) @@ -2376,6 +2407,7 @@ def create_twilio_provider( 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) @@ -2439,6 +2471,7 @@ def update_twilio_provider( 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) @@ -2504,6 +2537,7 @@ def create_vonage_provider( 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) @@ -2567,6 +2601,7 @@ def update_vonage_provider( 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) @@ -2606,6 +2641,7 @@ def get_provider( 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=Provider) @@ -2693,6 +2729,7 @@ def list_provider_logs( 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=LogList) @@ -2741,6 +2778,7 @@ def list_subscriber_logs( 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=LogList) @@ -2787,6 +2825,7 @@ def list_topics( 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=TopicList) @@ -2838,6 +2877,7 @@ def create_topic( 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=Topic) @@ -2877,6 +2917,7 @@ def get_topic( 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=Topic) @@ -2925,6 +2966,7 @@ def update_topic( 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=Topic) @@ -3012,6 +3054,7 @@ def list_topic_logs( 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=LogList) @@ -3065,6 +3108,7 @@ def list_subscribers( 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=SubscriberList) @@ -3118,6 +3162,7 @@ def create_subscriber( 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=Subscriber) @@ -3164,6 +3209,7 @@ def get_subscriber( 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=Subscriber) diff --git a/appwrite/services/oauth2.py b/appwrite/services/oauth2.py new file mode 100644 index 00000000..581d4e4e --- /dev/null +++ b/appwrite/services/oauth2.py @@ -0,0 +1,453 @@ +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.oauth2_approve import Oauth2Approve +from ..models.oauth2_authorize import Oauth2Authorize +from ..models.oauth2_device_authorization import Oauth2DeviceAuthorization +from ..models.oauth2_grant import Oauth2Grant +from ..models.oauth2_reject import Oauth2Reject +from ..models.oauth2_token import Oauth2Token + +class Oauth2(Service): + + def __init__(self, client) -> None: + super(Oauth2, self).__init__(client) + + def approve( + self, + grant_id: str, + authorization_details: Optional[str] = None + ) -> Oauth2Approve: + """ + Approve an OAuth2 grant after the user gives consent. Returns the `redirectUrl` the end user should be sent to. The consent screen may optionally pass enriched `authorization_details` to record the concrete resources the user selected. You can pass Accept header of `application/json` to receive a JSON response instead of a redirect. + + Parameters + ---------- + grant_id : str + Grant ID made during authorization, provided to consent screen in URL search params. + authorization_details : Optional[str] + Enriched `authorization_details` the user consented to, replacing what the client requested. Each entry must use a `type` the project accepts. Optional; omit to keep the originally requested details. + + Returns + ------- + Oauth2Approve + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/oauth2/{project_id}/approve' + api_params = {} + if grant_id is None: + raise AppwriteException('Missing required parameter: "grant_id"') + + api_path = api_path.replace('{project_id}', str(self._normalize_value(self.client.get_config('project')))) + + api_params['grant_id'] = self._normalize_value(grant_id) + if authorization_details is not None: + api_params['authorization_details'] = self._normalize_value(authorization_details) + + response = self.client.call('post', api_path, { + 'content-type': 'application/json', + 'accept': 'application/json', + }, api_params) + + return self._parse_response(response, model=Oauth2Approve) + + + def authorize( + self, + client_id: str, + redirect_uri: str, + response_type: str, + scope: str, + state: Optional[str] = None, + nonce: Optional[str] = None, + code_challenge: Optional[str] = None, + code_challenge_method: Optional[str] = None, + prompt: Optional[str] = None, + max_age: Optional[float] = None, + authorization_details: Optional[str] = None + ) -> Oauth2Authorize: + """ + Begin the OAuth2 authorization flow. When called without a session, the user is redirected to the consent screen without grant ID. When called with a session, the redirect URL includes param for grant ID. You can pass Accept header of `application/json` to receive a JSON response instead of a redirect. + + Parameters + ---------- + client_id : str + OAuth2 client ID. + redirect_uri : str + Redirect URI where visitor will be redirected after authorization, whether successful or not. + response_type : str + OAuth2 / OIDC response type. One of `code` (Authorization Code Flow), `id_token` (Implicit Flow, OIDC login only), or `code id_token` (Hybrid Flow). + scope : str + Space-separated OAuth2 scopes. Can include project scopes, and built-in scopes: `openid`, `email`, `profile`. + state : Optional[str] + OAuth2 state. You receive this back in the redirect URI. + nonce : Optional[str] + OIDC nonce parameter to prevent replay attacks. Required when response_type includes `id_token`. + code_challenge : Optional[str] + PKCE code challenge. Required when OAuth2 app is public. + code_challenge_method : Optional[str] + PKCE code challenge method. Required when OAuth2 app is public. + prompt : Optional[str] + OIDC prompt parameter for customization of consent screen. Space-separated list of: none, login, consent, select_account. + max_age : Optional[float] + OIDC max_age paraleter for customization of consent screen. Maximum allowable elapsed time in seconds since the user last authenticated. If exceeded, re-authentication is required. + authorization_details : Optional[str] + Rich authorization request. JSON array of objects, each with a `type` and project-defined fields + + Returns + ------- + Oauth2Authorize + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/oauth2/{project_id}/authorize' + api_params = {} + if client_id is None: + raise AppwriteException('Missing required parameter: "client_id"') + + if redirect_uri is None: + raise AppwriteException('Missing required parameter: "redirect_uri"') + + if response_type is None: + raise AppwriteException('Missing required parameter: "response_type"') + + if scope is None: + raise AppwriteException('Missing required parameter: "scope"') + + api_path = api_path.replace('{project_id}', str(self._normalize_value(self.client.get_config('project')))) + + api_params['client_id'] = self._normalize_value(client_id) + api_params['redirect_uri'] = self._normalize_value(redirect_uri) + api_params['response_type'] = self._normalize_value(response_type) + api_params['scope'] = self._normalize_value(scope) + if state is not None: + api_params['state'] = self._normalize_value(state) + if nonce is not None: + api_params['nonce'] = self._normalize_value(nonce) + if code_challenge is not None: + api_params['code_challenge'] = self._normalize_value(code_challenge) + if code_challenge_method is not None: + api_params['code_challenge_method'] = self._normalize_value(code_challenge_method) + if prompt is not None: + api_params['prompt'] = self._normalize_value(prompt) + if max_age is not None: + api_params['max_age'] = self._normalize_value(max_age) + if authorization_details is not None: + api_params['authorization_details'] = self._normalize_value(authorization_details) + + response = self.client.call('get', api_path, { + 'accept': 'application/json', + }, api_params) + + return self._parse_response(response, model=Oauth2Authorize) + + + def create_device_authorization( + self, + client_id: Optional[str] = None, + scope: Optional[str] = None, + authorization_details: Optional[str] = None + ) -> Oauth2DeviceAuthorization: + """ + Start the OAuth2 Device Authorization Grant. Returns the device code, user code, verification URL, expiration, and polling interval. + + Parameters + ---------- + client_id : Optional[str] + OAuth2 client ID. + scope : Optional[str] + Space-separated OAuth2 scopes. Can include project scopes, and built-in scopes: `openid`, `email`, `profile`. + authorization_details : Optional[str] + Rich authorization request. JSON array of objects, each with a `type` and project-defined fields + + Returns + ------- + Oauth2DeviceAuthorization + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/oauth2/{project_id}/device_authorization' + api_params = {} + api_path = api_path.replace('{project_id}', str(self._normalize_value(self.client.get_config('project')))) + + if client_id is not None: + api_params['client_id'] = self._normalize_value(client_id) + if scope is not None: + api_params['scope'] = self._normalize_value(scope) + if authorization_details is not None: + api_params['authorization_details'] = self._normalize_value(authorization_details) + + response = self.client.call('post', api_path, { + 'content-type': 'application/json', + 'accept': 'application/json', + }, api_params) + + return self._parse_response(response, model=Oauth2DeviceAuthorization) + + + def create_grant( + self, + user_code: str + ) -> Oauth2Grant: + """ + Exchange a device flow user code for an OAuth2 grant. The authenticated user is bound to the pending grant. Pass the returned grant ID to the get grant endpoint to render the consent screen, then to the approve or reject endpoint to complete the flow. + + Parameters + ---------- + user_code : str + User code displayed on the device. + + Returns + ------- + Oauth2Grant + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/oauth2/{project_id}/grants' + api_params = {} + if user_code is None: + raise AppwriteException('Missing required parameter: "user_code"') + + api_path = api_path.replace('{project_id}', str(self._normalize_value(self.client.get_config('project')))) + + api_params['user_code'] = self._normalize_value(user_code) + + response = self.client.call('post', api_path, { + 'content-type': 'application/json', + 'accept': 'application/json', + }, api_params) + + return self._parse_response(response, model=Oauth2Grant) + + + def get_grant( + self, + grant_id: str + ) -> Oauth2Grant: + """ + Get an OAuth2 grant by its ID. Used by the consent screen to display the details of the authorization the user is being asked to approve. A grant can only be read by the user it belongs to, or by server SDK. + + Parameters + ---------- + grant_id : str + Grant ID made during authorization, provided to consent screen in URL search params. + + Returns + ------- + Oauth2Grant + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/oauth2/{project_id}/grants/{grant_id}' + api_params = {} + if grant_id is None: + raise AppwriteException('Missing required parameter: "grant_id"') + + api_path = api_path.replace('{project_id}', str(self._normalize_value(self.client.get_config('project')))) + api_path = api_path.replace('{grant_id}', str(self._normalize_value(grant_id))) + + + response = self.client.call('get', api_path, { + 'accept': 'application/json', + }, api_params) + + return self._parse_response(response, model=Oauth2Grant) + + + def reject( + self, + grant_id: str + ) -> Oauth2Reject: + """ + Reject an OAuth2 grant when the user denies consent. Returns the `redirectUrl` the end user should be sent to with an `access_denied` error. You can pass Accept header of `application/json` to receive a JSON response instead of a redirect. + + Parameters + ---------- + grant_id : str + Grant ID made during authorization, provided to consent screen in URL search params. + + Returns + ------- + Oauth2Reject + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/oauth2/{project_id}/reject' + api_params = {} + if grant_id is None: + raise AppwriteException('Missing required parameter: "grant_id"') + + api_path = api_path.replace('{project_id}', str(self._normalize_value(self.client.get_config('project')))) + + api_params['grant_id'] = self._normalize_value(grant_id) + + response = self.client.call('post', api_path, { + 'content-type': 'application/json', + 'accept': 'application/json', + }, api_params) + + return self._parse_response(response, model=Oauth2Reject) + + + def revoke( + self, + token: str, + token_type_hint: Optional[str] = None, + client_id: Optional[str] = None, + client_secret: Optional[str] = None + ) -> Dict[str, Any]: + """ + Revoke an OAuth2 access token or refresh token. + + Parameters + ---------- + token : str + The access or refresh token to revoke. + token_type_hint : Optional[str] + Type of token to revoke (access_token or refresh_token). + client_id : Optional[str] + OAuth2 client ID. + client_secret : Optional[str] + OAuth2 client secret. Required for confidential apps; omitted for public apps. + + Returns + ------- + Dict[str, Any] + API response as a dictionary + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/oauth2/{project_id}/revoke' + 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 response + + + def create_token( + self, + grant_type: str, + code: Optional[str] = None, + refresh_token: Optional[str] = None, + device_code: Optional[str] = None, + client_id: Optional[str] = None, + client_secret: Optional[str] = None, + code_verifier: Optional[str] = None, + redirect_uri: Optional[str] = None + ) -> Oauth2Token: + """ + Exchange an OAuth2 authorization code, refresh token, or device code for access and refresh tokens. + + Parameters + ---------- + grant_type : str + OAuth2 grant type. Can be one of: `authorization_code`, `refresh_token`, `urn:ietf:params:oauth:grant-type:device_code`. + code : Optional[str] + Authorization code to be exchanged for access and refresh tokens. Required for `authorization_code` grant type. + refresh_token : Optional[str] + Refresh token to be exchanged for a new access and refresh tokens. Required for `refresh_token` grant type. + device_code : Optional[str] + Device code obtained from the device authorization endpoint. Required for `urn:ietf:params:oauth:grant-type:device_code` grant type. + client_id : Optional[str] + OAuth2 client ID. + client_secret : Optional[str] + OAuth2 client secret. Required for confidential apps. + code_verifier : Optional[str] + PKCE code verifier. Required for public apps. + redirect_uri : Optional[str] + Redirect URI. Required for `authorization_code` grant type. + + Returns + ------- + Oauth2Token + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/oauth2/{project_id}/token' + api_params = {} + if grant_type is None: + raise AppwriteException('Missing required parameter: "grant_type"') + + api_path = api_path.replace('{project_id}', str(self._normalize_value(self.client.get_config('project')))) + + api_params['grant_type'] = self._normalize_value(grant_type) + if code is not None: + api_params['code'] = self._normalize_value(code) + if refresh_token is not None: + api_params['refresh_token'] = self._normalize_value(refresh_token) + if device_code is not None: + api_params['device_code'] = self._normalize_value(device_code) + 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) + if code_verifier is not None: + api_params['code_verifier'] = self._normalize_value(code_verifier) + if redirect_uri is not None: + api_params['redirect_uri'] = self._normalize_value(redirect_uri) + + response = self.client.call('post', api_path, { + 'content-type': 'application/json', + 'accept': 'application/json', + }, api_params) + + return self._parse_response(response, model=Oauth2Token) + diff --git a/appwrite/services/organization.py b/appwrite/services/organization.py index b9fffe2a..7c63003a 100644 --- a/appwrite/services/organization.py +++ b/appwrite/services/organization.py @@ -51,6 +51,7 @@ def list_keys( 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) @@ -108,6 +109,7 @@ def create_key( 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=Key) @@ -146,6 +148,7 @@ def get_key( 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) @@ -203,6 +206,7 @@ def update_key( 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) @@ -288,6 +292,7 @@ def list_projects( 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) @@ -339,6 +344,7 @@ def create_project( 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=Project) @@ -423,6 +429,7 @@ def update_project( 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=Project) diff --git a/appwrite/services/presences.py b/appwrite/services/presences.py index f286cf61..af9fd815 100644 --- a/appwrite/services/presences.py +++ b/appwrite/services/presences.py @@ -53,6 +53,7 @@ def list( 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=PresenceList) @@ -92,6 +93,7 @@ def get( 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=Presence) @@ -161,6 +163,7 @@ def upsert( 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=Presence) @@ -233,6 +236,7 @@ def update( 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=Presence) diff --git a/appwrite/services/project.py b/appwrite/services/project.py index f5a4a902..cccde7a9 100644 --- a/appwrite/services/project.py +++ b/appwrite/services/project.py @@ -75,6 +75,7 @@ from ..models.policy_deny_aliased_email import PolicyDenyAliasedEmail from ..models.policy_deny_disposable_email import PolicyDenyDisposableEmail from ..models.policy_deny_free_email import PolicyDenyFreeEmail +from ..models.policy_deny_corporate_email import PolicyDenyCorporateEmail from ..enums.project_protocol_id import ProjectProtocolId from ..enums.project_service_id import ProjectServiceId from ..enums.project_smtp_secure import ProjectSMTPSecure @@ -186,6 +187,7 @@ def update_auth_method( 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) @@ -227,6 +229,7 @@ def list_keys( 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) @@ -286,6 +289,7 @@ def create_key( 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=Key) @@ -334,6 +338,7 @@ def create_ephemeral_key( 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) @@ -372,6 +377,7 @@ def get_key( 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) @@ -429,6 +435,7 @@ def update_key( 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) @@ -507,6 +514,7 @@ def update_labels( 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=ProjectModel) @@ -548,6 +556,7 @@ def list_mock_phones( 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=MockNumberList) @@ -594,6 +603,7 @@ def create_mock_phone( 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=MockNumber) @@ -632,6 +642,7 @@ def get_mock_phone( 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=MockNumber) @@ -678,6 +689,7 @@ def update_mock_phone( 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=MockNumber) @@ -758,6 +770,7 @@ def list_o_auth2_providers( 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=OAuth2ProviderList) @@ -768,11 +781,16 @@ def update_o_auth2_server( enabled: bool, authorization_url: str, scopes: Optional[List[str]] = None, + authorization_details_types: Optional[List[str]] = None, access_token_duration: Optional[float] = None, refresh_token_duration: Optional[float] = None, public_access_token_duration: Optional[float] = None, public_refresh_token_duration: Optional[float] = None, - confidential_pkce: Optional[bool] = None + confidential_pkce: Optional[bool] = None, + verification_url: Optional[str] = None, + user_code_length: Optional[float] = None, + user_code_format: Optional[str] = None, + device_code_duration: Optional[float] = None ) -> ProjectModel: """ Update the OAuth2 server (OIDC provider) configuration. @@ -785,6 +803,8 @@ def update_o_auth2_server( URL to your application with consent screen. scopes : Optional[List[str]] List of allowed OAuth2 scopes. Maximum of 100 scopes are allowed, each up to 128 characters long. + authorization_details_types : Optional[List[str]] + List of accepted `authorization_details` types. Maximum of 100 types are allowed, each up to 128 characters long. access_token_duration : Optional[float] Access token duration in seconds for confidential clients (server-side apps that authenticate with a client secret). Leave empty to use default 8 hours. refresh_token_duration : Optional[float] @@ -795,6 +815,14 @@ def update_o_auth2_server( Refresh token duration in seconds for public clients (SPAs, mobile, and native apps that cannot keep a client secret). Leave empty to use default 30 days. confidential_pkce : Optional[bool] When enabled, PKCE is required for confidential clients (server-side flows using client_secret). PKCE is always required for public clients regardless of this setting. + verification_url : Optional[str] + URL to your application page where users enter the device flow user code. Required to enable the Device Authorization Grant. + user_code_length : Optional[float] + Number of characters in the device flow user code, excluding the formatting separator. Shorter codes are easier to type but weaker; pair short codes with short expiry. Leave empty to use default 8. + user_code_format : Optional[str] + Character set for device flow user codes: `numeric` (digits only — best for numeric keypads and TV remotes), `alphabetic` (letters only), or `alphanumeric` (letters and digits — highest entropy per character). Defaults to `alphanumeric`. + device_code_duration : Optional[float] + Lifetime in seconds of device flow device codes and user codes. Device codes are intentionally short-lived. Leave empty to use default 600. Returns ------- @@ -820,15 +848,24 @@ def update_o_auth2_server( api_params['authorizationUrl'] = self._normalize_value(authorization_url) if scopes is not None: api_params['scopes'] = self._normalize_value(scopes) + if authorization_details_types is not None: + api_params['authorizationDetailsTypes'] = self._normalize_value(authorization_details_types) api_params['accessTokenDuration'] = self._normalize_value(access_token_duration) api_params['refreshTokenDuration'] = self._normalize_value(refresh_token_duration) api_params['publicAccessTokenDuration'] = self._normalize_value(public_access_token_duration) api_params['publicRefreshTokenDuration'] = self._normalize_value(public_refresh_token_duration) api_params['confidentialPkce'] = self._normalize_value(confidential_pkce) + if verification_url is not None: + api_params['verificationUrl'] = self._normalize_value(verification_url) + api_params['userCodeLength'] = self._normalize_value(user_code_length) + if user_code_format is not None: + api_params['userCodeFormat'] = self._normalize_value(user_code_format) + api_params['deviceCodeDuration'] = self._normalize_value(device_code_duration) 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=ProjectModel) @@ -873,6 +910,7 @@ def update_o_auth2_amazon( 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=OAuth2Amazon) @@ -925,6 +963,7 @@ def update_o_auth2_apple( 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=OAuth2Apple) @@ -973,6 +1012,7 @@ def update_o_auth2_auth0( 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=OAuth2Auth0) @@ -1021,6 +1061,7 @@ def update_o_auth2_authentik( 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=OAuth2Authentik) @@ -1065,6 +1106,7 @@ def update_o_auth2_autodesk( 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=OAuth2Autodesk) @@ -1109,6 +1151,7 @@ def update_o_auth2_bitbucket( 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=OAuth2Bitbucket) @@ -1153,6 +1196,7 @@ def update_o_auth2_bitly( 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=OAuth2Bitly) @@ -1197,6 +1241,7 @@ def update_o_auth2_box( 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=OAuth2Box) @@ -1241,6 +1286,7 @@ def update_o_auth2_dailymotion( 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=OAuth2Dailymotion) @@ -1285,6 +1331,7 @@ def update_o_auth2_discord( 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=OAuth2Discord) @@ -1329,6 +1376,7 @@ def update_o_auth2_disqus( 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=OAuth2Disqus) @@ -1373,6 +1421,7 @@ def update_o_auth2_dropbox( 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=OAuth2Dropbox) @@ -1417,6 +1466,7 @@ def update_o_auth2_etsy( 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=OAuth2Etsy) @@ -1461,6 +1511,7 @@ def update_o_auth2_facebook( 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=OAuth2Facebook) @@ -1505,6 +1556,7 @@ def update_o_auth2_figma( 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=OAuth2Figma) @@ -1553,6 +1605,7 @@ def update_o_auth2_fusion_auth( 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=OAuth2FusionAuth) @@ -1597,6 +1650,7 @@ def update_o_auth2_git_hub( 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=OAuth2Github) @@ -1645,6 +1699,7 @@ def update_o_auth2_gitlab( 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=OAuth2Gitlab) @@ -1693,6 +1748,7 @@ def update_o_auth2_google( 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=OAuth2Google) @@ -1745,6 +1801,7 @@ def update_o_auth2_keycloak( 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=OAuth2Keycloak) @@ -1789,6 +1846,7 @@ def update_o_auth2_kick( 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=OAuth2Kick) @@ -1833,6 +1891,7 @@ def update_o_auth2_linkedin( 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=OAuth2Linkedin) @@ -1881,6 +1940,7 @@ def update_o_auth2_microsoft( 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=OAuth2Microsoft) @@ -1925,6 +1985,7 @@ def update_o_auth2_notion( 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=OAuth2Notion) @@ -1985,6 +2046,7 @@ def update_o_auth2_oidc( 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=OAuth2Oidc) @@ -2037,6 +2099,7 @@ def update_o_auth2_okta( 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=OAuth2Okta) @@ -2081,6 +2144,7 @@ def update_o_auth2_paypal( 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=OAuth2Paypal) @@ -2125,6 +2189,7 @@ def update_o_auth2_paypal_sandbox( 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=OAuth2Paypal) @@ -2169,6 +2234,7 @@ def update_o_auth2_podio( 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=OAuth2Podio) @@ -2213,6 +2279,7 @@ def update_o_auth2_salesforce( 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=OAuth2Salesforce) @@ -2257,6 +2324,7 @@ def update_o_auth2_slack( 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=OAuth2Slack) @@ -2301,6 +2369,7 @@ def update_o_auth2_spotify( 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=OAuth2Spotify) @@ -2345,6 +2414,7 @@ def update_o_auth2_stripe( 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=OAuth2Stripe) @@ -2389,6 +2459,7 @@ def update_o_auth2_tradeshift( 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=OAuth2Tradeshift) @@ -2433,6 +2504,7 @@ def update_o_auth2_tradeshift_sandbox( 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=OAuth2Tradeshift) @@ -2477,6 +2549,7 @@ def update_o_auth2_twitch( 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=OAuth2Twitch) @@ -2521,6 +2594,7 @@ def update_o_auth2_word_press( 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=OAuth2WordPress) @@ -2565,6 +2639,7 @@ def update_o_auth2_x( 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=OAuth2X) @@ -2609,6 +2684,7 @@ def update_o_auth2_yahoo( 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=OAuth2Yahoo) @@ -2653,6 +2729,7 @@ def update_o_auth2_yandex( 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=OAuth2Yandex) @@ -2697,6 +2774,7 @@ def update_o_auth2_zoho( 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=OAuth2Zoho) @@ -2741,6 +2819,7 @@ def update_o_auth2_zoom( 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=OAuth2Zoom) @@ -2779,6 +2858,7 @@ def get_o_auth2_provider( 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') @@ -2942,6 +3022,7 @@ def list_platforms( 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=PlatformList) @@ -2995,6 +3076,7 @@ def create_android_platform( 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=PlatformAndroid) @@ -3048,6 +3130,7 @@ def update_android_platform( 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=PlatformAndroid) @@ -3101,6 +3184,7 @@ def create_apple_platform( 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=PlatformApple) @@ -3154,6 +3238,7 @@ def update_apple_platform( 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=PlatformApple) @@ -3207,6 +3292,7 @@ def create_linux_platform( 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=PlatformLinux) @@ -3260,6 +3346,7 @@ def update_linux_platform( 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=PlatformLinux) @@ -3313,6 +3400,7 @@ def create_web_platform( 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=PlatformWeb) @@ -3366,6 +3454,7 @@ def update_web_platform( 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=PlatformWeb) @@ -3419,6 +3508,7 @@ def create_windows_platform( 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=PlatformWindows) @@ -3472,6 +3562,7 @@ def update_windows_platform( 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=PlatformWindows) @@ -3510,6 +3601,7 @@ def get_platform( 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') @@ -3607,6 +3699,7 @@ def list_policies( 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=PolicyList) @@ -3646,6 +3739,47 @@ def update_deny_aliased_email_policy( 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_deny_corporate_email_policy( + self, + enabled: bool + ) -> ProjectModel: + """ + Configures if only corporate email addresses (non-free and non-disposable domains) are allowed during new user sign-ups and email updates. + + Parameters + ---------- + enabled : bool + Set whether or not to restrict sign-ups and email updates to corporate email addresses only. + + Returns + ------- + ProjectModel + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/project/policies/deny-corporate-email' + api_params = {} + if enabled is None: + raise AppwriteException('Missing required parameter: "enabled"') + + + 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=ProjectModel) @@ -3685,6 +3819,7 @@ def update_deny_disposable_email_policy( 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) @@ -3724,6 +3859,7 @@ def update_deny_free_email_policy( 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) @@ -3735,7 +3871,8 @@ def update_membership_privacy_policy( user_email: Optional[bool] = None, user_phone: Optional[bool] = None, user_name: Optional[bool] = None, - user_mfa: Optional[bool] = None + user_mfa: Optional[bool] = None, + user_accessed_at: Optional[bool] = None ) -> ProjectModel: """ Updating this policy allows you to control if team members can see other members information. When enabled, all team members can see ID, name, email, phone number, and MFA status of other members.. @@ -3752,6 +3889,8 @@ def update_membership_privacy_policy( Set to true if you want make user name visible to all team members, or false to hide it. user_mfa : Optional[bool] Set to true if you want make user MFA status visible to all team members, or false to hide it. + user_accessed_at : Optional[bool] + Set to true if you want make user last access time visible to all team members, or false to hide it. Returns ------- @@ -3777,10 +3916,13 @@ def update_membership_privacy_policy( api_params['userName'] = self._normalize_value(user_name) if user_mfa is not None: api_params['userMFA'] = self._normalize_value(user_mfa) + if user_accessed_at is not None: + api_params['userAccessedAt'] = self._normalize_value(user_accessed_at) 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) @@ -3820,6 +3962,7 @@ def update_password_dictionary_policy( 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) @@ -3858,6 +4001,7 @@ def update_password_history_policy( 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) @@ -3897,6 +4041,7 @@ def update_password_personal_data_policy( 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) @@ -3954,6 +4099,7 @@ def update_password_strength_policy( 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=PolicyPasswordStrength) @@ -3993,6 +4139,7 @@ def update_session_alert_policy( 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) @@ -4032,6 +4179,7 @@ def update_session_duration_policy( 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) @@ -4071,6 +4219,7 @@ def update_session_invalidation_policy( 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) @@ -4107,6 +4256,7 @@ def update_session_limit_policy( 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) @@ -4143,6 +4293,7 @@ def update_user_limit_policy( 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) @@ -4151,18 +4302,18 @@ def update_user_limit_policy( def get_policy( self, policy_id: ProjectPolicyId - ) -> Union[PolicyPasswordDictionary, PolicyPasswordHistory, PolicyPasswordStrength, PolicyPasswordPersonalData, PolicySessionAlert, PolicySessionDuration, PolicySessionInvalidation, PolicySessionLimit, PolicyUserLimit, PolicyMembershipPrivacy, PolicyDenyAliasedEmail, PolicyDenyDisposableEmail, PolicyDenyFreeEmail]: + ) -> Union[PolicyPasswordDictionary, PolicyPasswordHistory, PolicyPasswordStrength, PolicyPasswordPersonalData, PolicySessionAlert, PolicySessionDuration, PolicySessionInvalidation, PolicySessionLimit, PolicyUserLimit, PolicyMembershipPrivacy, PolicyDenyAliasedEmail, PolicyDenyDisposableEmail, PolicyDenyFreeEmail, PolicyDenyCorporateEmail]: """ Get a policy by its unique ID. This endpoint returns the current configuration for the requested project policy. Parameters ---------- policy_id : ProjectPolicyId - 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, deny-aliased-email, deny-disposable-email, deny-free-email. + 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, deny-aliased-email, deny-disposable-email, deny-free-email, deny-corporate-email. Returns ------- - Union[PolicyPasswordDictionary, PolicyPasswordHistory, PolicyPasswordStrength, PolicyPasswordPersonalData, PolicySessionAlert, PolicySessionDuration, PolicySessionInvalidation, PolicySessionLimit, PolicyUserLimit, PolicyMembershipPrivacy, PolicyDenyAliasedEmail, PolicyDenyDisposableEmail, PolicyDenyFreeEmail] + Union[PolicyPasswordDictionary, PolicyPasswordHistory, PolicyPasswordStrength, PolicyPasswordPersonalData, PolicySessionAlert, PolicySessionDuration, PolicySessionInvalidation, PolicySessionLimit, PolicyUserLimit, PolicyMembershipPrivacy, PolicyDenyAliasedEmail, PolicyDenyDisposableEmail, PolicyDenyFreeEmail, PolicyDenyCorporateEmail] API response as one of the typed response models Raises @@ -4181,6 +4332,7 @@ def get_policy( 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') @@ -4224,6 +4376,9 @@ def get_policy( if response.get('$id') == 'deny-free-email': return self._parse_response(response, model=PolicyDenyFreeEmail) + if response.get('$id') == 'deny-corporate-email': + return self._parse_response(response, model=PolicyDenyCorporateEmail) + raise AppwriteException('Unable to match response to any known model') @@ -4268,6 +4423,7 @@ def update_protocol( 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) @@ -4284,7 +4440,7 @@ def update_service( Parameters ---------- service_id : ProjectServiceId - Service name. Can be one of: account, avatars, databases, tablesdb, locale, health, project, storage, teams, users, vcs, sites, functions, proxy, graphql, migrations, messaging, advisor + Service name. Can be one of: account, avatars, databases, tablesdb, locale, health, project, storage, teams, users, vcs, sites, functions, proxy, graphql, migrations, messaging, advisor, oauth2 enabled : bool Service status. @@ -4314,6 +4470,7 @@ def update_service( 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) @@ -4386,6 +4543,7 @@ def update_smtp( 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) @@ -4466,6 +4624,7 @@ def list_email_templates( 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=EmailTemplateList) @@ -4534,6 +4693,7 @@ def update_email_template( 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=EmailTemplate) @@ -4577,6 +4737,7 @@ def get_email_template( 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=EmailTemplate) @@ -4618,6 +4779,7 @@ def list_variables( 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=VariableList) @@ -4676,6 +4838,7 @@ def create_variable( 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=Variable) @@ -4714,6 +4877,7 @@ def get_variable( 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=Variable) @@ -4765,6 +4929,7 @@ def update_variable( 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=Variable) diff --git a/appwrite/services/proxy.py b/appwrite/services/proxy.py index 09ca4fec..44f18747 100644 --- a/appwrite/services/proxy.py +++ b/appwrite/services/proxy.py @@ -49,6 +49,7 @@ def list_rules( 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=ProxyRuleList) @@ -90,6 +91,7 @@ def create_api_rule( 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=ProxyRule) @@ -143,6 +145,7 @@ def create_function_rule( 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=ProxyRule) @@ -212,6 +215,7 @@ def create_redirect_rule( 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=ProxyRule) @@ -265,6 +269,7 @@ def create_site_rule( 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=ProxyRule) @@ -303,6 +308,7 @@ def get_rule( 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=ProxyRule) @@ -381,6 +387,7 @@ def update_rule_status( 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=ProxyRule) diff --git a/appwrite/services/sites.py b/appwrite/services/sites.py index 279baff2..ce0c23f1 100644 --- a/appwrite/services/sites.py +++ b/appwrite/services/sites.py @@ -67,6 +67,7 @@ def list( 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=SiteList) @@ -222,6 +223,7 @@ def create( 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=Site) @@ -249,6 +251,7 @@ def list_frameworks( 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=FrameworkList) @@ -276,6 +279,7 @@ def list_specifications( 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=SpecificationList) @@ -314,6 +318,7 @@ def get( 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=Site) @@ -465,6 +470,7 @@ def update( 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=Site) @@ -550,6 +556,7 @@ def update_site_deployment( 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=Site) @@ -603,6 +610,7 @@ def list_deployments( 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=DeploymentList) @@ -677,6 +685,7 @@ def create_deployment( 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) return self._parse_response(response, model=Deployment) @@ -723,6 +732,7 @@ def create_duplicate_deployment( 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=Deployment) @@ -804,6 +814,7 @@ def create_template_deployment( 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=Deployment) @@ -864,6 +875,7 @@ def create_vcs_deployment( 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=Deployment) @@ -909,6 +921,7 @@ def get_deployment( 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=Deployment) @@ -1005,6 +1018,7 @@ def get_deployment_download( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': '*/*', }, api_params) return response @@ -1051,6 +1065,7 @@ def update_deployment_status( 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=Deployment) @@ -1099,6 +1114,7 @@ def list_logs( 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=ExecutionList) @@ -1144,6 +1160,7 @@ def get_log( 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=Execution) @@ -1190,6 +1207,7 @@ def delete_log( 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 @@ -1238,6 +1256,7 @@ def list_variables( 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=VariableList) @@ -1303,6 +1322,7 @@ def create_variable( 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=Variable) @@ -1348,6 +1368,7 @@ def get_variable( 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=Variable) @@ -1406,6 +1427,7 @@ def update_variable( 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=Variable) diff --git a/appwrite/services/storage.py b/appwrite/services/storage.py index 6d80de9c..7d1a1eaf 100644 --- a/appwrite/services/storage.py +++ b/appwrite/services/storage.py @@ -58,6 +58,7 @@ def list_buckets( 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=BucketList) @@ -148,6 +149,7 @@ def create_bucket( 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=Bucket) @@ -186,6 +188,7 @@ def get_bucket( 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=Bucket) @@ -276,6 +279,7 @@ def update_bucket( 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=Bucket) @@ -368,6 +372,7 @@ def list_files( 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=FileList) @@ -442,6 +447,7 @@ def create_file( 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) return self._parse_response(response, model=File) @@ -487,6 +493,7 @@ def get_file( 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=File) @@ -542,6 +549,7 @@ def update_file( 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=File) @@ -638,6 +646,7 @@ def get_file_download( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': '*/*', }, api_params) return response @@ -743,6 +752,7 @@ def get_file_preview( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'image/*', }, api_params) return response @@ -793,6 +803,7 @@ def get_file_view( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': '*/*', }, api_params) return response diff --git a/appwrite/services/tables_db.py b/appwrite/services/tables_db.py index 97a1499f..7ea86989 100644 --- a/appwrite/services/tables_db.py +++ b/appwrite/services/tables_db.py @@ -85,6 +85,7 @@ def list( 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=DatabaseList) @@ -94,7 +95,8 @@ def create( self, database_id: str, name: str, - enabled: Optional[bool] = None + enabled: Optional[bool] = None, + dedicated_database_id: Optional[str] = None ) -> Database: """ Create a new Database. @@ -108,6 +110,8 @@ def create( Database name. Max length: 128 chars. enabled : Optional[bool] Is the database enabled? When set to 'disabled', users cannot access the database but Server SDKs with an API key can still read and write to the database. No data is lost when this is toggled. + dedicated_database_id : Optional[str] + Optional dedicated database (compute) ID to attach this database to. Leave empty to create a database on the shared pool. Returns ------- @@ -133,10 +137,13 @@ def create( api_params['name'] = self._normalize_value(name) if enabled is not None: api_params['enabled'] = self._normalize_value(enabled) + if dedicated_database_id is not None: + api_params['dedicatedDatabaseId'] = self._normalize_value(dedicated_database_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=Database) @@ -173,6 +180,7 @@ def list_transactions( 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=TransactionList) @@ -210,6 +218,7 @@ def create_transaction( 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=Transaction) @@ -248,6 +257,7 @@ def get_transaction( 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=Transaction) @@ -297,6 +307,7 @@ def update_transaction( 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=Transaction) @@ -380,6 +391,7 @@ def create_operations( 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=Transaction) @@ -418,6 +430,7 @@ def get( 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=Database) @@ -467,6 +480,7 @@ def update( 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=Database) @@ -559,6 +573,7 @@ def list_tables( 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=TableList) @@ -636,6 +651,7 @@ def create_table( 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=Table) @@ -681,6 +697,7 @@ def get_table( 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=Table) @@ -751,6 +768,7 @@ def update_table( 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=Table) @@ -852,6 +870,7 @@ def list_columns( 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=ColumnList) @@ -930,6 +949,7 @@ def create_big_int_column( 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=ColumnBigint) @@ -1007,6 +1027,7 @@ def update_big_int_column( 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=ColumnBigint) @@ -1077,6 +1098,7 @@ def create_boolean_column( 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=ColumnBoolean) @@ -1145,6 +1167,7 @@ def update_boolean_column( 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=ColumnBoolean) @@ -1214,6 +1237,7 @@ def create_datetime_column( 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=ColumnDatetime) @@ -1282,6 +1306,7 @@ def update_datetime_column( 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=ColumnDatetime) @@ -1352,6 +1377,7 @@ def create_email_column( 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=ColumnEmail) @@ -1421,6 +1447,7 @@ def update_email_column( 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=ColumnEmail) @@ -1497,6 +1524,7 @@ def create_enum_column( 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=ColumnEnum) @@ -1573,6 +1601,7 @@ def update_enum_column( 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=ColumnEnum) @@ -1651,6 +1680,7 @@ def create_float_column( 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=ColumnFloat) @@ -1728,6 +1758,7 @@ def update_float_column( 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=ColumnFloat) @@ -1806,6 +1837,7 @@ def create_integer_column( 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=ColumnInteger) @@ -1883,6 +1915,7 @@ def update_integer_column( 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=ColumnInteger) @@ -1953,6 +1986,7 @@ def create_ip_column( 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=ColumnIp) @@ -2022,6 +2056,7 @@ def update_ip_column( 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=ColumnIp) @@ -2033,7 +2068,7 @@ def create_line_column( table_id: str, key: str, required: bool, - default: Optional[List[Any]] = None + default: Optional[List[List[Any]]] = None ) -> ColumnLine: """ Create a geometric line column. @@ -2048,7 +2083,7 @@ def create_line_column( Column Key. required : bool Is column required? - default : Optional[List[Any]] + default : Optional[List[List[Any]]] Default value for column when not provided, two-dimensional array of coordinate pairs, [[longitude, latitude], [longitude, latitude], …], listing the vertices of the line in order. Cannot be set when column is required. Returns @@ -2086,6 +2121,7 @@ def create_line_column( 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=ColumnLine) @@ -2097,7 +2133,7 @@ def update_line_column( table_id: str, key: str, required: bool, - default: Optional[List[Any]] = None, + default: Optional[List[List[Any]]] = None, new_key: Optional[str] = None ) -> ColumnLine: """ @@ -2113,7 +2149,7 @@ def update_line_column( Column Key. required : bool Is column required? - default : Optional[List[Any]] + default : Optional[List[List[Any]]] Default value for column when not provided, two-dimensional array of coordinate pairs, [[longitude, latitude], [longitude, latitude], …], listing the vertices of the line in order. Cannot be set when column is required. new_key : Optional[str] New Column Key. @@ -2154,6 +2190,7 @@ def update_line_column( 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=ColumnLine) @@ -2229,6 +2266,7 @@ def create_longtext_column( 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=ColumnLongtext) @@ -2298,6 +2336,7 @@ def update_longtext_column( 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=ColumnLongtext) @@ -2373,6 +2412,7 @@ def create_mediumtext_column( 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=ColumnMediumtext) @@ -2442,6 +2482,7 @@ def update_mediumtext_column( 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=ColumnMediumtext) @@ -2453,7 +2494,7 @@ def create_point_column( table_id: str, key: str, required: bool, - default: Optional[List[Any]] = None + default: Optional[List[float]] = None ) -> ColumnPoint: """ Create a geometric point column. @@ -2468,7 +2509,7 @@ def create_point_column( Column Key. required : bool Is column required? - default : Optional[List[Any]] + default : Optional[List[float]] Default value for column when not provided, array of two numbers [longitude, latitude], representing a single coordinate. Cannot be set when column is required. Returns @@ -2506,6 +2547,7 @@ def create_point_column( 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=ColumnPoint) @@ -2517,7 +2559,7 @@ def update_point_column( table_id: str, key: str, required: bool, - default: Optional[List[Any]] = None, + default: Optional[List[float]] = None, new_key: Optional[str] = None ) -> ColumnPoint: """ @@ -2533,7 +2575,7 @@ def update_point_column( Column Key. required : bool Is column required? - default : Optional[List[Any]] + default : Optional[List[float]] Default value for column when not provided, array of two numbers [longitude, latitude], representing a single coordinate. Cannot be set when column is required. new_key : Optional[str] New Column Key. @@ -2574,6 +2616,7 @@ def update_point_column( 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=ColumnPoint) @@ -2585,7 +2628,7 @@ def create_polygon_column( table_id: str, key: str, required: bool, - default: Optional[List[Any]] = None + default: Optional[List[List[Any]]] = None ) -> ColumnPolygon: """ Create a geometric polygon column. @@ -2600,7 +2643,7 @@ def create_polygon_column( Column Key. required : bool Is column required? - default : Optional[List[Any]] + default : Optional[List[List[Any]]] Default value for column when not provided, three-dimensional array where the outer array holds one or more linear rings, [[[longitude, latitude], …], …], the first ring is the exterior boundary, any additional rings are interior holes, and each ring must start and end with the same coordinate pair. Cannot be set when column is required. Returns @@ -2638,6 +2681,7 @@ def create_polygon_column( 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=ColumnPolygon) @@ -2649,7 +2693,7 @@ def update_polygon_column( table_id: str, key: str, required: bool, - default: Optional[List[Any]] = None, + default: Optional[List[List[Any]]] = None, new_key: Optional[str] = None ) -> ColumnPolygon: """ @@ -2665,7 +2709,7 @@ def update_polygon_column( Column Key. required : bool Is column required? - default : Optional[List[Any]] + default : Optional[List[List[Any]]] Default value for column when not provided, three-dimensional array where the outer array holds one or more linear rings, [[[longitude, latitude], …], …], the first ring is the exterior boundary, any additional rings are interior holes, and each ring must start and end with the same coordinate pair. Cannot be set when column is required. new_key : Optional[str] New Column Key. @@ -2706,6 +2750,7 @@ def update_polygon_column( 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=ColumnPolygon) @@ -2785,6 +2830,7 @@ def create_relationship_column( 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=ColumnRelationship) @@ -2870,6 +2916,7 @@ def create_string_column( 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=ColumnString) @@ -2946,6 +2993,7 @@ def update_string_column( 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=ColumnString) @@ -3021,6 +3069,7 @@ def create_text_column( 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=ColumnText) @@ -3090,6 +3139,7 @@ def update_text_column( 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=ColumnText) @@ -3160,6 +3210,7 @@ def create_url_column( 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=ColumnUrl) @@ -3229,6 +3280,7 @@ def update_url_column( 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=ColumnUrl) @@ -3311,6 +3363,7 @@ def create_varchar_column( 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=ColumnVarchar) @@ -3384,6 +3437,7 @@ def update_varchar_column( 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=ColumnVarchar) @@ -3436,6 +3490,7 @@ def get_column( 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') @@ -3583,6 +3638,7 @@ def update_relationship_column( 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=ColumnRelationship) @@ -3638,6 +3694,7 @@ def list_indexes( 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=ColumnIndexList) @@ -3716,6 +3773,7 @@ def create_index( 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=ColumnIndex) @@ -3768,6 +3826,7 @@ def get_index( 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=ColumnIndex) @@ -3890,6 +3949,7 @@ def list_rows( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', }, api_params) return RowList.with_data(response, model_type) @@ -3962,6 +4022,7 @@ def create_row( 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 Row.with_data(response, model_type) @@ -4023,6 +4084,7 @@ def create_rows( 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 RowList.with_data(response, model_type) @@ -4085,6 +4147,7 @@ def upsert_rows( 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 RowList.with_data(response, model_type) @@ -4149,6 +4212,7 @@ def update_rows( 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 RowList.with_data(response, model_type) @@ -4203,11 +4267,13 @@ def delete_rows( if queries is not None: api_params['queries'] = self._normalize_value(queries) - api_params['transactionId'] = self._normalize_value(transaction_id) + if transaction_id is not None: + api_params['transactionId'] = self._normalize_value(transaction_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 RowList.with_data(response, model_type) @@ -4274,6 +4340,7 @@ def get_row( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', }, api_params) return Row.with_data(response, model_type) @@ -4344,6 +4411,7 @@ def upsert_row( 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 Row.with_data(response, model_type) @@ -4414,6 +4482,7 @@ def update_row( 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 Row.with_data(response, model_type) @@ -4466,7 +4535,8 @@ def delete_row( api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) api_path = api_path.replace('{rowId}', str(self._normalize_value(row_id))) - api_params['transactionId'] = self._normalize_value(transaction_id) + if transaction_id is not None: + api_params['transactionId'] = self._normalize_value(transaction_id) response = self.client.call('delete', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), @@ -4548,6 +4618,7 @@ def decrement_row_column( 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 Row.with_data(response, model_type) @@ -4625,6 +4696,7 @@ def increment_row_column( 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 Row.with_data(response, model_type) diff --git a/appwrite/services/teams.py b/appwrite/services/teams.py index ee9333a7..6b8a6fc9 100644 --- a/appwrite/services/teams.py +++ b/appwrite/services/teams.py @@ -61,6 +61,7 @@ def list( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', }, api_params) return TeamList.with_data(response, model_type) @@ -116,6 +117,7 @@ def create( 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 Team.with_data(response, model_type) @@ -158,6 +160,7 @@ def get( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', }, api_params) return Team.with_data(response, model_type) @@ -208,6 +211,7 @@ def update_name( 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 Team.with_data(response, model_type) @@ -300,6 +304,7 @@ def list_memberships( 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=MembershipList) @@ -378,6 +383,7 @@ def create_membership( 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=Membership) @@ -423,6 +429,7 @@ def get_membership( 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=Membership) @@ -477,6 +484,7 @@ def update_membership( 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=Membership) @@ -586,6 +594,7 @@ def update_membership_status( 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=Membership) @@ -628,6 +637,7 @@ def get_prefs( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', }, api_params) return Preferences.with_data(response, model_type) @@ -678,6 +688,7 @@ def update_prefs( 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 Preferences.with_data(response, model_type) diff --git a/appwrite/services/tokens.py b/appwrite/services/tokens.py index 046129ae..0c04dfe3 100644 --- a/appwrite/services/tokens.py +++ b/appwrite/services/tokens.py @@ -61,6 +61,7 @@ def list( 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=ResourceTokenList) @@ -111,6 +112,7 @@ def create_file_token( 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=ResourceToken) @@ -149,6 +151,7 @@ def get( 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=ResourceToken) @@ -192,6 +195,7 @@ def update( 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=ResourceToken) diff --git a/appwrite/services/usage.py b/appwrite/services/usage.py index 2a6e5f5e..de300c7f 100644 --- a/appwrite/services/usage.py +++ b/appwrite/services/usage.py @@ -13,18 +13,51 @@ def __init__(self, client) -> None: def list_events( self, - queries: Optional[List[str]] = None, - total: Optional[bool] = None + metrics: List[str], + resource: Optional[str] = None, + resource_id: Optional[str] = None, + interval: Optional[str] = None, + dimensions: Optional[List[str]] = None, + start_at: Optional[str] = None, + end_at: Optional[str] = None, + order_by: Optional[str] = None, + order_dir: Optional[str] = None, + limit: Optional[float] = None, + offset: Optional[float] = None ) -> UsageEventList: """ - Query usage event metrics from the usage database. Returns individual event rows with full metadata. Pass Query objects as JSON strings to filter, paginate, and order results. Supported query methods: equal, greaterThanEqual, lessThanEqual, orderAsc, orderDesc, limit, offset. Supported filter attributes: metric, path, method, status, resource, resourceId, country, userAgent, time (these match the underlying column names — note that the response surfaces `resource` as `resourceType` and `country` as `countryCode`). When no time filter is supplied the endpoint defaults to the last 7 days. Default `limit(100)` is applied if none is given; user-supplied limits are capped at 500. The `total` field is capped at 5000 to keep counts predictable — pass `total=false` to skip the count entirely. + Aggregate usage event metrics. `metrics[]` (1-10) is required; the response always contains one entry per requested metric, each with its own `points[]` time series. + + **Two response shapes**: + - Omit `interval` for a flat top-N table — one point per dimension combination, no time axis. Useful for "top 10 paths by bandwidth in the last 7 days". + - Pass `interval` (`1m`, `15m`, `30m`, `1h`, `1d`) for a time series — one point per (time bucket × dimension combination). + + `dimensions[]` breaks each point down by one or more attributes (service, path, status, country, …). Pass multiple metrics to render stacked charts in one round-trip. `resource` and `resourceId` filter the underlying events. `orderBy=value`+`orderDir=desc`+`limit=N` returns the top-N by aggregated value. When `startAt` is omitted, the default window adapts to `interval` (or 7d when interval is omitted). Parameters ---------- - queries : Optional[List[str]] - Array of query strings as JSON. Supported: equal("metric", [...]), equal("path", [...]), equal("method", [...]), equal("status", [...]), equal("resource", [...]), equal("resourceId", [...]), equal("country", [...]), equal("userAgent", [...]), greaterThanEqual("time", "..."), lessThanEqual("time", "..."), orderAsc("time"), orderDesc("time"), limit(N), offset(N). - total : Optional[bool] - When set to false, the total count returned will be 0 and will not be calculated. + metrics : List[str] + One to ten metric names. Single-metric callers pass a one-element array. Example: `metrics[]=executions` or `metrics[]=executions&metrics[]=executions.compute` for stacked charts. + resource : Optional[str] + Resource type filter (singular form). Common values: function, site, database, bucket, file, webhook, team, user, project. + resource_id : Optional[str] + Resource id filter. + interval : Optional[str] + Time interval size. Omit (null) for a flat aggregate over the whole window. Allowed: 1m, 15m, 30m, 1h, 1d. + dimensions : Optional[List[str]] + Break-down dimensions (max 10). Allowed: path, method, status, service, country, region, hostname, osName, clientType, clientName, deviceName, teamId, resourceId. + start_at : Optional[str] + Range start in ISO 8601. Defaults adapt to interval (7d for the no-interval aggregate). + end_at : Optional[str] + Range end in ISO 8601. Defaults to the current time. + order_by : Optional[str] + Column to order by. Allowed: time, value. Default time when an interval is set; otherwise value. + order_dir : Optional[str] + Sort direction: asc or desc. Default desc — paired with the default limit, returns the most recent / highest-value groups first. + limit : Optional[float] + Maximum rows to return (1-5000). + offset : Optional[float] + Pagination offset (0-100000). Returns ------- @@ -39,14 +72,35 @@ def list_events( api_path = '/usage/events' 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) + if metrics is None: + raise AppwriteException('Missing required parameter: "metrics"') + + + api_params['metrics'] = self._normalize_value(metrics) + if resource is not None: + api_params['resource'] = self._normalize_value(resource) + if resource_id is not None: + api_params['resourceId'] = self._normalize_value(resource_id) + if interval is not None: + api_params['interval'] = self._normalize_value(interval) + if dimensions is not None: + api_params['dimensions'] = self._normalize_value(dimensions) + if start_at is not None: + api_params['startAt'] = self._normalize_value(start_at) + if end_at is not None: + api_params['endAt'] = self._normalize_value(end_at) + if order_by is not None: + api_params['orderBy'] = self._normalize_value(order_by) + if order_dir is not None: + api_params['orderDir'] = self._normalize_value(order_dir) + if limit is not None: + api_params['limit'] = self._normalize_value(limit) + if offset is not None: + api_params['offset'] = self._normalize_value(offset) 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=UsageEventList) @@ -54,18 +108,51 @@ def list_events( def list_gauges( self, - queries: Optional[List[str]] = None, - total: Optional[bool] = None + metrics: List[str], + resource_id: Optional[str] = None, + team_id: Optional[str] = None, + interval: Optional[str] = None, + dimensions: Optional[List[str]] = None, + start_at: Optional[str] = None, + end_at: Optional[str] = None, + order_by: Optional[str] = None, + order_dir: Optional[str] = None, + limit: Optional[float] = None, + offset: Optional[float] = None ) -> UsageGaugeList: """ - Query usage gauge metrics (point-in-time resource snapshots) from the usage database. Returns individual gauge snapshots with metric, value, timestamp, resourceType, and resourceId. Pass Query objects as JSON strings to filter, paginate, and order results. Supported query methods: equal, greaterThanEqual, lessThanEqual, orderAsc, orderDesc, limit, offset. Supported filter attributes: metric, time. Use `orderDesc("time"), limit(1)` to fetch the most recent snapshot. When no time filter is supplied the endpoint defaults to the last 7 days. Default `limit(100)` is applied if none is given; user-supplied limits are capped at 500. The `total` field is capped at 5000 to keep counts predictable — pass `total=false` to skip the count entirely. + Aggregate usage gauge snapshots. Gauges are point-in-time values (storage totals, resource counts, …); each point carries the latest snapshot in its interval via `argMax(value, time)`. `metrics[]` (1-10) is required; the response always contains one entry per requested metric, each with its own `points[]` time series. + + **Two response shapes**: + - Omit `interval` for a flat top-N table — `argMax(value, time)` per dimension combination over the whole window, no time axis. Useful for "top 10 resources by current storage". + - Pass `interval` (`1m`, `15m`, `30m`, `1h`, `1d`) for a time series — one snapshot per (time bucket × dimension combination). + + `dimensions[]` breaks each point down further. Supported on gauges: `resourceId`, `teamId`, `service`, `resource`. `service` and `resource` enable per-service / per-resource-type panels (e.g. storage-by-service: group `files.storage`, `deployments.storage`, `builds.storage`, `databases.storage` by `service`). Pass multiple metrics to render stacked charts in one round-trip. `resourceId` and `teamId` parameters filter the underlying rows. `orderBy=value`+`orderDir=desc`+`limit=N` returns the top-N. When `startAt` is omitted, the default window adapts to interval (or 7d when interval is omitted). Parameters ---------- - queries : Optional[List[str]] - Array of query strings as JSON. Supported: equal("metric", [...]), greaterThanEqual("time", "..."), lessThanEqual("time", "..."), orderAsc("time"), orderDesc("time"), limit(N), offset(N). - total : Optional[bool] - When set to false, the total count returned will be 0 and will not be calculated. + metrics : List[str] + One to ten metric names. Single-metric callers pass a one-element array. Example: `metrics[]=files.storage` or `metrics[]=files.storage&metrics[]=deployments.storage` for stacked charts. + resource_id : Optional[str] + Resource id filter. + team_id : Optional[str] + Team id filter. + interval : Optional[str] + Time interval size. Omit (null) for a flat aggregate over the whole window. Allowed: 1m, 15m, 30m, 1h, 1d. + dimensions : Optional[List[str]] + Break-down dimensions. Allowed: resourceId, teamId, service, resource. + start_at : Optional[str] + Range start in ISO 8601. Defaults to endAt - 7d. + end_at : Optional[str] + Range end in ISO 8601. Defaults to the current time. + order_by : Optional[str] + Column to order by. Allowed: time, value. Default time. + order_dir : Optional[str] + Sort direction: asc or desc. Default desc — paired with the default limit, this returns the most recent groups first. Pass asc for chronological charting. + limit : Optional[float] + Maximum rows to return (1-5000). + offset : Optional[float] + Pagination offset (0-100000). Returns ------- @@ -80,14 +167,35 @@ def list_gauges( api_path = '/usage/gauges' 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) + if metrics is None: + raise AppwriteException('Missing required parameter: "metrics"') + + + api_params['metrics'] = self._normalize_value(metrics) + if resource_id is not None: + api_params['resourceId'] = self._normalize_value(resource_id) + if team_id is not None: + api_params['teamId'] = self._normalize_value(team_id) + if interval is not None: + api_params['interval'] = self._normalize_value(interval) + if dimensions is not None: + api_params['dimensions'] = self._normalize_value(dimensions) + if start_at is not None: + api_params['startAt'] = self._normalize_value(start_at) + if end_at is not None: + api_params['endAt'] = self._normalize_value(end_at) + if order_by is not None: + api_params['orderBy'] = self._normalize_value(order_by) + if order_dir is not None: + api_params['orderDir'] = self._normalize_value(order_dir) + if limit is not None: + api_params['limit'] = self._normalize_value(limit) + if offset is not None: + api_params['offset'] = self._normalize_value(offset) 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=UsageGaugeList) diff --git a/appwrite/services/users.py b/appwrite/services/users.py index 705c111c..00bd630f 100644 --- a/appwrite/services/users.py +++ b/appwrite/services/users.py @@ -73,6 +73,7 @@ def list( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', }, api_params) return UserList.with_data(response, model_type) @@ -134,6 +135,7 @@ def create( 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 User.with_data(response, model_type) @@ -196,6 +198,7 @@ def create_argon2_user( 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 User.with_data(response, model_type) @@ -258,6 +261,7 @@ def create_bcrypt_user( 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 User.with_data(response, model_type) @@ -304,6 +308,7 @@ def list_identities( 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=IdentityList) @@ -405,6 +410,7 @@ def create_md5_user( 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 User.with_data(response, model_type) @@ -467,6 +473,7 @@ def create_ph_pass_user( 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 User.with_data(response, model_type) @@ -564,6 +571,7 @@ def create_scrypt_user( 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 User.with_data(response, model_type) @@ -647,6 +655,7 @@ def create_scrypt_modified_user( 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 User.with_data(response, model_type) @@ -714,6 +723,7 @@ def create_sha_user( 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 User.with_data(response, model_type) @@ -756,6 +766,7 @@ def get( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', }, api_params) return User.with_data(response, model_type) @@ -845,6 +856,7 @@ def update_email( 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 User.with_data(response, model_type) @@ -896,6 +908,7 @@ def update_impersonator( 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 User.with_data(response, model_type) @@ -945,6 +958,7 @@ def create_jwt( 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=Jwt) @@ -997,6 +1011,7 @@ def update_labels( 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 User.with_data(response, model_type) @@ -1045,6 +1060,7 @@ def list_logs( 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=LogList) @@ -1098,6 +1114,7 @@ def list_memberships( 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=MembershipList) @@ -1148,6 +1165,7 @@ def update_mfa( 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 User.with_data(response, model_type) @@ -1232,6 +1250,7 @@ def list_mfa_factors( 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=MfaFactors) @@ -1270,6 +1289,7 @@ def get_mfa_recovery_codes( 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=MfaRecoveryCodes) @@ -1309,6 +1329,7 @@ def update_mfa_recovery_codes( 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=MfaRecoveryCodes) @@ -1348,6 +1369,7 @@ def create_mfa_recovery_codes( 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=MfaRecoveryCodes) @@ -1398,6 +1420,7 @@ def update_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 User.with_data(response, model_type) @@ -1448,6 +1471,7 @@ def update_password( 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 User.with_data(response, model_type) @@ -1498,6 +1522,7 @@ def update_phone( 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 User.with_data(response, model_type) @@ -1540,6 +1565,7 @@ def get_prefs( response = self.client.call('get', api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', }, api_params) return Preferences.with_data(response, model_type) @@ -1590,6 +1616,7 @@ def update_prefs( 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 Preferences.with_data(response, model_type) @@ -1633,6 +1660,7 @@ def list_sessions( 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=SessionList) @@ -1674,6 +1702,7 @@ def create_session( 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) @@ -1809,6 +1838,7 @@ def update_status( 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 User.with_data(response, model_type) @@ -1857,6 +1887,7 @@ def list_targets( 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=TargetList) @@ -1927,6 +1958,7 @@ def create_target( 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=Target) @@ -1972,6 +2004,7 @@ def get_target( 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=Target) @@ -2033,6 +2066,7 @@ def update_target( 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=Target) @@ -2129,6 +2163,7 @@ def create_token( 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) @@ -2179,6 +2214,7 @@ def update_email_verification( 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 User.with_data(response, model_type) @@ -2229,6 +2265,7 @@ def update_phone_verification( 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 User.with_data(response, model_type) diff --git a/appwrite/services/webhooks.py b/appwrite/services/webhooks.py index d4abdcd3..b9c99e8e 100644 --- a/appwrite/services/webhooks.py +++ b/appwrite/services/webhooks.py @@ -47,6 +47,7 @@ def list( 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=WebhookList) @@ -131,6 +132,7 @@ def create( 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=Webhook) @@ -169,6 +171,7 @@ def get( 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=Webhook) @@ -249,6 +252,7 @@ def update( 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=Webhook) @@ -331,6 +335,7 @@ def update_secret( 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=Webhook) diff --git a/docs/examples/account/create.md b/docs/examples/account/create.md index 87c8faba..503b3701 100644 --- a/docs/examples/account/create.md +++ b/docs/examples/account/create.md @@ -13,7 +13,7 @@ account = Account(client) result: User = account.create( user_id = '', email = 'email@example.com', - password = '', + password = 'password', name = '' # optional ) diff --git a/docs/examples/account/update-password.md b/docs/examples/account/update-password.md index e93a5aa4..2c6db58b 100644 --- a/docs/examples/account/update-password.md +++ b/docs/examples/account/update-password.md @@ -11,8 +11,8 @@ client.set_session('') # The user session to authenticate with account = Account(client) result: User = account.update_password( - password = '', - old_password = '' # optional + password = 'password', + old_password = 'password' # optional ) print(result.model_dump()) diff --git a/docs/examples/account/update-recovery.md b/docs/examples/account/update-recovery.md index 90ed3096..3201722e 100644 --- a/docs/examples/account/update-recovery.md +++ b/docs/examples/account/update-recovery.md @@ -13,7 +13,7 @@ account = Account(client) result: Token = account.update_recovery( user_id = '', secret = '', - password = '' + password = 'password' ) print(result.model_dump()) diff --git a/docs/examples/apps/create-secret.md b/docs/examples/apps/create-secret.md new file mode 100644 index 00000000..3c901c7e --- /dev/null +++ b/docs/examples/apps/create-secret.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.apps import Apps +from appwrite.models import AppSecretPlaintext + +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 + +apps = Apps(client) + +result: AppSecretPlaintext = apps.create_secret( + app_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/apps/create.md b/docs/examples/apps/create.md new file mode 100644 index 00000000..04524904 --- /dev/null +++ b/docs/examples/apps/create.md @@ -0,0 +1,36 @@ +```python +from appwrite.client import Client +from appwrite.services.apps import Apps +from appwrite.models import App + +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 + +apps = Apps(client) + +result: App = apps.create( + app_id = '', + name = '', + redirect_uris = [], + description = '', # optional + client_uri = 'https://example.com', # optional + logo_uri = 'https://example.com', # optional + privacy_policy_url = 'https://example.com', # optional + terms_url = 'https://example.com', # optional + contacts = [], # optional + tagline = '', # optional + tags = [], # optional + images = [], # optional + support_url = 'https://example.com', # optional + data_deletion_url = 'https://example.com', # optional + post_logout_redirect_uris = [], # optional + enabled = False, # optional + type = 'public', # optional + device_flow = False, # optional + team_id = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/apps/delete-secret.md b/docs/examples/apps/delete-secret.md new file mode 100644 index 00000000..ae7f0976 --- /dev/null +++ b/docs/examples/apps/delete-secret.md @@ -0,0 +1,16 @@ +```python +from appwrite.client import Client +from appwrite.services.apps import Apps + +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 + +apps = Apps(client) + +result = apps.delete_secret( + app_id = '', + secret_id = '' +) +``` diff --git a/docs/examples/apps/delete-tokens.md b/docs/examples/apps/delete-tokens.md new file mode 100644 index 00000000..60c7f6ff --- /dev/null +++ b/docs/examples/apps/delete-tokens.md @@ -0,0 +1,15 @@ +```python +from appwrite.client import Client +from appwrite.services.apps import Apps + +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 + +apps = Apps(client) + +result = apps.delete_tokens( + app_id = '' +) +``` diff --git a/docs/examples/apps/delete.md b/docs/examples/apps/delete.md new file mode 100644 index 00000000..2318e2ef --- /dev/null +++ b/docs/examples/apps/delete.md @@ -0,0 +1,15 @@ +```python +from appwrite.client import Client +from appwrite.services.apps import Apps + +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 + +apps = Apps(client) + +result = apps.delete( + app_id = '' +) +``` diff --git a/docs/examples/apps/get-secret.md b/docs/examples/apps/get-secret.md new file mode 100644 index 00000000..deaea447 --- /dev/null +++ b/docs/examples/apps/get-secret.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.apps import Apps +from appwrite.models import AppSecret + +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 + +apps = Apps(client) + +result: AppSecret = apps.get_secret( + app_id = '', + secret_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/apps/get.md b/docs/examples/apps/get.md new file mode 100644 index 00000000..05a82fdc --- /dev/null +++ b/docs/examples/apps/get.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.apps import Apps +from appwrite.models import App + +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 + +apps = Apps(client) + +result: App = apps.get( + app_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/apps/list-secrets.md b/docs/examples/apps/list-secrets.md new file mode 100644 index 00000000..83a4dcd3 --- /dev/null +++ b/docs/examples/apps/list-secrets.md @@ -0,0 +1,20 @@ +```python +from appwrite.client import Client +from appwrite.services.apps import Apps +from appwrite.models import AppSecretList + +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 + +apps = Apps(client) + +result: AppSecretList = apps.list_secrets( + app_id = '', + queries = [], # optional + total = False # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/apps/list.md b/docs/examples/apps/list.md new file mode 100644 index 00000000..d8edd5f4 --- /dev/null +++ b/docs/examples/apps/list.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.apps import Apps +from appwrite.models import AppsList + +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 + +apps = Apps(client) + +result: AppsList = apps.list( + queries = [], # optional + total = False # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/apps/update-team.md b/docs/examples/apps/update-team.md new file mode 100644 index 00000000..44203fff --- /dev/null +++ b/docs/examples/apps/update-team.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.apps import Apps +from appwrite.models import App + +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 + +apps = Apps(client) + +result: App = apps.update_team( + app_id = '', + team_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/apps/update.md b/docs/examples/apps/update.md new file mode 100644 index 00000000..49c85efb --- /dev/null +++ b/docs/examples/apps/update.md @@ -0,0 +1,35 @@ +```python +from appwrite.client import Client +from appwrite.services.apps import Apps +from appwrite.models import App + +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 + +apps = Apps(client) + +result: App = apps.update( + app_id = '', + name = '', + description = '', # optional + client_uri = 'https://example.com', # optional + logo_uri = 'https://example.com', # optional + privacy_policy_url = 'https://example.com', # optional + terms_url = 'https://example.com', # optional + contacts = [], # optional + tagline = '', # optional + tags = [], # optional + images = [], # optional + support_url = 'https://example.com', # optional + data_deletion_url = 'https://example.com', # optional + enabled = False, # optional + redirect_uris = [], # optional + post_logout_redirect_uris = [], # optional + type = 'public', # optional + device_flow = False # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/messaging/create-smtp-provider.md b/docs/examples/messaging/create-smtp-provider.md index 55e5b6ea..fd5995f2 100644 --- a/docs/examples/messaging/create-smtp-provider.md +++ b/docs/examples/messaging/create-smtp-provider.md @@ -17,7 +17,7 @@ result: Provider = messaging.create_smtp_provider( host = '', port = 1, # optional username = '', # optional - password = '', # optional + password = 'password', # optional encryption = SmtpEncryption.NONE, # optional auto_tls = False, # optional mailer = '', # optional diff --git a/docs/examples/messaging/update-smtp-provider.md b/docs/examples/messaging/update-smtp-provider.md index b4712500..23294e88 100644 --- a/docs/examples/messaging/update-smtp-provider.md +++ b/docs/examples/messaging/update-smtp-provider.md @@ -17,7 +17,7 @@ result: Provider = messaging.update_smtp_provider( host = '', # optional port = 1, # optional username = '', # optional - password = '', # optional + password = 'password', # optional encryption = SmtpEncryption.NONE, # optional auto_tls = False, # optional mailer = '', # optional diff --git a/docs/examples/oauth2/approve.md b/docs/examples/oauth2/approve.md new file mode 100644 index 00000000..b3313599 --- /dev/null +++ b/docs/examples/oauth2/approve.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.oauth2 import Oauth2 +from appwrite.models import Oauth2Approve + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_session('') # The user session to authenticate with +client.set_project('') # Your project ID + +oauth2 = Oauth2(client) + +result: Oauth2Approve = oauth2.approve( + grant_id = '', + authorization_details = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/oauth2/authorize.md b/docs/examples/oauth2/authorize.md new file mode 100644 index 00000000..3ea83a66 --- /dev/null +++ b/docs/examples/oauth2/authorize.md @@ -0,0 +1,28 @@ +```python +from appwrite.client import Client +from appwrite.services.oauth2 import Oauth2 +from appwrite.models import Oauth2Authorize + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_session('') # The user session to authenticate with +client.set_project('') # Your project ID + +oauth2 = Oauth2(client) + +result: Oauth2Authorize = oauth2.authorize( + client_id = '', + redirect_uri = 'https://example.com', + response_type = 'code', + scope = '', + state = '', # optional + nonce = '', # optional + code_challenge = '', # optional + code_challenge_method = 's256', # optional + prompt = '', # optional + max_age = 0, # optional + authorization_details = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/oauth2/create-device-authorization.md b/docs/examples/oauth2/create-device-authorization.md new file mode 100644 index 00000000..4ba20f77 --- /dev/null +++ b/docs/examples/oauth2/create-device-authorization.md @@ -0,0 +1,20 @@ +```python +from appwrite.client import Client +from appwrite.services.oauth2 import Oauth2 +from appwrite.models import Oauth2DeviceAuthorization + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_session('') # The user session to authenticate with +client.set_project('') # Your project ID + +oauth2 = Oauth2(client) + +result: Oauth2DeviceAuthorization = oauth2.create_device_authorization( + client_id = '', # optional + scope = '', # optional + authorization_details = '' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/oauth2/create-grant.md b/docs/examples/oauth2/create-grant.md new file mode 100644 index 00000000..1a87716c --- /dev/null +++ b/docs/examples/oauth2/create-grant.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.oauth2 import Oauth2 +from appwrite.models import Oauth2Grant + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_session('') # The user session to authenticate with +client.set_project('') # Your project ID + +oauth2 = Oauth2(client) + +result: Oauth2Grant = oauth2.create_grant( + user_code = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/oauth2/create-token.md b/docs/examples/oauth2/create-token.md new file mode 100644 index 00000000..ac698593 --- /dev/null +++ b/docs/examples/oauth2/create-token.md @@ -0,0 +1,25 @@ +```python +from appwrite.client import Client +from appwrite.services.oauth2 import Oauth2 +from appwrite.models import Oauth2Token + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_session('') # The user session to authenticate with +client.set_project('') # Your project ID + +oauth2 = Oauth2(client) + +result: Oauth2Token = oauth2.create_token( + grant_type = '', + code = '', # optional + refresh_token = '', # optional + device_code = '', # optional + client_id = '', # optional + client_secret = '', # optional + code_verifier = '', # optional + redirect_uri = 'https://example.com' # optional +) + +print(result.model_dump()) +``` diff --git a/docs/examples/oauth2/get-grant.md b/docs/examples/oauth2/get-grant.md new file mode 100644 index 00000000..51f617f4 --- /dev/null +++ b/docs/examples/oauth2/get-grant.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.oauth2 import Oauth2 +from appwrite.models import Oauth2Grant + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_session('') # The user session to authenticate with +client.set_project('') # Your project ID + +oauth2 = Oauth2(client) + +result: Oauth2Grant = oauth2.get_grant( + grant_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/oauth2/reject.md b/docs/examples/oauth2/reject.md new file mode 100644 index 00000000..63f3335f --- /dev/null +++ b/docs/examples/oauth2/reject.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.oauth2 import Oauth2 +from appwrite.models import Oauth2Reject + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_session('') # The user session to authenticate with +client.set_project('') # Your project ID + +oauth2 = Oauth2(client) + +result: Oauth2Reject = oauth2.reject( + grant_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/oauth2/revoke.md b/docs/examples/oauth2/revoke.md new file mode 100644 index 00000000..70b94f6d --- /dev/null +++ b/docs/examples/oauth2/revoke.md @@ -0,0 +1,18 @@ +```python +from appwrite.client import Client +from appwrite.services.oauth2 import Oauth2 + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_session('') # The user session to authenticate with +client.set_project('') # Your project ID + +oauth2 = Oauth2(client) + +result = oauth2.revoke( + token = '', + token_type_hint = 'access_token', # optional + client_id = '', # optional + client_secret = '' # optional +) +``` diff --git a/docs/examples/project/get-policy.md b/docs/examples/project/get-policy.md index a26145e1..f9487669 100644 --- a/docs/examples/project/get-policy.md +++ b/docs/examples/project/get-policy.md @@ -14,6 +14,7 @@ from appwrite.models import PolicyMembershipPrivacy from appwrite.models import PolicyDenyAliasedEmail from appwrite.models import PolicyDenyDisposableEmail from appwrite.models import PolicyDenyFreeEmail +from appwrite.models import PolicyDenyCorporateEmail from typing import Union from appwrite.enums import ProjectPolicyId @@ -24,7 +25,7 @@ client.set_key('') # Your secret API key project = Project(client) -result: Union[PolicyPasswordDictionary, PolicyPasswordHistory, PolicyPasswordStrength, PolicyPasswordPersonalData, PolicySessionAlert, PolicySessionDuration, PolicySessionInvalidation, PolicySessionLimit, PolicyUserLimit, PolicyMembershipPrivacy, PolicyDenyAliasedEmail, PolicyDenyDisposableEmail, PolicyDenyFreeEmail] = project.get_policy( +result: Union[PolicyPasswordDictionary, PolicyPasswordHistory, PolicyPasswordStrength, PolicyPasswordPersonalData, PolicySessionAlert, PolicySessionDuration, PolicySessionInvalidation, PolicySessionLimit, PolicyUserLimit, PolicyMembershipPrivacy, PolicyDenyAliasedEmail, PolicyDenyDisposableEmail, PolicyDenyFreeEmail, PolicyDenyCorporateEmail] = project.get_policy( policy_id = ProjectPolicyId.PASSWORD_DICTIONARY ) diff --git a/docs/examples/project/update-deny-corporate-email-policy.md b/docs/examples/project/update-deny-corporate-email-policy.md new file mode 100644 index 00000000..21f4f8a6 --- /dev/null +++ b/docs/examples/project/update-deny-corporate-email-policy.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.update_deny_corporate_email_policy( + enabled = False +) + +print(result.model_dump()) +``` diff --git a/docs/examples/project/update-membership-privacy-policy.md b/docs/examples/project/update-membership-privacy-policy.md index 733699b1..f6878ee4 100644 --- a/docs/examples/project/update-membership-privacy-policy.md +++ b/docs/examples/project/update-membership-privacy-policy.md @@ -15,7 +15,8 @@ result: ProjectModel = project.update_membership_privacy_policy( user_email = False, # optional user_phone = False, # optional user_name = False, # optional - user_mfa = False # optional + user_mfa = False, # optional + user_accessed_at = False # optional ) print(result.model_dump()) diff --git a/docs/examples/project/update-o-auth-2-server.md b/docs/examples/project/update-o-auth-2-server.md index 91334190..6c5b2578 100644 --- a/docs/examples/project/update-o-auth-2-server.md +++ b/docs/examples/project/update-o-auth-2-server.md @@ -14,11 +14,16 @@ result: ProjectModel = project.update_o_auth2_server( enabled = False, authorization_url = 'https://example.com', scopes = [], # optional + authorization_details_types = [], # optional access_token_duration = 60, # optional refresh_token_duration = 60, # optional public_access_token_duration = 60, # optional public_refresh_token_duration = 60, # optional - confidential_pkce = False # optional + confidential_pkce = False, # optional + verification_url = 'https://example.com', # optional + user_code_length = 6, # optional + user_code_format = 'numeric', # optional + device_code_duration = 60 # optional ) print(result.model_dump()) diff --git a/docs/examples/project/update-smtp.md b/docs/examples/project/update-smtp.md index 66428e01..b5f7847b 100644 --- a/docs/examples/project/update-smtp.md +++ b/docs/examples/project/update-smtp.md @@ -15,7 +15,7 @@ result: ProjectModel = project.update_smtp( host = '', # optional port = None, # optional username = '', # optional - password = '', # optional + password = 'password', # optional sender_email = 'email@example.com', # optional sender_name = '', # optional reply_to_email = 'email@example.com', # optional diff --git a/docs/examples/tablesdb/create.md b/docs/examples/tablesdb/create.md index fb6bf0fb..c50f28e7 100644 --- a/docs/examples/tablesdb/create.md +++ b/docs/examples/tablesdb/create.md @@ -13,7 +13,8 @@ tables_db = TablesDB(client) result: Database = tables_db.create( database_id = '', name = '', - enabled = False # optional + enabled = False, # optional + dedicated_database_id = '' # optional ) print(result.model_dump()) diff --git a/docs/examples/usage/list-events.md b/docs/examples/usage/list-events.md index d3ab1d25..83f8d725 100644 --- a/docs/examples/usage/list-events.md +++ b/docs/examples/usage/list-events.md @@ -11,8 +11,17 @@ client.set_key('') # Your secret API key usage = Usage(client) result: UsageEventList = usage.list_events( - queries = [], # optional - total = False # optional + metrics = [], + resource = '', # optional + resource_id = '', # optional + interval = '1m', # optional + dimensions = [], # optional + start_at = '2020-10-15T06:38:00.000+00:00', # optional + end_at = '2020-10-15T06:38:00.000+00:00', # optional + order_by = 'time', # optional + order_dir = 'asc', # optional + limit = 1, # optional + offset = 0 # optional ) print(result.model_dump()) diff --git a/docs/examples/usage/list-gauges.md b/docs/examples/usage/list-gauges.md index 2904b968..fb221f9a 100644 --- a/docs/examples/usage/list-gauges.md +++ b/docs/examples/usage/list-gauges.md @@ -11,8 +11,17 @@ client.set_key('') # Your secret API key usage = Usage(client) result: UsageGaugeList = usage.list_gauges( - queries = [], # optional - total = False # optional + metrics = [], + resource_id = '', # optional + team_id = '', # optional + interval = '1m', # optional + dimensions = [], # optional + start_at = '2020-10-15T06:38:00.000+00:00', # optional + end_at = '2020-10-15T06:38:00.000+00:00', # optional + order_by = 'time', # optional + order_dir = 'asc', # optional + limit = 1, # optional + offset = 0 # optional ) print(result.model_dump()) diff --git a/docs/examples/users/create.md b/docs/examples/users/create.md index 38361cbf..0a7a7eee 100644 --- a/docs/examples/users/create.md +++ b/docs/examples/users/create.md @@ -14,7 +14,7 @@ result: User = users.create( user_id = '', email = 'email@example.com', # optional phone = '+12065550100', # optional - password = '', # optional + password = 'password', # optional name = '' # optional ) diff --git a/docs/examples/users/update-password.md b/docs/examples/users/update-password.md index 2a0c9323..d0238ec3 100644 --- a/docs/examples/users/update-password.md +++ b/docs/examples/users/update-password.md @@ -12,7 +12,7 @@ users = Users(client) result: User = users.update_password( user_id = '', - password = '' + password = 'password' ) print(result.model_dump()) diff --git a/docs/examples/webhooks/create.md b/docs/examples/webhooks/create.md index d0292221..53d45317 100644 --- a/docs/examples/webhooks/create.md +++ b/docs/examples/webhooks/create.md @@ -18,7 +18,7 @@ result: Webhook = webhooks.create( enabled = False, # optional tls = False, # optional auth_username = '', # optional - auth_password = '', # optional + auth_password = 'password', # optional secret = '' # optional ) diff --git a/docs/examples/webhooks/update.md b/docs/examples/webhooks/update.md index 626d793c..b399d55c 100644 --- a/docs/examples/webhooks/update.md +++ b/docs/examples/webhooks/update.md @@ -18,7 +18,7 @@ result: Webhook = webhooks.update( enabled = False, # optional tls = False, # optional auth_username = '', # optional - auth_password = '' # optional + auth_password = 'password' # optional ) print(result.model_dump()) diff --git a/pyproject.toml b/pyproject.toml index 80db5e40..64acd0d7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "appwrite" -version = "20.1.0" +version = "21.0.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 9fdc9256..bedddde5 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ setuptools.setup( name = 'appwrite', packages = setuptools.find_packages(), - version = '20.1.0', + version = '21.0.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/20.1.0.tar.gz', + download_url='https://github.com/appwrite/sdk-for-python/archive/21.0.0.tar.gz', install_requires=[ 'requests', 'pydantic>=2,<3', diff --git a/test/services/test_account.py b/test/services/test_account.py index ccf075df..4ab80f3b 100644 --- a/test/services/test_account.py +++ b/test/services/test_account.py @@ -67,7 +67,7 @@ def test_create(self, m): response = self.account.create( '', 'email@example.com', - '', + 'password', ) self.assertEqual(response.to_dict(), data) @@ -581,7 +581,7 @@ def test_update_password(self, m): m.request(requests_mock.ANY, requests_mock.ANY, text=json.dumps(data), headers=headers) response = self.account.update_password( - '', + 'password', ) self.assertEqual(response.to_dict(), data) @@ -693,7 +693,7 @@ def test_update_recovery(self, m): response = self.account.update_recovery( '', '', - '', + 'password', ) self.assertEqual(response.to_dict(), data) diff --git a/test/services/test_activities.py b/test/services/test_activities.py index a96b831f..41d9d8b1 100644 --- a/test/services/test_activities.py +++ b/test/services/test_activities.py @@ -48,18 +48,6 @@ def test_get_event(self, m): "projectId": "610fc2f985ee0", "teamId": "610fc2f985ee0", "hostname": "appwrite.io", - "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" } diff --git a/test/services/test_apps.py b/test/services/test_apps.py new file mode 100644 index 00000000..a8d5984d --- /dev/null +++ b/test/services/test_apps.py @@ -0,0 +1,272 @@ +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.apps import Apps + +class AppsServiceTest(unittest.TestCase): + + def setUp(self): + self.client = Client() + self.apps = Apps(self.client) + + @requests_mock.Mocker() + def test_list(self, m): + data = { + "total": 5.0, + "apps": [] +} + headers = {'Content-Type': 'application/json'} + m.request(requests_mock.ANY, requests_mock.ANY, text=json.dumps(data), headers=headers) + + response = self.apps.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", + "name": "My Application", + "description": "Connect your workspace to My Application.", + "clientUri": "https:\/\/example.com", + "logoUri": "https:\/\/example.com\/logo.png", + "privacyPolicyUrl": "https:\/\/example.com\/privacy", + "termsUrl": "https:\/\/example.com\/terms", + "contacts": [], + "tagline": "Automate your workspace.", + "tags": [], + "images": [], + "supportUrl": "https:\/\/example.com\/support", + "dataDeletionUrl": "https:\/\/example.com\/data-deletion", + "redirectUris": [], + "postLogoutRedirectUris": [], + "enabled": True, + "type": "confidential", + "deviceFlow": True, + "teamId": "5e5ea5c16897e", + "userId": "5e5ea5c16897e", + "secrets": [] +} + headers = {'Content-Type': 'application/json'} + m.request(requests_mock.ANY, requests_mock.ANY, text=json.dumps(data), headers=headers) + + response = self.apps.create( + '', + '', + [], + ) + + 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", + "name": "My Application", + "description": "Connect your workspace to My Application.", + "clientUri": "https:\/\/example.com", + "logoUri": "https:\/\/example.com\/logo.png", + "privacyPolicyUrl": "https:\/\/example.com\/privacy", + "termsUrl": "https:\/\/example.com\/terms", + "contacts": [], + "tagline": "Automate your workspace.", + "tags": [], + "images": [], + "supportUrl": "https:\/\/example.com\/support", + "dataDeletionUrl": "https:\/\/example.com\/data-deletion", + "redirectUris": [], + "postLogoutRedirectUris": [], + "enabled": True, + "type": "confidential", + "deviceFlow": True, + "teamId": "5e5ea5c16897e", + "userId": "5e5ea5c16897e", + "secrets": [] +} + headers = {'Content-Type': 'application/json'} + m.request(requests_mock.ANY, requests_mock.ANY, text=json.dumps(data), headers=headers) + + response = self.apps.get( + '', + ) + + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_update(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 Application", + "description": "Connect your workspace to My Application.", + "clientUri": "https:\/\/example.com", + "logoUri": "https:\/\/example.com\/logo.png", + "privacyPolicyUrl": "https:\/\/example.com\/privacy", + "termsUrl": "https:\/\/example.com\/terms", + "contacts": [], + "tagline": "Automate your workspace.", + "tags": [], + "images": [], + "supportUrl": "https:\/\/example.com\/support", + "dataDeletionUrl": "https:\/\/example.com\/data-deletion", + "redirectUris": [], + "postLogoutRedirectUris": [], + "enabled": True, + "type": "confidential", + "deviceFlow": True, + "teamId": "5e5ea5c16897e", + "userId": "5e5ea5c16897e", + "secrets": [] +} + headers = {'Content-Type': 'application/json'} + m.request(requests_mock.ANY, requests_mock.ANY, text=json.dumps(data), headers=headers) + + response = self.apps.update( + '', + '', + ) + + 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.apps.delete( + '', + ) + + self.assertEqual(response, data) + + @requests_mock.Mocker() + def test_list_secrets(self, m): + data = { + "total": 5.0, + "secrets": [] +} + headers = {'Content-Type': 'application/json'} + m.request(requests_mock.ANY, requests_mock.ANY, text=json.dumps(data), headers=headers) + + response = self.apps.list_secrets( + '', + ) + + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_secret(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "appId": "5e5ea5c16897e", + "secret": "5f3c8d2a1b9e4f7a6c8b2d1e9f4a7b3c5d8e1f2a9b4c7d6e3f5a8b1c4d7e2f9a", + "hint": "f5c6c7", + "createdById": "5e5ea5c16897e", + "createdByName": "Walter White" +} + headers = {'Content-Type': 'application/json'} + m.request(requests_mock.ANY, requests_mock.ANY, text=json.dumps(data), headers=headers) + + response = self.apps.create_secret( + '', + ) + + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_get_secret(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "appId": "5e5ea5c16897e", + "secret": "$argon2i$v=19$m=16,t=2,p=1$MTIzMTIzMTIzMTIzMQ$3\/ZUl3IWERBO2RIm5rHltg", + "hint": "f5c6c7", + "createdById": "5e5ea5c16897e", + "createdByName": "Walter White" +} + headers = {'Content-Type': 'application/json'} + m.request(requests_mock.ANY, requests_mock.ANY, text=json.dumps(data), headers=headers) + + response = self.apps.get_secret( + '', + '', + ) + + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_delete_secret(self, m): + data = '' + headers = {'Content-Type': 'application/json'} + m.request(requests_mock.ANY, requests_mock.ANY, text=json.dumps(data), headers=headers) + + response = self.apps.delete_secret( + '', + '', + ) + + 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", + "name": "My Application", + "description": "Connect your workspace to My Application.", + "clientUri": "https:\/\/example.com", + "logoUri": "https:\/\/example.com\/logo.png", + "privacyPolicyUrl": "https:\/\/example.com\/privacy", + "termsUrl": "https:\/\/example.com\/terms", + "contacts": [], + "tagline": "Automate your workspace.", + "tags": [], + "images": [], + "supportUrl": "https:\/\/example.com\/support", + "dataDeletionUrl": "https:\/\/example.com\/data-deletion", + "redirectUris": [], + "postLogoutRedirectUris": [], + "enabled": True, + "type": "confidential", + "deviceFlow": True, + "teamId": "5e5ea5c16897e", + "userId": "5e5ea5c16897e", + "secrets": [] +} + headers = {'Content-Type': 'application/json'} + m.request(requests_mock.ANY, requests_mock.ANY, text=json.dumps(data), headers=headers) + + response = self.apps.update_team( + '', + '', + ) + + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_delete_tokens(self, m): + data = '' + headers = {'Content-Type': 'application/json'} + m.request(requests_mock.ANY, requests_mock.ANY, text=json.dumps(data), headers=headers) + + response = self.apps.delete_tokens( + '', + ) + + self.assertEqual(response, data) + diff --git a/test/services/test_backups.py b/test/services/test_backups.py index f9413c2d..83c59835 100644 --- a/test/services/test_backups.py +++ b/test/services/test_backups.py @@ -110,6 +110,7 @@ def test_create_policy(self, m): "resources": [], "retention": 7.0, "schedule": "0 * * * *", + "type": "full", "enabled": True } headers = {'Content-Type': 'application/json'} @@ -135,6 +136,7 @@ def test_get_policy(self, m): "resources": [], "retention": 7.0, "schedule": "0 * * * *", + "type": "full", "enabled": True } headers = {'Content-Type': 'application/json'} @@ -157,6 +159,7 @@ def test_update_policy(self, m): "resources": [], "retention": 7.0, "schedule": "0 * * * *", + "type": "full", "enabled": True } headers = {'Content-Type': 'application/json'} diff --git a/test/services/test_oauth2.py b/test/services/test_oauth2.py new file mode 100644 index 00000000..4096d693 --- /dev/null +++ b/test/services/test_oauth2.py @@ -0,0 +1,157 @@ +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.oauth2 import Oauth2 + +class Oauth2ServiceTest(unittest.TestCase): + + def setUp(self): + self.client = Client() + self.oauth2 = Oauth2(self.client) + + @requests_mock.Mocker() + def test_approve(self, m): + data = { + "redirectUrl": "https:\/\/example.com\/callback?code=abcde&state=fghij" +} + headers = {'Content-Type': 'application/json'} + m.request(requests_mock.ANY, requests_mock.ANY, text=json.dumps(data), headers=headers) + + response = self.oauth2.approve( + '', + ) + + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_authorize(self, m): + data = { + "grantId": "5e5ea5c16897e", + "redirectUrl": "https:\/\/example.com\/callback?code=abcde&state=fghij" +} + headers = {'Content-Type': 'application/json'} + m.request(requests_mock.ANY, requests_mock.ANY, text=json.dumps(data), headers=headers) + + response = self.oauth2.authorize( + '', + 'https://example.com', + 'code', + '', + ) + + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_device_authorization(self, m): + data = { + "device_code": "5f3c8d2a1b9e4f7a6c8b2d1e9f4a7b3c5d8e1f2a9b4c7d6e3f5a8b1c4d7e2f9a", + "user_code": "ABCD-EFGH", + "verification_uri": "https:\/\/cloud.appwrite.io\/console\/oauth2\/device", + "verification_uri_complete": "https:\/\/cloud.appwrite.io\/console\/oauth2\/device?user_code=ABCD-EFGH", + "expires_in": 900.0, + "interval": 5.0 +} + headers = {'Content-Type': 'application/json'} + m.request(requests_mock.ANY, requests_mock.ANY, text=json.dumps(data), headers=headers) + + response = self.oauth2.create_device_authorization( + ) + + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_create_grant(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "userId": "5e5ea5c16897e", + "appId": "5e5ea5c16897e", + "scopes": [], + "authorizationDetails": "[{\"type\":\"calendar\",\"identifier\":\"primary\",\"actions\":[\"read_events\",\"create_event\"]}]", + "prompt": "login", + "redirectUri": "https:\/\/example.com\/callback", + "authTime": 1592981250.0, + "expire": "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.oauth2.create_grant( + '', + ) + + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_get_grant(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "userId": "5e5ea5c16897e", + "appId": "5e5ea5c16897e", + "scopes": [], + "authorizationDetails": "[{\"type\":\"calendar\",\"identifier\":\"primary\",\"actions\":[\"read_events\",\"create_event\"]}]", + "prompt": "login", + "redirectUri": "https:\/\/example.com\/callback", + "authTime": 1592981250.0, + "expire": "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.oauth2.get_grant( + '', + ) + + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_reject(self, m): + data = { + "redirectUrl": "https:\/\/example.com\/callback?error=access_denied&state=fghij" +} + headers = {'Content-Type': 'application/json'} + m.request(requests_mock.ANY, requests_mock.ANY, text=json.dumps(data), headers=headers) + + response = self.oauth2.reject( + '', + ) + + self.assertEqual(response.to_dict(), data) + + @requests_mock.Mocker() + def test_revoke(self, m): + data = '' + headers = {'Content-Type': 'application/json'} + m.request(requests_mock.ANY, requests_mock.ANY, text=json.dumps(data), headers=headers) + + response = self.oauth2.revoke( + '', + ) + + self.assertEqual(response, data) + + @requests_mock.Mocker() + def test_create_token(self, m): + data = { + "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...", + "token_type": "Bearer", + "expires_in": 3600.0, + "refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...", + "scope": "openid email profile" +} + headers = {'Content-Type': 'application/json'} + m.request(requests_mock.ANY, requests_mock.ANY, text=json.dumps(data), headers=headers) + + response = self.oauth2.create_token( + '', + ) + + self.assertEqual(response.to_dict(), data) + diff --git a/test/services/test_organization.py b/test/services/test_organization.py index ac221c35..a4e32d24 100644 --- a/test/services/test_organization.py +++ b/test/services/test_organization.py @@ -141,7 +141,7 @@ def test_create_project(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -151,16 +151,7 @@ def test_create_project(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -190,7 +181,7 @@ def test_get_project(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -200,16 +191,7 @@ def test_get_project(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -238,7 +220,7 @@ def test_update_project(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -248,16 +230,7 @@ def test_update_project(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) diff --git a/test/services/test_project.py b/test/services/test_project.py index 556761df..9440e29e 100644 --- a/test/services/test_project.py +++ b/test/services/test_project.py @@ -31,7 +31,7 @@ def test_get(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -41,16 +41,7 @@ def test_get(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -89,7 +80,7 @@ def test_update_auth_method(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -99,16 +90,7 @@ def test_update_auth_method(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -257,7 +239,7 @@ def test_update_labels(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -267,16 +249,7 @@ def test_update_labels(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -398,7 +371,7 @@ def test_update_o_auth2_server(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -408,16 +381,7 @@ def test_update_o_auth2_server(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -1421,7 +1385,7 @@ def test_update_deny_aliased_email_policy(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -1431,16 +1395,7 @@ def test_update_deny_aliased_email_policy(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -1451,6 +1406,45 @@ def test_update_deny_aliased_email_policy(self, m): self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() + def test_update_deny_corporate_email_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", + "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_deny_corporate_email_policy( + True, + ) + + self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() def test_update_deny_disposable_email_policy(self, m): data = { @@ -1469,7 +1463,7 @@ def test_update_deny_disposable_email_policy(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -1479,16 +1473,7 @@ def test_update_deny_disposable_email_policy(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -1517,7 +1502,7 @@ def test_update_deny_free_email_policy(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -1527,16 +1512,7 @@ def test_update_deny_free_email_policy(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -1565,7 +1541,7 @@ def test_update_membership_privacy_policy(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -1575,16 +1551,7 @@ def test_update_membership_privacy_policy(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -1612,7 +1579,7 @@ def test_update_password_dictionary_policy(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -1622,16 +1589,7 @@ def test_update_password_dictionary_policy(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -1660,7 +1618,7 @@ def test_update_password_history_policy(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -1670,16 +1628,7 @@ def test_update_password_history_policy(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -1708,7 +1657,7 @@ def test_update_password_personal_data_policy(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -1718,16 +1667,7 @@ def test_update_password_personal_data_policy(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -1774,7 +1714,7 @@ def test_update_session_alert_policy(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -1784,16 +1724,7 @@ def test_update_session_alert_policy(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -1822,7 +1753,7 @@ def test_update_session_duration_policy(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -1832,16 +1763,7 @@ def test_update_session_duration_policy(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -1870,7 +1792,7 @@ def test_update_session_invalidation_policy(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -1880,16 +1802,7 @@ def test_update_session_invalidation_policy(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -1918,7 +1831,7 @@ def test_update_session_limit_policy(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -1928,16 +1841,7 @@ def test_update_session_limit_policy(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -1966,7 +1870,7 @@ def test_update_user_limit_policy(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -1976,16 +1880,7 @@ def test_update_user_limit_policy(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -2029,7 +1924,7 @@ def test_update_protocol(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -2039,16 +1934,7 @@ def test_update_protocol(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -2078,7 +1964,7 @@ def test_update_service(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -2088,16 +1974,7 @@ def test_update_service(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) @@ -2127,7 +2004,7 @@ def test_update_smtp(self, m): "smtpHost": "mail.appwrite.io", "smtpPort": 25.0, "smtpUsername": "emailuser", - "smtpPassword": "", + "smtpPassword": "smtp-password", "smtpSecure": "tls", "pingCount": 1.0, "pingedAt": "2020-10-15T06:38:00.000+00:00", @@ -2137,16 +2014,7 @@ def test_update_smtp(self, m): "services": [], "protocols": [], "blocks": [], - "consoleAccessedAt": "2020-10-15T06:38:00.000+00:00", - "oAuth2ServerEnabled": True, - "oAuth2ServerAuthorizationUrl": "https:\/\/cloud.appwrite.io\/oauth2\/.well-known\/openid-configuration", - "oAuth2ServerScopes": [], - "oAuth2ServerAccessTokenDuration": 3600.0, - "oAuth2ServerRefreshTokenDuration": 86400.0, - "oAuth2ServerPublicAccessTokenDuration": 3600.0, - "oAuth2ServerPublicRefreshTokenDuration": 2592000.0, - "oAuth2ServerConfidentialPkce": True, - "oAuth2ServerDiscoveryUrl": "https:\/\/auth.example.com\/.well-known\/openid-configuration" + "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) diff --git a/test/services/test_teams.py b/test/services/test_teams.py index e83b1046..84688663 100644 --- a/test/services/test_teams.py +++ b/test/services/test_teams.py @@ -129,6 +129,7 @@ def test_create_membership(self, m): "joined": "2020-10-15T06:38:00.000+00:00", "confirm": True, "mfa": True, + "userAccessedAt": "2020-10-15T06:38:00.000+00:00", "roles": [] } headers = {'Content-Type': 'application/json'} @@ -157,6 +158,7 @@ def test_get_membership(self, m): "joined": "2020-10-15T06:38:00.000+00:00", "confirm": True, "mfa": True, + "userAccessedAt": "2020-10-15T06:38:00.000+00:00", "roles": [] } headers = {'Content-Type': 'application/json'} @@ -185,6 +187,7 @@ def test_update_membership(self, m): "joined": "2020-10-15T06:38:00.000+00:00", "confirm": True, "mfa": True, + "userAccessedAt": "2020-10-15T06:38:00.000+00:00", "roles": [] } headers = {'Content-Type': 'application/json'} @@ -227,6 +230,7 @@ def test_update_membership_status(self, m): "joined": "2020-10-15T06:38:00.000+00:00", "confirm": True, "mfa": True, + "userAccessedAt": "2020-10-15T06:38:00.000+00:00", "roles": [] } headers = {'Content-Type': 'application/json'} diff --git a/test/services/test_usage.py b/test/services/test_usage.py index 6f4617dc..d54ff32f 100644 --- a/test/services/test_usage.py +++ b/test/services/test_usage.py @@ -16,13 +16,14 @@ def setUp(self): @requests_mock.Mocker() def test_list_events(self, m): data = { - "total": 5.0, - "events": [] + "interval": "1d", + "metrics": [] } headers = {'Content-Type': 'application/json'} m.request(requests_mock.ANY, requests_mock.ANY, text=json.dumps(data), headers=headers) response = self.usage.list_events( + [], ) self.assertEqual(response.to_dict(), data) @@ -30,13 +31,14 @@ def test_list_events(self, m): @requests_mock.Mocker() def test_list_gauges(self, m): data = { - "total": 5.0, - "gauges": [] + "interval": "1d", + "metrics": [] } headers = {'Content-Type': 'application/json'} m.request(requests_mock.ANY, requests_mock.ANY, text=json.dumps(data), headers=headers) response = self.usage.list_gauges( + [], ) self.assertEqual(response.to_dict(), data) diff --git a/test/services/test_users.py b/test/services/test_users.py index 2ecc1c1b..cd4eb71f 100644 --- a/test/services/test_users.py +++ b/test/services/test_users.py @@ -741,7 +741,7 @@ def test_update_password(self, m): response = self.users.update_password( '', - '', + 'password', ) self.assertEqual(response.to_dict(), data) diff --git a/test/services/test_webhooks.py b/test/services/test_webhooks.py index eb7f1f13..c5e4e219 100644 --- a/test/services/test_webhooks.py +++ b/test/services/test_webhooks.py @@ -38,7 +38,7 @@ def test_create(self, m): "events": [], "tls": True, "authUsername": "username", - "authPassword": "password", + "authPassword": "webhook-password", "secret": "ad3d581ca230e2b7059c545e5a", "enabled": True, "logs": "Failed to connect to remote server.", @@ -67,7 +67,7 @@ def test_get(self, m): "events": [], "tls": True, "authUsername": "username", - "authPassword": "password", + "authPassword": "webhook-password", "secret": "ad3d581ca230e2b7059c545e5a", "enabled": True, "logs": "Failed to connect to remote server.", @@ -93,7 +93,7 @@ def test_update(self, m): "events": [], "tls": True, "authUsername": "username", - "authPassword": "password", + "authPassword": "webhook-password", "secret": "ad3d581ca230e2b7059c545e5a", "enabled": True, "logs": "Failed to connect to remote server.", @@ -134,7 +134,7 @@ def test_update_secret(self, m): "events": [], "tls": True, "authUsername": "username", - "authPassword": "password", + "authPassword": "webhook-password", "secret": "ad3d581ca230e2b7059c545e5a", "enabled": True, "logs": "Failed to connect to remote server.",