diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a41a9e4..099e71cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Change Log +## 27.1.0 + +* Added: `Apps` service for managing OAuth2 applications, keys, and installations +* Added: `OAuth2` service with authorize, grant, device authorization, and consent flows +* Added: `Account` OAuth2 consent methods `listConsents`, `getConsent`, `deleteConsent`, and consent token methods +* Added: app installation management methods to `Organization` and `Teams` services +* Added: `installationAccessTokenDuration` parameter to `Project::updateOAuth2Server` +* Added: `token` parameter to `Sites::getDeploymentDownload` +* Added: `oauth2.introspect` and organization installation key scopes + ## 27.0.0 * Breaking: Removed `Health` service with its models and enums diff --git a/docs/account.md b/docs/account.md index 31ac8d2e..7600b611 100644 --- a/docs/account.md +++ b/docs/account.md @@ -24,6 +24,89 @@ POST https://cloud.appwrite.io/v1/account | name | string | User name. Max length: 128 chars. | | +```http request +GET https://cloud.appwrite.io/v1/account/consents +``` + +** Get a list of the OAuth2 consents the current user has given to third-party apps. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| queries | array | 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 | boolean | When set to false, the total count returned will be 0 and will not be calculated. | 1 | + + +```http request +GET https://cloud.appwrite.io/v1/account/consents/{consentId} +``` + +** Get an OAuth2 consent the current user has given to a third-party app by its unique ID. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| consentId | string | **Required** Consent unique ID. | | + + +```http request +DELETE https://cloud.appwrite.io/v1/account/consents/{consentId} +``` + +** Delete an OAuth2 consent by its unique ID. All token families issued under the consent are revoked, and the app must ask for consent again to regain access. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| consentId | string | **Required** Consent unique ID. | | + + +```http request +GET https://cloud.appwrite.io/v1/account/consents/{consentId}/tokens +``` + +** Get a list of the token families issued under an OAuth2 consent. Each entry represents one authorized device or session; the token secrets themselves are never returned. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| consentId | string | **Required** Consent unique ID. | | +| queries | array | 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 | boolean | When set to false, the total count returned will be 0 and will not be calculated. | 1 | + + +```http request +GET https://cloud.appwrite.io/v1/account/consents/{consentId}/tokens/{tokenId} +``` + +** Get a token family issued under an OAuth2 consent by its unique ID. The token secrets themselves are never returned. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| consentId | string | **Required** Consent unique ID. | | +| tokenId | string | **Required** Token unique ID. | | + + +```http request +DELETE https://cloud.appwrite.io/v1/account/consents/{consentId}/tokens/{tokenId} +``` + +** Delete a token family issued under an OAuth2 consent by its unique ID. The access and refresh tokens of the family stop working immediately; other token families and the consent itself are unaffected. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| consentId | string | **Required** Consent unique ID. | | +| tokenId | string | **Required** Token unique ID. | | + + ```http request PATCH https://cloud.appwrite.io/v1/account/email ``` diff --git a/docs/apps.md b/docs/apps.md new file mode 100644 index 00000000..a8d9a2e8 --- /dev/null +++ b/docs/apps.md @@ -0,0 +1,315 @@ +# Apps Service + + +```http request +GET https://cloud.appwrite.io/v1/apps +``` + +** List applications. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| queries | array | 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 | boolean | When set to false, the total count returned will be 0 and will not be calculated. | 1 | + + +```http request +POST https://cloud.appwrite.io/v1/apps +``` + +** Create a new application. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| appId | string | 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 | string | Application name. | | +| description | string | Application description shown to users during OAuth2 consent. | | +| clientUri | string | Application homepage URL shown to users during OAuth2 consent. | | +| logoUri | string | Application logo URL shown to users during OAuth2 consent. | | +| privacyPolicyUrl | string | Application privacy policy URL shown to users during OAuth2 consent. | | +| termsUrl | string | Application terms of service URL shown to users during OAuth2 consent. | | +| contacts | array | Application support or security contact emails. Maximum of 100 contacts are allowed. | [] | +| tagline | string | Application tagline shown to users during OAuth2 consent. | | +| tags | array | Application tags shown to users during OAuth2 consent. Maximum of 100 tags are allowed, each up to 64 characters long. | [] | +| images | array | Application image URLs shown to users during OAuth2 consent. Maximum of 100 images are allowed. | [] | +| supportUrl | string | Application support URL shown to users during OAuth2 consent. | | +| dataDeletionUrl | string | Application data deletion URL shown to users during OAuth2 consent. | | +| redirectUris | array | Redirect URIs. Each must be an https URL, an http loopback URL (localhost, 127.0.0.1, [::1]), or a private-use scheme URI (e.g. com.example.app:/oauth), and must not contain a fragment. | | +| postLogoutRedirectUris | array | Post-logout redirect URIs for OpenID Connect RP-Initiated Logout. Each must be an https URL, an http loopback URL, or a private-use scheme URI, and must not contain a fragment. After ending the user session, the logout endpoint only redirects to URIs in this list. | [] | +| enabled | boolean | Is application enabled? | 1 | +| type | string | 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`. | confidential | +| deviceFlow | boolean | Allow this client to use the OAuth2 Device Authorization Grant (RFC 8628) for input-constrained devices such as TVs and CLIs. Defaults to false. | | +| teamId | string | Team unique ID. | | + + +```http request +GET https://cloud.appwrite.io/v1/apps/scopes/installations +``` + +** List scopes an application can request when installed on a team. ** + + +```http request +GET https://cloud.appwrite.io/v1/apps/scopes/oauth2 +``` + +** List scopes an application can request during the OAuth2 flow. ** + + +```http request +GET https://cloud.appwrite.io/v1/apps/{appId} +``` + +** Get an application by its unique ID. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| appId | string | **Required** Application unique ID or HTTPS client ID metadata document URL. | | + + +```http request +PUT https://cloud.appwrite.io/v1/apps/{appId} +``` + +** Update an application by its unique ID. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| appId | string | **Required** Application unique ID. | | +| name | string | Application name. | | +| description | string | Application description shown to users during OAuth2 consent. | | +| clientUri | string | Application homepage URL shown to users during OAuth2 consent. | | +| logoUri | string | Application logo URL shown to users during OAuth2 consent. | | +| privacyPolicyUrl | string | Application privacy policy URL shown to users during OAuth2 consent. | | +| termsUrl | string | Application terms of service URL shown to users during OAuth2 consent. | | +| contacts | array | Application support or security contact emails. Maximum of 100 contacts are allowed. | [] | +| tagline | string | Application tagline shown to users during OAuth2 consent. | | +| tags | array | Application tags shown to users during OAuth2 consent. Maximum of 100 tags are allowed, each up to 64 characters long. | [] | +| images | array | Application image URLs shown to users during OAuth2 consent. Maximum of 100 images are allowed. | [] | +| supportUrl | string | Application support URL shown to users during OAuth2 consent. | | +| dataDeletionUrl | string | Application data deletion URL shown to users during OAuth2 consent. | | +| enabled | boolean | Is application enabled? | 1 | +| redirectUris | array | Redirect URIs. Each must be an https URL, an http loopback URL (localhost, 127.0.0.1, [::1]), or a private-use scheme URI (e.g. com.example.app:/oauth), and must not contain a fragment. | [] | +| postLogoutRedirectUris | array | Post-logout redirect URIs for OpenID Connect RP-Initiated Logout. Each must be an https URL, an http loopback URL, or a private-use scheme URI, and must not contain a fragment. After ending the user session, the logout endpoint only redirects to URIs in this list. | [] | +| type | string | 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`. | confidential | +| deviceFlow | boolean | Allow this client to use the OAuth2 Device Authorization Grant (RFC 8628) for input-constrained devices such as TVs and CLIs. Defaults to false. | | +| installationScopes | array | Scopes the application requests when installed on a team. Organization-level and project-level scopes only; use the list scopes endpoint with `type=installation` to discover available values. Maximum of 100 scopes are allowed. | [] | +| installationRedirectUrl | string | URL users are redirected to after creating or updating an installation of this application. Must be an https URL, an http loopback URL (localhost, 127.0.0.1, [::1]), or a private-use scheme URI, and must not contain a fragment. Leave empty for no redirect. | | + + +```http request +DELETE https://cloud.appwrite.io/v1/apps/{appId} +``` + +** Delete an application by its unique ID. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| appId | string | **Required** Application unique ID. | | + + +```http request +GET https://cloud.appwrite.io/v1/apps/{appId}/installations +``` + +** List installations of an application. Requires an app key sent in the `X-Appwrite-Key` header alongside the `X-Appwrite-App` header. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| appId | string | **Required** Application unique ID. | | +| queries | array | 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 | boolean | When set to false, the total count returned will be 0 and will not be calculated. | 1 | + + +```http request +GET https://cloud.appwrite.io/v1/apps/{appId}/installations/{installationId} +``` + +** Get an installation of an application by its unique ID. Requires an app key sent in the `X-Appwrite-Key` header alongside the `X-Appwrite-App` header. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| appId | string | **Required** Application unique ID. | | +| installationId | string | **Required** Installation unique ID. | | + + +```http request +POST https://cloud.appwrite.io/v1/apps/{appId}/installations/{installationId}/tokens +``` + +** Create a token for an installation of an application. Requires an app key sent in the `X-Appwrite-Key` header alongside the `X-Appwrite-App` header. The returned token carries the scopes and authorization details granted to the installation, and can be used as an `Authorization: Bearer` header everywhere OAuth2 access tokens are accepted. Multiple tokens can be active for the same installation at once; each token stays valid until it expires or the installation is updated or deleted. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| appId | string | **Required** Application unique ID. | | +| installationId | string | **Required** Installation unique ID. | | + + +```http request +GET https://cloud.appwrite.io/v1/apps/{appId}/keys +``` + +** List app keys for an application. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| appId | string | **Required** Application unique ID. | | +| queries | array | 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 | boolean | When set to false, the total count returned will be 0 and will not be calculated. | 1 | + + +```http request +POST https://cloud.appwrite.io/v1/apps/{appId}/keys +``` + +** Create a new app key for an application. App keys carry no scopes; send one in the `X-Appwrite-Key` header alongside the `X-Appwrite-App` header to list the application's installations and create installation access tokens. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| appId | string | **Required** Application unique ID. | | + + +```http request +GET https://cloud.appwrite.io/v1/apps/{appId}/keys/{keyId} +``` + +** Get an app key by its unique ID. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| appId | string | **Required** Application unique ID. | | +| keyId | string | **Required** App key unique ID. | | + + +```http request +DELETE https://cloud.appwrite.io/v1/apps/{appId}/keys/{keyId} +``` + +** Delete an app key by its unique ID. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| appId | string | **Required** Application unique ID. | | +| keyId | string | **Required** App key unique ID. | | + + +```http request +PUT https://cloud.appwrite.io/v1/apps/{appId}/labels +``` + +** Update the labels of an application. Labels are read-only for clients; only a server SDK using a project API key can set them. Replaces the previous labels. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| appId | string | **Required** Application unique ID. | | +| labels | array | Array of application labels. Replaces the previous labels. Maximum of 1000 labels are allowed, each up to 36 alphanumeric characters long. | | + + +```http request +GET https://cloud.appwrite.io/v1/apps/{appId}/secrets +``` + +** List client secrets for an application. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| appId | string | **Required** Application unique ID. | | +| queries | array | 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 | boolean | When set to false, the total count returned will be 0 and will not be calculated. | 1 | + + +```http request +POST https://cloud.appwrite.io/v1/apps/{appId}/secrets +``` + +** Create a new client secret for an application. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| appId | string | **Required** Application unique ID. | | + + +```http request +GET https://cloud.appwrite.io/v1/apps/{appId}/secrets/{secretId} +``` + +** Get an application client secret by its unique ID. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| appId | string | **Required** Application unique ID. | | +| secretId | string | **Required** Secret unique ID. | | + + +```http request +DELETE https://cloud.appwrite.io/v1/apps/{appId}/secrets/{secretId} +``` + +** Delete an application client secret by its unique ID. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| appId | string | **Required** Application unique ID. | | +| secretId | string | **Required** Secret unique ID. | | + + +```http request +PATCH https://cloud.appwrite.io/v1/apps/{appId}/team +``` + +** Transfer an application to another team by its unique ID. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| appId | string | **Required** Application unique ID. | | +| teamId | string | Team ID of the team to transfer application to. | | + + +```http request +DELETE https://cloud.appwrite.io/v1/apps/{appId}/tokens +``` + +** Revoke all tokens for an application by its unique ID. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| appId | string | **Required** Application unique ID. | | + diff --git a/docs/backups.md b/docs/backups.md index 3ad1f4eb..3ba25e1d 100644 --- a/docs/backups.md +++ b/docs/backups.md @@ -135,7 +135,13 @@ POST https://cloud.appwrite.io/v1/backups/restoration ** Create and trigger a new restoration for a backup on a project. -When restoring a DocumentsDB or VectorsDB database to a new resource, pass `newSpecification` to provision the restored database on a different specification than the archived one (for example, restoring onto a larger or smaller dedicated database). Use `serverless` to restore onto the shared pool, or a dedicated specification slug to restore onto a dedicated database of that size. The specification must be permitted by the organization's plan. `newSpecification` is not supported for legacy/TablesDB databases or for bucket restores. +For a backup of one database, the restoration resolves its destination before it is queued. Pass `newResourceId` to restore into that database ID, including the archived database ID to overwrite it. When `newResourceId` is omitted, a new database ID is generated and returned in `options`. + +The restoration migration records the archived database in `resourceId` and `resourceType`, and the resolved database in `destinationResourceId` and `destinationResourceType`. Database types are stored canonically as `database`, `documentsdb`, or `vectorsdb`. Project-wide restorations leave these fields empty because they do not have a single source or destination database. + +To list every migration related to one database, use its canonical type in a nested `OR(AND(...), AND(...), AND(...))` across the root, parent, and destination relation pairs: `(resourceType, resourceId)`, `(parentResourceType, parentResourceId)`, and `(destinationResourceType, destinationResourceId)`. Legacy and TablesDB databases use `database`; the operational `resourceType` of a table migration is not rewritten to `tablesdb`. + +When restoring a DocumentsDB or VectorsDB database to a new resource from a dedicated source, the restore provisions a fresh dedicated backing database at the source database's own specification. ** ### Parameters @@ -144,9 +150,8 @@ When restoring a DocumentsDB or VectorsDB database to a new resource, pass `newS | --- | --- | --- | --- | | archiveId | string | Backup archive ID to restore | | | services | array | Array of services to restore | | -| newResourceId | string | Unique 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. | | +| newResourceId | string | Destination resource ID. Omit to generate a new ID, or pass the archived resource ID to overwrite it. 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. | | | newResourceName | string | Database name. Max length: 128 chars. | | -| newSpecification | string | Specification to provision the restored database on, when restoring a DocumentsDB or VectorsDB database to a new resource. Defaults to the archived database's specification. Use `serverless` for the shared pool or a dedicated specification slug. | | ```http request diff --git a/docs/examples/account/delete-consent-token.md b/docs/examples/account/delete-consent-token.md new file mode 100644 index 00000000..1cb8fcce --- /dev/null +++ b/docs/examples/account/delete-consent-token.md @@ -0,0 +1,17 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$account = new Account($client); + +$result = $account->deleteConsentToken( + consentId: '', + tokenId: '' +);``` diff --git a/docs/examples/account/delete-consent.md b/docs/examples/account/delete-consent.md new file mode 100644 index 00000000..0aebb0a5 --- /dev/null +++ b/docs/examples/account/delete-consent.md @@ -0,0 +1,16 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$account = new Account($client); + +$result = $account->deleteConsent( + consentId: '' +);``` diff --git a/docs/examples/account/get-consent-token.md b/docs/examples/account/get-consent-token.md new file mode 100644 index 00000000..dda1a1ca --- /dev/null +++ b/docs/examples/account/get-consent-token.md @@ -0,0 +1,17 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$account = new Account($client); + +$result = $account->getConsentToken( + consentId: '', + tokenId: '' +);``` diff --git a/docs/examples/account/get-consent.md b/docs/examples/account/get-consent.md new file mode 100644 index 00000000..f6ce59fc --- /dev/null +++ b/docs/examples/account/get-consent.md @@ -0,0 +1,16 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$account = new Account($client); + +$result = $account->getConsent( + consentId: '' +);``` diff --git a/docs/examples/account/list-consent-tokens.md b/docs/examples/account/list-consent-tokens.md new file mode 100644 index 00000000..0088745c --- /dev/null +++ b/docs/examples/account/list-consent-tokens.md @@ -0,0 +1,18 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$account = new Account($client); + +$result = $account->listConsentTokens( + consentId: '', + queries: [], // optional + total: false // optional +);``` diff --git a/docs/examples/account/list-consents.md b/docs/examples/account/list-consents.md new file mode 100644 index 00000000..b2c63a30 --- /dev/null +++ b/docs/examples/account/list-consents.md @@ -0,0 +1,17 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$account = new Account($client); + +$result = $account->listConsents( + queries: [], // optional + total: false // optional +);``` diff --git a/docs/examples/apps/create-installation-token.md b/docs/examples/apps/create-installation-token.md new file mode 100644 index 00000000..ef4ca380 --- /dev/null +++ b/docs/examples/apps/create-installation-token.md @@ -0,0 +1,17 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$apps = new Apps($client); + +$result = $apps->createInstallationToken( + appId: '', + installationId: '' +);``` diff --git a/docs/examples/apps/create-key.md b/docs/examples/apps/create-key.md new file mode 100644 index 00000000..7690aeaa --- /dev/null +++ b/docs/examples/apps/create-key.md @@ -0,0 +1,16 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$apps = new Apps($client); + +$result = $apps->createKey( + appId: '' +);``` diff --git a/docs/examples/apps/create-secret.md b/docs/examples/apps/create-secret.md new file mode 100644 index 00000000..cff66b3b --- /dev/null +++ b/docs/examples/apps/create-secret.md @@ -0,0 +1,16 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$apps = new Apps($client); + +$result = $apps->createSecret( + appId: '' +);``` diff --git a/docs/examples/apps/create.md b/docs/examples/apps/create.md new file mode 100644 index 00000000..8c7c2869 --- /dev/null +++ b/docs/examples/apps/create.md @@ -0,0 +1,34 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$apps = new Apps($client); + +$result = $apps->create( + appId: '', + name: '', + redirectUris: [], + description: '', // optional + clientUri: 'https://example.com', // optional + logoUri: 'https://example.com', // optional + privacyPolicyUrl: 'https://example.com', // optional + termsUrl: 'https://example.com', // optional + contacts: [], // optional + tagline: '', // optional + tags: [], // optional + images: [], // optional + supportUrl: 'https://example.com', // optional + dataDeletionUrl: 'https://example.com', // optional + postLogoutRedirectUris: [], // optional + enabled: false, // optional + type: 'public', // optional + deviceFlow: false, // optional + teamId: '' // optional +);``` diff --git a/docs/examples/apps/delete-key.md b/docs/examples/apps/delete-key.md new file mode 100644 index 00000000..d07194eb --- /dev/null +++ b/docs/examples/apps/delete-key.md @@ -0,0 +1,17 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$apps = new Apps($client); + +$result = $apps->deleteKey( + appId: '', + keyId: '' +);``` diff --git a/docs/examples/apps/delete-secret.md b/docs/examples/apps/delete-secret.md new file mode 100644 index 00000000..df614d6a --- /dev/null +++ b/docs/examples/apps/delete-secret.md @@ -0,0 +1,17 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$apps = new Apps($client); + +$result = $apps->deleteSecret( + appId: '', + secretId: '' +);``` diff --git a/docs/examples/apps/delete-tokens.md b/docs/examples/apps/delete-tokens.md new file mode 100644 index 00000000..200cb924 --- /dev/null +++ b/docs/examples/apps/delete-tokens.md @@ -0,0 +1,16 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$apps = new Apps($client); + +$result = $apps->deleteTokens( + appId: '' +);``` diff --git a/docs/examples/apps/delete.md b/docs/examples/apps/delete.md new file mode 100644 index 00000000..38cfcf55 --- /dev/null +++ b/docs/examples/apps/delete.md @@ -0,0 +1,16 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$apps = new Apps($client); + +$result = $apps->delete( + appId: '' +);``` diff --git a/docs/examples/apps/get-installation.md b/docs/examples/apps/get-installation.md new file mode 100644 index 00000000..63de2616 --- /dev/null +++ b/docs/examples/apps/get-installation.md @@ -0,0 +1,17 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$apps = new Apps($client); + +$result = $apps->getInstallation( + appId: '', + installationId: '' +);``` diff --git a/docs/examples/apps/get-key.md b/docs/examples/apps/get-key.md new file mode 100644 index 00000000..78e30e19 --- /dev/null +++ b/docs/examples/apps/get-key.md @@ -0,0 +1,17 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$apps = new Apps($client); + +$result = $apps->getKey( + appId: '', + keyId: '' +);``` diff --git a/docs/examples/apps/get-secret.md b/docs/examples/apps/get-secret.md new file mode 100644 index 00000000..ef4c1d4f --- /dev/null +++ b/docs/examples/apps/get-secret.md @@ -0,0 +1,17 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$apps = new Apps($client); + +$result = $apps->getSecret( + appId: '', + secretId: '' +);``` diff --git a/docs/examples/apps/get.md b/docs/examples/apps/get.md new file mode 100644 index 00000000..7c9ce18a --- /dev/null +++ b/docs/examples/apps/get.md @@ -0,0 +1,16 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$apps = new Apps($client); + +$result = $apps->get( + appId: '' +);``` diff --git a/docs/examples/apps/list-installation-scopes.md b/docs/examples/apps/list-installation-scopes.md new file mode 100644 index 00000000..f60f6c51 --- /dev/null +++ b/docs/examples/apps/list-installation-scopes.md @@ -0,0 +1,15 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$apps = new Apps($client); + +$result = $apps->listInstallationScopes(); +``` diff --git a/docs/examples/apps/list-installations.md b/docs/examples/apps/list-installations.md new file mode 100644 index 00000000..fbdff242 --- /dev/null +++ b/docs/examples/apps/list-installations.md @@ -0,0 +1,18 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$apps = new Apps($client); + +$result = $apps->listInstallations( + appId: '', + queries: [], // optional + total: false // optional +);``` diff --git a/docs/examples/apps/list-keys.md b/docs/examples/apps/list-keys.md new file mode 100644 index 00000000..8d816537 --- /dev/null +++ b/docs/examples/apps/list-keys.md @@ -0,0 +1,18 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$apps = new Apps($client); + +$result = $apps->listKeys( + appId: '', + queries: [], // optional + total: false // optional +);``` diff --git a/docs/examples/apps/list-o-auth-2-scopes.md b/docs/examples/apps/list-o-auth-2-scopes.md new file mode 100644 index 00000000..4bcfa44b --- /dev/null +++ b/docs/examples/apps/list-o-auth-2-scopes.md @@ -0,0 +1,15 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$apps = new Apps($client); + +$result = $apps->listOAuth2Scopes(); +``` diff --git a/docs/examples/apps/list-secrets.md b/docs/examples/apps/list-secrets.md new file mode 100644 index 00000000..341fa345 --- /dev/null +++ b/docs/examples/apps/list-secrets.md @@ -0,0 +1,18 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$apps = new Apps($client); + +$result = $apps->listSecrets( + appId: '', + queries: [], // optional + total: false // optional +);``` diff --git a/docs/examples/apps/list.md b/docs/examples/apps/list.md new file mode 100644 index 00000000..9add376d --- /dev/null +++ b/docs/examples/apps/list.md @@ -0,0 +1,17 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$apps = new Apps($client); + +$result = $apps->list( + queries: [], // optional + total: false // optional +);``` diff --git a/docs/examples/apps/update-labels.md b/docs/examples/apps/update-labels.md new file mode 100644 index 00000000..e3786e42 --- /dev/null +++ b/docs/examples/apps/update-labels.md @@ -0,0 +1,17 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$apps = new Apps($client); + +$result = $apps->updateLabels( + appId: '', + labels: [] +);``` diff --git a/docs/examples/apps/update-team.md b/docs/examples/apps/update-team.md new file mode 100644 index 00000000..76ea6ce2 --- /dev/null +++ b/docs/examples/apps/update-team.md @@ -0,0 +1,17 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$apps = new Apps($client); + +$result = $apps->updateTeam( + appId: '', + teamId: '' +);``` diff --git a/docs/examples/apps/update.md b/docs/examples/apps/update.md new file mode 100644 index 00000000..5d914c74 --- /dev/null +++ b/docs/examples/apps/update.md @@ -0,0 +1,35 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$apps = new Apps($client); + +$result = $apps->update( + appId: '', + name: '', + description: '', // optional + clientUri: 'https://example.com', // optional + logoUri: 'https://example.com', // optional + privacyPolicyUrl: 'https://example.com', // optional + termsUrl: 'https://example.com', // optional + contacts: [], // optional + tagline: '', // optional + tags: [], // optional + images: [], // optional + supportUrl: 'https://example.com', // optional + dataDeletionUrl: 'https://example.com', // optional + enabled: false, // optional + redirectUris: [], // optional + postLogoutRedirectUris: [], // optional + type: 'public', // optional + deviceFlow: false, // optional + installationScopes: [], // optional + installationRedirectUrl: 'https://example.com' // optional +);``` diff --git a/docs/examples/backups/create-restoration.md b/docs/examples/backups/create-restoration.md index e572dd47..61d9e0b2 100644 --- a/docs/examples/backups/create-restoration.md +++ b/docs/examples/backups/create-restoration.md @@ -16,6 +16,5 @@ $result = $backups->createRestoration( archiveId: '', services: [BackupServices::DATABASES()], newResourceId: '', // optional - newResourceName: '', // optional - newSpecification: 'serverless' // optional + newResourceName: '' // optional );``` diff --git a/docs/examples/oauth2/approve.md b/docs/examples/oauth2/approve.md new file mode 100644 index 00000000..f3c77d1a --- /dev/null +++ b/docs/examples/oauth2/approve.md @@ -0,0 +1,18 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setSession('') // The user session to authenticate with + ->setProject(''); // Your project ID + +$oauth2 = new Oauth2($client); + +$result = $oauth2->approve( + grantId: '', + authorizationDetails: '', // optional + scope: '' // optional +);``` diff --git a/docs/examples/oauth2/authorize-post.md b/docs/examples/oauth2/authorize-post.md new file mode 100644 index 00000000..8f2b1251 --- /dev/null +++ b/docs/examples/oauth2/authorize-post.md @@ -0,0 +1,29 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setSession('') // The user session to authenticate with + ->setProject(''); // Your project ID + +$oauth2 = new Oauth2($client); + +$result = $oauth2->authorizePost( + clientId: '', // optional + redirectUri: 'https://example.com', // optional + responseType: '', // optional + scope: '', // optional + state: '', // optional + nonce: '', // optional + codeChallenge: '', // optional + codeChallengeMethod: 's256', // optional + prompt: '', // optional + maxAge: 0, // optional + authorizationDetails: '', // optional + resource: '', // optional + audience: '', // optional + requestUri: '' // optional +);``` diff --git a/docs/examples/oauth2/authorize.md b/docs/examples/oauth2/authorize.md new file mode 100644 index 00000000..c0217125 --- /dev/null +++ b/docs/examples/oauth2/authorize.md @@ -0,0 +1,29 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setSession('') // The user session to authenticate with + ->setProject(''); // Your project ID + +$oauth2 = new Oauth2($client); + +$result = $oauth2->authorize( + clientId: '', // optional + redirectUri: 'https://example.com', // optional + responseType: '', // optional + scope: '', // optional + state: '', // optional + nonce: '', // optional + codeChallenge: '', // optional + codeChallengeMethod: 's256', // optional + prompt: '', // optional + maxAge: 0, // optional + authorizationDetails: '', // optional + resource: '', // optional + audience: '', // optional + requestUri: '' // optional +);``` diff --git a/docs/examples/oauth2/create-device-authorization.md b/docs/examples/oauth2/create-device-authorization.md new file mode 100644 index 00000000..6da66a8b --- /dev/null +++ b/docs/examples/oauth2/create-device-authorization.md @@ -0,0 +1,20 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setSession('') // The user session to authenticate with + ->setProject(''); // Your project ID + +$oauth2 = new Oauth2($client); + +$result = $oauth2->createDeviceAuthorization( + clientId: '', // optional + scope: '', // optional + authorizationDetails: '', // optional + resource: '', // optional + audience: '' // optional +);``` diff --git a/docs/examples/oauth2/create-grant.md b/docs/examples/oauth2/create-grant.md new file mode 100644 index 00000000..598470f6 --- /dev/null +++ b/docs/examples/oauth2/create-grant.md @@ -0,0 +1,16 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setSession('') // The user session to authenticate with + ->setProject(''); // Your project ID + +$oauth2 = new Oauth2($client); + +$result = $oauth2->createGrant( + userCode: '' +);``` diff --git a/docs/examples/oauth2/create-par.md b/docs/examples/oauth2/create-par.md new file mode 100644 index 00000000..ca770f1b --- /dev/null +++ b/docs/examples/oauth2/create-par.md @@ -0,0 +1,28 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setSession('') // The user session to authenticate with + ->setProject(''); // Your project ID + +$oauth2 = new Oauth2($client); + +$result = $oauth2->createPAR( + clientId: '', + redirectUri: 'https://example.com', + responseType: 'code', + scope: '', // optional + state: '', // optional + nonce: '', // optional + codeChallenge: '', // optional + codeChallengeMethod: 's256', // optional + prompt: '', // optional + maxAge: 0, // optional + authorizationDetails: '', // optional + resource: '', // optional + audience: '' // optional +);``` diff --git a/docs/examples/oauth2/create-token.md b/docs/examples/oauth2/create-token.md new file mode 100644 index 00000000..61905d60 --- /dev/null +++ b/docs/examples/oauth2/create-token.md @@ -0,0 +1,25 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setSession('') // The user session to authenticate with + ->setProject(''); // Your project ID + +$oauth2 = new Oauth2($client); + +$result = $oauth2->createToken( + grantType: '', + code: '', // optional + refreshToken: '', // optional + deviceCode: '', // optional + clientId: '', // optional + clientSecret: '', // optional + codeVerifier: '', // optional + redirectUri: 'https://example.com', // optional + resource: '', // optional + audience: '' // optional +);``` diff --git a/docs/examples/oauth2/get-grant.md b/docs/examples/oauth2/get-grant.md new file mode 100644 index 00000000..b4979828 --- /dev/null +++ b/docs/examples/oauth2/get-grant.md @@ -0,0 +1,16 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setSession('') // The user session to authenticate with + ->setProject(''); // Your project ID + +$oauth2 = new Oauth2($client); + +$result = $oauth2->getGrant( + grantId: '' +);``` diff --git a/docs/examples/oauth2/list-organizations.md b/docs/examples/oauth2/list-organizations.md new file mode 100644 index 00000000..1c2fb1c4 --- /dev/null +++ b/docs/examples/oauth2/list-organizations.md @@ -0,0 +1,18 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setSession('') // The user session to authenticate with + ->setProject(''); // Your project ID + +$oauth2 = new Oauth2($client); + +$result = $oauth2->listOrganizations( + limit: 1, // optional + offset: 0, // optional + search: '' // optional +);``` diff --git a/docs/examples/oauth2/list-projects.md b/docs/examples/oauth2/list-projects.md new file mode 100644 index 00000000..ea4ff032 --- /dev/null +++ b/docs/examples/oauth2/list-projects.md @@ -0,0 +1,18 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setSession('') // The user session to authenticate with + ->setProject(''); // Your project ID + +$oauth2 = new Oauth2($client); + +$result = $oauth2->listProjects( + limit: 1, // optional + offset: 0, // optional + search: '' // optional +);``` diff --git a/docs/examples/oauth2/reject.md b/docs/examples/oauth2/reject.md new file mode 100644 index 00000000..65deab84 --- /dev/null +++ b/docs/examples/oauth2/reject.md @@ -0,0 +1,16 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setSession('') // The user session to authenticate with + ->setProject(''); // Your project ID + +$oauth2 = new Oauth2($client); + +$result = $oauth2->reject( + grantId: '' +);``` diff --git a/docs/examples/oauth2/revoke.md b/docs/examples/oauth2/revoke.md new file mode 100644 index 00000000..97c7b861 --- /dev/null +++ b/docs/examples/oauth2/revoke.md @@ -0,0 +1,19 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setSession('') // The user session to authenticate with + ->setProject(''); // Your project ID + +$oauth2 = new Oauth2($client); + +$result = $oauth2->revoke( + token: '', + tokenTypeHint: 'access_token', // optional + clientId: '', // optional + clientSecret: '' // optional +);``` diff --git a/docs/examples/organization/create-installation.md b/docs/examples/organization/create-installation.md new file mode 100644 index 00000000..51855c47 --- /dev/null +++ b/docs/examples/organization/create-installation.md @@ -0,0 +1,17 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$organization = new Organization($client); + +$result = $organization->createInstallation( + appId: '', + authorizationDetails: '' // optional +);``` diff --git a/docs/examples/organization/delete-installation.md b/docs/examples/organization/delete-installation.md new file mode 100644 index 00000000..23b8e692 --- /dev/null +++ b/docs/examples/organization/delete-installation.md @@ -0,0 +1,16 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$organization = new Organization($client); + +$result = $organization->deleteInstallation( + installationId: '' +);``` diff --git a/docs/examples/organization/get-installation.md b/docs/examples/organization/get-installation.md new file mode 100644 index 00000000..5e4b6763 --- /dev/null +++ b/docs/examples/organization/get-installation.md @@ -0,0 +1,16 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$organization = new Organization($client); + +$result = $organization->getInstallation( + installationId: '' +);``` diff --git a/docs/examples/organization/list-installations.md b/docs/examples/organization/list-installations.md new file mode 100644 index 00000000..170243d3 --- /dev/null +++ b/docs/examples/organization/list-installations.md @@ -0,0 +1,17 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$organization = new Organization($client); + +$result = $organization->listInstallations( + queries: [], // optional + total: false // optional +);``` diff --git a/docs/examples/organization/update-installation.md b/docs/examples/organization/update-installation.md new file mode 100644 index 00000000..a35f797e --- /dev/null +++ b/docs/examples/organization/update-installation.md @@ -0,0 +1,17 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$organization = new Organization($client); + +$result = $organization->updateInstallation( + installationId: '', + authorizationDetails: '' // optional +);``` diff --git a/docs/examples/project/update-o-auth-2-server.md b/docs/examples/project/update-o-auth-2-server.md index 9c3eb9a8..4a7782f2 100644 --- a/docs/examples/project/update-o-auth-2-server.md +++ b/docs/examples/project/update-o-auth-2-server.md @@ -20,6 +20,7 @@ $result = $project->updateOAuth2Server( refreshTokenDuration: 60, // optional publicAccessTokenDuration: 60, // optional publicRefreshTokenDuration: 60, // optional + installationAccessTokenDuration: 60, // optional confidentialPkce: false, // optional verificationUrl: 'https://example.com', // optional userCodeLength: 6, // optional diff --git a/docs/examples/sites/get-deployment-download.md b/docs/examples/sites/get-deployment-download.md index 5582e964..bfa02f11 100644 --- a/docs/examples/sites/get-deployment-download.md +++ b/docs/examples/sites/get-deployment-download.md @@ -15,5 +15,6 @@ $sites = new Sites($client); $result = $sites->getDeploymentDownload( siteId: '', deploymentId: '', - type: DeploymentDownloadType::SOURCE() // optional + type: DeploymentDownloadType::SOURCE(), // optional + token: '' // optional );``` diff --git a/docs/examples/tablesdb/create-failover.md b/docs/examples/tablesdb/create-failover.md new file mode 100644 index 00000000..fbd2837b --- /dev/null +++ b/docs/examples/tablesdb/create-failover.md @@ -0,0 +1,17 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$tablesDB = new TablesDB($client); + +$result = $tablesDB->createFailover( + databaseId: '', + targetReplicaId: '' // optional +);``` diff --git a/docs/examples/tablesdb/create.md b/docs/examples/tablesdb/create.md index 9cbbf307..87c81dd2 100644 --- a/docs/examples/tablesdb/create.md +++ b/docs/examples/tablesdb/create.md @@ -15,5 +15,6 @@ $result = $tablesDB->create( databaseId: '', name: '', enabled: false, // optional - specification: 'serverless' // optional + specification: 'serverless', // optional + replicas: 0 // optional );``` diff --git a/docs/examples/tablesdb/get-replicas.md b/docs/examples/tablesdb/get-replicas.md new file mode 100644 index 00000000..0bc85769 --- /dev/null +++ b/docs/examples/tablesdb/get-replicas.md @@ -0,0 +1,16 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$tablesDB = new TablesDB($client); + +$result = $tablesDB->getReplicas( + databaseId: '' +);``` diff --git a/docs/examples/tablesdb/get-status.md b/docs/examples/tablesdb/get-status.md new file mode 100644 index 00000000..e7a227c5 --- /dev/null +++ b/docs/examples/tablesdb/get-status.md @@ -0,0 +1,16 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$tablesDB = new TablesDB($client); + +$result = $tablesDB->getStatus( + databaseId: '' +);``` diff --git a/docs/examples/tablesdb/list-specifications.md b/docs/examples/tablesdb/list-specifications.md new file mode 100644 index 00000000..b4080072 --- /dev/null +++ b/docs/examples/tablesdb/list-specifications.md @@ -0,0 +1,15 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$tablesDB = new TablesDB($client); + +$result = $tablesDB->listSpecifications(); +``` diff --git a/docs/examples/tablesdb/update.md b/docs/examples/tablesdb/update.md index 126b3caf..e6c703af 100644 --- a/docs/examples/tablesdb/update.md +++ b/docs/examples/tablesdb/update.md @@ -14,5 +14,6 @@ $tablesDB = new TablesDB($client); $result = $tablesDB->update( databaseId: '', name: '', // optional - enabled: false // optional + enabled: false, // optional + replicas: 0 // optional );``` diff --git a/docs/examples/teams/create-installation.md b/docs/examples/teams/create-installation.md new file mode 100644 index 00000000..e462cf6b --- /dev/null +++ b/docs/examples/teams/create-installation.md @@ -0,0 +1,18 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$teams = new Teams($client); + +$result = $teams->createInstallation( + teamId: '', + appId: '', + authorizationDetails: '' // optional +);``` diff --git a/docs/examples/teams/delete-installation.md b/docs/examples/teams/delete-installation.md new file mode 100644 index 00000000..091ae091 --- /dev/null +++ b/docs/examples/teams/delete-installation.md @@ -0,0 +1,17 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$teams = new Teams($client); + +$result = $teams->deleteInstallation( + teamId: '', + installationId: '' +);``` diff --git a/docs/examples/teams/get-installation.md b/docs/examples/teams/get-installation.md new file mode 100644 index 00000000..440afa82 --- /dev/null +++ b/docs/examples/teams/get-installation.md @@ -0,0 +1,17 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$teams = new Teams($client); + +$result = $teams->getInstallation( + teamId: '', + installationId: '' +);``` diff --git a/docs/examples/teams/list-installations.md b/docs/examples/teams/list-installations.md new file mode 100644 index 00000000..678ab4bc --- /dev/null +++ b/docs/examples/teams/list-installations.md @@ -0,0 +1,18 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$teams = new Teams($client); + +$result = $teams->listInstallations( + teamId: '', + queries: [], // optional + total: false // optional +);``` diff --git a/docs/examples/teams/update-installation.md b/docs/examples/teams/update-installation.md new file mode 100644 index 00000000..36cdd030 --- /dev/null +++ b/docs/examples/teams/update-installation.md @@ -0,0 +1,18 @@ +```php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setSession(''); // The user session to authenticate with + +$teams = new Teams($client); + +$result = $teams->updateInstallation( + teamId: '', + installationId: '', + authorizationDetails: '' // optional +);``` diff --git a/docs/functions.md b/docs/functions.md index 86be1ee9..eb12a051 100644 --- a/docs/functions.md +++ b/docs/functions.md @@ -113,7 +113,7 @@ PUT https://cloud.appwrite.io/v1/functions/{functionId} | providerBranches | array | List of branch name patterns to trigger automatic deployments. Supports wildcards. Leave empty to deploy on all branches. | | | providerPaths | array | List of file path patterns to trigger automatic deployments. Supports wildcards. Leave empty to deploy on all file changes. | | | buildSpecification | string | Build specification for the function deployments. | | -| runtimeSpecification | string | Runtime specification for the function executions. | [] | +| runtimeSpecification | string | Runtime specification for the function executions. | | | deploymentRetention | integer | Days to keep non-active deployments before deletion. Value 0 means all deployments will be kept. | 0 | diff --git a/docs/oauth2.md b/docs/oauth2.md new file mode 100644 index 00000000..c5e315e6 --- /dev/null +++ b/docs/oauth2.md @@ -0,0 +1,230 @@ +# Oauth2 Service + + +```http request +POST https://cloud.appwrite.io/v1/oauth2/{project_id}/approve +``` + +** 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 + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| project_id | string | **Required** Project ID in which OAuth2 client exists. | | +| grant_id | string | Grant ID made during authorization, provided to consent screen in URL search params. | | +| authorization_details | string | 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. | | +| scope | string | Space-separated scopes the user consented to. Must be a subset of the scopes originally requested; identity scopes such as `openid` are always retained. Optional; omit to keep the originally requested scopes. | | + + +```http request +GET https://cloud.appwrite.io/v1/oauth2/{project_id}/authorize +``` + +** 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 + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| project_id | string | **Required** Project ID in which OAuth2 client exists. | | +| client_id | string | OAuth2 client ID. Either a registered app ID or an HTTPS client ID metadata document URL. | | +| redirect_uri | string | Redirect URI where visitor will be redirected after authorization, whether successful or not. | | +| response_type | string | OAuth2 / OIDC response type. One of `code` (Authorization Code Flow), `id_token` (Implicit Flow, OIDC login only), or `code id_token` (Hybrid Flow). | | +| scope | string | Space-separated OAuth2 scopes. Can include project scopes, and built-in scopes: `openid`, `email`, `profile`, `phone`. | | +| state | string | OAuth2 state. You receive this back in the redirect URI. | | +| nonce | string | OIDC nonce parameter to prevent replay attacks. Required when response_type includes `id_token`. | | +| code_challenge | string | PKCE code challenge. Required when OAuth2 app is public. | | +| code_challenge_method | string | PKCE code challenge method. Required when OAuth2 app is public. | | +| prompt | string | OIDC prompt parameter for customization of consent screen. Space-separated list of: none, login, consent, select_account. | | +| max_age | integer | 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 | string | Rich authorization request. JSON array of objects, each with a `type` and project-defined fields | | +| resource | string | RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. | [] | +| audience | string | Compatibility alias for a single OAuth2 resource indicator URI. | | +| request_uri | string | OAuth2 authorization request handle returned by the pushed authorization request endpoint. | | + + +```http request +POST https://cloud.appwrite.io/v1/oauth2/{project_id}/authorize +``` + +** 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 + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| project_id | string | **Required** Project ID in which OAuth2 client exists. | | +| client_id | string | OAuth2 client ID. Either a registered app ID or an HTTPS client ID metadata document URL. | | +| redirect_uri | string | Redirect URI where visitor will be redirected after authorization, whether successful or not. | | +| response_type | string | OAuth2 / OIDC response type. One of `code` (Authorization Code Flow), `id_token` (Implicit Flow, OIDC login only), or `code id_token` (Hybrid Flow). | | +| scope | string | Space-separated OAuth2 scopes. Can include project scopes, and built-in scopes: `openid`, `email`, `profile`, `phone`. | | +| state | string | OAuth2 state. You receive this back in the redirect URI. | | +| nonce | string | OIDC nonce parameter to prevent replay attacks. Required when response_type includes `id_token`. | | +| code_challenge | string | PKCE code challenge. Required when OAuth2 app is public. | | +| code_challenge_method | string | PKCE code challenge method. Required when OAuth2 app is public. | | +| prompt | string | OIDC prompt parameter for customization of consent screen. Space-separated list of: none, login, consent, select_account. | | +| max_age | integer | 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 | string | Rich authorization request. JSON array of objects, each with a `type` and project-defined fields | | +| resource | string | RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. | [] | +| audience | string | Compatibility alias for a single OAuth2 resource indicator URI. | | +| request_uri | string | OAuth2 authorization request handle returned by the pushed authorization request endpoint. | | + + +```http request +POST https://cloud.appwrite.io/v1/oauth2/{project_id}/device_authorization +``` + +** Start the OAuth2 Device Authorization Grant. Returns the device code, user code, verification URL, expiration, and polling interval. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| project_id | string | **Required** Project ID in which OAuth2 client exists. | | +| client_id | string | OAuth2 client ID. Either a registered app ID or an HTTPS client ID metadata document URL. | | +| scope | string | Space-separated OAuth2 scopes. Can include project scopes, and built-in scopes: `openid`, `email`, `profile`. | | +| authorization_details | string | Rich authorization request. JSON array of objects, each with a `type` and project-defined fields | | +| resource | string | RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. | [] | +| audience | string | Compatibility alias for a single OAuth2 resource indicator URI. | | + + +```http request +POST https://cloud.appwrite.io/v1/oauth2/{project_id}/grants +``` + +** 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 + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| project_id | string | **Required** Project ID in which OAuth2 client exists. | | +| user_code | string | User code displayed on the device. | | + + +```http request +GET https://cloud.appwrite.io/v1/oauth2/{project_id}/grants/{grant_id} +``` + +** 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 + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| project_id | string | **Required** Project ID in which OAuth2 client that created grant during authorization exists. | | +| grant_id | string | **Required** Grant ID made during authorization, provided to consent screen in URL search params. | | + + +```http request +GET https://cloud.appwrite.io/v1/oauth2/{project_id}/organizations +``` + +** List the organizations the OAuth2 access token can access. Resolves the token's `organization` authorization details, expanding the `*` wildcard into the concrete set of organizations the user can see. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| project_id | string | **Required** Project ID of the console project the OAuth2 access token was issued for. | | +| limit | integer | Maximum number of organizations to return. Between 1 and 5000. | 25 | +| offset | integer | Number of organizations to skip before returning results. Used for pagination. | 0 | +| search | string | Search term to filter your list results. Max length: 256 chars. | | + + +```http request +POST https://cloud.appwrite.io/v1/oauth2/{project_id}/par +``` + +** Store an OAuth2 authorization request server-side and receive a short-lived request_uri handle for the authorize endpoint. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| project_id | string | **Required** Project ID in which OAuth2 client exists. | | +| client_id | string | OAuth2 client ID. Either a registered app ID or an HTTPS client ID metadata document URL. | | +| redirect_uri | string | Redirect URI where visitor will be redirected after authorization, whether successful or not. | | +| response_type | string | OAuth2 / OIDC response type. | | +| scope | string | Space-separated OAuth2 scopes. Can include project scopes, and built-in scopes: `openid`, `email`, `profile`, `phone`. | | +| state | string | OAuth2 state. You receive this back in the redirect URI. | | +| nonce | string | OIDC nonce parameter to prevent replay attacks. Required when response_type includes `id_token`. | | +| code_challenge | string | PKCE code challenge. Required when OAuth2 app is public. | | +| code_challenge_method | string | PKCE code challenge method. Required when OAuth2 app is public. | | +| prompt | string | OIDC prompt parameter for customization of consent screen. Space-separated list of: none, login, consent, select_account. | | +| max_age | integer | OIDC max_age parameter for customization of consent screen. | | +| authorization_details | string | Rich authorization request. JSON array of objects, each with a `type` and project-defined fields | | +| resource | string | RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. | [] | +| audience | string | Compatibility alias for a single OAuth2 resource indicator URI. | | + + +```http request +GET https://cloud.appwrite.io/v1/oauth2/{project_id}/projects +``` + +** List the projects the OAuth2 access token can access. Resolves the token's `project` authorization details, expanding the `*` wildcard into the concrete set of projects the user can see. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| project_id | string | **Required** Project ID of the console project the OAuth2 access token was issued for. | | +| limit | integer | Maximum number of projects to return. Between 1 and 5000. | 25 | +| offset | integer | Number of projects to skip before returning results. Used for pagination. | 0 | +| search | string | Search term to filter your list results. Max length: 256 chars. | | + + +```http request +POST https://cloud.appwrite.io/v1/oauth2/{project_id}/reject +``` + +** 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 + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| project_id | string | **Required** Project ID in which OAuth2 client exists. | | +| grant_id | string | Grant ID made during authorization, provided to consent screen in URL search params. | | + + +```http request +POST https://cloud.appwrite.io/v1/oauth2/{project_id}/revoke +``` + +** Revoke an OAuth2 access token or refresh token. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| project_id | string | **Required** Project ID in which OAuth2 client exists. | | +| token | string | The access or refresh token to revoke. | | +| token_type_hint | string | Type of token to revoke (access_token or refresh_token). | | +| client_id | string | OAuth2 client ID. Either a registered app ID or an HTTPS client ID metadata document URL. | | +| client_secret | string | OAuth2 client secret. Required for confidential apps; omitted for public apps. | | + + +```http request +POST https://cloud.appwrite.io/v1/oauth2/{project_id}/token +``` + +** Exchange an OAuth2 authorization code, refresh token, or device code for access and refresh tokens. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| project_id | string | **Required** Project ID in which OAuth2 client exists. | | +| grant_type | string | OAuth2 grant type. Can be one of: `authorization_code`, `refresh_token`, `urn:ietf:params:oauth:grant-type:device_code`. | | +| code | string | Authorization code to be exchanged for access and refresh tokens. Required for `authorization_code` grant type. | | +| refresh_token | string | Refresh token to be exchanged for a new access and refresh tokens. Required for `refresh_token` grant type. | | +| device_code | string | Device code obtained from the device authorization endpoint. Required for `urn:ietf:params:oauth:grant-type:device_code` grant type. | | +| client_id | string | OAuth2 client ID. Either a registered app ID or an HTTPS client ID metadata document URL. | | +| client_secret | string | OAuth2 client secret. Required for confidential apps. | | +| code_verifier | string | PKCE code verifier. Required for public apps. | | +| redirect_uri | string | Redirect URI. Required for `authorization_code` grant type. | | +| resource | string | RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. | [] | +| audience | string | Compatibility alias for a single OAuth2 resource indicator URI. | | + diff --git a/docs/organization.md b/docs/organization.md index 65a24932..1508fbc8 100644 --- a/docs/organization.md +++ b/docs/organization.md @@ -28,6 +28,74 @@ DELETE https://cloud.appwrite.io/v1/organization ** Delete the current organization. All projects that belong to the organization are deleted as well. ** +```http request +GET https://cloud.appwrite.io/v1/organization/installations +``` + +** List app installations on the organization. Any organization member can read installations. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| queries | array | 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 | boolean | When set to false, the total count returned will be 0 and will not be calculated. | 1 | + + +```http request +POST https://cloud.appwrite.io/v1/organization/installations +``` + +** Install an app on the organization. Only organization members with the owner role can install apps. The installation is granted the scopes the app currently requests. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| appId | string | Application unique ID. | | +| authorizationDetails | string | Authorization details granted to the installation as a JSON array of objects, each with a `type` and app-defined fields. The Appwrite Console stores authorized project IDs here. | | + + +```http request +GET https://cloud.appwrite.io/v1/organization/installations/{installationId} +``` + +** Get an app installation on the organization by its unique ID. Any organization member can read installations. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| installationId | string | **Required** Installation unique ID. | | + + +```http request +PUT https://cloud.appwrite.io/v1/organization/installations/{installationId} +``` + +** Update an app installation on the organization. Only organization members with the owner role can update installations. The installation's granted scopes are refreshed to the scopes the app currently requests; previously issued installation access tokens are revoked. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| installationId | string | **Required** Installation unique ID. | | +| authorizationDetails | string | Authorization details granted to the installation as a JSON array of objects, each with a `type` and app-defined fields. Omit to keep the current value. | | + + +```http request +DELETE https://cloud.appwrite.io/v1/organization/installations/{installationId} +``` + +** Uninstall an app from the organization by its installation ID. Only organization members with the owner role can remove installations. Previously issued installation access tokens are revoked. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| installationId | string | **Required** Installation unique ID. | | + + ```http request GET https://cloud.appwrite.io/v1/organization/keys ``` diff --git a/docs/project.md b/docs/project.md index ca8f7cb6..c98ef4bc 100644 --- a/docs/project.md +++ b/docs/project.md @@ -232,6 +232,7 @@ PUT https://cloud.appwrite.io/v1/project/oauth2-server | refreshTokenDuration | integer | Refresh token duration in seconds for confidential clients (server-side apps that authenticate with a client secret). Leave empty to use default 1 year. | | | publicAccessTokenDuration | integer | Access token duration in seconds for public clients (SPAs, mobile, and native apps that cannot keep a client secret). Leave empty to use default 1 hour. | | | publicRefreshTokenDuration | integer | 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. | | +| installationAccessTokenDuration | integer | Access token duration in seconds for app installation access tokens. Leave empty to use default 1 hour. | | | confidentialPkce | boolean | 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. | | | verificationUrl | string | URL to your application page where users enter the device flow user code. Required to enable the Device Authorization Grant. | | | userCodeLength | integer | 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. | | diff --git a/docs/sites.md b/docs/sites.md index 74c000aa..68f9b7d2 100644 --- a/docs/sites.md +++ b/docs/sites.md @@ -274,6 +274,7 @@ GET https://cloud.appwrite.io/v1/sites/{siteId}/deployments/{deploymentId}/downl | siteId | string | **Required** Site ID. | | | deploymentId | string | **Required** Deployment ID. | | | type | string | Deployment file to download. Can be: "source", "output". | source | +| token | string | Presigned source-download token for accessing this deployment without a session (jobs-service). | | ```http request diff --git a/docs/tablesdb.md b/docs/tablesdb.md index 1df71a2b..eefcfcde 100644 --- a/docs/tablesdb.md +++ b/docs/tablesdb.md @@ -31,6 +31,14 @@ POST https://cloud.appwrite.io/v1/tablesdb | name | string | Database name. Max length: 128 chars. | | | enabled | boolean | 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. | 1 | | specification | string | Database specification. Defaults to `serverless`, which creates the database on the shared pool. Any other value provisions a dedicated database on that specification. | serverless | +| replicas | integer | Number of high availability replicas (0-5) for the dedicated database backing this database. Requires a dedicated `specification`; must be 0 for a serverless database. High availability is enabled when greater than 0. | 0 | + + +```http request +GET https://cloud.appwrite.io/v1/tablesdb/specifications +``` + +** List the dedicated database specifications available on the current plan. Each specification reports its resource limits, pricing, and whether it is enabled for the organization. ** ```http request @@ -140,6 +148,7 @@ PUT https://cloud.appwrite.io/v1/tablesdb/{databaseId} | databaseId | string | **Required** Database ID. | | | name | string | Database name. Max length: 128 chars. | | | enabled | boolean | Is 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. | 1 | +| replicas | integer | Number of high availability replicas (0-5) for the dedicated database backing this database. Only valid when the database is backed by a dedicated specification. High availability is enabled when greater than 0. | | ```http request @@ -155,6 +164,46 @@ DELETE https://cloud.appwrite.io/v1/tablesdb/{databaseId} | databaseId | string | **Required** Database ID. | | +```http request +POST https://cloud.appwrite.io/v1/tablesdb/{databaseId}/failovers +``` + +** Trigger a manual failover for a dedicated database with high availability enabled. Promotes a replica to primary. The failover runs asynchronously; poll the database document for status updates. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| databaseId | string | **Required** Database ID. | | +| targetReplicaId | string | Target replica ID to promote. If not specified, the healthiest replica is selected. | | + + +```http request +GET https://cloud.appwrite.io/v1/tablesdb/{databaseId}/replicas +``` + +** Get high availability status for a dedicated database. Returns replica statuses, replication lag, and sync mode. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| databaseId | string | **Required** Database ID. | | + + +```http request +GET https://cloud.appwrite.io/v1/tablesdb/{databaseId}/status +``` + +** Get real-time health and status information for a dedicated database. Returns health status, readiness, uptime, connection info, replica status, and volume information. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| databaseId | string | **Required** Database ID. | | + + ```http request GET https://cloud.appwrite.io/v1/tablesdb/{databaseId}/tables ``` diff --git a/docs/teams.md b/docs/teams.md index 7874cf5d..60315577 100644 --- a/docs/teams.md +++ b/docs/teams.md @@ -71,6 +71,79 @@ DELETE https://cloud.appwrite.io/v1/teams/{teamId} | teamId | string | **Required** Team ID. | | +```http request +GET https://cloud.appwrite.io/v1/teams/{teamId}/installations +``` + +** List app installations on a team. Any team member can read installations. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| teamId | string | **Required** Team ID. | | +| queries | array | 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 | boolean | When set to false, the total count returned will be 0 and will not be calculated. | 1 | + + +```http request +POST https://cloud.appwrite.io/v1/teams/{teamId}/installations +``` + +** Install an app on a team. When authenticated as a user, only team members with the owner role can install apps. Requests using an API key or in admin mode can install apps on any team. The installation is granted the scopes the app currently requests. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| teamId | string | **Required** Team ID. | | +| appId | string | Application unique ID. | | +| authorizationDetails | string | Authorization details granted to the installation as a JSON array of objects, each with a `type` and app-defined fields. The Appwrite Console stores authorized project IDs here. | | + + +```http request +GET https://cloud.appwrite.io/v1/teams/{teamId}/installations/{installationId} +``` + +** Get an app installation on a team by its unique ID. Any team member can read installations. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| teamId | string | **Required** Team ID. | | +| installationId | string | **Required** Installation unique ID. | | + + +```http request +PUT https://cloud.appwrite.io/v1/teams/{teamId}/installations/{installationId} +``` + +** Update an app installation on a team. Only team members with the owner role can update installations. The installation's granted scopes are refreshed to the scopes the app currently requests; previously issued installation access tokens are revoked. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| teamId | string | **Required** Team ID. | | +| installationId | string | **Required** Installation unique ID. | | +| authorizationDetails | string | Authorization details granted to the installation as a JSON array of objects, each with a `type` and app-defined fields. Omit to keep the current value. | | + + +```http request +DELETE https://cloud.appwrite.io/v1/teams/{teamId}/installations/{installationId} +``` + +** Uninstall an app from a team by its installation ID. Only team members with the owner role can remove installations. Previously issued installation access tokens are revoked. ** + +### Parameters + +| Field Name | Type | Description | Default | +| --- | --- | --- | --- | +| teamId | string | **Required** Team ID. | | +| installationId | string | **Required** Installation unique ID. | | + + ```http request GET https://cloud.appwrite.io/v1/teams/{teamId}/memberships ``` diff --git a/src/Appwrite/Client.php b/src/Appwrite/Client.php index 9a1a4cd9..23ee27b6 100644 --- a/src/Appwrite/Client.php +++ b/src/Appwrite/Client.php @@ -40,11 +40,11 @@ class Client */ protected array $headers = [ 'content-type' => '', - 'user-agent' => 'AppwritePHPSDK/27.0.0 ()', + 'user-agent' => 'AppwritePHPSDK/27.1.0 ()', 'x-sdk-name'=> 'PHP', 'x-sdk-platform'=> 'server', 'x-sdk-language'=> 'php', - 'x-sdk-version'=> '27.0.0', + 'x-sdk-version'=> '27.1.0', ]; /** diff --git a/src/Appwrite/Enums/DatabaseStatus.php b/src/Appwrite/Enums/DatabaseStatus.php index 0555a062..870c3932 100644 --- a/src/Appwrite/Enums/DatabaseStatus.php +++ b/src/Appwrite/Enums/DatabaseStatus.php @@ -8,7 +8,18 @@ class DatabaseStatus implements JsonSerializable { private static DatabaseStatus $PROVISIONING; private static DatabaseStatus $READY; + private static DatabaseStatus $INACTIVE; + private static DatabaseStatus $PAUSED; private static DatabaseStatus $FAILED; + private static DatabaseStatus $DELETING; + private static DatabaseStatus $DELETED; + private static DatabaseStatus $RESTORING; + private static DatabaseStatus $SCALING; + private static DatabaseStatus $UPGRADING; + private static DatabaseStatus $MIGRATING; + private static DatabaseStatus $PAUSING; + private static DatabaseStatus $RESUMING; + private static DatabaseStatus $FAILINGOVER; private string $value; @@ -41,6 +52,20 @@ public static function READY(): DatabaseStatus } return self::$READY; } + public static function INACTIVE(): DatabaseStatus + { + if (!isset(self::$INACTIVE)) { + self::$INACTIVE = new DatabaseStatus('inactive'); + } + return self::$INACTIVE; + } + public static function PAUSED(): DatabaseStatus + { + if (!isset(self::$PAUSED)) { + self::$PAUSED = new DatabaseStatus('paused'); + } + return self::$PAUSED; + } public static function FAILED(): DatabaseStatus { if (!isset(self::$FAILED)) { @@ -48,13 +73,87 @@ public static function FAILED(): DatabaseStatus } return self::$FAILED; } + public static function DELETING(): DatabaseStatus + { + if (!isset(self::$DELETING)) { + self::$DELETING = new DatabaseStatus('deleting'); + } + return self::$DELETING; + } + public static function DELETED(): DatabaseStatus + { + if (!isset(self::$DELETED)) { + self::$DELETED = new DatabaseStatus('deleted'); + } + return self::$DELETED; + } + public static function RESTORING(): DatabaseStatus + { + if (!isset(self::$RESTORING)) { + self::$RESTORING = new DatabaseStatus('restoring'); + } + return self::$RESTORING; + } + public static function SCALING(): DatabaseStatus + { + if (!isset(self::$SCALING)) { + self::$SCALING = new DatabaseStatus('scaling'); + } + return self::$SCALING; + } + public static function UPGRADING(): DatabaseStatus + { + if (!isset(self::$UPGRADING)) { + self::$UPGRADING = new DatabaseStatus('upgrading'); + } + return self::$UPGRADING; + } + public static function MIGRATING(): DatabaseStatus + { + if (!isset(self::$MIGRATING)) { + self::$MIGRATING = new DatabaseStatus('migrating'); + } + return self::$MIGRATING; + } + public static function PAUSING(): DatabaseStatus + { + if (!isset(self::$PAUSING)) { + self::$PAUSING = new DatabaseStatus('pausing'); + } + return self::$PAUSING; + } + public static function RESUMING(): DatabaseStatus + { + if (!isset(self::$RESUMING)) { + self::$RESUMING = new DatabaseStatus('resuming'); + } + return self::$RESUMING; + } + public static function FAILINGOVER(): DatabaseStatus + { + if (!isset(self::$FAILINGOVER)) { + self::$FAILINGOVER = new DatabaseStatus('failing-over'); + } + return self::$FAILINGOVER; + } public static function from(string $value): self { return match ($value) { 'provisioning' => self::PROVISIONING(), 'ready' => self::READY(), + 'inactive' => self::INACTIVE(), + 'paused' => self::PAUSED(), 'failed' => self::FAILED(), + 'deleting' => self::DELETING(), + 'deleted' => self::DELETED(), + 'restoring' => self::RESTORING(), + 'scaling' => self::SCALING(), + 'upgrading' => self::UPGRADING(), + 'migrating' => self::MIGRATING(), + 'pausing' => self::PAUSING(), + 'resuming' => self::RESUMING(), + 'failing-over' => self::FAILINGOVER(), default => throw new \InvalidArgumentException('Unknown DatabaseStatus value: ' . $value), }; } diff --git a/src/Appwrite/Enums/DatabaseType.php b/src/Appwrite/Enums/DatabaseType.php index e5d7dfe5..56d1cff0 100644 --- a/src/Appwrite/Enums/DatabaseType.php +++ b/src/Appwrite/Enums/DatabaseType.php @@ -10,6 +10,9 @@ class DatabaseType implements JsonSerializable private static DatabaseType $TABLESDB; private static DatabaseType $DOCUMENTSDB; private static DatabaseType $VECTORSDB; + private static DatabaseType $MYSQL; + private static DatabaseType $POSTGRESQL; + private static DatabaseType $MONGODB; private string $value; @@ -56,6 +59,27 @@ public static function VECTORSDB(): DatabaseType } return self::$VECTORSDB; } + public static function MYSQL(): DatabaseType + { + if (!isset(self::$MYSQL)) { + self::$MYSQL = new DatabaseType('mysql'); + } + return self::$MYSQL; + } + public static function POSTGRESQL(): DatabaseType + { + if (!isset(self::$POSTGRESQL)) { + self::$POSTGRESQL = new DatabaseType('postgresql'); + } + return self::$POSTGRESQL; + } + public static function MONGODB(): DatabaseType + { + if (!isset(self::$MONGODB)) { + self::$MONGODB = new DatabaseType('mongodb'); + } + return self::$MONGODB; + } public static function from(string $value): self { @@ -64,6 +88,9 @@ public static function from(string $value): self 'tablesdb' => self::TABLESDB(), 'documentsdb' => self::DOCUMENTSDB(), 'vectorsdb' => self::VECTORSDB(), + 'mysql' => self::MYSQL(), + 'postgresql' => self::POSTGRESQL(), + 'mongodb' => self::MONGODB(), default => throw new \InvalidArgumentException('Unknown DatabaseType value: ' . $value), }; } diff --git a/src/Appwrite/Enums/OrganizationKeyScopes.php b/src/Appwrite/Enums/OrganizationKeyScopes.php index 7bf3987f..2d0e5d85 100644 --- a/src/Appwrite/Enums/OrganizationKeyScopes.php +++ b/src/Appwrite/Enums/OrganizationKeyScopes.php @@ -12,6 +12,8 @@ class OrganizationKeyScopes implements JsonSerializable private static OrganizationKeyScopes $DEVKEYSWRITE; private static OrganizationKeyScopes $ORGANIZATIONKEYSREAD; private static OrganizationKeyScopes $ORGANIZATIONKEYSWRITE; + private static OrganizationKeyScopes $ORGANIZATIONINSTALLATIONSREAD; + private static OrganizationKeyScopes $ORGANIZATIONINSTALLATIONSWRITE; private static OrganizationKeyScopes $ORGANIZATIONMEMBERSHIPSREAD; private static OrganizationKeyScopes $ORGANIZATIONMEMBERSHIPSWRITE; private static OrganizationKeyScopes $ORGANIZATIONREAD; @@ -80,6 +82,20 @@ public static function ORGANIZATIONKEYSWRITE(): OrganizationKeyScopes } return self::$ORGANIZATIONKEYSWRITE; } + public static function ORGANIZATIONINSTALLATIONSREAD(): OrganizationKeyScopes + { + if (!isset(self::$ORGANIZATIONINSTALLATIONSREAD)) { + self::$ORGANIZATIONINSTALLATIONSREAD = new OrganizationKeyScopes('organization.installations.read'); + } + return self::$ORGANIZATIONINSTALLATIONSREAD; + } + public static function ORGANIZATIONINSTALLATIONSWRITE(): OrganizationKeyScopes + { + if (!isset(self::$ORGANIZATIONINSTALLATIONSWRITE)) { + self::$ORGANIZATIONINSTALLATIONSWRITE = new OrganizationKeyScopes('organization.installations.write'); + } + return self::$ORGANIZATIONINSTALLATIONSWRITE; + } public static function ORGANIZATIONMEMBERSHIPSREAD(): OrganizationKeyScopes { if (!isset(self::$ORGANIZATIONMEMBERSHIPSREAD)) { @@ -146,6 +162,8 @@ public static function from(string $value): self 'devKeys.write' => self::DEVKEYSWRITE(), 'organization.keys.read' => self::ORGANIZATIONKEYSREAD(), 'organization.keys.write' => self::ORGANIZATIONKEYSWRITE(), + 'organization.installations.read' => self::ORGANIZATIONINSTALLATIONSREAD(), + 'organization.installations.write' => self::ORGANIZATIONINSTALLATIONSWRITE(), 'organization.memberships.read' => self::ORGANIZATIONMEMBERSHIPSREAD(), 'organization.memberships.write' => self::ORGANIZATIONMEMBERSHIPSWRITE(), 'organization.read' => self::ORGANIZATIONREAD(), diff --git a/src/Appwrite/Enums/ProjectKeyScopes.php b/src/Appwrite/Enums/ProjectKeyScopes.php index c087a037..b7d37a76 100644 --- a/src/Appwrite/Enums/ProjectKeyScopes.php +++ b/src/Appwrite/Enums/ProjectKeyScopes.php @@ -101,11 +101,14 @@ class ProjectKeyScopes implements JsonSerializable private static ProjectKeyScopes $DEDICATEDDATABASESEXECUTE; private static ProjectKeyScopes $DOMAINSREAD; private static ProjectKeyScopes $DOMAINSWRITE; + private static ProjectKeyScopes $WAFRULESREAD; + private static ProjectKeyScopes $WAFRULESWRITE; private static ProjectKeyScopes $EVENTSREAD; private static ProjectKeyScopes $APPSREAD; private static ProjectKeyScopes $APPSWRITE; private static ProjectKeyScopes $OAUTH2READ; private static ProjectKeyScopes $OAUTH2WRITE; + private static ProjectKeyScopes $OAUTH2INTROSPECT; private static ProjectKeyScopes $USAGEREAD; private string $value; @@ -790,6 +793,20 @@ public static function DOMAINSWRITE(): ProjectKeyScopes } return self::$DOMAINSWRITE; } + public static function WAFRULESREAD(): ProjectKeyScopes + { + if (!isset(self::$WAFRULESREAD)) { + self::$WAFRULESREAD = new ProjectKeyScopes('wafRules.read'); + } + return self::$WAFRULESREAD; + } + public static function WAFRULESWRITE(): ProjectKeyScopes + { + if (!isset(self::$WAFRULESWRITE)) { + self::$WAFRULESWRITE = new ProjectKeyScopes('wafRules.write'); + } + return self::$WAFRULESWRITE; + } public static function EVENTSREAD(): ProjectKeyScopes { if (!isset(self::$EVENTSREAD)) { @@ -825,6 +842,13 @@ public static function OAUTH2WRITE(): ProjectKeyScopes } return self::$OAUTH2WRITE; } + public static function OAUTH2INTROSPECT(): ProjectKeyScopes + { + if (!isset(self::$OAUTH2INTROSPECT)) { + self::$OAUTH2INTROSPECT = new ProjectKeyScopes('oauth2.introspect'); + } + return self::$OAUTH2INTROSPECT; + } public static function USAGEREAD(): ProjectKeyScopes { if (!isset(self::$USAGEREAD)) { @@ -931,11 +955,14 @@ public static function from(string $value): self 'dedicatedDatabases.execute' => self::DEDICATEDDATABASESEXECUTE(), 'domains.read' => self::DOMAINSREAD(), 'domains.write' => self::DOMAINSWRITE(), + 'wafRules.read' => self::WAFRULESREAD(), + 'wafRules.write' => self::WAFRULESWRITE(), 'events.read' => self::EVENTSREAD(), 'apps.read' => self::APPSREAD(), 'apps.write' => self::APPSWRITE(), 'oauth2.read' => self::OAUTH2READ(), 'oauth2.write' => self::OAUTH2WRITE(), + 'oauth2.introspect' => self::OAUTH2INTROSPECT(), 'usage.read' => self::USAGEREAD(), default => throw new \InvalidArgumentException('Unknown ProjectKeyScopes value: ' . $value), }; diff --git a/src/Appwrite/Models/ActivityEvent.php b/src/Appwrite/Models/ActivityEvent.php index 5c6429ab..3bb7b87c 100644 --- a/src/Appwrite/Models/ActivityEvent.php +++ b/src/Appwrite/Models/ActivityEvent.php @@ -26,10 +26,21 @@ * @param string $ip ip address. * @param string $mode api mode when event triggered. * @param string $country location. + * @param string $continentCode continent code. + * @param string $city city name. + * @param string $subdivisions region/state chain. + * @param string $isp internet service provider. + * @param string $autonomousSystemNumber autonomous system number (asn). + * @param string $autonomousSystemOrganization organization that owns the asn. + * @param string $connectionType connection type (e.g. cable, cellular, corporate). + * @param string $connectionUsageType user type (e.g. residential, business, hosting). + * @param string $connectionOrganization registered organization of the ip. * @param string $time log creation date in iso 8601 format. * @param string $projectId project id. * @param string $teamId team id. * @param string $hostname hostname. + * @param string $sdk name of the sdk that triggered the event. + * @param string $sdkVersion version of the sdk that triggered the event. */ public function __construct( public string $id, @@ -46,10 +57,21 @@ public function __construct( public string $ip, public string $mode, public string $country, + public string $continentCode, + public string $city, + public string $subdivisions, + public string $isp, + public string $autonomousSystemNumber, + public string $autonomousSystemOrganization, + public string $connectionType, + public string $connectionUsageType, + public string $connectionOrganization, public string $time, public string $projectId, public string $teamId, - public string $hostname + public string $hostname, + public string $sdk, + public string $sdkVersion ) { } @@ -100,6 +122,33 @@ public static function from(array $data): static if (!array_key_exists('country', $data)) { throw new \InvalidArgumentException('Missing required field "country" for ' . static::class . '.'); } + if (!array_key_exists('continentCode', $data)) { + throw new \InvalidArgumentException('Missing required field "continentCode" for ' . static::class . '.'); + } + if (!array_key_exists('city', $data)) { + throw new \InvalidArgumentException('Missing required field "city" for ' . static::class . '.'); + } + if (!array_key_exists('subdivisions', $data)) { + throw new \InvalidArgumentException('Missing required field "subdivisions" for ' . static::class . '.'); + } + if (!array_key_exists('isp', $data)) { + throw new \InvalidArgumentException('Missing required field "isp" for ' . static::class . '.'); + } + if (!array_key_exists('autonomousSystemNumber', $data)) { + throw new \InvalidArgumentException('Missing required field "autonomousSystemNumber" for ' . static::class . '.'); + } + if (!array_key_exists('autonomousSystemOrganization', $data)) { + throw new \InvalidArgumentException('Missing required field "autonomousSystemOrganization" for ' . static::class . '.'); + } + if (!array_key_exists('connectionType', $data)) { + throw new \InvalidArgumentException('Missing required field "connectionType" for ' . static::class . '.'); + } + if (!array_key_exists('connectionUsageType', $data)) { + throw new \InvalidArgumentException('Missing required field "connectionUsageType" for ' . static::class . '.'); + } + if (!array_key_exists('connectionOrganization', $data)) { + throw new \InvalidArgumentException('Missing required field "connectionOrganization" for ' . static::class . '.'); + } if (!array_key_exists('time', $data)) { throw new \InvalidArgumentException('Missing required field "time" for ' . static::class . '.'); } @@ -112,6 +161,12 @@ public static function from(array $data): static if (!array_key_exists('hostname', $data)) { throw new \InvalidArgumentException('Missing required field "hostname" for ' . static::class . '.'); } + if (!array_key_exists('sdk', $data)) { + throw new \InvalidArgumentException('Missing required field "sdk" for ' . static::class . '.'); + } + if (!array_key_exists('sdkVersion', $data)) { + throw new \InvalidArgumentException('Missing required field "sdkVersion" for ' . static::class . '.'); + } return new static( id: $data['$id'], @@ -128,10 +183,21 @@ public static function from(array $data): static ip: $data['ip'], mode: $data['mode'], country: $data['country'], + continentCode: $data['continentCode'], + city: $data['city'], + subdivisions: $data['subdivisions'], + isp: $data['isp'], + autonomousSystemNumber: $data['autonomousSystemNumber'], + autonomousSystemOrganization: $data['autonomousSystemOrganization'], + connectionType: $data['connectionType'], + connectionUsageType: $data['connectionUsageType'], + connectionOrganization: $data['connectionOrganization'], time: $data['time'], projectId: $data['projectId'], teamId: $data['teamId'], - hostname: $data['hostname'] + hostname: $data['hostname'], + sdk: $data['sdk'], + sdkVersion: $data['sdkVersion'] ); } @@ -155,10 +221,21 @@ public function toArray(): array 'ip' => static::serializeValue($this->ip), 'mode' => static::serializeValue($this->mode), 'country' => static::serializeValue($this->country), + 'continentCode' => static::serializeValue($this->continentCode), + 'city' => static::serializeValue($this->city), + 'subdivisions' => static::serializeValue($this->subdivisions), + 'isp' => static::serializeValue($this->isp), + 'autonomousSystemNumber' => static::serializeValue($this->autonomousSystemNumber), + 'autonomousSystemOrganization' => static::serializeValue($this->autonomousSystemOrganization), + 'connectionType' => static::serializeValue($this->connectionType), + 'connectionUsageType' => static::serializeValue($this->connectionUsageType), + 'connectionOrganization' => static::serializeValue($this->connectionOrganization), 'time' => static::serializeValue($this->time), 'projectId' => static::serializeValue($this->projectId), 'teamId' => static::serializeValue($this->teamId), - 'hostname' => static::serializeValue($this->hostname) + 'hostname' => static::serializeValue($this->hostname), + 'sdk' => static::serializeValue($this->sdk), + 'sdkVersion' => static::serializeValue($this->sdkVersion) ]; return $result; diff --git a/src/Appwrite/Models/App.php b/src/Appwrite/Models/App.php new file mode 100644 index 00000000..c6d447ef --- /dev/null +++ b/src/Appwrite/Models/App.php @@ -0,0 +1,227 @@ + $secrets list of application secrets. + */ + public function __construct( + public string $id, + public string $createdAt, + public string $updatedAt, + public string $name, + public string $description, + public string $clientUri, + public string $logoUri, + public string $privacyPolicyUrl, + public string $termsUrl, + public array $contacts, + public string $tagline, + public array $tags, + public array $labels, + public array $images, + public string $supportUrl, + public string $dataDeletionUrl, + public array $redirectUris, + public array $postLogoutRedirectUris, + public bool $enabled, + public string $type, + public bool $deviceFlow, + public string $teamId, + public string $userId, + public array $installationScopes, + public string $installationRedirectUrl, + public array $secrets + ) { + } + + /** + * @param array $data + */ + public static function from(array $data): static + { + if (!array_key_exists('$id', $data)) { + throw new \InvalidArgumentException('Missing required field "$id" for ' . static::class . '.'); + } + if (!array_key_exists('$createdAt', $data)) { + throw new \InvalidArgumentException('Missing required field "$createdAt" for ' . static::class . '.'); + } + if (!array_key_exists('$updatedAt', $data)) { + throw new \InvalidArgumentException('Missing required field "$updatedAt" for ' . static::class . '.'); + } + if (!array_key_exists('name', $data)) { + throw new \InvalidArgumentException('Missing required field "name" for ' . static::class . '.'); + } + if (!array_key_exists('description', $data)) { + throw new \InvalidArgumentException('Missing required field "description" for ' . static::class . '.'); + } + if (!array_key_exists('clientUri', $data)) { + throw new \InvalidArgumentException('Missing required field "clientUri" for ' . static::class . '.'); + } + if (!array_key_exists('logoUri', $data)) { + throw new \InvalidArgumentException('Missing required field "logoUri" for ' . static::class . '.'); + } + if (!array_key_exists('privacyPolicyUrl', $data)) { + throw new \InvalidArgumentException('Missing required field "privacyPolicyUrl" for ' . static::class . '.'); + } + if (!array_key_exists('termsUrl', $data)) { + throw new \InvalidArgumentException('Missing required field "termsUrl" for ' . static::class . '.'); + } + if (!array_key_exists('contacts', $data)) { + throw new \InvalidArgumentException('Missing required field "contacts" for ' . static::class . '.'); + } + if (!array_key_exists('tagline', $data)) { + throw new \InvalidArgumentException('Missing required field "tagline" for ' . static::class . '.'); + } + if (!array_key_exists('tags', $data)) { + throw new \InvalidArgumentException('Missing required field "tags" for ' . static::class . '.'); + } + if (!array_key_exists('labels', $data)) { + throw new \InvalidArgumentException('Missing required field "labels" for ' . static::class . '.'); + } + if (!array_key_exists('images', $data)) { + throw new \InvalidArgumentException('Missing required field "images" for ' . static::class . '.'); + } + if (!array_key_exists('supportUrl', $data)) { + throw new \InvalidArgumentException('Missing required field "supportUrl" for ' . static::class . '.'); + } + if (!array_key_exists('dataDeletionUrl', $data)) { + throw new \InvalidArgumentException('Missing required field "dataDeletionUrl" for ' . static::class . '.'); + } + if (!array_key_exists('redirectUris', $data)) { + throw new \InvalidArgumentException('Missing required field "redirectUris" for ' . static::class . '.'); + } + if (!array_key_exists('postLogoutRedirectUris', $data)) { + throw new \InvalidArgumentException('Missing required field "postLogoutRedirectUris" for ' . static::class . '.'); + } + if (!array_key_exists('enabled', $data)) { + throw new \InvalidArgumentException('Missing required field "enabled" for ' . static::class . '.'); + } + if (!array_key_exists('type', $data)) { + throw new \InvalidArgumentException('Missing required field "type" for ' . static::class . '.'); + } + if (!array_key_exists('deviceFlow', $data)) { + throw new \InvalidArgumentException('Missing required field "deviceFlow" for ' . static::class . '.'); + } + if (!array_key_exists('teamId', $data)) { + throw new \InvalidArgumentException('Missing required field "teamId" for ' . static::class . '.'); + } + if (!array_key_exists('userId', $data)) { + throw new \InvalidArgumentException('Missing required field "userId" for ' . static::class . '.'); + } + if (!array_key_exists('installationScopes', $data)) { + throw new \InvalidArgumentException('Missing required field "installationScopes" for ' . static::class . '.'); + } + if (!array_key_exists('installationRedirectUrl', $data)) { + throw new \InvalidArgumentException('Missing required field "installationRedirectUrl" for ' . static::class . '.'); + } + if (!array_key_exists('secrets', $data)) { + throw new \InvalidArgumentException('Missing required field "secrets" for ' . static::class . '.'); + } + + return new static( + id: $data['$id'], + createdAt: $data['$createdAt'], + updatedAt: $data['$updatedAt'], + name: $data['name'], + description: $data['description'], + clientUri: $data['clientUri'], + logoUri: $data['logoUri'], + privacyPolicyUrl: $data['privacyPolicyUrl'], + termsUrl: $data['termsUrl'], + contacts: $data['contacts'], + tagline: $data['tagline'], + tags: $data['tags'], + labels: $data['labels'], + images: $data['images'], + supportUrl: $data['supportUrl'], + dataDeletionUrl: $data['dataDeletionUrl'], + redirectUris: $data['redirectUris'], + postLogoutRedirectUris: $data['postLogoutRedirectUris'], + enabled: $data['enabled'], + type: $data['type'], + deviceFlow: $data['deviceFlow'], + teamId: $data['teamId'], + userId: $data['userId'], + installationScopes: $data['installationScopes'], + installationRedirectUrl: $data['installationRedirectUrl'], + secrets: is_array($data['secrets']) + ? array_map( + static fn (mixed $item): mixed => static::hydrateTypedValue(AppSecret::class, $item), + $data['secrets'] + ) + : $data['secrets'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + '$id' => static::serializeValue($this->id), + '$createdAt' => static::serializeValue($this->createdAt), + '$updatedAt' => static::serializeValue($this->updatedAt), + 'name' => static::serializeValue($this->name), + 'description' => static::serializeValue($this->description), + 'clientUri' => static::serializeValue($this->clientUri), + 'logoUri' => static::serializeValue($this->logoUri), + 'privacyPolicyUrl' => static::serializeValue($this->privacyPolicyUrl), + 'termsUrl' => static::serializeValue($this->termsUrl), + 'contacts' => static::serializeValue($this->contacts), + 'tagline' => static::serializeValue($this->tagline), + 'tags' => static::serializeValue($this->tags), + 'labels' => static::serializeValue($this->labels), + 'images' => static::serializeValue($this->images), + 'supportUrl' => static::serializeValue($this->supportUrl), + 'dataDeletionUrl' => static::serializeValue($this->dataDeletionUrl), + 'redirectUris' => static::serializeValue($this->redirectUris), + 'postLogoutRedirectUris' => static::serializeValue($this->postLogoutRedirectUris), + 'enabled' => static::serializeValue($this->enabled), + 'type' => static::serializeValue($this->type), + 'deviceFlow' => static::serializeValue($this->deviceFlow), + 'teamId' => static::serializeValue($this->teamId), + 'userId' => static::serializeValue($this->userId), + 'installationScopes' => static::serializeValue($this->installationScopes), + 'installationRedirectUrl' => static::serializeValue($this->installationRedirectUrl), + 'secrets' => static::serializeValue($this->secrets) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/AppInstallation.php b/src/Appwrite/Models/AppInstallation.php new file mode 100644 index 00000000..1d13ce2f --- /dev/null +++ b/src/Appwrite/Models/AppInstallation.php @@ -0,0 +1,107 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('$id', $data)) { + throw new \InvalidArgumentException('Missing required field "$id" for ' . static::class . '.'); + } + if (!array_key_exists('$createdAt', $data)) { + throw new \InvalidArgumentException('Missing required field "$createdAt" for ' . static::class . '.'); + } + if (!array_key_exists('$updatedAt', $data)) { + throw new \InvalidArgumentException('Missing required field "$updatedAt" for ' . static::class . '.'); + } + if (!array_key_exists('appId', $data)) { + throw new \InvalidArgumentException('Missing required field "appId" for ' . static::class . '.'); + } + if (!array_key_exists('teamId', $data)) { + throw new \InvalidArgumentException('Missing required field "teamId" for ' . static::class . '.'); + } + if (!array_key_exists('scopes', $data)) { + throw new \InvalidArgumentException('Missing required field "scopes" for ' . static::class . '.'); + } + if (!array_key_exists('authorizationDetails', $data)) { + throw new \InvalidArgumentException('Missing required field "authorizationDetails" for ' . static::class . '.'); + } + if (!array_key_exists('createdById', $data)) { + throw new \InvalidArgumentException('Missing required field "createdById" for ' . static::class . '.'); + } + if (!array_key_exists('createdByName', $data)) { + throw new \InvalidArgumentException('Missing required field "createdByName" for ' . static::class . '.'); + } + + return new static( + id: $data['$id'], + createdAt: $data['$createdAt'], + updatedAt: $data['$updatedAt'], + appId: $data['appId'], + teamId: $data['teamId'], + scopes: $data['scopes'], + authorizationDetails: $data['authorizationDetails'], + createdById: $data['createdById'], + createdByName: $data['createdByName'], + lastAccessedAt: array_key_exists('lastAccessedAt', $data) ? $data['lastAccessedAt'] : null + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + '$id' => static::serializeValue($this->id), + '$createdAt' => static::serializeValue($this->createdAt), + '$updatedAt' => static::serializeValue($this->updatedAt), + 'appId' => static::serializeValue($this->appId), + 'teamId' => static::serializeValue($this->teamId), + 'scopes' => static::serializeValue($this->scopes), + 'authorizationDetails' => static::serializeValue($this->authorizationDetails), + 'createdById' => static::serializeValue($this->createdById), + 'createdByName' => static::serializeValue($this->createdByName), + 'lastAccessedAt' => static::serializeValue($this->lastAccessedAt) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/AppInstallationList.php b/src/Appwrite/Models/AppInstallationList.php new file mode 100644 index 00000000..86a00699 --- /dev/null +++ b/src/Appwrite/Models/AppInstallationList.php @@ -0,0 +1,59 @@ + $installations list of installations. + */ + public function __construct( + public int $total, + public array $installations + ) { + } + + /** + * @param array $data + */ + public static function from(array $data): static + { + if (!array_key_exists('total', $data)) { + throw new \InvalidArgumentException('Missing required field "total" for ' . static::class . '.'); + } + if (!array_key_exists('installations', $data)) { + throw new \InvalidArgumentException('Missing required field "installations" for ' . static::class . '.'); + } + + return new static( + total: $data['total'], + installations: is_array($data['installations']) + ? array_map( + static fn (mixed $item): mixed => static::hydrateTypedValue(AppInstallation::class, $item), + $data['installations'] + ) + : $data['installations'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'total' => static::serializeValue($this->total), + 'installations' => static::serializeValue($this->installations) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/AppKey.php b/src/Appwrite/Models/AppKey.php new file mode 100644 index 00000000..471de01f --- /dev/null +++ b/src/Appwrite/Models/AppKey.php @@ -0,0 +1,100 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('$id', $data)) { + throw new \InvalidArgumentException('Missing required field "$id" for ' . static::class . '.'); + } + if (!array_key_exists('$createdAt', $data)) { + throw new \InvalidArgumentException('Missing required field "$createdAt" for ' . static::class . '.'); + } + if (!array_key_exists('$updatedAt', $data)) { + throw new \InvalidArgumentException('Missing required field "$updatedAt" for ' . static::class . '.'); + } + if (!array_key_exists('appId', $data)) { + throw new \InvalidArgumentException('Missing required field "appId" for ' . static::class . '.'); + } + if (!array_key_exists('secret', $data)) { + throw new \InvalidArgumentException('Missing required field "secret" for ' . static::class . '.'); + } + if (!array_key_exists('hint', $data)) { + throw new \InvalidArgumentException('Missing required field "hint" for ' . static::class . '.'); + } + if (!array_key_exists('createdById', $data)) { + throw new \InvalidArgumentException('Missing required field "createdById" for ' . static::class . '.'); + } + if (!array_key_exists('createdByName', $data)) { + throw new \InvalidArgumentException('Missing required field "createdByName" for ' . static::class . '.'); + } + + return new static( + id: $data['$id'], + createdAt: $data['$createdAt'], + updatedAt: $data['$updatedAt'], + appId: $data['appId'], + secret: $data['secret'], + hint: $data['hint'], + createdById: $data['createdById'], + createdByName: $data['createdByName'], + lastAccessedAt: array_key_exists('lastAccessedAt', $data) ? $data['lastAccessedAt'] : null + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + '$id' => static::serializeValue($this->id), + '$createdAt' => static::serializeValue($this->createdAt), + '$updatedAt' => static::serializeValue($this->updatedAt), + 'appId' => static::serializeValue($this->appId), + 'secret' => static::serializeValue($this->secret), + 'hint' => static::serializeValue($this->hint), + 'createdById' => static::serializeValue($this->createdById), + 'createdByName' => static::serializeValue($this->createdByName), + 'lastAccessedAt' => static::serializeValue($this->lastAccessedAt) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/AppKeyList.php b/src/Appwrite/Models/AppKeyList.php new file mode 100644 index 00000000..a5753ead --- /dev/null +++ b/src/Appwrite/Models/AppKeyList.php @@ -0,0 +1,59 @@ + $keys list of keys. + */ + public function __construct( + public int $total, + public array $keys + ) { + } + + /** + * @param array $data + */ + public static function from(array $data): static + { + if (!array_key_exists('total', $data)) { + throw new \InvalidArgumentException('Missing required field "total" for ' . static::class . '.'); + } + if (!array_key_exists('keys', $data)) { + throw new \InvalidArgumentException('Missing required field "keys" for ' . static::class . '.'); + } + + return new static( + total: $data['total'], + keys: is_array($data['keys']) + ? array_map( + static fn (mixed $item): mixed => static::hydrateTypedValue(AppKey::class, $item), + $data['keys'] + ) + : $data['keys'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'total' => static::serializeValue($this->total), + 'keys' => static::serializeValue($this->keys) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/AppScope.php b/src/Appwrite/Models/AppScope.php new file mode 100644 index 00000000..d0517995 --- /dev/null +++ b/src/Appwrite/Models/AppScope.php @@ -0,0 +1,75 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('value', $data)) { + throw new \InvalidArgumentException('Missing required field "value" for ' . static::class . '.'); + } + if (!array_key_exists('description', $data)) { + throw new \InvalidArgumentException('Missing required field "description" for ' . static::class . '.'); + } + if (!array_key_exists('type', $data)) { + throw new \InvalidArgumentException('Missing required field "type" for ' . static::class . '.'); + } + if (!array_key_exists('category', $data)) { + throw new \InvalidArgumentException('Missing required field "category" for ' . static::class . '.'); + } + if (!array_key_exists('deprecated', $data)) { + throw new \InvalidArgumentException('Missing required field "deprecated" for ' . static::class . '.'); + } + + return new static( + value: $data['value'], + description: $data['description'], + type: $data['type'], + category: $data['category'], + deprecated: $data['deprecated'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'value' => static::serializeValue($this->value), + 'description' => static::serializeValue($this->description), + 'type' => static::serializeValue($this->type), + 'category' => static::serializeValue($this->category), + 'deprecated' => static::serializeValue($this->deprecated) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/AppScopeList.php b/src/Appwrite/Models/AppScopeList.php new file mode 100644 index 00000000..32090a96 --- /dev/null +++ b/src/Appwrite/Models/AppScopeList.php @@ -0,0 +1,59 @@ + $scopes list of scopes. + */ + public function __construct( + public int $total, + public array $scopes + ) { + } + + /** + * @param array $data + */ + public static function from(array $data): static + { + if (!array_key_exists('total', $data)) { + throw new \InvalidArgumentException('Missing required field "total" for ' . static::class . '.'); + } + if (!array_key_exists('scopes', $data)) { + throw new \InvalidArgumentException('Missing required field "scopes" for ' . static::class . '.'); + } + + return new static( + total: $data['total'], + scopes: is_array($data['scopes']) + ? array_map( + static fn (mixed $item): mixed => static::hydrateTypedValue(AppScope::class, $item), + $data['scopes'] + ) + : $data['scopes'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'total' => static::serializeValue($this->total), + 'scopes' => static::serializeValue($this->scopes) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/AppSecret.php b/src/Appwrite/Models/AppSecret.php new file mode 100644 index 00000000..5308587c --- /dev/null +++ b/src/Appwrite/Models/AppSecret.php @@ -0,0 +1,100 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('$id', $data)) { + throw new \InvalidArgumentException('Missing required field "$id" for ' . static::class . '.'); + } + if (!array_key_exists('$createdAt', $data)) { + throw new \InvalidArgumentException('Missing required field "$createdAt" for ' . static::class . '.'); + } + if (!array_key_exists('$updatedAt', $data)) { + throw new \InvalidArgumentException('Missing required field "$updatedAt" for ' . static::class . '.'); + } + if (!array_key_exists('appId', $data)) { + throw new \InvalidArgumentException('Missing required field "appId" for ' . static::class . '.'); + } + if (!array_key_exists('secret', $data)) { + throw new \InvalidArgumentException('Missing required field "secret" for ' . static::class . '.'); + } + if (!array_key_exists('hint', $data)) { + throw new \InvalidArgumentException('Missing required field "hint" for ' . static::class . '.'); + } + if (!array_key_exists('createdById', $data)) { + throw new \InvalidArgumentException('Missing required field "createdById" for ' . static::class . '.'); + } + if (!array_key_exists('createdByName', $data)) { + throw new \InvalidArgumentException('Missing required field "createdByName" for ' . static::class . '.'); + } + + return new static( + id: $data['$id'], + createdAt: $data['$createdAt'], + updatedAt: $data['$updatedAt'], + appId: $data['appId'], + secret: $data['secret'], + hint: $data['hint'], + createdById: $data['createdById'], + createdByName: $data['createdByName'], + lastAccessedAt: array_key_exists('lastAccessedAt', $data) ? $data['lastAccessedAt'] : null + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + '$id' => static::serializeValue($this->id), + '$createdAt' => static::serializeValue($this->createdAt), + '$updatedAt' => static::serializeValue($this->updatedAt), + 'appId' => static::serializeValue($this->appId), + 'secret' => static::serializeValue($this->secret), + 'hint' => static::serializeValue($this->hint), + 'createdById' => static::serializeValue($this->createdById), + 'createdByName' => static::serializeValue($this->createdByName), + 'lastAccessedAt' => static::serializeValue($this->lastAccessedAt) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/AppSecretList.php b/src/Appwrite/Models/AppSecretList.php new file mode 100644 index 00000000..2568f739 --- /dev/null +++ b/src/Appwrite/Models/AppSecretList.php @@ -0,0 +1,59 @@ + $secrets list of secrets. + */ + public function __construct( + public int $total, + public array $secrets + ) { + } + + /** + * @param array $data + */ + public static function from(array $data): static + { + if (!array_key_exists('total', $data)) { + throw new \InvalidArgumentException('Missing required field "total" for ' . static::class . '.'); + } + if (!array_key_exists('secrets', $data)) { + throw new \InvalidArgumentException('Missing required field "secrets" for ' . static::class . '.'); + } + + return new static( + total: $data['total'], + secrets: is_array($data['secrets']) + ? array_map( + static fn (mixed $item): mixed => static::hydrateTypedValue(AppSecret::class, $item), + $data['secrets'] + ) + : $data['secrets'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'total' => static::serializeValue($this->total), + 'secrets' => static::serializeValue($this->secrets) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/AppSecretPlaintext.php b/src/Appwrite/Models/AppSecretPlaintext.php new file mode 100644 index 00000000..35c321cb --- /dev/null +++ b/src/Appwrite/Models/AppSecretPlaintext.php @@ -0,0 +1,100 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('$id', $data)) { + throw new \InvalidArgumentException('Missing required field "$id" for ' . static::class . '.'); + } + if (!array_key_exists('$createdAt', $data)) { + throw new \InvalidArgumentException('Missing required field "$createdAt" for ' . static::class . '.'); + } + if (!array_key_exists('$updatedAt', $data)) { + throw new \InvalidArgumentException('Missing required field "$updatedAt" for ' . static::class . '.'); + } + if (!array_key_exists('appId', $data)) { + throw new \InvalidArgumentException('Missing required field "appId" for ' . static::class . '.'); + } + if (!array_key_exists('secret', $data)) { + throw new \InvalidArgumentException('Missing required field "secret" for ' . static::class . '.'); + } + if (!array_key_exists('hint', $data)) { + throw new \InvalidArgumentException('Missing required field "hint" for ' . static::class . '.'); + } + if (!array_key_exists('createdById', $data)) { + throw new \InvalidArgumentException('Missing required field "createdById" for ' . static::class . '.'); + } + if (!array_key_exists('createdByName', $data)) { + throw new \InvalidArgumentException('Missing required field "createdByName" for ' . static::class . '.'); + } + + return new static( + id: $data['$id'], + createdAt: $data['$createdAt'], + updatedAt: $data['$updatedAt'], + appId: $data['appId'], + secret: $data['secret'], + hint: $data['hint'], + createdById: $data['createdById'], + createdByName: $data['createdByName'], + lastAccessedAt: array_key_exists('lastAccessedAt', $data) ? $data['lastAccessedAt'] : null + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + '$id' => static::serializeValue($this->id), + '$createdAt' => static::serializeValue($this->createdAt), + '$updatedAt' => static::serializeValue($this->updatedAt), + 'appId' => static::serializeValue($this->appId), + 'secret' => static::serializeValue($this->secret), + 'hint' => static::serializeValue($this->hint), + 'createdById' => static::serializeValue($this->createdById), + 'createdByName' => static::serializeValue($this->createdByName), + 'lastAccessedAt' => static::serializeValue($this->lastAccessedAt) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/AppsList.php b/src/Appwrite/Models/AppsList.php new file mode 100644 index 00000000..547ab60d --- /dev/null +++ b/src/Appwrite/Models/AppsList.php @@ -0,0 +1,59 @@ + $apps list of apps. + */ + public function __construct( + public int $total, + public array $apps + ) { + } + + /** + * @param array $data + */ + public static function from(array $data): static + { + if (!array_key_exists('total', $data)) { + throw new \InvalidArgumentException('Missing required field "total" for ' . static::class . '.'); + } + if (!array_key_exists('apps', $data)) { + throw new \InvalidArgumentException('Missing required field "apps" for ' . static::class . '.'); + } + + return new static( + total: $data['total'], + apps: is_array($data['apps']) + ? array_map( + static fn (mixed $item): mixed => static::hydrateTypedValue(App::class, $item), + $data['apps'] + ) + : $data['apps'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'total' => static::serializeValue($this->total), + 'apps' => static::serializeValue($this->apps) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/BillingPlan.php b/src/Appwrite/Models/BillingPlan.php index dcfd652e..951b4073 100644 --- a/src/Appwrite/Models/BillingPlan.php +++ b/src/Appwrite/Models/BillingPlan.php @@ -26,6 +26,7 @@ * @param int $screenshotsGenerated screenshots generated * @param int $members members * @param int $webhooks webhooks + * @param int $wafRules maximum waf rules per project * @param int $projects projects * @param int $platforms platforms * @param int $users users @@ -96,6 +97,7 @@ public function __construct( public int $screenshotsGenerated, public int $members, public int $webhooks, + public int $wafRules, public int $projects, public int $platforms, public int $users, @@ -196,6 +198,9 @@ public static function from(array $data): static if (!array_key_exists('webhooks', $data)) { throw new \InvalidArgumentException('Missing required field "webhooks" for ' . static::class . '.'); } + if (!array_key_exists('wafRules', $data)) { + throw new \InvalidArgumentException('Missing required field "wafRules" for ' . static::class . '.'); + } if (!array_key_exists('projects', $data)) { throw new \InvalidArgumentException('Missing required field "projects" for ' . static::class . '.'); } @@ -366,6 +371,7 @@ public static function from(array $data): static screenshotsGenerated: $data['screenshotsGenerated'], members: $data['members'], webhooks: $data['webhooks'], + wafRules: $data['wafRules'], projects: $data['projects'], platforms: $data['platforms'], users: $data['users'], @@ -443,6 +449,7 @@ public function toArray(): array 'screenshotsGenerated' => static::serializeValue($this->screenshotsGenerated), 'members' => static::serializeValue($this->members), 'webhooks' => static::serializeValue($this->webhooks), + 'wafRules' => static::serializeValue($this->wafRules), 'projects' => static::serializeValue($this->projects), 'platforms' => static::serializeValue($this->platforms), 'users' => static::serializeValue($this->users), diff --git a/src/Appwrite/Models/Database.php b/src/Appwrite/Models/Database.php index 6a226440..fb6f77f3 100644 --- a/src/Appwrite/Models/Database.php +++ b/src/Appwrite/Models/Database.php @@ -21,9 +21,12 @@ * @param string $updatedAt database update date in iso 8601 format. * @param bool $enabled if database is enabled. can be 'enabled' or 'disabled'. when disabled, the database is inaccessible to users, but remains accessible to server sdks using api keys. * @param DatabaseType $type database type. - * @param list $policies database backup policies. - * @param list $archives database backup archives. - * @param DatabaseStatus|null $status database status. possible values: `provisioning`, `ready` or `failed` + * @param DatabaseStatus|null $status dedicated database lifecycle status. null when the database has no valid dedicated backing. + * @param string|null $engine underlying engine of the dedicated backing: postgresql, mysql, mariadb, or mongodb. a managed product (tablesdb, documentsdb, vectorsdb) reports the engine it runs on, so its type and engine can differ. null when the database has no dedicated backing. + * @param string|null $specification compute specification identifier of the dedicated backing, e.g. s-2vcpu-2gb. null when the database has no dedicated backing. + * @param int|null $replicas number of secondary high availability replicas, excluding the primary. null when backing configuration is unavailable. + * @param list|null $policies database backup policies. + * @param list|null $archives database backup archives. */ public function __construct( public string $id, @@ -32,9 +35,12 @@ public function __construct( public string $updatedAt, public bool $enabled, public DatabaseType $type, - public array $policies, - public array $archives, - public ?DatabaseStatus $status = null + public ?DatabaseStatus $status = null, + public ?string $engine = null, + public ?string $specification = null, + public ?int $replicas = null, + public ?array $policies = null, + public ?array $archives = null ) { } @@ -61,12 +67,6 @@ public static function from(array $data): static if (!array_key_exists('type', $data)) { throw new \InvalidArgumentException('Missing required field "type" for ' . static::class . '.'); } - if (!array_key_exists('policies', $data)) { - throw new \InvalidArgumentException('Missing required field "policies" for ' . static::class . '.'); - } - if (!array_key_exists('archives', $data)) { - throw new \InvalidArgumentException('Missing required field "archives" for ' . static::class . '.'); - } return new static( id: $data['$id'], @@ -75,19 +75,30 @@ public static function from(array $data): static updatedAt: $data['$updatedAt'], enabled: $data['enabled'], type: static::hydrateTypedValue(DatabaseType::class, $data['type']), - policies: is_array($data['policies']) - ? array_map( - static fn (mixed $item): mixed => static::hydrateTypedValue(BackupPolicy::class, $item), - $data['policies'] + status: array_key_exists('status', $data) ? static::hydrateTypedValue(DatabaseStatus::class, $data['status'], true) : null, + engine: array_key_exists('engine', $data) ? $data['engine'] : null, + specification: array_key_exists('specification', $data) ? $data['specification'] : null, + replicas: array_key_exists('replicas', $data) ? $data['replicas'] : null, + policies: array_key_exists('policies', $data) + ? ( + is_array($data['policies']) + ? array_map( + static fn (mixed $item): mixed => static::hydrateTypedValue(BackupPolicy::class, $item), + $data['policies'] + ) + : $data['policies'] ) - : $data['policies'], - archives: is_array($data['archives']) - ? array_map( - static fn (mixed $item): mixed => static::hydrateTypedValue(BackupArchive::class, $item), - $data['archives'] + : null, + archives: array_key_exists('archives', $data) + ? ( + is_array($data['archives']) + ? array_map( + static fn (mixed $item): mixed => static::hydrateTypedValue(BackupArchive::class, $item), + $data['archives'] + ) + : $data['archives'] ) - : $data['archives'], - status: array_key_exists('status', $data) ? static::hydrateTypedValue(DatabaseStatus::class, $data['status'], true) : null + : null ); } @@ -104,6 +115,9 @@ public function toArray(): array 'enabled' => static::serializeValue($this->enabled), 'type' => static::serializeValue($this->type), 'status' => static::serializeValue($this->status), + 'engine' => static::serializeValue($this->engine), + 'specification' => static::serializeValue($this->specification), + 'replicas' => static::serializeValue($this->replicas), 'policies' => static::serializeValue($this->policies), 'archives' => static::serializeValue($this->archives) ]; diff --git a/src/Appwrite/Models/DatabaseStatus.php b/src/Appwrite/Models/DatabaseStatus.php new file mode 100644 index 00000000..59b30ffd --- /dev/null +++ b/src/Appwrite/Models/DatabaseStatus.php @@ -0,0 +1,106 @@ + $replicas list of database replicas and their status. + * @param list $volumes storage volume information. + */ + public function __construct( + public string $health, + public bool $ready, + public string $engine, + public string $version, + public int $uptime, + public DatabaseStatusConnections $connections, + public array $replicas, + public array $volumes + ) { + } + + /** + * @param array $data + */ + public static function from(array $data): static + { + if (!array_key_exists('health', $data)) { + throw new \InvalidArgumentException('Missing required field "health" for ' . static::class . '.'); + } + if (!array_key_exists('ready', $data)) { + throw new \InvalidArgumentException('Missing required field "ready" for ' . static::class . '.'); + } + if (!array_key_exists('engine', $data)) { + throw new \InvalidArgumentException('Missing required field "engine" for ' . static::class . '.'); + } + if (!array_key_exists('version', $data)) { + throw new \InvalidArgumentException('Missing required field "version" for ' . static::class . '.'); + } + if (!array_key_exists('uptime', $data)) { + throw new \InvalidArgumentException('Missing required field "uptime" for ' . static::class . '.'); + } + if (!array_key_exists('connections', $data)) { + throw new \InvalidArgumentException('Missing required field "connections" for ' . static::class . '.'); + } + if (!array_key_exists('replicas', $data)) { + throw new \InvalidArgumentException('Missing required field "replicas" for ' . static::class . '.'); + } + if (!array_key_exists('volumes', $data)) { + throw new \InvalidArgumentException('Missing required field "volumes" for ' . static::class . '.'); + } + + return new static( + health: $data['health'], + ready: $data['ready'], + engine: $data['engine'], + version: $data['version'], + uptime: $data['uptime'], + connections: static::hydrateTypedValue(DatabaseStatusConnections::class, $data['connections']), + replicas: is_array($data['replicas']) + ? array_map( + static fn (mixed $item): mixed => static::hydrateTypedValue(DatabaseStatusReplica::class, $item), + $data['replicas'] + ) + : $data['replicas'], + volumes: is_array($data['volumes']) + ? array_map( + static fn (mixed $item): mixed => static::hydrateTypedValue(DatabaseStatusVolume::class, $item), + $data['volumes'] + ) + : $data['volumes'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'health' => static::serializeValue($this->health), + 'ready' => static::serializeValue($this->ready), + 'engine' => static::serializeValue($this->engine), + 'version' => static::serializeValue($this->version), + 'uptime' => static::serializeValue($this->uptime), + 'connections' => static::serializeValue($this->connections), + 'replicas' => static::serializeValue($this->replicas), + 'volumes' => static::serializeValue($this->volumes) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/DatabaseStatusConnections.php b/src/Appwrite/Models/DatabaseStatusConnections.php new file mode 100644 index 00000000..b1917238 --- /dev/null +++ b/src/Appwrite/Models/DatabaseStatusConnections.php @@ -0,0 +1,54 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('current', $data)) { + throw new \InvalidArgumentException('Missing required field "current" for ' . static::class . '.'); + } + if (!array_key_exists('max', $data)) { + throw new \InvalidArgumentException('Missing required field "max" for ' . static::class . '.'); + } + + return new static( + current: $data['current'], + max: $data['max'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'current' => static::serializeValue($this->current), + 'max' => static::serializeValue($this->max) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/DatabaseStatusReplica.php b/src/Appwrite/Models/DatabaseStatusReplica.php new file mode 100644 index 00000000..acf6559c --- /dev/null +++ b/src/Appwrite/Models/DatabaseStatusReplica.php @@ -0,0 +1,65 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('index', $data)) { + throw new \InvalidArgumentException('Missing required field "index" for ' . static::class . '.'); + } + if (!array_key_exists('role', $data)) { + throw new \InvalidArgumentException('Missing required field "role" for ' . static::class . '.'); + } + if (!array_key_exists('healthy', $data)) { + throw new \InvalidArgumentException('Missing required field "healthy" for ' . static::class . '.'); + } + + return new static( + index: $data['index'], + role: $data['role'], + healthy: $data['healthy'], + lagSeconds: array_key_exists('lagSeconds', $data) ? $data['lagSeconds'] : null + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'index' => static::serializeValue($this->index), + 'role' => static::serializeValue($this->role), + 'healthy' => static::serializeValue($this->healthy), + 'lagSeconds' => static::serializeValue($this->lagSeconds) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/DatabaseStatusVolume.php b/src/Appwrite/Models/DatabaseStatusVolume.php new file mode 100644 index 00000000..974ce9cf --- /dev/null +++ b/src/Appwrite/Models/DatabaseStatusVolume.php @@ -0,0 +1,68 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('path', $data)) { + throw new \InvalidArgumentException('Missing required field "path" for ' . static::class . '.'); + } + if (!array_key_exists('usedPercent', $data)) { + throw new \InvalidArgumentException('Missing required field "usedPercent" for ' . static::class . '.'); + } + if (!array_key_exists('available', $data)) { + throw new \InvalidArgumentException('Missing required field "available" for ' . static::class . '.'); + } + if (!array_key_exists('mounted', $data)) { + throw new \InvalidArgumentException('Missing required field "mounted" for ' . static::class . '.'); + } + + return new static( + path: $data['path'], + usedPercent: $data['usedPercent'], + available: $data['available'], + mounted: $data['mounted'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'path' => static::serializeValue($this->path), + 'usedPercent' => static::serializeValue($this->usedPercent), + 'available' => static::serializeValue($this->available), + 'mounted' => static::serializeValue($this->mounted) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/DedicatedDatabase.php b/src/Appwrite/Models/DedicatedDatabase.php new file mode 100644 index 00000000..963e95fa --- /dev/null +++ b/src/Appwrite/Models/DedicatedDatabase.php @@ -0,0 +1,377 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('$id', $data)) { + throw new \InvalidArgumentException('Missing required field "$id" for ' . static::class . '.'); + } + if (!array_key_exists('$createdAt', $data)) { + throw new \InvalidArgumentException('Missing required field "$createdAt" for ' . static::class . '.'); + } + if (!array_key_exists('$updatedAt', $data)) { + throw new \InvalidArgumentException('Missing required field "$updatedAt" for ' . static::class . '.'); + } + if (!array_key_exists('projectId', $data)) { + throw new \InvalidArgumentException('Missing required field "projectId" for ' . static::class . '.'); + } + if (!array_key_exists('name', $data)) { + throw new \InvalidArgumentException('Missing required field "name" for ' . static::class . '.'); + } + if (!array_key_exists('api', $data)) { + throw new \InvalidArgumentException('Missing required field "api" for ' . static::class . '.'); + } + if (!array_key_exists('engine', $data)) { + throw new \InvalidArgumentException('Missing required field "engine" for ' . static::class . '.'); + } + if (!array_key_exists('version', $data)) { + throw new \InvalidArgumentException('Missing required field "version" for ' . static::class . '.'); + } + if (!array_key_exists('specification', $data)) { + throw new \InvalidArgumentException('Missing required field "specification" for ' . static::class . '.'); + } + if (!array_key_exists('backend', $data)) { + throw new \InvalidArgumentException('Missing required field "backend" for ' . static::class . '.'); + } + if (!array_key_exists('hostname', $data)) { + throw new \InvalidArgumentException('Missing required field "hostname" for ' . static::class . '.'); + } + if (!array_key_exists('connectionPort', $data)) { + throw new \InvalidArgumentException('Missing required field "connectionPort" for ' . static::class . '.'); + } + if (!array_key_exists('connectionUser', $data)) { + throw new \InvalidArgumentException('Missing required field "connectionUser" for ' . static::class . '.'); + } + if (!array_key_exists('connectionPassword', $data)) { + throw new \InvalidArgumentException('Missing required field "connectionPassword" for ' . static::class . '.'); + } + if (!array_key_exists('connectionString', $data)) { + throw new \InvalidArgumentException('Missing required field "connectionString" for ' . static::class . '.'); + } + if (!array_key_exists('ssl', $data)) { + throw new \InvalidArgumentException('Missing required field "ssl" for ' . static::class . '.'); + } + if (!array_key_exists('status', $data)) { + throw new \InvalidArgumentException('Missing required field "status" for ' . static::class . '.'); + } + if (!array_key_exists('containerStatus', $data)) { + throw new \InvalidArgumentException('Missing required field "containerStatus" for ' . static::class . '.'); + } + if (!array_key_exists('lifecycleState', $data)) { + throw new \InvalidArgumentException('Missing required field "lifecycleState" for ' . static::class . '.'); + } + if (!array_key_exists('idleTimeoutMinutes', $data)) { + throw new \InvalidArgumentException('Missing required field "idleTimeoutMinutes" for ' . static::class . '.'); + } + if (!array_key_exists('cpu', $data)) { + throw new \InvalidArgumentException('Missing required field "cpu" for ' . static::class . '.'); + } + if (!array_key_exists('memory', $data)) { + throw new \InvalidArgumentException('Missing required field "memory" for ' . static::class . '.'); + } + if (!array_key_exists('storage', $data)) { + throw new \InvalidArgumentException('Missing required field "storage" for ' . static::class . '.'); + } + if (!array_key_exists('storageClass', $data)) { + throw new \InvalidArgumentException('Missing required field "storageClass" for ' . static::class . '.'); + } + if (!array_key_exists('storageMaxGb', $data)) { + throw new \InvalidArgumentException('Missing required field "storageMaxGb" for ' . static::class . '.'); + } + if (!array_key_exists('nodePool', $data)) { + throw new \InvalidArgumentException('Missing required field "nodePool" for ' . static::class . '.'); + } + if (!array_key_exists('replicas', $data)) { + throw new \InvalidArgumentException('Missing required field "replicas" for ' . static::class . '.'); + } + if (!array_key_exists('syncMode', $data)) { + throw new \InvalidArgumentException('Missing required field "syncMode" for ' . static::class . '.'); + } + if (!array_key_exists('crossRegionReplicas', $data)) { + throw new \InvalidArgumentException('Missing required field "crossRegionReplicas" for ' . static::class . '.'); + } + if (!array_key_exists('networkMaxConnections', $data)) { + throw new \InvalidArgumentException('Missing required field "networkMaxConnections" for ' . static::class . '.'); + } + if (!array_key_exists('networkIdleTimeoutSeconds', $data)) { + throw new \InvalidArgumentException('Missing required field "networkIdleTimeoutSeconds" for ' . static::class . '.'); + } + if (!array_key_exists('networkIPAllowlist', $data)) { + throw new \InvalidArgumentException('Missing required field "networkIPAllowlist" for ' . static::class . '.'); + } + if (!array_key_exists('backupEnabled', $data)) { + throw new \InvalidArgumentException('Missing required field "backupEnabled" for ' . static::class . '.'); + } + if (!array_key_exists('pitr', $data)) { + throw new \InvalidArgumentException('Missing required field "pitr" for ' . static::class . '.'); + } + if (!array_key_exists('pitrRetentionDays', $data)) { + throw new \InvalidArgumentException('Missing required field "pitrRetentionDays" for ' . static::class . '.'); + } + if (!array_key_exists('storageAutoscaling', $data)) { + throw new \InvalidArgumentException('Missing required field "storageAutoscaling" for ' . static::class . '.'); + } + if (!array_key_exists('storageAutoscalingThresholdPercent', $data)) { + throw new \InvalidArgumentException('Missing required field "storageAutoscalingThresholdPercent" for ' . static::class . '.'); + } + if (!array_key_exists('storageAutoscalingMaxGb', $data)) { + throw new \InvalidArgumentException('Missing required field "storageAutoscalingMaxGb" for ' . static::class . '.'); + } + if (!array_key_exists('maintenanceWindowDay', $data)) { + throw new \InvalidArgumentException('Missing required field "maintenanceWindowDay" for ' . static::class . '.'); + } + if (!array_key_exists('maintenanceWindowHourUtc', $data)) { + throw new \InvalidArgumentException('Missing required field "maintenanceWindowHourUtc" for ' . static::class . '.'); + } + if (!array_key_exists('metricsEnabled', $data)) { + throw new \InvalidArgumentException('Missing required field "metricsEnabled" for ' . static::class . '.'); + } + if (!array_key_exists('sqlApiEnabled', $data)) { + throw new \InvalidArgumentException('Missing required field "sqlApiEnabled" for ' . static::class . '.'); + } + if (!array_key_exists('sqlApiAllowedStatements', $data)) { + throw new \InvalidArgumentException('Missing required field "sqlApiAllowedStatements" for ' . static::class . '.'); + } + if (!array_key_exists('sqlApiMaxRows', $data)) { + throw new \InvalidArgumentException('Missing required field "sqlApiMaxRows" for ' . static::class . '.'); + } + if (!array_key_exists('sqlApiMaxBytes', $data)) { + throw new \InvalidArgumentException('Missing required field "sqlApiMaxBytes" for ' . static::class . '.'); + } + if (!array_key_exists('sqlApiTimeoutSeconds', $data)) { + throw new \InvalidArgumentException('Missing required field "sqlApiTimeoutSeconds" for ' . static::class . '.'); + } + if (!array_key_exists('error', $data)) { + throw new \InvalidArgumentException('Missing required field "error" for ' . static::class . '.'); + } + + return new static( + id: $data['$id'], + createdAt: $data['$createdAt'], + updatedAt: $data['$updatedAt'], + projectId: $data['projectId'], + name: $data['name'], + api: $data['api'], + engine: $data['engine'], + version: $data['version'], + specification: $data['specification'], + backend: $data['backend'], + hostname: $data['hostname'], + connectionPort: $data['connectionPort'], + connectionUser: $data['connectionUser'], + connectionPassword: $data['connectionPassword'], + connectionString: $data['connectionString'], + ssl: $data['ssl'], + status: $data['status'], + containerStatus: $data['containerStatus'], + lifecycleState: $data['lifecycleState'], + idleTimeoutMinutes: $data['idleTimeoutMinutes'], + cpu: $data['cpu'], + memory: $data['memory'], + storage: $data['storage'], + storageClass: $data['storageClass'], + storageMaxGb: $data['storageMaxGb'], + nodePool: $data['nodePool'], + replicas: $data['replicas'], + syncMode: $data['syncMode'], + crossRegionReplicas: $data['crossRegionReplicas'], + networkMaxConnections: $data['networkMaxConnections'], + networkIdleTimeoutSeconds: $data['networkIdleTimeoutSeconds'], + networkIPAllowlist: $data['networkIPAllowlist'], + backupEnabled: $data['backupEnabled'], + pitr: $data['pitr'], + pitrRetentionDays: $data['pitrRetentionDays'], + storageAutoscaling: $data['storageAutoscaling'], + storageAutoscalingThresholdPercent: $data['storageAutoscalingThresholdPercent'], + storageAutoscalingMaxGb: $data['storageAutoscalingMaxGb'], + maintenanceWindowDay: $data['maintenanceWindowDay'], + maintenanceWindowHourUtc: $data['maintenanceWindowHourUtc'], + metricsEnabled: $data['metricsEnabled'], + sqlApiEnabled: $data['sqlApiEnabled'], + sqlApiAllowedStatements: $data['sqlApiAllowedStatements'], + sqlApiMaxRows: $data['sqlApiMaxRows'], + sqlApiMaxBytes: $data['sqlApiMaxBytes'], + sqlApiTimeoutSeconds: $data['sqlApiTimeoutSeconds'], + error: $data['error'], + lastAccessedAt: array_key_exists('lastAccessedAt', $data) ? $data['lastAccessedAt'] : null, + idleUntil: array_key_exists('idleUntil', $data) ? $data['idleUntil'] : null + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + '$id' => static::serializeValue($this->id), + '$createdAt' => static::serializeValue($this->createdAt), + '$updatedAt' => static::serializeValue($this->updatedAt), + 'projectId' => static::serializeValue($this->projectId), + 'name' => static::serializeValue($this->name), + 'api' => static::serializeValue($this->api), + 'engine' => static::serializeValue($this->engine), + 'version' => static::serializeValue($this->version), + 'specification' => static::serializeValue($this->specification), + 'backend' => static::serializeValue($this->backend), + 'hostname' => static::serializeValue($this->hostname), + 'connectionPort' => static::serializeValue($this->connectionPort), + 'connectionUser' => static::serializeValue($this->connectionUser), + 'connectionPassword' => static::serializeValue($this->connectionPassword), + 'connectionString' => static::serializeValue($this->connectionString), + 'ssl' => static::serializeValue($this->ssl), + 'status' => static::serializeValue($this->status), + 'containerStatus' => static::serializeValue($this->containerStatus), + 'lastAccessedAt' => static::serializeValue($this->lastAccessedAt), + 'idleUntil' => static::serializeValue($this->idleUntil), + 'lifecycleState' => static::serializeValue($this->lifecycleState), + 'idleTimeoutMinutes' => static::serializeValue($this->idleTimeoutMinutes), + 'cpu' => static::serializeValue($this->cpu), + 'memory' => static::serializeValue($this->memory), + 'storage' => static::serializeValue($this->storage), + 'storageClass' => static::serializeValue($this->storageClass), + 'storageMaxGb' => static::serializeValue($this->storageMaxGb), + 'nodePool' => static::serializeValue($this->nodePool), + 'replicas' => static::serializeValue($this->replicas), + 'syncMode' => static::serializeValue($this->syncMode), + 'crossRegionReplicas' => static::serializeValue($this->crossRegionReplicas), + 'networkMaxConnections' => static::serializeValue($this->networkMaxConnections), + 'networkIdleTimeoutSeconds' => static::serializeValue($this->networkIdleTimeoutSeconds), + 'networkIPAllowlist' => static::serializeValue($this->networkIPAllowlist), + 'backupEnabled' => static::serializeValue($this->backupEnabled), + 'pitr' => static::serializeValue($this->pitr), + 'pitrRetentionDays' => static::serializeValue($this->pitrRetentionDays), + 'storageAutoscaling' => static::serializeValue($this->storageAutoscaling), + 'storageAutoscalingThresholdPercent' => static::serializeValue($this->storageAutoscalingThresholdPercent), + 'storageAutoscalingMaxGb' => static::serializeValue($this->storageAutoscalingMaxGb), + 'maintenanceWindowDay' => static::serializeValue($this->maintenanceWindowDay), + 'maintenanceWindowHourUtc' => static::serializeValue($this->maintenanceWindowHourUtc), + 'metricsEnabled' => static::serializeValue($this->metricsEnabled), + 'sqlApiEnabled' => static::serializeValue($this->sqlApiEnabled), + 'sqlApiAllowedStatements' => static::serializeValue($this->sqlApiAllowedStatements), + 'sqlApiMaxRows' => static::serializeValue($this->sqlApiMaxRows), + 'sqlApiMaxBytes' => static::serializeValue($this->sqlApiMaxBytes), + 'sqlApiTimeoutSeconds' => static::serializeValue($this->sqlApiTimeoutSeconds), + 'error' => static::serializeValue($this->error) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/DedicatedDatabaseMember.php b/src/Appwrite/Models/DedicatedDatabaseMember.php new file mode 100644 index 00000000..ba44af70 --- /dev/null +++ b/src/Appwrite/Models/DedicatedDatabaseMember.php @@ -0,0 +1,68 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('$id', $data)) { + throw new \InvalidArgumentException('Missing required field "$id" for ' . static::class . '.'); + } + if (!array_key_exists('role', $data)) { + throw new \InvalidArgumentException('Missing required field "role" for ' . static::class . '.'); + } + if (!array_key_exists('status', $data)) { + throw new \InvalidArgumentException('Missing required field "status" for ' . static::class . '.'); + } + if (!array_key_exists('lagSeconds', $data)) { + throw new \InvalidArgumentException('Missing required field "lagSeconds" for ' . static::class . '.'); + } + + return new static( + id: $data['$id'], + role: $data['role'], + status: $data['status'], + lagSeconds: $data['lagSeconds'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + '$id' => static::serializeValue($this->id), + 'role' => static::serializeValue($this->role), + 'status' => static::serializeValue($this->status), + 'lagSeconds' => static::serializeValue($this->lagSeconds) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/DedicatedDatabaseReplicas.php b/src/Appwrite/Models/DedicatedDatabaseReplicas.php new file mode 100644 index 00000000..37a760d2 --- /dev/null +++ b/src/Appwrite/Models/DedicatedDatabaseReplicas.php @@ -0,0 +1,66 @@ + $members per-pod statuses for the primary and every replica. + */ + public function __construct( + public int $replicas, + public string $syncMode, + public array $members + ) { + } + + /** + * @param array $data + */ + public static function from(array $data): static + { + if (!array_key_exists('replicas', $data)) { + throw new \InvalidArgumentException('Missing required field "replicas" for ' . static::class . '.'); + } + if (!array_key_exists('syncMode', $data)) { + throw new \InvalidArgumentException('Missing required field "syncMode" for ' . static::class . '.'); + } + if (!array_key_exists('members', $data)) { + throw new \InvalidArgumentException('Missing required field "members" for ' . static::class . '.'); + } + + return new static( + replicas: $data['replicas'], + syncMode: $data['syncMode'], + members: is_array($data['members']) + ? array_map( + static fn (mixed $item): mixed => static::hydrateTypedValue(DedicatedDatabaseMember::class, $item), + $data['members'] + ) + : $data['members'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'replicas' => static::serializeValue($this->replicas), + 'syncMode' => static::serializeValue($this->syncMode), + 'members' => static::serializeValue($this->members) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/DedicatedDatabaseSpecification.php b/src/Appwrite/Models/DedicatedDatabaseSpecification.php new file mode 100644 index 00000000..5a1a5a29 --- /dev/null +++ b/src/Appwrite/Models/DedicatedDatabaseSpecification.php @@ -0,0 +1,103 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('slug', $data)) { + throw new \InvalidArgumentException('Missing required field "slug" for ' . static::class . '.'); + } + if (!array_key_exists('name', $data)) { + throw new \InvalidArgumentException('Missing required field "name" for ' . static::class . '.'); + } + if (!array_key_exists('price', $data)) { + throw new \InvalidArgumentException('Missing required field "price" for ' . static::class . '.'); + } + if (!array_key_exists('cpu', $data)) { + throw new \InvalidArgumentException('Missing required field "cpu" for ' . static::class . '.'); + } + if (!array_key_exists('memory', $data)) { + throw new \InvalidArgumentException('Missing required field "memory" for ' . static::class . '.'); + } + if (!array_key_exists('maxConnections', $data)) { + throw new \InvalidArgumentException('Missing required field "maxConnections" for ' . static::class . '.'); + } + if (!array_key_exists('includedStorage', $data)) { + throw new \InvalidArgumentException('Missing required field "includedStorage" for ' . static::class . '.'); + } + if (!array_key_exists('includedBandwidth', $data)) { + throw new \InvalidArgumentException('Missing required field "includedBandwidth" for ' . static::class . '.'); + } + if (!array_key_exists('enabled', $data)) { + throw new \InvalidArgumentException('Missing required field "enabled" for ' . static::class . '.'); + } + + return new static( + slug: $data['slug'], + name: $data['name'], + price: $data['price'], + cpu: $data['cpu'], + memory: $data['memory'], + maxConnections: $data['maxConnections'], + includedStorage: $data['includedStorage'], + includedBandwidth: $data['includedBandwidth'], + enabled: $data['enabled'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'slug' => static::serializeValue($this->slug), + 'name' => static::serializeValue($this->name), + 'price' => static::serializeValue($this->price), + 'cpu' => static::serializeValue($this->cpu), + 'memory' => static::serializeValue($this->memory), + 'maxConnections' => static::serializeValue($this->maxConnections), + 'includedStorage' => static::serializeValue($this->includedStorage), + 'includedBandwidth' => static::serializeValue($this->includedBandwidth), + 'enabled' => static::serializeValue($this->enabled) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/DedicatedDatabaseSpecificationList.php b/src/Appwrite/Models/DedicatedDatabaseSpecificationList.php new file mode 100644 index 00000000..fb040cd3 --- /dev/null +++ b/src/Appwrite/Models/DedicatedDatabaseSpecificationList.php @@ -0,0 +1,66 @@ + $specifications list of dedicated database specifications. + * @param int $total total number of specifications. + * @param DedicatedDatabaseSpecificationPricing $pricing overage and add-on pricing shared across all specifications. + */ + public function __construct( + public array $specifications, + public int $total, + public DedicatedDatabaseSpecificationPricing $pricing + ) { + } + + /** + * @param array $data + */ + public static function from(array $data): static + { + if (!array_key_exists('specifications', $data)) { + throw new \InvalidArgumentException('Missing required field "specifications" for ' . static::class . '.'); + } + if (!array_key_exists('total', $data)) { + throw new \InvalidArgumentException('Missing required field "total" for ' . static::class . '.'); + } + if (!array_key_exists('pricing', $data)) { + throw new \InvalidArgumentException('Missing required field "pricing" for ' . static::class . '.'); + } + + return new static( + specifications: is_array($data['specifications']) + ? array_map( + static fn (mixed $item): mixed => static::hydrateTypedValue(DedicatedDatabaseSpecification::class, $item), + $data['specifications'] + ) + : $data['specifications'], + total: $data['total'], + pricing: static::hydrateTypedValue(DedicatedDatabaseSpecificationPricing::class, $data['pricing']) + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'specifications' => static::serializeValue($this->specifications), + 'total' => static::serializeValue($this->total), + 'pricing' => static::serializeValue($this->pricing) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/DedicatedDatabaseSpecificationPricing.php b/src/Appwrite/Models/DedicatedDatabaseSpecificationPricing.php new file mode 100644 index 00000000..37a3b4c2 --- /dev/null +++ b/src/Appwrite/Models/DedicatedDatabaseSpecificationPricing.php @@ -0,0 +1,75 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('storageOverageRate', $data)) { + throw new \InvalidArgumentException('Missing required field "storageOverageRate" for ' . static::class . '.'); + } + if (!array_key_exists('bandwidthOverageRate', $data)) { + throw new \InvalidArgumentException('Missing required field "bandwidthOverageRate" for ' . static::class . '.'); + } + if (!array_key_exists('replicaRate', $data)) { + throw new \InvalidArgumentException('Missing required field "replicaRate" for ' . static::class . '.'); + } + if (!array_key_exists('crossRegionReplicaRate', $data)) { + throw new \InvalidArgumentException('Missing required field "crossRegionReplicaRate" for ' . static::class . '.'); + } + if (!array_key_exists('pitrRate', $data)) { + throw new \InvalidArgumentException('Missing required field "pitrRate" for ' . static::class . '.'); + } + + return new static( + storageOverageRate: $data['storageOverageRate'], + bandwidthOverageRate: $data['bandwidthOverageRate'], + replicaRate: $data['replicaRate'], + crossRegionReplicaRate: $data['crossRegionReplicaRate'], + pitrRate: $data['pitrRate'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'storageOverageRate' => static::serializeValue($this->storageOverageRate), + 'bandwidthOverageRate' => static::serializeValue($this->bandwidthOverageRate), + 'replicaRate' => static::serializeValue($this->replicaRate), + 'crossRegionReplicaRate' => static::serializeValue($this->crossRegionReplicaRate), + 'pitrRate' => static::serializeValue($this->pitrRate) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/Oauth2Approve.php b/src/Appwrite/Models/Oauth2Approve.php new file mode 100644 index 00000000..e4f896d3 --- /dev/null +++ b/src/Appwrite/Models/Oauth2Approve.php @@ -0,0 +1,47 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('redirectUrl', $data)) { + throw new \InvalidArgumentException('Missing required field "redirectUrl" for ' . static::class . '.'); + } + + return new static( + redirectUrl: $data['redirectUrl'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'redirectUrl' => static::serializeValue($this->redirectUrl) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/Oauth2Authorize.php b/src/Appwrite/Models/Oauth2Authorize.php new file mode 100644 index 00000000..4667084b --- /dev/null +++ b/src/Appwrite/Models/Oauth2Authorize.php @@ -0,0 +1,54 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('grantId', $data)) { + throw new \InvalidArgumentException('Missing required field "grantId" for ' . static::class . '.'); + } + if (!array_key_exists('redirectUrl', $data)) { + throw new \InvalidArgumentException('Missing required field "redirectUrl" for ' . static::class . '.'); + } + + return new static( + grantId: $data['grantId'], + redirectUrl: $data['redirectUrl'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'grantId' => static::serializeValue($this->grantId), + 'redirectUrl' => static::serializeValue($this->redirectUrl) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/Oauth2Consent.php b/src/Appwrite/Models/Oauth2Consent.php new file mode 100644 index 00000000..248995ec --- /dev/null +++ b/src/Appwrite/Models/Oauth2Consent.php @@ -0,0 +1,110 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('$id', $data)) { + throw new \InvalidArgumentException('Missing required field "$id" for ' . static::class . '.'); + } + if (!array_key_exists('$createdAt', $data)) { + throw new \InvalidArgumentException('Missing required field "$createdAt" for ' . static::class . '.'); + } + if (!array_key_exists('$updatedAt', $data)) { + throw new \InvalidArgumentException('Missing required field "$updatedAt" for ' . static::class . '.'); + } + if (!array_key_exists('userId', $data)) { + throw new \InvalidArgumentException('Missing required field "userId" for ' . static::class . '.'); + } + if (!array_key_exists('appId', $data)) { + throw new \InvalidArgumentException('Missing required field "appId" for ' . static::class . '.'); + } + if (!array_key_exists('cimdUrl', $data)) { + throw new \InvalidArgumentException('Missing required field "cimdUrl" for ' . static::class . '.'); + } + if (!array_key_exists('scopes', $data)) { + throw new \InvalidArgumentException('Missing required field "scopes" for ' . static::class . '.'); + } + if (!array_key_exists('resources', $data)) { + throw new \InvalidArgumentException('Missing required field "resources" for ' . static::class . '.'); + } + if (!array_key_exists('authorizationDetails', $data)) { + throw new \InvalidArgumentException('Missing required field "authorizationDetails" for ' . static::class . '.'); + } + if (!array_key_exists('expire', $data)) { + throw new \InvalidArgumentException('Missing required field "expire" for ' . static::class . '.'); + } + + return new static( + id: $data['$id'], + createdAt: $data['$createdAt'], + updatedAt: $data['$updatedAt'], + userId: $data['userId'], + appId: $data['appId'], + cimdUrl: $data['cimdUrl'], + scopes: $data['scopes'], + resources: $data['resources'], + authorizationDetails: $data['authorizationDetails'], + expire: $data['expire'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + '$id' => static::serializeValue($this->id), + '$createdAt' => static::serializeValue($this->createdAt), + '$updatedAt' => static::serializeValue($this->updatedAt), + 'userId' => static::serializeValue($this->userId), + 'appId' => static::serializeValue($this->appId), + 'cimdUrl' => static::serializeValue($this->cimdUrl), + 'scopes' => static::serializeValue($this->scopes), + 'resources' => static::serializeValue($this->resources), + 'authorizationDetails' => static::serializeValue($this->authorizationDetails), + 'expire' => static::serializeValue($this->expire) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/Oauth2ConsentList.php b/src/Appwrite/Models/Oauth2ConsentList.php new file mode 100644 index 00000000..e6b0da7b --- /dev/null +++ b/src/Appwrite/Models/Oauth2ConsentList.php @@ -0,0 +1,59 @@ + $consents list of consents. + */ + public function __construct( + public int $total, + public array $consents + ) { + } + + /** + * @param array $data + */ + public static function from(array $data): static + { + if (!array_key_exists('total', $data)) { + throw new \InvalidArgumentException('Missing required field "total" for ' . static::class . '.'); + } + if (!array_key_exists('consents', $data)) { + throw new \InvalidArgumentException('Missing required field "consents" for ' . static::class . '.'); + } + + return new static( + total: $data['total'], + consents: is_array($data['consents']) + ? array_map( + static fn (mixed $item): mixed => static::hydrateTypedValue(Oauth2Consent::class, $item), + $data['consents'] + ) + : $data['consents'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'total' => static::serializeValue($this->total), + 'consents' => static::serializeValue($this->consents) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/Oauth2ConsentToken.php b/src/Appwrite/Models/Oauth2ConsentToken.php new file mode 100644 index 00000000..1c363fb4 --- /dev/null +++ b/src/Appwrite/Models/Oauth2ConsentToken.php @@ -0,0 +1,117 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('$id', $data)) { + throw new \InvalidArgumentException('Missing required field "$id" for ' . static::class . '.'); + } + if (!array_key_exists('$createdAt', $data)) { + throw new \InvalidArgumentException('Missing required field "$createdAt" for ' . static::class . '.'); + } + if (!array_key_exists('$updatedAt', $data)) { + throw new \InvalidArgumentException('Missing required field "$updatedAt" for ' . static::class . '.'); + } + if (!array_key_exists('consentId', $data)) { + throw new \InvalidArgumentException('Missing required field "consentId" for ' . static::class . '.'); + } + if (!array_key_exists('userId', $data)) { + throw new \InvalidArgumentException('Missing required field "userId" for ' . static::class . '.'); + } + if (!array_key_exists('appId', $data)) { + throw new \InvalidArgumentException('Missing required field "appId" for ' . static::class . '.'); + } + if (!array_key_exists('cimdUrl', $data)) { + throw new \InvalidArgumentException('Missing required field "cimdUrl" for ' . static::class . '.'); + } + if (!array_key_exists('scopes', $data)) { + throw new \InvalidArgumentException('Missing required field "scopes" for ' . static::class . '.'); + } + if (!array_key_exists('resources', $data)) { + throw new \InvalidArgumentException('Missing required field "resources" for ' . static::class . '.'); + } + if (!array_key_exists('authorizationDetails', $data)) { + throw new \InvalidArgumentException('Missing required field "authorizationDetails" for ' . static::class . '.'); + } + if (!array_key_exists('expire', $data)) { + throw new \InvalidArgumentException('Missing required field "expire" for ' . static::class . '.'); + } + + return new static( + id: $data['$id'], + createdAt: $data['$createdAt'], + updatedAt: $data['$updatedAt'], + consentId: $data['consentId'], + userId: $data['userId'], + appId: $data['appId'], + cimdUrl: $data['cimdUrl'], + scopes: $data['scopes'], + resources: $data['resources'], + authorizationDetails: $data['authorizationDetails'], + expire: $data['expire'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + '$id' => static::serializeValue($this->id), + '$createdAt' => static::serializeValue($this->createdAt), + '$updatedAt' => static::serializeValue($this->updatedAt), + 'consentId' => static::serializeValue($this->consentId), + 'userId' => static::serializeValue($this->userId), + 'appId' => static::serializeValue($this->appId), + 'cimdUrl' => static::serializeValue($this->cimdUrl), + 'scopes' => static::serializeValue($this->scopes), + 'resources' => static::serializeValue($this->resources), + 'authorizationDetails' => static::serializeValue($this->authorizationDetails), + 'expire' => static::serializeValue($this->expire) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/Oauth2ConsentTokenList.php b/src/Appwrite/Models/Oauth2ConsentTokenList.php new file mode 100644 index 00000000..d24f6382 --- /dev/null +++ b/src/Appwrite/Models/Oauth2ConsentTokenList.php @@ -0,0 +1,59 @@ + $tokens list of tokens. + */ + public function __construct( + public int $total, + public array $tokens + ) { + } + + /** + * @param array $data + */ + public static function from(array $data): static + { + if (!array_key_exists('total', $data)) { + throw new \InvalidArgumentException('Missing required field "total" for ' . static::class . '.'); + } + if (!array_key_exists('tokens', $data)) { + throw new \InvalidArgumentException('Missing required field "tokens" for ' . static::class . '.'); + } + + return new static( + total: $data['total'], + tokens: is_array($data['tokens']) + ? array_map( + static fn (mixed $item): mixed => static::hydrateTypedValue(Oauth2ConsentToken::class, $item), + $data['tokens'] + ) + : $data['tokens'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'total' => static::serializeValue($this->total), + 'tokens' => static::serializeValue($this->tokens) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/Oauth2DeviceAuthorization.php b/src/Appwrite/Models/Oauth2DeviceAuthorization.php new file mode 100644 index 00000000..6f295a44 --- /dev/null +++ b/src/Appwrite/Models/Oauth2DeviceAuthorization.php @@ -0,0 +1,82 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('device_code', $data)) { + throw new \InvalidArgumentException('Missing required field "device_code" for ' . static::class . '.'); + } + if (!array_key_exists('user_code', $data)) { + throw new \InvalidArgumentException('Missing required field "user_code" for ' . static::class . '.'); + } + if (!array_key_exists('verification_uri', $data)) { + throw new \InvalidArgumentException('Missing required field "verification_uri" for ' . static::class . '.'); + } + if (!array_key_exists('verification_uri_complete', $data)) { + throw new \InvalidArgumentException('Missing required field "verification_uri_complete" for ' . static::class . '.'); + } + if (!array_key_exists('expires_in', $data)) { + throw new \InvalidArgumentException('Missing required field "expires_in" for ' . static::class . '.'); + } + if (!array_key_exists('interval', $data)) { + throw new \InvalidArgumentException('Missing required field "interval" for ' . static::class . '.'); + } + + return new static( + deviceCode: $data['device_code'], + userCode: $data['user_code'], + verificationUri: $data['verification_uri'], + verificationUriComplete: $data['verification_uri_complete'], + expiresIn: $data['expires_in'], + interval: $data['interval'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'device_code' => static::serializeValue($this->deviceCode), + 'user_code' => static::serializeValue($this->userCode), + 'verification_uri' => static::serializeValue($this->verificationUri), + 'verification_uri_complete' => static::serializeValue($this->verificationUriComplete), + 'expires_in' => static::serializeValue($this->expiresIn), + 'interval' => static::serializeValue($this->interval) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/Oauth2Grant.php b/src/Appwrite/Models/Oauth2Grant.php new file mode 100644 index 00000000..4b8de2f9 --- /dev/null +++ b/src/Appwrite/Models/Oauth2Grant.php @@ -0,0 +1,124 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('$id', $data)) { + throw new \InvalidArgumentException('Missing required field "$id" for ' . static::class . '.'); + } + if (!array_key_exists('$createdAt', $data)) { + throw new \InvalidArgumentException('Missing required field "$createdAt" for ' . static::class . '.'); + } + if (!array_key_exists('$updatedAt', $data)) { + throw new \InvalidArgumentException('Missing required field "$updatedAt" for ' . static::class . '.'); + } + if (!array_key_exists('userId', $data)) { + throw new \InvalidArgumentException('Missing required field "userId" for ' . static::class . '.'); + } + if (!array_key_exists('appId', $data)) { + throw new \InvalidArgumentException('Missing required field "appId" for ' . static::class . '.'); + } + if (!array_key_exists('scopes', $data)) { + throw new \InvalidArgumentException('Missing required field "scopes" for ' . static::class . '.'); + } + if (!array_key_exists('resources', $data)) { + throw new \InvalidArgumentException('Missing required field "resources" for ' . static::class . '.'); + } + if (!array_key_exists('authorizationDetails', $data)) { + throw new \InvalidArgumentException('Missing required field "authorizationDetails" for ' . static::class . '.'); + } + if (!array_key_exists('prompt', $data)) { + throw new \InvalidArgumentException('Missing required field "prompt" for ' . static::class . '.'); + } + if (!array_key_exists('redirectUri', $data)) { + throw new \InvalidArgumentException('Missing required field "redirectUri" for ' . static::class . '.'); + } + if (!array_key_exists('authTime', $data)) { + throw new \InvalidArgumentException('Missing required field "authTime" for ' . static::class . '.'); + } + if (!array_key_exists('expire', $data)) { + throw new \InvalidArgumentException('Missing required field "expire" for ' . static::class . '.'); + } + + return new static( + id: $data['$id'], + createdAt: $data['$createdAt'], + updatedAt: $data['$updatedAt'], + userId: $data['userId'], + appId: $data['appId'], + scopes: $data['scopes'], + resources: $data['resources'], + authorizationDetails: $data['authorizationDetails'], + prompt: $data['prompt'], + redirectUri: $data['redirectUri'], + authTime: $data['authTime'], + expire: $data['expire'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + '$id' => static::serializeValue($this->id), + '$createdAt' => static::serializeValue($this->createdAt), + '$updatedAt' => static::serializeValue($this->updatedAt), + 'userId' => static::serializeValue($this->userId), + 'appId' => static::serializeValue($this->appId), + 'scopes' => static::serializeValue($this->scopes), + 'resources' => static::serializeValue($this->resources), + 'authorizationDetails' => static::serializeValue($this->authorizationDetails), + 'prompt' => static::serializeValue($this->prompt), + 'redirectUri' => static::serializeValue($this->redirectUri), + 'authTime' => static::serializeValue($this->authTime), + 'expire' => static::serializeValue($this->expire) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/Oauth2Organization.php b/src/Appwrite/Models/Oauth2Organization.php new file mode 100644 index 00000000..25a7dcff --- /dev/null +++ b/src/Appwrite/Models/Oauth2Organization.php @@ -0,0 +1,47 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('$id', $data)) { + throw new \InvalidArgumentException('Missing required field "$id" for ' . static::class . '.'); + } + + return new static( + id: $data['$id'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + '$id' => static::serializeValue($this->id) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/Oauth2OrganizationList.php b/src/Appwrite/Models/Oauth2OrganizationList.php new file mode 100644 index 00000000..2f29ee00 --- /dev/null +++ b/src/Appwrite/Models/Oauth2OrganizationList.php @@ -0,0 +1,59 @@ + $organizations list of organizations. + */ + public function __construct( + public int $total, + public array $organizations + ) { + } + + /** + * @param array $data + */ + public static function from(array $data): static + { + if (!array_key_exists('total', $data)) { + throw new \InvalidArgumentException('Missing required field "total" for ' . static::class . '.'); + } + if (!array_key_exists('organizations', $data)) { + throw new \InvalidArgumentException('Missing required field "organizations" for ' . static::class . '.'); + } + + return new static( + total: $data['total'], + organizations: is_array($data['organizations']) + ? array_map( + static fn (mixed $item): mixed => static::hydrateTypedValue(Oauth2Organization::class, $item), + $data['organizations'] + ) + : $data['organizations'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'total' => static::serializeValue($this->total), + 'organizations' => static::serializeValue($this->organizations) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/Oauth2PAR.php b/src/Appwrite/Models/Oauth2PAR.php new file mode 100644 index 00000000..d6f7d677 --- /dev/null +++ b/src/Appwrite/Models/Oauth2PAR.php @@ -0,0 +1,54 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('request_uri', $data)) { + throw new \InvalidArgumentException('Missing required field "request_uri" for ' . static::class . '.'); + } + if (!array_key_exists('expires_in', $data)) { + throw new \InvalidArgumentException('Missing required field "expires_in" for ' . static::class . '.'); + } + + return new static( + requestUri: $data['request_uri'], + expiresIn: $data['expires_in'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'request_uri' => static::serializeValue($this->requestUri), + 'expires_in' => static::serializeValue($this->expiresIn) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/Oauth2Project.php b/src/Appwrite/Models/Oauth2Project.php new file mode 100644 index 00000000..e7f9725d --- /dev/null +++ b/src/Appwrite/Models/Oauth2Project.php @@ -0,0 +1,61 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('$id', $data)) { + throw new \InvalidArgumentException('Missing required field "$id" for ' . static::class . '.'); + } + if (!array_key_exists('region', $data)) { + throw new \InvalidArgumentException('Missing required field "region" for ' . static::class . '.'); + } + if (!array_key_exists('endpoint', $data)) { + throw new \InvalidArgumentException('Missing required field "endpoint" for ' . static::class . '.'); + } + + return new static( + id: $data['$id'], + region: $data['region'], + endpoint: $data['endpoint'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + '$id' => static::serializeValue($this->id), + 'region' => static::serializeValue($this->region), + 'endpoint' => static::serializeValue($this->endpoint) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/Oauth2ProjectList.php b/src/Appwrite/Models/Oauth2ProjectList.php new file mode 100644 index 00000000..efa948b8 --- /dev/null +++ b/src/Appwrite/Models/Oauth2ProjectList.php @@ -0,0 +1,59 @@ + $projects list of projects. + */ + public function __construct( + public int $total, + public array $projects + ) { + } + + /** + * @param array $data + */ + public static function from(array $data): static + { + if (!array_key_exists('total', $data)) { + throw new \InvalidArgumentException('Missing required field "total" for ' . static::class . '.'); + } + if (!array_key_exists('projects', $data)) { + throw new \InvalidArgumentException('Missing required field "projects" for ' . static::class . '.'); + } + + return new static( + total: $data['total'], + projects: is_array($data['projects']) + ? array_map( + static fn (mixed $item): mixed => static::hydrateTypedValue(Oauth2Project::class, $item), + $data['projects'] + ) + : $data['projects'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'total' => static::serializeValue($this->total), + 'projects' => static::serializeValue($this->projects) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/Oauth2Reject.php b/src/Appwrite/Models/Oauth2Reject.php new file mode 100644 index 00000000..57304a14 --- /dev/null +++ b/src/Appwrite/Models/Oauth2Reject.php @@ -0,0 +1,47 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('redirectUrl', $data)) { + throw new \InvalidArgumentException('Missing required field "redirectUrl" for ' . static::class . '.'); + } + + return new static( + redirectUrl: $data['redirectUrl'] + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'redirectUrl' => static::serializeValue($this->redirectUrl) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/Oauth2Token.php b/src/Appwrite/Models/Oauth2Token.php new file mode 100644 index 00000000..b9bbb593 --- /dev/null +++ b/src/Appwrite/Models/Oauth2Token.php @@ -0,0 +1,83 @@ + $data + */ + public static function from(array $data): static + { + if (!array_key_exists('access_token', $data)) { + throw new \InvalidArgumentException('Missing required field "access_token" for ' . static::class . '.'); + } + if (!array_key_exists('token_type', $data)) { + throw new \InvalidArgumentException('Missing required field "token_type" for ' . static::class . '.'); + } + if (!array_key_exists('expires_in', $data)) { + throw new \InvalidArgumentException('Missing required field "expires_in" for ' . static::class . '.'); + } + if (!array_key_exists('refresh_token', $data)) { + throw new \InvalidArgumentException('Missing required field "refresh_token" for ' . static::class . '.'); + } + if (!array_key_exists('scope', $data)) { + throw new \InvalidArgumentException('Missing required field "scope" for ' . static::class . '.'); + } + + return new static( + accessToken: $data['access_token'], + tokenType: $data['token_type'], + expiresIn: $data['expires_in'], + refreshToken: $data['refresh_token'], + scope: $data['scope'], + authorizationDetails: array_key_exists('authorization_details', $data) ? $data['authorization_details'] : null, + idToken: array_key_exists('id_token', $data) ? $data['id_token'] : null + ); + } + + /** + * @return array + */ + public function toArray(): array + { + $result = [ + 'access_token' => static::serializeValue($this->accessToken), + 'token_type' => static::serializeValue($this->tokenType), + 'expires_in' => static::serializeValue($this->expiresIn), + 'refresh_token' => static::serializeValue($this->refreshToken), + 'scope' => static::serializeValue($this->scope), + 'authorization_details' => static::serializeValue($this->authorizationDetails), + 'id_token' => static::serializeValue($this->idToken) + ]; + + return $result; + } +} diff --git a/src/Appwrite/Models/Project.php b/src/Appwrite/Models/Project.php index f2af24d4..f9013ca9 100644 --- a/src/Appwrite/Models/Project.php +++ b/src/Appwrite/Models/Project.php @@ -39,6 +39,7 @@ * @param list $protocols list of protocols. * @param list $blocks project blocks information * @param string $consoleAccessedAt last time the project was accessed via console. used with plan's projectinactivitydays to determine if project is paused. + * @param bool $wafEnabled whether waf enforcement is enabled for the project. * @param BillingLimits|null $billingLimits billing limits reached * @param bool|null $oAuth2ServerEnabled oauth2 server status * @param string|null $oAuth2ServerAuthorizationUrl oauth2 server authorization url @@ -49,6 +50,7 @@ * @param int|null $oAuth2ServerRefreshTokenDuration oauth2 server refresh token duration in seconds for confidential clients * @param int|null $oAuth2ServerPublicAccessTokenDuration oauth2 server access token duration in seconds for public clients (spas, mobile, native) * @param int|null $oAuth2ServerPublicRefreshTokenDuration oauth2 server refresh token duration in seconds for public clients (spas, mobile, native) + * @param int|null $oAuth2ServerInstallationAccessTokenDuration oauth2 server access token duration in seconds for app installation access tokens * @param bool|null $oAuth2ServerConfidentialPkce 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. * @param string|null $oAuth2ServerVerificationUrl url to your application page where users enter the device flow user code. empty when the device authorization grant is not configured. * @param int|null $oAuth2ServerUserCodeLength number of characters in the device flow user code, excluding the formatting separator. @@ -84,6 +86,7 @@ public function __construct( public array $protocols, public array $blocks, public string $consoleAccessedAt, + public bool $wafEnabled, public ?BillingLimits $billingLimits = null, public ?bool $oAuth2ServerEnabled = null, public ?string $oAuth2ServerAuthorizationUrl = null, @@ -94,6 +97,7 @@ public function __construct( public ?int $oAuth2ServerRefreshTokenDuration = null, public ?int $oAuth2ServerPublicAccessTokenDuration = null, public ?int $oAuth2ServerPublicRefreshTokenDuration = null, + public ?int $oAuth2ServerInstallationAccessTokenDuration = null, public ?bool $oAuth2ServerConfidentialPkce = null, public ?string $oAuth2ServerVerificationUrl = null, public ?int $oAuth2ServerUserCodeLength = null, @@ -189,6 +193,9 @@ public static function from(array $data): static if (!array_key_exists('consoleAccessedAt', $data)) { throw new \InvalidArgumentException('Missing required field "consoleAccessedAt" for ' . static::class . '.'); } + if (!array_key_exists('wafEnabled', $data)) { + throw new \InvalidArgumentException('Missing required field "wafEnabled" for ' . static::class . '.'); + } return new static( id: $data['$id'], @@ -243,6 +250,7 @@ public static function from(array $data): static ) : $data['blocks'], consoleAccessedAt: $data['consoleAccessedAt'], + wafEnabled: $data['wafEnabled'], billingLimits: array_key_exists('billingLimits', $data) ? static::hydrateTypedValue(BillingLimits::class, $data['billingLimits'], true) : null, oAuth2ServerEnabled: array_key_exists('oAuth2ServerEnabled', $data) ? $data['oAuth2ServerEnabled'] : null, oAuth2ServerAuthorizationUrl: array_key_exists('oAuth2ServerAuthorizationUrl', $data) ? $data['oAuth2ServerAuthorizationUrl'] : null, @@ -253,6 +261,7 @@ public static function from(array $data): static oAuth2ServerRefreshTokenDuration: array_key_exists('oAuth2ServerRefreshTokenDuration', $data) ? $data['oAuth2ServerRefreshTokenDuration'] : null, oAuth2ServerPublicAccessTokenDuration: array_key_exists('oAuth2ServerPublicAccessTokenDuration', $data) ? $data['oAuth2ServerPublicAccessTokenDuration'] : null, oAuth2ServerPublicRefreshTokenDuration: array_key_exists('oAuth2ServerPublicRefreshTokenDuration', $data) ? $data['oAuth2ServerPublicRefreshTokenDuration'] : null, + oAuth2ServerInstallationAccessTokenDuration: array_key_exists('oAuth2ServerInstallationAccessTokenDuration', $data) ? $data['oAuth2ServerInstallationAccessTokenDuration'] : null, oAuth2ServerConfidentialPkce: array_key_exists('oAuth2ServerConfidentialPkce', $data) ? $data['oAuth2ServerConfidentialPkce'] : null, oAuth2ServerVerificationUrl: array_key_exists('oAuth2ServerVerificationUrl', $data) ? $data['oAuth2ServerVerificationUrl'] : null, oAuth2ServerUserCodeLength: array_key_exists('oAuth2ServerUserCodeLength', $data) ? $data['oAuth2ServerUserCodeLength'] : null, @@ -295,6 +304,7 @@ public function toArray(): array 'protocols' => static::serializeValue($this->protocols), 'blocks' => static::serializeValue($this->blocks), 'consoleAccessedAt' => static::serializeValue($this->consoleAccessedAt), + 'wafEnabled' => static::serializeValue($this->wafEnabled), 'billingLimits' => static::serializeValue($this->billingLimits), 'oAuth2ServerEnabled' => static::serializeValue($this->oAuth2ServerEnabled), 'oAuth2ServerAuthorizationUrl' => static::serializeValue($this->oAuth2ServerAuthorizationUrl), @@ -305,6 +315,7 @@ public function toArray(): array 'oAuth2ServerRefreshTokenDuration' => static::serializeValue($this->oAuth2ServerRefreshTokenDuration), 'oAuth2ServerPublicAccessTokenDuration' => static::serializeValue($this->oAuth2ServerPublicAccessTokenDuration), 'oAuth2ServerPublicRefreshTokenDuration' => static::serializeValue($this->oAuth2ServerPublicRefreshTokenDuration), + 'oAuth2ServerInstallationAccessTokenDuration' => static::serializeValue($this->oAuth2ServerInstallationAccessTokenDuration), 'oAuth2ServerConfidentialPkce' => static::serializeValue($this->oAuth2ServerConfidentialPkce), 'oAuth2ServerVerificationUrl' => static::serializeValue($this->oAuth2ServerVerificationUrl), 'oAuth2ServerUserCodeLength' => static::serializeValue($this->oAuth2ServerUserCodeLength), diff --git a/src/Appwrite/Services/Account.php b/src/Appwrite/Services/Account.php index e5b62b63..441e05da 100644 --- a/src/Appwrite/Services/Account.php +++ b/src/Appwrite/Services/Account.php @@ -105,6 +105,253 @@ public function create(string $userId, string $email, string $password, ?string } + /** + * Get a list of the OAuth2 consents the current user has given to third-party + * apps. + * + * @param ?array $queries + * @param ?bool $total + * @throws AppwriteException + * @return \Appwrite\Models\Oauth2ConsentList + */ + public function listConsents(?array $queries = null, ?bool $total = null): \Appwrite\Models\Oauth2ConsentList + { + $apiPath = str_replace( + [], + [], + '/account/consents' + ); + + $apiParams = []; + + if (!is_null($queries)) { + $apiParams['queries'] = $queries; + } + + if (!is_null($total)) { + $apiParams['total'] = $total; + } + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\Oauth2ConsentList::from($response); + + } + + /** + * Get an OAuth2 consent the current user has given to a third-party app by + * its unique ID. + * + * @param string $consentId + * @throws AppwriteException + * @return \Appwrite\Models\Oauth2Consent + */ + public function getConsent(string $consentId): \Appwrite\Models\Oauth2Consent + { + $apiPath = str_replace( + ['{consentId}'], + [$consentId], + '/account/consents/{consentId}' + ); + + $apiParams = []; + $apiParams['consentId'] = $consentId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\Oauth2Consent::from($response); + + } + + /** + * Delete an OAuth2 consent by its unique ID. All token families issued under + * the consent are revoked, and the app must ask for consent again to regain + * access. + * + * @param string $consentId + * @throws AppwriteException + * @return string + */ + public function deleteConsent(string $consentId): string + { + $apiPath = str_replace( + ['{consentId}'], + [$consentId], + '/account/consents/{consentId}' + ); + + $apiParams = []; + $apiParams['consentId'] = $consentId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_DELETE, + $apiPath, + $apiHeaders, + $apiParams + ); + + return $response; + + } + + /** + * Get a list of the token families issued under an OAuth2 consent. Each entry + * represents one authorized device or session; the token secrets themselves + * are never returned. + * + * @param string $consentId + * @param ?array $queries + * @param ?bool $total + * @throws AppwriteException + * @return \Appwrite\Models\Oauth2ConsentTokenList + */ + public function listConsentTokens(string $consentId, ?array $queries = null, ?bool $total = null): \Appwrite\Models\Oauth2ConsentTokenList + { + $apiPath = str_replace( + ['{consentId}'], + [$consentId], + '/account/consents/{consentId}/tokens' + ); + + $apiParams = []; + $apiParams['consentId'] = $consentId; + + if (!is_null($queries)) { + $apiParams['queries'] = $queries; + } + + if (!is_null($total)) { + $apiParams['total'] = $total; + } + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\Oauth2ConsentTokenList::from($response); + + } + + /** + * Get a token family issued under an OAuth2 consent by its unique ID. The + * token secrets themselves are never returned. + * + * @param string $consentId + * @param string $tokenId + * @throws AppwriteException + * @return \Appwrite\Models\Oauth2ConsentToken + */ + public function getConsentToken(string $consentId, string $tokenId): \Appwrite\Models\Oauth2ConsentToken + { + $apiPath = str_replace( + ['{consentId}', '{tokenId}'], + [$consentId, $tokenId], + '/account/consents/{consentId}/tokens/{tokenId}' + ); + + $apiParams = []; + $apiParams['consentId'] = $consentId; + $apiParams['tokenId'] = $tokenId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\Oauth2ConsentToken::from($response); + + } + + /** + * Delete a token family issued under an OAuth2 consent by its unique ID. The + * access and refresh tokens of the family stop working immediately; other + * token families and the consent itself are unaffected. + * + * @param string $consentId + * @param string $tokenId + * @throws AppwriteException + * @return string + */ + public function deleteConsentToken(string $consentId, string $tokenId): string + { + $apiPath = str_replace( + ['{consentId}', '{tokenId}'], + [$consentId, $tokenId], + '/account/consents/{consentId}/tokens/{tokenId}' + ); + + $apiParams = []; + $apiParams['consentId'] = $consentId; + $apiParams['tokenId'] = $tokenId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_DELETE, + $apiPath, + $apiHeaders, + $apiParams + ); + + return $response; + + } + /** * Update currently logged in user account email address. After changing user * address, the user confirmation status will get reset. A new confirmation diff --git a/src/Appwrite/Services/Apps.php b/src/Appwrite/Services/Apps.php new file mode 100644 index 00000000..d0a9c896 --- /dev/null +++ b/src/Appwrite/Services/Apps.php @@ -0,0 +1,1026 @@ +client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\AppsList::from($response); + + } + + /** + * Create a new application. + * + * @param string $appId + * @param string $name + * @param array $redirectUris + * @param ?string $description + * @param ?string $clientUri + * @param ?string $logoUri + * @param ?string $privacyPolicyUrl + * @param ?string $termsUrl + * @param ?array $contacts + * @param ?string $tagline + * @param ?array $tags + * @param ?array $images + * @param ?string $supportUrl + * @param ?string $dataDeletionUrl + * @param ?array $postLogoutRedirectUris + * @param ?bool $enabled + * @param ?string $type + * @param ?bool $deviceFlow + * @param ?string $teamId + * @throws AppwriteException + * @return \Appwrite\Models\App + */ + public function create(string $appId, string $name, array $redirectUris, ?string $description = null, ?string $clientUri = null, ?string $logoUri = null, ?string $privacyPolicyUrl = null, ?string $termsUrl = null, ?array $contacts = null, ?string $tagline = null, ?array $tags = null, ?array $images = null, ?string $supportUrl = null, ?string $dataDeletionUrl = null, ?array $postLogoutRedirectUris = null, ?bool $enabled = null, ?string $type = null, ?bool $deviceFlow = null, ?string $teamId = null): \Appwrite\Models\App + { + $apiPath = str_replace( + [], + [], + '/apps' + ); + + $apiParams = []; + $apiParams['appId'] = $appId; + $apiParams['name'] = $name; + $apiParams['redirectUris'] = $redirectUris; + + if (!is_null($description)) { + $apiParams['description'] = $description; + } + + if (!is_null($clientUri)) { + $apiParams['clientUri'] = $clientUri; + } + + if (!is_null($logoUri)) { + $apiParams['logoUri'] = $logoUri; + } + + if (!is_null($privacyPolicyUrl)) { + $apiParams['privacyPolicyUrl'] = $privacyPolicyUrl; + } + + if (!is_null($termsUrl)) { + $apiParams['termsUrl'] = $termsUrl; + } + + if (!is_null($contacts)) { + $apiParams['contacts'] = $contacts; + } + + if (!is_null($tagline)) { + $apiParams['tagline'] = $tagline; + } + + if (!is_null($tags)) { + $apiParams['tags'] = $tags; + } + + if (!is_null($images)) { + $apiParams['images'] = $images; + } + + if (!is_null($supportUrl)) { + $apiParams['supportUrl'] = $supportUrl; + } + + if (!is_null($dataDeletionUrl)) { + $apiParams['dataDeletionUrl'] = $dataDeletionUrl; + } + + if (!is_null($postLogoutRedirectUris)) { + $apiParams['postLogoutRedirectUris'] = $postLogoutRedirectUris; + } + + if (!is_null($enabled)) { + $apiParams['enabled'] = $enabled; + } + + if (!is_null($type)) { + $apiParams['type'] = $type; + } + + if (!is_null($deviceFlow)) { + $apiParams['deviceFlow'] = $deviceFlow; + } + + if (!is_null($teamId)) { + $apiParams['teamId'] = $teamId; + } + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_POST, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\App::from($response); + + } + + /** + * List scopes an application can request when installed on a team. + * + * @throws AppwriteException + * @return \Appwrite\Models\AppScopeList + */ + public function listInstallationScopes(): \Appwrite\Models\AppScopeList + { + $apiPath = str_replace( + [], + [], + '/apps/scopes/installations' + ); + + $apiParams = []; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\AppScopeList::from($response); + + } + + /** + * List scopes an application can request during the OAuth2 flow. + * + * @throws AppwriteException + * @return \Appwrite\Models\AppScopeList + */ + public function listOAuth2Scopes(): \Appwrite\Models\AppScopeList + { + $apiPath = str_replace( + [], + [], + '/apps/scopes/oauth2' + ); + + $apiParams = []; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\AppScopeList::from($response); + + } + + /** + * Get an application by its unique ID. + * + * @param string $appId + * @throws AppwriteException + * @return \Appwrite\Models\App + */ + public function get(string $appId): \Appwrite\Models\App + { + $apiPath = str_replace( + ['{appId}'], + [$appId], + '/apps/{appId}' + ); + + $apiParams = []; + $apiParams['appId'] = $appId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\App::from($response); + + } + + /** + * Update an application by its unique ID. + * + * @param string $appId + * @param string $name + * @param ?string $description + * @param ?string $clientUri + * @param ?string $logoUri + * @param ?string $privacyPolicyUrl + * @param ?string $termsUrl + * @param ?array $contacts + * @param ?string $tagline + * @param ?array $tags + * @param ?array $images + * @param ?string $supportUrl + * @param ?string $dataDeletionUrl + * @param ?bool $enabled + * @param ?array $redirectUris + * @param ?array $postLogoutRedirectUris + * @param ?string $type + * @param ?bool $deviceFlow + * @param ?array $installationScopes + * @param ?string $installationRedirectUrl + * @throws AppwriteException + * @return \Appwrite\Models\App + */ + public function update(string $appId, string $name, ?string $description = null, ?string $clientUri = null, ?string $logoUri = null, ?string $privacyPolicyUrl = null, ?string $termsUrl = null, ?array $contacts = null, ?string $tagline = null, ?array $tags = null, ?array $images = null, ?string $supportUrl = null, ?string $dataDeletionUrl = null, ?bool $enabled = null, ?array $redirectUris = null, ?array $postLogoutRedirectUris = null, ?string $type = null, ?bool $deviceFlow = null, ?array $installationScopes = null, ?string $installationRedirectUrl = null): \Appwrite\Models\App + { + $apiPath = str_replace( + ['{appId}'], + [$appId], + '/apps/{appId}' + ); + + $apiParams = []; + $apiParams['appId'] = $appId; + $apiParams['name'] = $name; + + if (!is_null($description)) { + $apiParams['description'] = $description; + } + + if (!is_null($clientUri)) { + $apiParams['clientUri'] = $clientUri; + } + + if (!is_null($logoUri)) { + $apiParams['logoUri'] = $logoUri; + } + + if (!is_null($privacyPolicyUrl)) { + $apiParams['privacyPolicyUrl'] = $privacyPolicyUrl; + } + + if (!is_null($termsUrl)) { + $apiParams['termsUrl'] = $termsUrl; + } + + if (!is_null($contacts)) { + $apiParams['contacts'] = $contacts; + } + + if (!is_null($tagline)) { + $apiParams['tagline'] = $tagline; + } + + if (!is_null($tags)) { + $apiParams['tags'] = $tags; + } + + if (!is_null($images)) { + $apiParams['images'] = $images; + } + + if (!is_null($supportUrl)) { + $apiParams['supportUrl'] = $supportUrl; + } + + if (!is_null($dataDeletionUrl)) { + $apiParams['dataDeletionUrl'] = $dataDeletionUrl; + } + + if (!is_null($enabled)) { + $apiParams['enabled'] = $enabled; + } + + if (!is_null($redirectUris)) { + $apiParams['redirectUris'] = $redirectUris; + } + + if (!is_null($postLogoutRedirectUris)) { + $apiParams['postLogoutRedirectUris'] = $postLogoutRedirectUris; + } + + if (!is_null($type)) { + $apiParams['type'] = $type; + } + + if (!is_null($deviceFlow)) { + $apiParams['deviceFlow'] = $deviceFlow; + } + + if (!is_null($installationScopes)) { + $apiParams['installationScopes'] = $installationScopes; + } + + if (!is_null($installationRedirectUrl)) { + $apiParams['installationRedirectUrl'] = $installationRedirectUrl; + } + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_PUT, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\App::from($response); + + } + + /** + * Delete an application by its unique ID. + * + * @param string $appId + * @throws AppwriteException + * @return string + */ + public function delete(string $appId): string + { + $apiPath = str_replace( + ['{appId}'], + [$appId], + '/apps/{appId}' + ); + + $apiParams = []; + $apiParams['appId'] = $appId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_DELETE, + $apiPath, + $apiHeaders, + $apiParams + ); + + return $response; + + } + + /** + * List installations of an application. Requires an app key sent in the + * `X-Appwrite-Key` header alongside the `X-Appwrite-App` header. + * + * @param string $appId + * @param ?array $queries + * @param ?bool $total + * @throws AppwriteException + * @return \Appwrite\Models\AppInstallationList + */ + public function listInstallations(string $appId, ?array $queries = null, ?bool $total = null): \Appwrite\Models\AppInstallationList + { + $apiPath = str_replace( + ['{appId}'], + [$appId], + '/apps/{appId}/installations' + ); + + $apiParams = []; + $apiParams['appId'] = $appId; + + if (!is_null($queries)) { + $apiParams['queries'] = $queries; + } + + if (!is_null($total)) { + $apiParams['total'] = $total; + } + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\AppInstallationList::from($response); + + } + + /** + * Get an installation of an application by its unique ID. Requires an app key + * sent in the `X-Appwrite-Key` header alongside the `X-Appwrite-App` header. + * + * @param string $appId + * @param string $installationId + * @throws AppwriteException + * @return \Appwrite\Models\AppInstallation + */ + public function getInstallation(string $appId, string $installationId): \Appwrite\Models\AppInstallation + { + $apiPath = str_replace( + ['{appId}', '{installationId}'], + [$appId, $installationId], + '/apps/{appId}/installations/{installationId}' + ); + + $apiParams = []; + $apiParams['appId'] = $appId; + $apiParams['installationId'] = $installationId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\AppInstallation::from($response); + + } + + /** + * Create a token for an installation of an application. Requires an app key + * sent in the `X-Appwrite-Key` header alongside the `X-Appwrite-App` header. + * The returned token carries the scopes and authorization details granted to + * the installation, and can be used as an `Authorization: Bearer` header + * everywhere OAuth2 access tokens are accepted. Multiple tokens can be active + * for the same installation at once; each token stays valid until it expires + * or the installation is updated or deleted. + * + * @param string $appId + * @param string $installationId + * @throws AppwriteException + * @return \Appwrite\Models\Oauth2Token + */ + public function createInstallationToken(string $appId, string $installationId): \Appwrite\Models\Oauth2Token + { + $apiPath = str_replace( + ['{appId}', '{installationId}'], + [$appId, $installationId], + '/apps/{appId}/installations/{installationId}/tokens' + ); + + $apiParams = []; + $apiParams['appId'] = $appId; + $apiParams['installationId'] = $installationId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_POST, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\Oauth2Token::from($response); + + } + + /** + * List app keys for an application. + * + * @param string $appId + * @param ?array $queries + * @param ?bool $total + * @throws AppwriteException + * @return \Appwrite\Models\AppKeyList + */ + public function listKeys(string $appId, ?array $queries = null, ?bool $total = null): \Appwrite\Models\AppKeyList + { + $apiPath = str_replace( + ['{appId}'], + [$appId], + '/apps/{appId}/keys' + ); + + $apiParams = []; + $apiParams['appId'] = $appId; + + if (!is_null($queries)) { + $apiParams['queries'] = $queries; + } + + if (!is_null($total)) { + $apiParams['total'] = $total; + } + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\AppKeyList::from($response); + + } + + /** + * Create a new app key for an application. App keys carry no scopes; send one + * in the `X-Appwrite-Key` header alongside the `X-Appwrite-App` header to + * list the application's installations and create installation access tokens. + * + * @param string $appId + * @throws AppwriteException + * @return \Appwrite\Models\AppKey + */ + public function createKey(string $appId): \Appwrite\Models\AppKey + { + $apiPath = str_replace( + ['{appId}'], + [$appId], + '/apps/{appId}/keys' + ); + + $apiParams = []; + $apiParams['appId'] = $appId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_POST, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\AppKey::from($response); + + } + + /** + * Get an app key by its unique ID. + * + * @param string $appId + * @param string $keyId + * @throws AppwriteException + * @return \Appwrite\Models\AppKey + */ + public function getKey(string $appId, string $keyId): \Appwrite\Models\AppKey + { + $apiPath = str_replace( + ['{appId}', '{keyId}'], + [$appId, $keyId], + '/apps/{appId}/keys/{keyId}' + ); + + $apiParams = []; + $apiParams['appId'] = $appId; + $apiParams['keyId'] = $keyId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\AppKey::from($response); + + } + + /** + * Delete an app key by its unique ID. + * + * @param string $appId + * @param string $keyId + * @throws AppwriteException + * @return string + */ + public function deleteKey(string $appId, string $keyId): string + { + $apiPath = str_replace( + ['{appId}', '{keyId}'], + [$appId, $keyId], + '/apps/{appId}/keys/{keyId}' + ); + + $apiParams = []; + $apiParams['appId'] = $appId; + $apiParams['keyId'] = $keyId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_DELETE, + $apiPath, + $apiHeaders, + $apiParams + ); + + return $response; + + } + + /** + * Update the labels of an application. Labels are read-only for clients; only + * a server SDK using a project API key can set them. Replaces the previous + * labels. + * + * @param string $appId + * @param array $labels + * @throws AppwriteException + * @return \Appwrite\Models\App + */ + public function updateLabels(string $appId, array $labels): \Appwrite\Models\App + { + $apiPath = str_replace( + ['{appId}'], + [$appId], + '/apps/{appId}/labels' + ); + + $apiParams = []; + $apiParams['appId'] = $appId; + $apiParams['labels'] = $labels; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_PUT, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\App::from($response); + + } + + /** + * List client secrets for an application. + * + * @param string $appId + * @param ?array $queries + * @param ?bool $total + * @throws AppwriteException + * @return \Appwrite\Models\AppSecretList + */ + public function listSecrets(string $appId, ?array $queries = null, ?bool $total = null): \Appwrite\Models\AppSecretList + { + $apiPath = str_replace( + ['{appId}'], + [$appId], + '/apps/{appId}/secrets' + ); + + $apiParams = []; + $apiParams['appId'] = $appId; + + if (!is_null($queries)) { + $apiParams['queries'] = $queries; + } + + if (!is_null($total)) { + $apiParams['total'] = $total; + } + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\AppSecretList::from($response); + + } + + /** + * Create a new client secret for an application. + * + * @param string $appId + * @throws AppwriteException + * @return \Appwrite\Models\AppSecretPlaintext + */ + public function createSecret(string $appId): \Appwrite\Models\AppSecretPlaintext + { + $apiPath = str_replace( + ['{appId}'], + [$appId], + '/apps/{appId}/secrets' + ); + + $apiParams = []; + $apiParams['appId'] = $appId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_POST, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\AppSecretPlaintext::from($response); + + } + + /** + * Get an application client secret by its unique ID. + * + * @param string $appId + * @param string $secretId + * @throws AppwriteException + * @return \Appwrite\Models\AppSecret + */ + public function getSecret(string $appId, string $secretId): \Appwrite\Models\AppSecret + { + $apiPath = str_replace( + ['{appId}', '{secretId}'], + [$appId, $secretId], + '/apps/{appId}/secrets/{secretId}' + ); + + $apiParams = []; + $apiParams['appId'] = $appId; + $apiParams['secretId'] = $secretId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\AppSecret::from($response); + + } + + /** + * Delete an application client secret by its unique ID. + * + * @param string $appId + * @param string $secretId + * @throws AppwriteException + * @return string + */ + public function deleteSecret(string $appId, string $secretId): string + { + $apiPath = str_replace( + ['{appId}', '{secretId}'], + [$appId, $secretId], + '/apps/{appId}/secrets/{secretId}' + ); + + $apiParams = []; + $apiParams['appId'] = $appId; + $apiParams['secretId'] = $secretId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_DELETE, + $apiPath, + $apiHeaders, + $apiParams + ); + + return $response; + + } + + /** + * Transfer an application to another team by its unique ID. + * + * @param string $appId + * @param string $teamId + * @throws AppwriteException + * @return \Appwrite\Models\App + */ + public function updateTeam(string $appId, string $teamId): \Appwrite\Models\App + { + $apiPath = str_replace( + ['{appId}'], + [$appId], + '/apps/{appId}/team' + ); + + $apiParams = []; + $apiParams['appId'] = $appId; + $apiParams['teamId'] = $teamId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_PATCH, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\App::from($response); + + } + + /** + * Revoke all tokens for an application by its unique ID. + * + * @param string $appId + * @throws AppwriteException + * @return string + */ + public function deleteTokens(string $appId): string + { + $apiPath = str_replace( + ['{appId}'], + [$appId], + '/apps/{appId}/tokens' + ); + + $apiParams = []; + $apiParams['appId'] = $appId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_DELETE, + $apiPath, + $apiHeaders, + $apiParams + ); + + return $response; + + } +} diff --git a/src/Appwrite/Services/Backups.php b/src/Appwrite/Services/Backups.php index c6cc9542..527176ed 100644 --- a/src/Appwrite/Services/Backups.php +++ b/src/Appwrite/Services/Backups.php @@ -385,25 +385,39 @@ public function deletePolicy(string $policyId): string /** * Create and trigger a new restoration for a backup on a project. * - * When restoring a DocumentsDB or VectorsDB database to a new resource, pass - * `newSpecification` to provision the restored database on a different - * specification than the archived one (for example, restoring onto a larger - * or smaller dedicated database). Use `serverless` to restore onto the shared - * pool, or a dedicated specification slug to restore onto a dedicated - * database of that size. The specification must be permitted by the - * organization's plan. `newSpecification` is not supported for - * legacy/TablesDB databases or for bucket restores. + * For a backup of one database, the restoration resolves its destination + * before it is queued. Pass `newResourceId` to restore into that database ID, + * including the archived database ID to overwrite it. When `newResourceId` is + * omitted, a new database ID is generated and returned in `options`. + * + * The restoration migration records the archived database in `resourceId` and + * `resourceType`, and the resolved database in `destinationResourceId` and + * `destinationResourceType`. Database types are stored canonically as + * `database`, `documentsdb`, or `vectorsdb`. Project-wide restorations leave + * these fields empty because they do not have a single source or destination + * database. + * + * To list every migration related to one database, use its canonical type in + * a nested `OR(AND(...), AND(...), AND(...))` across the root, parent, and + * destination relation pairs: `(resourceType, resourceId)`, + * `(parentResourceType, parentResourceId)`, and `(destinationResourceType, + * destinationResourceId)`. Legacy and TablesDB databases use `database`; the + * operational `resourceType` of a table migration is not rewritten to + * `tablesdb`. + * + * When restoring a DocumentsDB or VectorsDB database to a new resource from a + * dedicated source, the restore provisions a fresh dedicated backing database + * at the source database's own specification. * * * @param string $archiveId * @param array $services * @param ?string $newResourceId * @param ?string $newResourceName - * @param ?string $newSpecification * @throws AppwriteException * @return \Appwrite\Models\BackupRestoration */ - public function createRestoration(string $archiveId, array $services, ?string $newResourceId = null, ?string $newResourceName = null, ?string $newSpecification = null): \Appwrite\Models\BackupRestoration + public function createRestoration(string $archiveId, array $services, ?string $newResourceId = null, ?string $newResourceName = null): \Appwrite\Models\BackupRestoration { $apiPath = str_replace( [], @@ -423,10 +437,6 @@ public function createRestoration(string $archiveId, array $services, ?string $n $apiParams['newResourceName'] = $newResourceName; } - if (!is_null($newSpecification)) { - $apiParams['newSpecification'] = $newSpecification; - } - $apiHeaders = []; $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); $apiHeaders['content-type'] = 'application/json'; diff --git a/src/Appwrite/Services/Functions.php b/src/Appwrite/Services/Functions.php index 1db8154c..52531fd8 100644 --- a/src/Appwrite/Services/Functions.php +++ b/src/Appwrite/Services/Functions.php @@ -422,10 +422,7 @@ public function update(string $functionId, string $name, ?Runtime $runtime = nul $apiParams['providerBranches'] = $providerBranches; $apiParams['providerPaths'] = $providerPaths; $apiParams['buildSpecification'] = $buildSpecification; - - if (!is_null($runtimeSpecification)) { - $apiParams['runtimeSpecification'] = $runtimeSpecification; - } + $apiParams['runtimeSpecification'] = $runtimeSpecification; if (!is_null($deploymentRetention)) { $apiParams['deploymentRetention'] = $deploymentRetention; diff --git a/src/Appwrite/Services/Oauth2.php b/src/Appwrite/Services/Oauth2.php new file mode 100644 index 00000000..bc4d8614 --- /dev/null +++ b/src/Appwrite/Services/Oauth2.php @@ -0,0 +1,782 @@ +client->getConfig('project')], + '/oauth2/{project_id}/approve' + ); + + $apiParams = []; + $apiParams['grant_id'] = $grantId; + + if (!is_null($authorizationDetails)) { + $apiParams['authorization_details'] = $authorizationDetails; + } + + if (!is_null($scope)) { + $apiParams['scope'] = $scope; + } + + $apiHeaders = []; + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_POST, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\Oauth2Approve::from($response); + + } + + /** + * 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. + * + * @param ?string $clientId + * @param ?string $redirectUri + * @param ?string $responseType + * @param ?string $scope + * @param ?string $state + * @param ?string $nonce + * @param ?string $codeChallenge + * @param ?string $codeChallengeMethod + * @param ?string $prompt + * @param ?int $maxAge + * @param ?string $authorizationDetails + * @param ?string $resource + * @param ?string $audience + * @param ?string $requestUri + * @throws AppwriteException + * @return \Appwrite\Models\Oauth2Authorize + */ + public function authorize(?string $clientId = null, ?string $redirectUri = null, ?string $responseType = null, ?string $scope = null, ?string $state = null, ?string $nonce = null, ?string $codeChallenge = null, ?string $codeChallengeMethod = null, ?string $prompt = null, ?int $maxAge = null, ?string $authorizationDetails = null, ?string $resource = null, ?string $audience = null, ?string $requestUri = null): \Appwrite\Models\Oauth2Authorize + { + $apiPath = str_replace( + ['{project_id}'], + [$this->client->getConfig('project')], + '/oauth2/{project_id}/authorize' + ); + + $apiParams = []; + + if (!is_null($clientId)) { + $apiParams['client_id'] = $clientId; + } + + if (!is_null($redirectUri)) { + $apiParams['redirect_uri'] = $redirectUri; + } + + if (!is_null($responseType)) { + $apiParams['response_type'] = $responseType; + } + + if (!is_null($scope)) { + $apiParams['scope'] = $scope; + } + + if (!is_null($state)) { + $apiParams['state'] = $state; + } + + if (!is_null($nonce)) { + $apiParams['nonce'] = $nonce; + } + + if (!is_null($codeChallenge)) { + $apiParams['code_challenge'] = $codeChallenge; + } + + if (!is_null($codeChallengeMethod)) { + $apiParams['code_challenge_method'] = $codeChallengeMethod; + } + + if (!is_null($prompt)) { + $apiParams['prompt'] = $prompt; + } + + if (!is_null($maxAge)) { + $apiParams['max_age'] = $maxAge; + } + + if (!is_null($authorizationDetails)) { + $apiParams['authorization_details'] = $authorizationDetails; + } + + if (!is_null($resource)) { + $apiParams['resource'] = $resource; + } + + if (!is_null($audience)) { + $apiParams['audience'] = $audience; + } + + if (!is_null($requestUri)) { + $apiParams['request_uri'] = $requestUri; + } + + $apiHeaders = []; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\Oauth2Authorize::from($response); + + } + + /** + * 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. + * + * @param ?string $clientId + * @param ?string $redirectUri + * @param ?string $responseType + * @param ?string $scope + * @param ?string $state + * @param ?string $nonce + * @param ?string $codeChallenge + * @param ?string $codeChallengeMethod + * @param ?string $prompt + * @param ?int $maxAge + * @param ?string $authorizationDetails + * @param ?string $resource + * @param ?string $audience + * @param ?string $requestUri + * @throws AppwriteException + * @return \Appwrite\Models\Oauth2Authorize + */ + public function authorizePost(?string $clientId = null, ?string $redirectUri = null, ?string $responseType = null, ?string $scope = null, ?string $state = null, ?string $nonce = null, ?string $codeChallenge = null, ?string $codeChallengeMethod = null, ?string $prompt = null, ?int $maxAge = null, ?string $authorizationDetails = null, ?string $resource = null, ?string $audience = null, ?string $requestUri = null): \Appwrite\Models\Oauth2Authorize + { + $apiPath = str_replace( + ['{project_id}'], + [$this->client->getConfig('project')], + '/oauth2/{project_id}/authorize' + ); + + $apiParams = []; + + if (!is_null($clientId)) { + $apiParams['client_id'] = $clientId; + } + + if (!is_null($redirectUri)) { + $apiParams['redirect_uri'] = $redirectUri; + } + + if (!is_null($responseType)) { + $apiParams['response_type'] = $responseType; + } + + if (!is_null($scope)) { + $apiParams['scope'] = $scope; + } + + if (!is_null($state)) { + $apiParams['state'] = $state; + } + + if (!is_null($nonce)) { + $apiParams['nonce'] = $nonce; + } + + if (!is_null($codeChallenge)) { + $apiParams['code_challenge'] = $codeChallenge; + } + + if (!is_null($codeChallengeMethod)) { + $apiParams['code_challenge_method'] = $codeChallengeMethod; + } + + if (!is_null($prompt)) { + $apiParams['prompt'] = $prompt; + } + $apiParams['max_age'] = $maxAge; + + if (!is_null($authorizationDetails)) { + $apiParams['authorization_details'] = $authorizationDetails; + } + + if (!is_null($resource)) { + $apiParams['resource'] = $resource; + } + + if (!is_null($audience)) { + $apiParams['audience'] = $audience; + } + + if (!is_null($requestUri)) { + $apiParams['request_uri'] = $requestUri; + } + + $apiHeaders = []; + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_POST, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\Oauth2Authorize::from($response); + + } + + /** + * Start the OAuth2 Device Authorization Grant. Returns the device code, user + * code, verification URL, expiration, and polling interval. + * + * @param ?string $clientId + * @param ?string $scope + * @param ?string $authorizationDetails + * @param ?string $resource + * @param ?string $audience + * @throws AppwriteException + * @return \Appwrite\Models\Oauth2DeviceAuthorization + */ + public function createDeviceAuthorization(?string $clientId = null, ?string $scope = null, ?string $authorizationDetails = null, ?string $resource = null, ?string $audience = null): \Appwrite\Models\Oauth2DeviceAuthorization + { + $apiPath = str_replace( + ['{project_id}'], + [$this->client->getConfig('project')], + '/oauth2/{project_id}/device_authorization' + ); + + $apiParams = []; + + if (!is_null($clientId)) { + $apiParams['client_id'] = $clientId; + } + + if (!is_null($scope)) { + $apiParams['scope'] = $scope; + } + + if (!is_null($authorizationDetails)) { + $apiParams['authorization_details'] = $authorizationDetails; + } + + if (!is_null($resource)) { + $apiParams['resource'] = $resource; + } + + if (!is_null($audience)) { + $apiParams['audience'] = $audience; + } + + $apiHeaders = []; + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_POST, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\Oauth2DeviceAuthorization::from($response); + + } + + /** + * 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. + * + * @param string $userCode + * @throws AppwriteException + * @return \Appwrite\Models\Oauth2Grant + */ + public function createGrant(string $userCode): \Appwrite\Models\Oauth2Grant + { + $apiPath = str_replace( + ['{project_id}'], + [$this->client->getConfig('project')], + '/oauth2/{project_id}/grants' + ); + + $apiParams = []; + $apiParams['user_code'] = $userCode; + + $apiHeaders = []; + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_POST, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\Oauth2Grant::from($response); + + } + + /** + * 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. + * + * @param string $grantId + * @throws AppwriteException + * @return \Appwrite\Models\Oauth2Grant + */ + public function getGrant(string $grantId): \Appwrite\Models\Oauth2Grant + { + $apiPath = str_replace( + ['{project_id}', '{grant_id}'], + [$this->client->getConfig('project'), $grantId], + '/oauth2/{project_id}/grants/{grant_id}' + ); + + $apiParams = []; + $apiParams['grant_id'] = $grantId; + + $apiHeaders = []; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\Oauth2Grant::from($response); + + } + + /** + * List the organizations the OAuth2 access token can access. Resolves the + * token's `organization` authorization details, expanding the `*` wildcard + * into the concrete set of organizations the user can see. + * + * @param ?int $limit + * @param ?int $offset + * @param ?string $search + * @throws AppwriteException + * @return \Appwrite\Models\Oauth2OrganizationList + */ + public function listOrganizations(?int $limit = null, ?int $offset = null, ?string $search = null): \Appwrite\Models\Oauth2OrganizationList + { + $apiPath = str_replace( + ['{project_id}'], + [$this->client->getConfig('project')], + '/oauth2/{project_id}/organizations' + ); + + $apiParams = []; + + if (!is_null($limit)) { + $apiParams['limit'] = $limit; + } + + if (!is_null($offset)) { + $apiParams['offset'] = $offset; + } + + if (!is_null($search)) { + $apiParams['search'] = $search; + } + + $apiHeaders = []; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\Oauth2OrganizationList::from($response); + + } + + /** + * Store an OAuth2 authorization request server-side and receive a short-lived + * request_uri handle for the authorize endpoint. + * + * @param string $clientId + * @param string $redirectUri + * @param string $responseType + * @param ?string $scope + * @param ?string $state + * @param ?string $nonce + * @param ?string $codeChallenge + * @param ?string $codeChallengeMethod + * @param ?string $prompt + * @param ?int $maxAge + * @param ?string $authorizationDetails + * @param ?string $resource + * @param ?string $audience + * @throws AppwriteException + * @return \Appwrite\Models\Oauth2PAR + */ + public function createPAR(string $clientId, string $redirectUri, string $responseType, ?string $scope = null, ?string $state = null, ?string $nonce = null, ?string $codeChallenge = null, ?string $codeChallengeMethod = null, ?string $prompt = null, ?int $maxAge = null, ?string $authorizationDetails = null, ?string $resource = null, ?string $audience = null): \Appwrite\Models\Oauth2PAR + { + $apiPath = str_replace( + ['{project_id}'], + [$this->client->getConfig('project')], + '/oauth2/{project_id}/par' + ); + + $apiParams = []; + $apiParams['client_id'] = $clientId; + $apiParams['redirect_uri'] = $redirectUri; + $apiParams['response_type'] = $responseType; + + if (!is_null($scope)) { + $apiParams['scope'] = $scope; + } + + if (!is_null($state)) { + $apiParams['state'] = $state; + } + + if (!is_null($nonce)) { + $apiParams['nonce'] = $nonce; + } + + if (!is_null($codeChallenge)) { + $apiParams['code_challenge'] = $codeChallenge; + } + + if (!is_null($codeChallengeMethod)) { + $apiParams['code_challenge_method'] = $codeChallengeMethod; + } + + if (!is_null($prompt)) { + $apiParams['prompt'] = $prompt; + } + $apiParams['max_age'] = $maxAge; + + if (!is_null($authorizationDetails)) { + $apiParams['authorization_details'] = $authorizationDetails; + } + + if (!is_null($resource)) { + $apiParams['resource'] = $resource; + } + + if (!is_null($audience)) { + $apiParams['audience'] = $audience; + } + + $apiHeaders = []; + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_POST, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\Oauth2PAR::from($response); + + } + + /** + * List the projects the OAuth2 access token can access. Resolves the token's + * `project` authorization details, expanding the `*` wildcard into the + * concrete set of projects the user can see. + * + * @param ?int $limit + * @param ?int $offset + * @param ?string $search + * @throws AppwriteException + * @return \Appwrite\Models\Oauth2ProjectList + */ + public function listProjects(?int $limit = null, ?int $offset = null, ?string $search = null): \Appwrite\Models\Oauth2ProjectList + { + $apiPath = str_replace( + ['{project_id}'], + [$this->client->getConfig('project')], + '/oauth2/{project_id}/projects' + ); + + $apiParams = []; + + if (!is_null($limit)) { + $apiParams['limit'] = $limit; + } + + if (!is_null($offset)) { + $apiParams['offset'] = $offset; + } + + if (!is_null($search)) { + $apiParams['search'] = $search; + } + + $apiHeaders = []; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\Oauth2ProjectList::from($response); + + } + + /** + * 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. + * + * @param string $grantId + * @throws AppwriteException + * @return \Appwrite\Models\Oauth2Reject + */ + public function reject(string $grantId): \Appwrite\Models\Oauth2Reject + { + $apiPath = str_replace( + ['{project_id}'], + [$this->client->getConfig('project')], + '/oauth2/{project_id}/reject' + ); + + $apiParams = []; + $apiParams['grant_id'] = $grantId; + + $apiHeaders = []; + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_POST, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\Oauth2Reject::from($response); + + } + + /** + * Revoke an OAuth2 access token or refresh token. + * + * @param string $token + * @param ?string $tokenTypeHint + * @param ?string $clientId + * @param ?string $clientSecret + * @throws AppwriteException + * @return array + */ + public function revoke(string $token, ?string $tokenTypeHint = null, ?string $clientId = null, ?string $clientSecret = null): array + { + $apiPath = str_replace( + ['{project_id}'], + [$this->client->getConfig('project')], + '/oauth2/{project_id}/revoke' + ); + + $apiParams = []; + $apiParams['token'] = $token; + + if (!is_null($tokenTypeHint)) { + $apiParams['token_type_hint'] = $tokenTypeHint; + } + + if (!is_null($clientId)) { + $apiParams['client_id'] = $clientId; + } + + if (!is_null($clientSecret)) { + $apiParams['client_secret'] = $clientSecret; + } + + $apiHeaders = []; + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_POST, + $apiPath, + $apiHeaders, + $apiParams + ); + + return $response; + + } + + /** + * Exchange an OAuth2 authorization code, refresh token, or device code for + * access and refresh tokens. + * + * @param string $grantType + * @param ?string $code + * @param ?string $refreshToken + * @param ?string $deviceCode + * @param ?string $clientId + * @param ?string $clientSecret + * @param ?string $codeVerifier + * @param ?string $redirectUri + * @param ?string $resource + * @param ?string $audience + * @throws AppwriteException + * @return \Appwrite\Models\Oauth2Token + */ + public function createToken(string $grantType, ?string $code = null, ?string $refreshToken = null, ?string $deviceCode = null, ?string $clientId = null, ?string $clientSecret = null, ?string $codeVerifier = null, ?string $redirectUri = null, ?string $resource = null, ?string $audience = null): \Appwrite\Models\Oauth2Token + { + $apiPath = str_replace( + ['{project_id}'], + [$this->client->getConfig('project')], + '/oauth2/{project_id}/token' + ); + + $apiParams = []; + $apiParams['grant_type'] = $grantType; + + if (!is_null($code)) { + $apiParams['code'] = $code; + } + + if (!is_null($refreshToken)) { + $apiParams['refresh_token'] = $refreshToken; + } + + if (!is_null($deviceCode)) { + $apiParams['device_code'] = $deviceCode; + } + + if (!is_null($clientId)) { + $apiParams['client_id'] = $clientId; + } + + if (!is_null($clientSecret)) { + $apiParams['client_secret'] = $clientSecret; + } + + if (!is_null($codeVerifier)) { + $apiParams['code_verifier'] = $codeVerifier; + } + + if (!is_null($redirectUri)) { + $apiParams['redirect_uri'] = $redirectUri; + } + + if (!is_null($resource)) { + $apiParams['resource'] = $resource; + } + + if (!is_null($audience)) { + $apiParams['audience'] = $audience; + } + + $apiHeaders = []; + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_POST, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\Oauth2Token::from($response); + + } +} diff --git a/src/Appwrite/Services/Organization.php b/src/Appwrite/Services/Organization.php index e50f89f5..7c189a8f 100644 --- a/src/Appwrite/Services/Organization.php +++ b/src/Appwrite/Services/Organization.php @@ -121,6 +121,214 @@ public function delete(): string } + /** + * List app installations on the organization. Any organization member can + * read installations. + * + * @param ?array $queries + * @param ?bool $total + * @throws AppwriteException + * @return \Appwrite\Models\AppInstallationList + */ + public function listInstallations(?array $queries = null, ?bool $total = null): \Appwrite\Models\AppInstallationList + { + $apiPath = str_replace( + [], + [], + '/organization/installations' + ); + + $apiParams = []; + + if (!is_null($queries)) { + $apiParams['queries'] = $queries; + } + + if (!is_null($total)) { + $apiParams['total'] = $total; + } + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\AppInstallationList::from($response); + + } + + /** + * Install an app on the organization. Only organization members with the + * owner role can install apps. The installation is granted the scopes the app + * currently requests. + * + * @param string $appId + * @param ?string $authorizationDetails + * @throws AppwriteException + * @return \Appwrite\Models\AppInstallation + */ + public function createInstallation(string $appId, ?string $authorizationDetails = null): \Appwrite\Models\AppInstallation + { + $apiPath = str_replace( + [], + [], + '/organization/installations' + ); + + $apiParams = []; + $apiParams['appId'] = $appId; + + if (!is_null($authorizationDetails)) { + $apiParams['authorizationDetails'] = $authorizationDetails; + } + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_POST, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\AppInstallation::from($response); + + } + + /** + * Get an app installation on the organization by its unique ID. Any + * organization member can read installations. + * + * @param string $installationId + * @throws AppwriteException + * @return \Appwrite\Models\AppInstallation + */ + public function getInstallation(string $installationId): \Appwrite\Models\AppInstallation + { + $apiPath = str_replace( + ['{installationId}'], + [$installationId], + '/organization/installations/{installationId}' + ); + + $apiParams = []; + $apiParams['installationId'] = $installationId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\AppInstallation::from($response); + + } + + /** + * Update an app installation on the organization. Only organization members + * with the owner role can update installations. The installation's granted + * scopes are refreshed to the scopes the app currently requests; previously + * issued installation access tokens are revoked. + * + * @param string $installationId + * @param ?string $authorizationDetails + * @throws AppwriteException + * @return \Appwrite\Models\AppInstallation + */ + public function updateInstallation(string $installationId, ?string $authorizationDetails = null): \Appwrite\Models\AppInstallation + { + $apiPath = str_replace( + ['{installationId}'], + [$installationId], + '/organization/installations/{installationId}' + ); + + $apiParams = []; + $apiParams['installationId'] = $installationId; + $apiParams['authorizationDetails'] = $authorizationDetails; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_PUT, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\AppInstallation::from($response); + + } + + /** + * Uninstall an app from the organization by its installation ID. Only + * organization members with the owner role can remove installations. + * Previously issued installation access tokens are revoked. + * + * @param string $installationId + * @throws AppwriteException + * @return string + */ + public function deleteInstallation(string $installationId): string + { + $apiPath = str_replace( + ['{installationId}'], + [$installationId], + '/organization/installations/{installationId}' + ); + + $apiParams = []; + $apiParams['installationId'] = $installationId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_DELETE, + $apiPath, + $apiHeaders, + $apiParams + ); + + return $response; + + } + /** * Get a list of all API keys from the current organization. * diff --git a/src/Appwrite/Services/Project.php b/src/Appwrite/Services/Project.php index 475d5f8e..8ba6055b 100644 --- a/src/Appwrite/Services/Project.php +++ b/src/Appwrite/Services/Project.php @@ -681,6 +681,7 @@ public function listOAuth2Providers(?array $queries = null, ?bool $total = null) * @param ?int $refreshTokenDuration * @param ?int $publicAccessTokenDuration * @param ?int $publicRefreshTokenDuration + * @param ?int $installationAccessTokenDuration * @param ?bool $confidentialPkce * @param ?string $verificationUrl * @param ?int $userCodeLength @@ -690,7 +691,7 @@ public function listOAuth2Providers(?array $queries = null, ?bool $total = null) * @throws AppwriteException * @return \Appwrite\Models\Project */ - public function updateOAuth2Server(bool $enabled, string $authorizationUrl, ?array $scopes = null, ?array $authorizationDetailsTypes = null, ?int $accessTokenDuration = null, ?int $refreshTokenDuration = null, ?int $publicAccessTokenDuration = null, ?int $publicRefreshTokenDuration = null, ?bool $confidentialPkce = null, ?string $verificationUrl = null, ?int $userCodeLength = null, ?string $userCodeFormat = null, ?int $deviceCodeDuration = null, ?array $defaultScopes = null): \Appwrite\Models\Project + public function updateOAuth2Server(bool $enabled, string $authorizationUrl, ?array $scopes = null, ?array $authorizationDetailsTypes = null, ?int $accessTokenDuration = null, ?int $refreshTokenDuration = null, ?int $publicAccessTokenDuration = null, ?int $publicRefreshTokenDuration = null, ?int $installationAccessTokenDuration = null, ?bool $confidentialPkce = null, ?string $verificationUrl = null, ?int $userCodeLength = null, ?string $userCodeFormat = null, ?int $deviceCodeDuration = null, ?array $defaultScopes = null): \Appwrite\Models\Project { $apiPath = str_replace( [], @@ -713,6 +714,7 @@ public function updateOAuth2Server(bool $enabled, string $authorizationUrl, ?arr $apiParams['refreshTokenDuration'] = $refreshTokenDuration; $apiParams['publicAccessTokenDuration'] = $publicAccessTokenDuration; $apiParams['publicRefreshTokenDuration'] = $publicRefreshTokenDuration; + $apiParams['installationAccessTokenDuration'] = $installationAccessTokenDuration; $apiParams['confidentialPkce'] = $confidentialPkce; if (!is_null($verificationUrl)) { diff --git a/src/Appwrite/Services/Sites.php b/src/Appwrite/Services/Sites.php index b7e44fdb..0b373273 100644 --- a/src/Appwrite/Services/Sites.php +++ b/src/Appwrite/Services/Sites.php @@ -1114,10 +1114,11 @@ public function deleteDeployment(string $siteId, string $deploymentId): string * @param string $siteId * @param string $deploymentId * @param ?DeploymentDownloadType $type + * @param ?string $token * @throws AppwriteException * @return string */ - public function getDeploymentDownload(string $siteId, string $deploymentId, ?DeploymentDownloadType $type = null): string + public function getDeploymentDownload(string $siteId, string $deploymentId, ?DeploymentDownloadType $type = null, ?string $token = null): string { $apiPath = str_replace( ['{siteId}', '{deploymentId}'], @@ -1133,6 +1134,10 @@ public function getDeploymentDownload(string $siteId, string $deploymentId, ?Dep $apiParams['type'] = $type; } + if (!is_null($token)) { + $apiParams['token'] = $token; + } + $apiHeaders = []; $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); $apiHeaders['accept'] = '*/*'; diff --git a/src/Appwrite/Services/TablesDB.php b/src/Appwrite/Services/TablesDB.php index bff7d67b..f2c996ff 100644 --- a/src/Appwrite/Services/TablesDB.php +++ b/src/Appwrite/Services/TablesDB.php @@ -77,10 +77,11 @@ public function list(?array $queries = null, ?string $search = null, ?bool $tota * @param string $name * @param ?bool $enabled * @param ?string $specification + * @param ?int $replicas * @throws AppwriteException * @return \Appwrite\Models\Database */ - public function create(string $databaseId, string $name, ?bool $enabled = null, ?string $specification = null): \Appwrite\Models\Database + public function create(string $databaseId, string $name, ?bool $enabled = null, ?string $specification = null, ?int $replicas = null): \Appwrite\Models\Database { $apiPath = str_replace( [], @@ -100,6 +101,10 @@ public function create(string $databaseId, string $name, ?bool $enabled = null, $apiParams['specification'] = $specification; } + if (!is_null($replicas)) { + $apiParams['replicas'] = $replicas; + } + $apiHeaders = []; $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); $apiHeaders['content-type'] = 'application/json'; @@ -120,6 +125,43 @@ public function create(string $databaseId, string $name, ?bool $enabled = null, } + /** + * List the dedicated database specifications available on the current plan. + * Each specification reports its resource limits, pricing, and whether it is + * enabled for the organization. + * + * @throws AppwriteException + * @return \Appwrite\Models\DedicatedDatabaseSpecificationList + */ + public function listSpecifications(): \Appwrite\Models\DedicatedDatabaseSpecificationList + { + $apiPath = str_replace( + [], + [], + '/tablesdb/specifications' + ); + + $apiParams = []; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\DedicatedDatabaseSpecificationList::from($response); + + } + /** * List transactions across all databases. * @@ -406,10 +448,11 @@ public function get(string $databaseId): \Appwrite\Models\Database * @param string $databaseId * @param ?string $name * @param ?bool $enabled + * @param ?int $replicas * @throws AppwriteException * @return \Appwrite\Models\Database */ - public function update(string $databaseId, ?string $name = null, ?bool $enabled = null): \Appwrite\Models\Database + public function update(string $databaseId, ?string $name = null, ?bool $enabled = null, ?int $replicas = null): \Appwrite\Models\Database { $apiPath = str_replace( ['{databaseId}'], @@ -427,6 +470,7 @@ public function update(string $databaseId, ?string $name = null, ?bool $enabled if (!is_null($enabled)) { $apiParams['enabled'] = $enabled; } + $apiParams['replicas'] = $replicas; $apiHeaders = []; $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); @@ -482,6 +526,125 @@ public function delete(string $databaseId): string } + /** + * Trigger a manual failover for a dedicated database with high availability + * enabled. Promotes a replica to primary. The failover runs asynchronously; + * poll the database document for status updates. + * + * @param string $databaseId + * @param ?string $targetReplicaId + * @throws AppwriteException + * @return \Appwrite\Models\DedicatedDatabase + */ + public function createFailover(string $databaseId, ?string $targetReplicaId = null): \Appwrite\Models\DedicatedDatabase + { + $apiPath = str_replace( + ['{databaseId}'], + [$databaseId], + '/tablesdb/{databaseId}/failovers' + ); + + $apiParams = []; + $apiParams['databaseId'] = $databaseId; + $apiParams['targetReplicaId'] = $targetReplicaId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_POST, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\DedicatedDatabase::from($response); + + } + + /** + * Get high availability status for a dedicated database. Returns replica + * statuses, replication lag, and sync mode. + * + * @param string $databaseId + * @throws AppwriteException + * @return \Appwrite\Models\DedicatedDatabaseReplicas + */ + public function getReplicas(string $databaseId): \Appwrite\Models\DedicatedDatabaseReplicas + { + $apiPath = str_replace( + ['{databaseId}'], + [$databaseId], + '/tablesdb/{databaseId}/replicas' + ); + + $apiParams = []; + $apiParams['databaseId'] = $databaseId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\DedicatedDatabaseReplicas::from($response); + + } + + /** + * Get real-time health and status information for a dedicated database. + * Returns health status, readiness, uptime, connection info, replica status, + * and volume information. + * + * @param string $databaseId + * @throws AppwriteException + * @return \Appwrite\Models\DatabaseStatus + */ + public function getStatus(string $databaseId): \Appwrite\Models\DatabaseStatus + { + $apiPath = str_replace( + ['{databaseId}'], + [$databaseId], + '/tablesdb/{databaseId}/status' + ); + + $apiParams = []; + $apiParams['databaseId'] = $databaseId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\DatabaseStatus::from($response); + + } + /** * Get a list of all tables that belong to the provided databaseId. You can * use the search parameter to filter your results. diff --git a/src/Appwrite/Services/Teams.php b/src/Appwrite/Services/Teams.php index 4c17e3b9..53b32bcb 100644 --- a/src/Appwrite/Services/Teams.php +++ b/src/Appwrite/Services/Teams.php @@ -223,6 +223,224 @@ public function delete(string $teamId): string } + /** + * List app installations on a team. Any team member can read installations. + * + * @param string $teamId + * @param ?array $queries + * @param ?bool $total + * @throws AppwriteException + * @return \Appwrite\Models\AppInstallationList + */ + public function listInstallations(string $teamId, ?array $queries = null, ?bool $total = null): \Appwrite\Models\AppInstallationList + { + $apiPath = str_replace( + ['{teamId}'], + [$teamId], + '/teams/{teamId}/installations' + ); + + $apiParams = []; + $apiParams['teamId'] = $teamId; + + if (!is_null($queries)) { + $apiParams['queries'] = $queries; + } + + if (!is_null($total)) { + $apiParams['total'] = $total; + } + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\AppInstallationList::from($response); + + } + + /** + * Install an app on a team. When authenticated as a user, only team members + * with the owner role can install apps. Requests using an API key or in admin + * mode can install apps on any team. The installation is granted the scopes + * the app currently requests. + * + * @param string $teamId + * @param string $appId + * @param ?string $authorizationDetails + * @throws AppwriteException + * @return \Appwrite\Models\AppInstallation + */ + public function createInstallation(string $teamId, string $appId, ?string $authorizationDetails = null): \Appwrite\Models\AppInstallation + { + $apiPath = str_replace( + ['{teamId}'], + [$teamId], + '/teams/{teamId}/installations' + ); + + $apiParams = []; + $apiParams['teamId'] = $teamId; + $apiParams['appId'] = $appId; + + if (!is_null($authorizationDetails)) { + $apiParams['authorizationDetails'] = $authorizationDetails; + } + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_POST, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\AppInstallation::from($response); + + } + + /** + * Get an app installation on a team by its unique ID. Any team member can + * read installations. + * + * @param string $teamId + * @param string $installationId + * @throws AppwriteException + * @return \Appwrite\Models\AppInstallation + */ + public function getInstallation(string $teamId, string $installationId): \Appwrite\Models\AppInstallation + { + $apiPath = str_replace( + ['{teamId}', '{installationId}'], + [$teamId, $installationId], + '/teams/{teamId}/installations/{installationId}' + ); + + $apiParams = []; + $apiParams['teamId'] = $teamId; + $apiParams['installationId'] = $installationId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_GET, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\AppInstallation::from($response); + + } + + /** + * Update an app installation on a team. Only team members with the owner role + * can update installations. The installation's granted scopes are refreshed + * to the scopes the app currently requests; previously issued installation + * access tokens are revoked. + * + * @param string $teamId + * @param string $installationId + * @param ?string $authorizationDetails + * @throws AppwriteException + * @return \Appwrite\Models\AppInstallation + */ + public function updateInstallation(string $teamId, string $installationId, ?string $authorizationDetails = null): \Appwrite\Models\AppInstallation + { + $apiPath = str_replace( + ['{teamId}', '{installationId}'], + [$teamId, $installationId], + '/teams/{teamId}/installations/{installationId}' + ); + + $apiParams = []; + $apiParams['teamId'] = $teamId; + $apiParams['installationId'] = $installationId; + $apiParams['authorizationDetails'] = $authorizationDetails; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_PUT, + $apiPath, + $apiHeaders, + $apiParams + ); + + if (!is_array($response)) { + throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); + } + + return \Appwrite\Models\AppInstallation::from($response); + + } + + /** + * Uninstall an app from a team by its installation ID. Only team members with + * the owner role can remove installations. Previously issued installation + * access tokens are revoked. + * + * @param string $teamId + * @param string $installationId + * @throws AppwriteException + * @return string + */ + public function deleteInstallation(string $teamId, string $installationId): string + { + $apiPath = str_replace( + ['{teamId}', '{installationId}'], + [$teamId, $installationId], + '/teams/{teamId}/installations/{installationId}' + ); + + $apiParams = []; + $apiParams['teamId'] = $teamId; + $apiParams['installationId'] = $installationId; + + $apiHeaders = []; + $apiHeaders['X-Appwrite-Project'] = $this->client->getConfig('project'); + $apiHeaders['content-type'] = 'application/json'; + $apiHeaders['accept'] = 'application/json'; + + $response = $this->client->call( + Client::METHOD_DELETE, + $apiPath, + $apiHeaders, + $apiParams + ); + + return $response; + + } + /** * Use this endpoint to list a team's members using the team's ID. All team * members have read access to this endpoint. Hide sensitive attributes from diff --git a/tests/Appwrite/Services/AccountTest.php b/tests/Appwrite/Services/AccountTest.php index b6c0220e..eabfc829 100644 --- a/tests/Appwrite/Services/AccountTest.php +++ b/tests/Appwrite/Services/AccountTest.php @@ -113,6 +113,170 @@ public function testMethodCreate(): void $this->assertInstanceOf(\Appwrite\Models\User::class, $response); } + public function testMethodListConsents(): void + { + $data = array( + "total" => 5, + "consents" => array( + array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "userId" => "5e5ea5c16897e", + "appId" => "5e5ea5c16897e", + "cimdUrl" => "https://example.com/.well-known/client-metadata.json", + "scopes" => array(), + "resources" => array(), + "authorizationDetails" => "[{\"type\":\"calendar\",\"identifier\":\"primary\",\"actions\":[\"read_events\",\"create_event\"]}]", + "expire" => "2020-10-15T06:38:00.000+00:00" + ) + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->account->listConsents(); + + $this->assertInstanceOf(\Appwrite\Models\Oauth2ConsentList::class, $response); + } + + public function testMethodGetConsent(): void + { + $data = array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "userId" => "5e5ea5c16897e", + "appId" => "5e5ea5c16897e", + "cimdUrl" => "https://example.com/.well-known/client-metadata.json", + "scopes" => array(), + "resources" => array(), + "authorizationDetails" => "[{\"type\":\"calendar\",\"identifier\":\"primary\",\"actions\":[\"read_events\",\"create_event\"]}]", + "expire" => "2020-10-15T06:38:00.000+00:00" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->account->getConsent( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\Oauth2Consent::class, $response); + } + + public function testMethodDeleteConsent(): void + { + $data = ''; + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->account->deleteConsent( + "" + ); + + $this->assertSame($data, $response); + } + + public function testMethodListConsentTokens(): void + { + $data = array( + "total" => 5, + "tokens" => array( + array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "consentId" => "5e5ea5c16897e", + "userId" => "5e5ea5c16897e", + "appId" => "5e5ea5c16897e", + "cimdUrl" => "https://example.com/.well-known/client-metadata.json", + "scopes" => array(), + "resources" => array(), + "authorizationDetails" => "[{\"type\":\"calendar\",\"identifier\":\"primary\",\"actions\":[\"read_events\",\"create_event\"]}]", + "expire" => "2020-10-15T06:38:00.000+00:00" + ) + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->account->listConsentTokens( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\Oauth2ConsentTokenList::class, $response); + } + + public function testMethodGetConsentToken(): void + { + $data = array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "consentId" => "5e5ea5c16897e", + "userId" => "5e5ea5c16897e", + "appId" => "5e5ea5c16897e", + "cimdUrl" => "https://example.com/.well-known/client-metadata.json", + "scopes" => array(), + "resources" => array(), + "authorizationDetails" => "[{\"type\":\"calendar\",\"identifier\":\"primary\",\"actions\":[\"read_events\",\"create_event\"]}]", + "expire" => "2020-10-15T06:38:00.000+00:00" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->account->getConsentToken( + "", + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\Oauth2ConsentToken::class, $response); + } + + public function testMethodDeleteConsentToken(): void + { + $data = ''; + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->account->deleteConsentToken( + "", + "" + ); + + $this->assertSame($data, $response); + } + public function testMethodUpdateEmail(): void { $data = array( diff --git a/tests/Appwrite/Services/ActivitiesTest.php b/tests/Appwrite/Services/ActivitiesTest.php index f4daf521..b1d16072 100644 --- a/tests/Appwrite/Services/ActivitiesTest.php +++ b/tests/Appwrite/Services/ActivitiesTest.php @@ -38,10 +38,21 @@ public function testMethodListEvents(): void "ip" => "127.0.0.1", "mode" => "admin", "country" => "US", + "continentCode" => "NA", + "city" => "Mountain View", + "subdivisions" => "California", + "isp" => "Google", + "autonomousSystemNumber" => "15169", + "autonomousSystemOrganization" => "GOOGLE", + "connectionType" => "cable", + "connectionUsageType" => "residential", + "connectionOrganization" => "Google LLC", "time" => "2020-10-15T06:38:00.000+00:00", "projectId" => "610fc2f985ee0", "teamId" => "610fc2f985ee0", - "hostname" => "appwrite.io" + "hostname" => "appwrite.io", + "sdk" => "web", + "sdkVersion" => "14.0.0" ) ) ); @@ -75,10 +86,21 @@ public function testMethodGetEvent(): void "ip" => "127.0.0.1", "mode" => "admin", "country" => "US", + "continentCode" => "NA", + "city" => "Mountain View", + "subdivisions" => "California", + "isp" => "Google", + "autonomousSystemNumber" => "15169", + "autonomousSystemOrganization" => "GOOGLE", + "connectionType" => "cable", + "connectionUsageType" => "residential", + "connectionOrganization" => "Google LLC", "time" => "2020-10-15T06:38:00.000+00:00", "projectId" => "610fc2f985ee0", "teamId" => "610fc2f985ee0", - "hostname" => "appwrite.io" + "hostname" => "appwrite.io", + "sdk" => "web", + "sdkVersion" => "14.0.0" ); $this->client diff --git a/tests/Appwrite/Services/AppsTest.php b/tests/Appwrite/Services/AppsTest.php new file mode 100644 index 00000000..63767c7a --- /dev/null +++ b/tests/Appwrite/Services/AppsTest.php @@ -0,0 +1,754 @@ +client = Mockery::mock(Client::class); + $this->apps = new Apps($this->client); + } + + public function testMethodList(): void + { + $data = array( + "total" => 5, + "apps" => array( + array( + "\$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" => array(), + "tagline" => "Automate your workspace.", + "tags" => array(), + "labels" => array(), + "images" => array(), + "supportUrl" => "https://example.com/support", + "dataDeletionUrl" => "https://example.com/data-deletion", + "redirectUris" => array(), + "postLogoutRedirectUris" => array(), + "enabled" => true, + "type" => "confidential", + "deviceFlow" => true, + "teamId" => "5e5ea5c16897e", + "userId" => "5e5ea5c16897e", + "installationScopes" => array(), + "installationRedirectUrl" => "https://example.com/setup", + "secrets" => array( + array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "appId" => "5e5ea5c16897e", + "secret" => "[SECRET]", + "hint" => "f5c6c7", + "createdById" => "5e5ea5c16897e", + "createdByName" => "Walter White" + ) + ) + ) + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->list(); + + $this->assertInstanceOf(\Appwrite\Models\AppsList::class, $response); + } + + public function testMethodCreate(): void + { + $data = array( + "\$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" => array(), + "tagline" => "Automate your workspace.", + "tags" => array(), + "labels" => array(), + "images" => array(), + "supportUrl" => "https://example.com/support", + "dataDeletionUrl" => "https://example.com/data-deletion", + "redirectUris" => array(), + "postLogoutRedirectUris" => array(), + "enabled" => true, + "type" => "confidential", + "deviceFlow" => true, + "teamId" => "5e5ea5c16897e", + "userId" => "5e5ea5c16897e", + "installationScopes" => array(), + "installationRedirectUrl" => "https://example.com/setup", + "secrets" => array( + array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "appId" => "5e5ea5c16897e", + "secret" => "[SECRET]", + "hint" => "f5c6c7", + "createdById" => "5e5ea5c16897e", + "createdByName" => "Walter White" + ) + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->create( + "", + "", + array() + ); + + $this->assertInstanceOf(\Appwrite\Models\App::class, $response); + } + + public function testMethodListInstallationScopes(): void + { + $data = array( + "total" => 5, + "scopes" => array( + array( + "value" => "organization:organization.read", + "description" => "Access to read the organization", + "type" => "organization", + "category" => "Organization", + "deprecated" => true + ) + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->listInstallationScopes(); + + $this->assertInstanceOf(\Appwrite\Models\AppScopeList::class, $response); + } + + public function testMethodListOAuth2Scopes(): void + { + $data = array( + "total" => 5, + "scopes" => array( + array( + "value" => "organization:organization.read", + "description" => "Access to read the organization", + "type" => "organization", + "category" => "Organization", + "deprecated" => true + ) + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->listOAuth2Scopes(); + + $this->assertInstanceOf(\Appwrite\Models\AppScopeList::class, $response); + } + + public function testMethodGet(): void + { + $data = array( + "\$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" => array(), + "tagline" => "Automate your workspace.", + "tags" => array(), + "labels" => array(), + "images" => array(), + "supportUrl" => "https://example.com/support", + "dataDeletionUrl" => "https://example.com/data-deletion", + "redirectUris" => array(), + "postLogoutRedirectUris" => array(), + "enabled" => true, + "type" => "confidential", + "deviceFlow" => true, + "teamId" => "5e5ea5c16897e", + "userId" => "5e5ea5c16897e", + "installationScopes" => array(), + "installationRedirectUrl" => "https://example.com/setup", + "secrets" => array( + array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "appId" => "5e5ea5c16897e", + "secret" => "[SECRET]", + "hint" => "f5c6c7", + "createdById" => "5e5ea5c16897e", + "createdByName" => "Walter White" + ) + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->get( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\App::class, $response); + } + + public function testMethodUpdate(): void + { + $data = array( + "\$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" => array(), + "tagline" => "Automate your workspace.", + "tags" => array(), + "labels" => array(), + "images" => array(), + "supportUrl" => "https://example.com/support", + "dataDeletionUrl" => "https://example.com/data-deletion", + "redirectUris" => array(), + "postLogoutRedirectUris" => array(), + "enabled" => true, + "type" => "confidential", + "deviceFlow" => true, + "teamId" => "5e5ea5c16897e", + "userId" => "5e5ea5c16897e", + "installationScopes" => array(), + "installationRedirectUrl" => "https://example.com/setup", + "secrets" => array( + array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "appId" => "5e5ea5c16897e", + "secret" => "[SECRET]", + "hint" => "f5c6c7", + "createdById" => "5e5ea5c16897e", + "createdByName" => "Walter White" + ) + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->update( + "", + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\App::class, $response); + } + + public function testMethodDelete(): void + { + $data = ''; + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->delete( + "" + ); + + $this->assertSame($data, $response); + } + + public function testMethodListInstallations(): void + { + $data = array( + "total" => 5, + "installations" => array( + array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "appId" => "5e5ea5c16897e", + "teamId" => "5e5ea5c16897e", + "scopes" => array(), + "authorizationDetails" => array(), + "createdById" => "5e5ea5c16897e", + "createdByName" => "Walter White" + ) + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->listInstallations( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\AppInstallationList::class, $response); + } + + public function testMethodGetInstallation(): void + { + $data = array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "appId" => "5e5ea5c16897e", + "teamId" => "5e5ea5c16897e", + "scopes" => array(), + "authorizationDetails" => array(), + "createdById" => "5e5ea5c16897e", + "createdByName" => "Walter White" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->getInstallation( + "", + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\AppInstallation::class, $response); + } + + public function testMethodCreateInstallationToken(): void + { + $data = array( + "access_token" => "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...", + "token_type" => "Bearer", + "expires_in" => 3600, + "refresh_token" => "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...", + "scope" => "openid email profile" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->createInstallationToken( + "", + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\Oauth2Token::class, $response); + } + + public function testMethodListKeys(): void + { + $data = array( + "total" => 5, + "keys" => array( + array( + "\$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" + ) + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->listKeys( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\AppKeyList::class, $response); + } + + public function testMethodCreateKey(): void + { + $data = array( + "\$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" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->createKey( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\AppKey::class, $response); + } + + public function testMethodGetKey(): void + { + $data = array( + "\$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" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->getKey( + "", + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\AppKey::class, $response); + } + + public function testMethodDeleteKey(): void + { + $data = ''; + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->deleteKey( + "", + "" + ); + + $this->assertSame($data, $response); + } + + public function testMethodUpdateLabels(): void + { + $data = array( + "\$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" => array(), + "tagline" => "Automate your workspace.", + "tags" => array(), + "labels" => array(), + "images" => array(), + "supportUrl" => "https://example.com/support", + "dataDeletionUrl" => "https://example.com/data-deletion", + "redirectUris" => array(), + "postLogoutRedirectUris" => array(), + "enabled" => true, + "type" => "confidential", + "deviceFlow" => true, + "teamId" => "5e5ea5c16897e", + "userId" => "5e5ea5c16897e", + "installationScopes" => array(), + "installationRedirectUrl" => "https://example.com/setup", + "secrets" => array( + array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "appId" => "5e5ea5c16897e", + "secret" => "[SECRET]", + "hint" => "f5c6c7", + "createdById" => "5e5ea5c16897e", + "createdByName" => "Walter White" + ) + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->updateLabels( + "", + array() + ); + + $this->assertInstanceOf(\Appwrite\Models\App::class, $response); + } + + public function testMethodListSecrets(): void + { + $data = array( + "total" => 5, + "secrets" => array( + array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "appId" => "5e5ea5c16897e", + "secret" => "[SECRET]", + "hint" => "f5c6c7", + "createdById" => "5e5ea5c16897e", + "createdByName" => "Walter White" + ) + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->listSecrets( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\AppSecretList::class, $response); + } + + public function testMethodCreateSecret(): void + { + $data = array( + "\$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" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->createSecret( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\AppSecretPlaintext::class, $response); + } + + public function testMethodGetSecret(): void + { + $data = array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "appId" => "5e5ea5c16897e", + "secret" => "[SECRET]", + "hint" => "f5c6c7", + "createdById" => "5e5ea5c16897e", + "createdByName" => "Walter White" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->getSecret( + "", + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\AppSecret::class, $response); + } + + public function testMethodDeleteSecret(): void + { + $data = ''; + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->deleteSecret( + "", + "" + ); + + $this->assertSame($data, $response); + } + + public function testMethodUpdateTeam(): void + { + $data = array( + "\$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" => array(), + "tagline" => "Automate your workspace.", + "tags" => array(), + "labels" => array(), + "images" => array(), + "supportUrl" => "https://example.com/support", + "dataDeletionUrl" => "https://example.com/data-deletion", + "redirectUris" => array(), + "postLogoutRedirectUris" => array(), + "enabled" => true, + "type" => "confidential", + "deviceFlow" => true, + "teamId" => "5e5ea5c16897e", + "userId" => "5e5ea5c16897e", + "installationScopes" => array(), + "installationRedirectUrl" => "https://example.com/setup", + "secrets" => array( + array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "appId" => "5e5ea5c16897e", + "secret" => "[SECRET]", + "hint" => "f5c6c7", + "createdById" => "5e5ea5c16897e", + "createdByName" => "Walter White" + ) + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->updateTeam( + "", + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\App::class, $response); + } + + public function testMethodDeleteTokens(): void + { + $data = ''; + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->apps->deleteTokens( + "" + ); + + $this->assertSame($data, $response); + } + +} diff --git a/tests/Appwrite/Services/BackupsTest.php b/tests/Appwrite/Services/BackupsTest.php index da100a87..ee9d09d4 100644 --- a/tests/Appwrite/Services/BackupsTest.php +++ b/tests/Appwrite/Services/BackupsTest.php @@ -280,7 +280,7 @@ public function testMethodCreateRestoration(): void "migrationId" => "did8jx6ws45jana098ab7", "services" => array(), "resources" => array(), - "options" => "{databases.database[{oldId, newId, newName, newSpecification}]}" + "options" => "{databases.database[{oldId, newId, newName}]}" ); $this->client @@ -314,7 +314,7 @@ public function testMethodListRestorations(): void "migrationId" => "did8jx6ws45jana098ab7", "services" => array(), "resources" => array(), - "options" => "{databases.database[{oldId, newId, newName, newSpecification}]}" + "options" => "{databases.database[{oldId, newId, newName}]}" ) ) ); @@ -344,7 +344,7 @@ public function testMethodGetRestoration(): void "migrationId" => "did8jx6ws45jana098ab7", "services" => array(), "resources" => array(), - "options" => "{databases.database[{oldId, newId, newName, newSpecification}]}" + "options" => "{databases.database[{oldId, newId, newName}]}" ); $this->client diff --git a/tests/Appwrite/Services/DatabasesTest.php b/tests/Appwrite/Services/DatabasesTest.php index f7a0e312..cacd8583 100644 --- a/tests/Appwrite/Services/DatabasesTest.php +++ b/tests/Appwrite/Services/DatabasesTest.php @@ -33,35 +33,7 @@ public function testMethodList(): void "\$createdAt" => "2020-10-15T06:38:00.000+00:00", "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", "enabled" => true, - "type" => "legacy", - "policies" => array( - array( - "\$id" => "5e5ea5c16897e", - "name" => "Hourly backups", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "services" => array(), - "resources" => array(), - "retention" => 7, - "schedule" => "0 * * * *", - "type" => "full", - "enabled" => true - ) - ), - "archives" => array( - array( - "\$id" => "5e5ea5c16897e", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "policyId" => "did8jx6ws45jana098ab7", - "size" => 100000, - "status" => "completed", - "startedAt" => "2020-10-15T06:38:00.000+00:00", - "migrationId" => "did8jx6ws45jana098ab7", - "services" => array(), - "resources" => array() - ) - ) + "type" => "legacy" ) ) ); @@ -86,35 +58,7 @@ public function testMethodCreate(): void "\$createdAt" => "2020-10-15T06:38:00.000+00:00", "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", "enabled" => true, - "type" => "legacy", - "policies" => array( - array( - "\$id" => "5e5ea5c16897e", - "name" => "Hourly backups", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "services" => array(), - "resources" => array(), - "retention" => 7, - "schedule" => "0 * * * *", - "type" => "full", - "enabled" => true - ) - ), - "archives" => array( - array( - "\$id" => "5e5ea5c16897e", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "policyId" => "did8jx6ws45jana098ab7", - "size" => 100000, - "status" => "completed", - "startedAt" => "2020-10-15T06:38:00.000+00:00", - "migrationId" => "did8jx6ws45jana098ab7", - "services" => array(), - "resources" => array() - ) - ) + "type" => "legacy" ); $this->client @@ -284,35 +228,7 @@ public function testMethodGet(): void "\$createdAt" => "2020-10-15T06:38:00.000+00:00", "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", "enabled" => true, - "type" => "legacy", - "policies" => array( - array( - "\$id" => "5e5ea5c16897e", - "name" => "Hourly backups", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "services" => array(), - "resources" => array(), - "retention" => 7, - "schedule" => "0 * * * *", - "type" => "full", - "enabled" => true - ) - ), - "archives" => array( - array( - "\$id" => "5e5ea5c16897e", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "policyId" => "did8jx6ws45jana098ab7", - "size" => 100000, - "status" => "completed", - "startedAt" => "2020-10-15T06:38:00.000+00:00", - "migrationId" => "did8jx6ws45jana098ab7", - "services" => array(), - "resources" => array() - ) - ) + "type" => "legacy" ); $this->client @@ -337,35 +253,7 @@ public function testMethodUpdate(): void "\$createdAt" => "2020-10-15T06:38:00.000+00:00", "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", "enabled" => true, - "type" => "legacy", - "policies" => array( - array( - "\$id" => "5e5ea5c16897e", - "name" => "Hourly backups", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "services" => array(), - "resources" => array(), - "retention" => 7, - "schedule" => "0 * * * *", - "type" => "full", - "enabled" => true - ) - ), - "archives" => array( - array( - "\$id" => "5e5ea5c16897e", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "policyId" => "did8jx6ws45jana098ab7", - "size" => 100000, - "status" => "completed", - "startedAt" => "2020-10-15T06:38:00.000+00:00", - "migrationId" => "did8jx6ws45jana098ab7", - "services" => array(), - "resources" => array() - ) - ) + "type" => "legacy" ); $this->client diff --git a/tests/Appwrite/Services/Oauth2Test.php b/tests/Appwrite/Services/Oauth2Test.php new file mode 100644 index 00000000..3bf122fc --- /dev/null +++ b/tests/Appwrite/Services/Oauth2Test.php @@ -0,0 +1,297 @@ +client = Mockery::mock(Client::class); + $this->oauth2 = new Oauth2($this->client); + } + + public function testMethodApprove(): void + { + $data = array( + "redirectUrl" => "https://example.com/callback?code=abcde&state=fghij" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->oauth2->approve( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\Oauth2Approve::class, $response); + } + + public function testMethodAuthorize(): void + { + $data = array( + "grantId" => "5e5ea5c16897e", + "redirectUrl" => "https://example.com/callback?code=abcde&state=fghij" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->oauth2->authorize(); + + $this->assertInstanceOf(\Appwrite\Models\Oauth2Authorize::class, $response); + } + + public function testMethodAuthorizePost(): void + { + $data = array( + "grantId" => "5e5ea5c16897e", + "redirectUrl" => "https://example.com/callback?code=abcde&state=fghij" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->oauth2->authorizePost(); + + $this->assertInstanceOf(\Appwrite\Models\Oauth2Authorize::class, $response); + } + + public function testMethodCreateDeviceAuthorization(): void + { + $data = array( + "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, + "interval" => 5 + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->oauth2->createDeviceAuthorization(); + + $this->assertInstanceOf(\Appwrite\Models\Oauth2DeviceAuthorization::class, $response); + } + + public function testMethodCreateGrant(): void + { + $data = array( + "\$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" => array(), + "resources" => array(), + "authorizationDetails" => "[{\"type\":\"calendar\",\"identifier\":\"primary\",\"actions\":[\"read_events\",\"create_event\"]}]", + "prompt" => "login", + "redirectUri" => "https://example.com/callback", + "authTime" => 1592981250, + "expire" => "2020-10-15T06:38:00.000+00:00" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->oauth2->createGrant( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\Oauth2Grant::class, $response); + } + + public function testMethodGetGrant(): void + { + $data = array( + "\$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" => array(), + "resources" => array(), + "authorizationDetails" => "[{\"type\":\"calendar\",\"identifier\":\"primary\",\"actions\":[\"read_events\",\"create_event\"]}]", + "prompt" => "login", + "redirectUri" => "https://example.com/callback", + "authTime" => 1592981250, + "expire" => "2020-10-15T06:38:00.000+00:00" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->oauth2->getGrant( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\Oauth2Grant::class, $response); + } + + public function testMethodListOrganizations(): void + { + $data = array( + "total" => 5, + "organizations" => array( + array( + "\$id" => "5e5ea5c16897e" + ) + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->oauth2->listOrganizations(); + + $this->assertInstanceOf(\Appwrite\Models\Oauth2OrganizationList::class, $response); + } + + public function testMethodCreatePAR(): void + { + $data = array( + "request_uri" => "urn:appwrite:oauth2:request:5e5ea5c16897e", + "expires_in" => 600 + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->oauth2->createPAR( + "", + "https://example.com", + "code" + ); + + $this->assertInstanceOf(\Appwrite\Models\Oauth2PAR::class, $response); + } + + public function testMethodListProjects(): void + { + $data = array( + "total" => 5, + "projects" => array( + array( + "\$id" => "5e5ea5c16897e", + "region" => "fra", + "endpoint" => "https://fra.cloud.appwrite.io/v1" + ) + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->oauth2->listProjects(); + + $this->assertInstanceOf(\Appwrite\Models\Oauth2ProjectList::class, $response); + } + + public function testMethodReject(): void + { + $data = array( + "redirectUrl" => "https://example.com/callback?error=access_denied&state=fghij" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->oauth2->reject( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\Oauth2Reject::class, $response); + } + + public function testMethodRevoke(): void + { + $data = array(); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->oauth2->revoke( + "" + ); + + $this->assertSame($data, $response); + } + + public function testMethodCreateToken(): void + { + $data = array( + "access_token" => "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...", + "token_type" => "Bearer", + "expires_in" => 3600, + "refresh_token" => "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...", + "scope" => "openid email profile" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->oauth2->createToken( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\Oauth2Token::class, $response); + } + +} diff --git a/tests/Appwrite/Services/OrganizationTest.php b/tests/Appwrite/Services/OrganizationTest.php index 237ef05f..40c2dd57 100644 --- a/tests/Appwrite/Services/OrganizationTest.php +++ b/tests/Appwrite/Services/OrganizationTest.php @@ -46,6 +46,7 @@ public function testMethodGet(): void "screenshotsGenerated" => 50, "members" => 25, "webhooks" => 25, + "wafRules" => 2, "projects" => 2, "platforms" => 3, "users" => 25, @@ -276,6 +277,7 @@ public function testMethodUpdate(): void "screenshotsGenerated" => 50, "members" => 25, "webhooks" => 25, + "wafRules" => 2, "projects" => 2, "platforms" => 3, "users" => 25, @@ -498,6 +500,139 @@ public function testMethodDelete(): void $this->assertSame($data, $response); } + public function testMethodListInstallations(): void + { + $data = array( + "total" => 5, + "installations" => array( + array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "appId" => "5e5ea5c16897e", + "teamId" => "5e5ea5c16897e", + "scopes" => array(), + "authorizationDetails" => array(), + "createdById" => "5e5ea5c16897e", + "createdByName" => "Walter White" + ) + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->organization->listInstallations(); + + $this->assertInstanceOf(\Appwrite\Models\AppInstallationList::class, $response); + } + + public function testMethodCreateInstallation(): void + { + $data = array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "appId" => "5e5ea5c16897e", + "teamId" => "5e5ea5c16897e", + "scopes" => array(), + "authorizationDetails" => array(), + "createdById" => "5e5ea5c16897e", + "createdByName" => "Walter White" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->organization->createInstallation( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\AppInstallation::class, $response); + } + + public function testMethodGetInstallation(): void + { + $data = array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "appId" => "5e5ea5c16897e", + "teamId" => "5e5ea5c16897e", + "scopes" => array(), + "authorizationDetails" => array(), + "createdById" => "5e5ea5c16897e", + "createdByName" => "Walter White" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->organization->getInstallation( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\AppInstallation::class, $response); + } + + public function testMethodUpdateInstallation(): void + { + $data = array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "appId" => "5e5ea5c16897e", + "teamId" => "5e5ea5c16897e", + "scopes" => array(), + "authorizationDetails" => array(), + "createdById" => "5e5ea5c16897e", + "createdByName" => "Walter White" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->organization->updateInstallation( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\AppInstallation::class, $response); + } + + public function testMethodDeleteInstallation(): void + { + $data = ''; + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->organization->deleteInstallation( + "" + ); + + $this->assertSame($data, $response); + } + public function testMethodListKeys(): void { $data = array( @@ -863,7 +998,8 @@ public function testMethodListProjects(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ) ) ); @@ -947,7 +1083,8 @@ public function testMethodCreateProject(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -1032,7 +1169,8 @@ public function testMethodGetProject(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -1116,7 +1254,8 @@ public function testMethodUpdateProject(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client diff --git a/tests/Appwrite/Services/ProjectTest.php b/tests/Appwrite/Services/ProjectTest.php index 6cf56662..0213e34c 100644 --- a/tests/Appwrite/Services/ProjectTest.php +++ b/tests/Appwrite/Services/ProjectTest.php @@ -96,7 +96,8 @@ public function testMethodGet(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -194,7 +195,8 @@ public function testMethodUpdateAuthMethod(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -445,7 +447,8 @@ public function testMethodUpdateLabels(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -663,7 +666,8 @@ public function testMethodUpdateOAuth2Server(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -2053,7 +2057,8 @@ public function testMethodUpdateDenyAliasedEmailPolicy(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -2137,7 +2142,8 @@ public function testMethodUpdateDenyCorporateEmailPolicy(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -2221,7 +2227,8 @@ public function testMethodUpdateDenyDisposableEmailPolicy(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -2305,7 +2312,8 @@ public function testMethodUpdateDenyFreeEmailPolicy(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -2389,7 +2397,8 @@ public function testMethodUpdateMembershipPrivacyPolicy(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -2471,7 +2480,8 @@ public function testMethodUpdatePasswordDictionaryPolicy(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -2555,7 +2565,8 @@ public function testMethodUpdatePasswordHistoryPolicy(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -2639,7 +2650,8 @@ public function testMethodUpdatePasswordPersonalDataPolicy(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -2746,7 +2758,8 @@ public function testMethodUpdateSessionAlertPolicy(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -2830,7 +2843,8 @@ public function testMethodUpdateSessionDurationPolicy(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -2914,7 +2928,8 @@ public function testMethodUpdateSessionInvalidationPolicy(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -2998,7 +3013,8 @@ public function testMethodUpdateSessionLimitPolicy(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -3082,7 +3098,8 @@ public function testMethodUpdateUserLimitPolicy(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -3192,7 +3209,8 @@ public function testMethodUpdateProtocol(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -3277,7 +3295,8 @@ public function testMethodUpdateService(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client @@ -3362,7 +3381,8 @@ public function testMethodUpdateSMTP(): void "billingPlan" => "pro" ) ), - "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00" + "consoleAccessedAt" => "2020-10-15T06:38:00.000+00:00", + "wafEnabled" => true ); $this->client diff --git a/tests/Appwrite/Services/TablesDBTest.php b/tests/Appwrite/Services/TablesDBTest.php index f298c097..1c75086f 100644 --- a/tests/Appwrite/Services/TablesDBTest.php +++ b/tests/Appwrite/Services/TablesDBTest.php @@ -33,35 +33,7 @@ public function testMethodList(): void "\$createdAt" => "2020-10-15T06:38:00.000+00:00", "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", "enabled" => true, - "type" => "legacy", - "policies" => array( - array( - "\$id" => "5e5ea5c16897e", - "name" => "Hourly backups", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "services" => array(), - "resources" => array(), - "retention" => 7, - "schedule" => "0 * * * *", - "type" => "full", - "enabled" => true - ) - ), - "archives" => array( - array( - "\$id" => "5e5ea5c16897e", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "policyId" => "did8jx6ws45jana098ab7", - "size" => 100000, - "status" => "completed", - "startedAt" => "2020-10-15T06:38:00.000+00:00", - "migrationId" => "did8jx6ws45jana098ab7", - "services" => array(), - "resources" => array() - ) - ) + "type" => "legacy" ) ) ); @@ -86,35 +58,7 @@ public function testMethodCreate(): void "\$createdAt" => "2020-10-15T06:38:00.000+00:00", "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", "enabled" => true, - "type" => "legacy", - "policies" => array( - array( - "\$id" => "5e5ea5c16897e", - "name" => "Hourly backups", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "services" => array(), - "resources" => array(), - "retention" => 7, - "schedule" => "0 * * * *", - "type" => "full", - "enabled" => true - ) - ), - "archives" => array( - array( - "\$id" => "5e5ea5c16897e", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "policyId" => "did8jx6ws45jana098ab7", - "size" => 100000, - "status" => "completed", - "startedAt" => "2020-10-15T06:38:00.000+00:00", - "migrationId" => "did8jx6ws45jana098ab7", - "services" => array(), - "resources" => array() - ) - ) + "type" => "legacy" ); $this->client @@ -132,6 +76,44 @@ public function testMethodCreate(): void $this->assertInstanceOf(\Appwrite\Models\Database::class, $response); } + public function testMethodListSpecifications(): void + { + $data = array( + "specifications" => array( + array( + "slug" => "s-2vcpu-2gb", + "name" => "Standard", + "price" => 20, + "cpu" => 2000, + "memory" => 2048, + "maxConnections" => 200, + "includedStorage" => 25, + "includedBandwidth" => 200, + "enabled" => true + ) + ), + "total" => 9, + "pricing" => array( + "storageOverageRate" => 0.125, + "bandwidthOverageRate" => 0.08, + "replicaRate" => 1, + "crossRegionReplicaRate" => 1, + "pitrRate" => 0.2 + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->tablesDB->listSpecifications(); + + $this->assertInstanceOf(\Appwrite\Models\DedicatedDatabaseSpecificationList::class, $response); + } + public function testMethodListTransactions(): void { $data = array( @@ -284,35 +266,7 @@ public function testMethodGet(): void "\$createdAt" => "2020-10-15T06:38:00.000+00:00", "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", "enabled" => true, - "type" => "legacy", - "policies" => array( - array( - "\$id" => "5e5ea5c16897e", - "name" => "Hourly backups", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "services" => array(), - "resources" => array(), - "retention" => 7, - "schedule" => "0 * * * *", - "type" => "full", - "enabled" => true - ) - ), - "archives" => array( - array( - "\$id" => "5e5ea5c16897e", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "policyId" => "did8jx6ws45jana098ab7", - "size" => 100000, - "status" => "completed", - "startedAt" => "2020-10-15T06:38:00.000+00:00", - "migrationId" => "did8jx6ws45jana098ab7", - "services" => array(), - "resources" => array() - ) - ) + "type" => "legacy" ); $this->client @@ -337,35 +291,7 @@ public function testMethodUpdate(): void "\$createdAt" => "2020-10-15T06:38:00.000+00:00", "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", "enabled" => true, - "type" => "legacy", - "policies" => array( - array( - "\$id" => "5e5ea5c16897e", - "name" => "Hourly backups", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "services" => array(), - "resources" => array(), - "retention" => 7, - "schedule" => "0 * * * *", - "type" => "full", - "enabled" => true - ) - ), - "archives" => array( - array( - "\$id" => "5e5ea5c16897e", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "policyId" => "did8jx6ws45jana098ab7", - "size" => 100000, - "status" => "completed", - "startedAt" => "2020-10-15T06:38:00.000+00:00", - "migrationId" => "did8jx6ws45jana098ab7", - "services" => array(), - "resources" => array() - ) - ) + "type" => "legacy" ); $this->client @@ -400,6 +326,144 @@ public function testMethodDelete(): void $this->assertSame($data, $response); } + public function testMethodCreateFailover(): void + { + $data = array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "projectId" => "5e5ea5c16897e", + "name" => "My Production Database", + "api" => "postgresql", + "engine" => "postgresql", + "version" => "16", + "specification" => "s-2vcpu-2gb", + "backend" => "edge", + "hostname" => "db-myproject-mydb.fra.appwrite.center", + "connectionPort" => 5432, + "connectionUser" => "appwrite_user", + "connectionPassword" => "••••••••", + "connectionString" => "postgresql://user:pass@db-myproject-mydb.fra.appwrite.center:5432/postgres?sslmode=require", + "ssl" => true, + "status" => "ready", + "containerStatus" => "active", + "lifecycleState" => "active", + "idleTimeoutMinutes" => 15, + "cpu" => 2000, + "memory" => 4096, + "storage" => 100, + "storageClass" => "ssd", + "storageMaxGb" => 100, + "nodePool" => "db-pool-4vcpu-8gb", + "replicas" => 2, + "syncMode" => "async", + "crossRegionReplicas" => 1, + "networkMaxConnections" => 500, + "networkIdleTimeoutSeconds" => 900, + "networkIPAllowlist" => array(), + "backupEnabled" => true, + "pitr" => true, + "pitrRetentionDays" => 14, + "storageAutoscaling" => true, + "storageAutoscalingThresholdPercent" => 85, + "storageAutoscalingMaxGb" => 500, + "maintenanceWindowDay" => "sun", + "maintenanceWindowHourUtc" => 3, + "metricsEnabled" => true, + "sqlApiEnabled" => true, + "sqlApiAllowedStatements" => array(), + "sqlApiMaxRows" => 10000, + "sqlApiMaxBytes" => 10485760, + "sqlApiTimeoutSeconds" => 30, + "error" => "[ERROR]" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->tablesDB->createFailover( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\DedicatedDatabase::class, $response); + } + + public function testMethodGetReplicas(): void + { + $data = array( + "replicas" => 2, + "syncMode" => "async", + "members" => array( + array( + "\$id" => "1", + "role" => "replica", + "status" => "active", + "lagSeconds" => 0.5 + ) + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->tablesDB->getReplicas( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\DedicatedDatabaseReplicas::class, $response); + } + + public function testMethodGetStatus(): void + { + $data = array( + "health" => "healthy", + "ready" => true, + "engine" => "postgresql", + "version" => "17", + "uptime" => 86400, + "connections" => array( + "current" => 12, + "max" => 100 + ), + "replicas" => array( + array( + "index" => 0, + "role" => "primary", + "healthy" => true + ) + ), + "volumes" => array( + array( + "path" => "/var/lib/postgresql/data", + "usedPercent" => "45%", + "available" => "55GB", + "mounted" => true + ) + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->tablesDB->getStatus( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\DatabaseStatus::class, $response); + } + public function testMethodListTables(): void { $data = array( diff --git a/tests/Appwrite/Services/TeamsTest.php b/tests/Appwrite/Services/TeamsTest.php index 1e7fb2ff..376e81d1 100644 --- a/tests/Appwrite/Services/TeamsTest.php +++ b/tests/Appwrite/Services/TeamsTest.php @@ -141,6 +141,145 @@ public function testMethodDelete(): void $this->assertSame($data, $response); } + public function testMethodListInstallations(): void + { + $data = array( + "total" => 5, + "installations" => array( + array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "appId" => "5e5ea5c16897e", + "teamId" => "5e5ea5c16897e", + "scopes" => array(), + "authorizationDetails" => array(), + "createdById" => "5e5ea5c16897e", + "createdByName" => "Walter White" + ) + ) + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->teams->listInstallations( + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\AppInstallationList::class, $response); + } + + public function testMethodCreateInstallation(): void + { + $data = array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "appId" => "5e5ea5c16897e", + "teamId" => "5e5ea5c16897e", + "scopes" => array(), + "authorizationDetails" => array(), + "createdById" => "5e5ea5c16897e", + "createdByName" => "Walter White" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->teams->createInstallation( + "", + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\AppInstallation::class, $response); + } + + public function testMethodGetInstallation(): void + { + $data = array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "appId" => "5e5ea5c16897e", + "teamId" => "5e5ea5c16897e", + "scopes" => array(), + "authorizationDetails" => array(), + "createdById" => "5e5ea5c16897e", + "createdByName" => "Walter White" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->teams->getInstallation( + "", + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\AppInstallation::class, $response); + } + + public function testMethodUpdateInstallation(): void + { + $data = array( + "\$id" => "5e5ea5c16897e", + "\$createdAt" => "2020-10-15T06:38:00.000+00:00", + "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", + "appId" => "5e5ea5c16897e", + "teamId" => "5e5ea5c16897e", + "scopes" => array(), + "authorizationDetails" => array(), + "createdById" => "5e5ea5c16897e", + "createdByName" => "Walter White" + ); + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->teams->updateInstallation( + "", + "" + ); + + $this->assertInstanceOf(\Appwrite\Models\AppInstallation::class, $response); + } + + public function testMethodDeleteInstallation(): void + { + $data = ''; + + $this->client + ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) + ->andReturn($data); + $this->client + ->allows()->getConfig(Mockery::any()) + ->andReturn(''); + + $response = $this->teams->deleteInstallation( + "", + "" + ); + + $this->assertSame($data, $response); + } + public function testMethodListMemberships(): void { $data = array(