Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Change Log

## 26.0.0

* Breaking: Removed client, OS, and device fields (`osCode`, `clientName`, `deviceModel`, etc.) from `ActivityEvent`
* Breaking: Inserted `authorizationDetailsTypes` mid-signature in `project.updateOAuth2Server`
* Added: OAuth2 device flow options `verificationUrl`, `userCodeLength`, `userCodeFormat`, and `deviceCodeDuration` to `updateOAuth2Server`
* Added: `updateDenyCorporateEmailPolicy` and `PolicyDenyCorporateEmail` to `project`
* Added: `deny-corporate-email` to `ProjectPolicyId`
* Added: `oauth2` to `ProjectServiceId` and `dedicatedDatabases.execute` to `ProjectKeyScopes`
* Added: `emailCanonical`, `emailIsFree`, `emailIsDisposable`, `emailIsCorporate`, and `emailIsCanonical` to `User`
* Added: `userAccessedAt` to `Membership` and `PolicyMembershipPrivacy`
* Added: `type` to `BackupPolicy`
* Updated: Send an `accept` header on all requests, including chunked uploads

## 25.1.0

* Added: `createSesProvider` and `updateSesProvider` to `messaging`
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/account/create.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ $account = new Account($client);
$result = $account->create(
userId: '<USER_ID>',
email: 'email@example.com',
password: '',
password: 'password',
name: '<NAME>' // optional
);```
4 changes: 2 additions & 2 deletions docs/examples/account/update-password.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ $client = (new Client())
$account = new Account($client);

$result = $account->updatePassword(
password: '',
oldPassword: '<OLD_PASSWORD>' // optional
password: 'password',
oldPassword: 'password' // optional
);```
2 changes: 1 addition & 1 deletion docs/examples/account/update-recovery.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ $account = new Account($client);
$result = $account->updateRecovery(
userId: '<USER_ID>',
secret: '<SECRET>',
password: ''
password: 'password'
);```
2 changes: 1 addition & 1 deletion docs/examples/messaging/create-smtp-provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ $result = $messaging->createSMTPProvider(
host: '<HOST>',
port: 1, // optional
username: '<USERNAME>', // optional
password: '<PASSWORD>', // optional
password: 'password', // optional
encryption: SmtpEncryption::NONE(), // optional
autoTLS: false, // optional
mailer: '<MAILER>', // optional
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/messaging/update-smtp-provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ $result = $messaging->updateSMTPProvider(
host: '<HOST>', // optional
port: 1, // optional
username: '<USERNAME>', // optional
password: '<PASSWORD>', // optional
password: 'password', // optional
encryption: SmtpEncryption::NONE(), // optional
autoTLS: false, // optional
mailer: '<MAILER>', // optional
Expand Down
16 changes: 16 additions & 0 deletions docs/examples/project/update-deny-corporate-email-policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
```php
<?php

use Appwrite\Client;
use Appwrite\Services\Project;

$client = (new Client())
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<YOUR_PROJECT_ID>') // Your project ID
->setKey('<YOUR_API_KEY>'); // Your secret API key

$project = new Project($client);

$result = $project->updateDenyCorporateEmailPolicy(
enabled: false
);```
3 changes: 2 additions & 1 deletion docs/examples/project/update-membership-privacy-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ $result = $project->updateMembershipPrivacyPolicy(
userEmail: false, // optional
userPhone: false, // optional
userName: false, // optional
userMFA: false // optional
userMFA: false, // optional
userAccessedAt: false // optional
);```
7 changes: 6 additions & 1 deletion docs/examples/project/update-o-auth-2-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,14 @@ $result = $project->updateOAuth2Server(
enabled: false,
authorizationUrl: 'https://example.com',
scopes: [], // optional
authorizationDetailsTypes: [], // optional
accessTokenDuration: 60, // optional
refreshTokenDuration: 60, // optional
publicAccessTokenDuration: 60, // optional
publicRefreshTokenDuration: 60, // optional
confidentialPkce: false // optional
confidentialPkce: false, // optional
verificationUrl: 'https://example.com', // optional
userCodeLength: 6, // optional
userCodeFormat: 'numeric', // optional
deviceCodeDuration: 60 // optional
);```
2 changes: 1 addition & 1 deletion docs/examples/project/update-smtp.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ $result = $project->updateSMTP(
host: '', // optional
port: null, // optional
username: '<USERNAME>', // optional
password: '<PASSWORD>', // optional
password: 'password', // optional
senderEmail: 'email@example.com', // optional
senderName: '<SENDER_NAME>', // optional
replyToEmail: 'email@example.com', // optional
Expand Down
3 changes: 2 additions & 1 deletion docs/examples/tablesdb/create.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ $tablesDB = new TablesDB($client);
$result = $tablesDB->create(
databaseId: '<DATABASE_ID>',
name: '<NAME>',
enabled: false // optional
enabled: false, // optional
dedicatedDatabaseId: '<DEDICATED_DATABASE_ID>' // optional
);```
2 changes: 1 addition & 1 deletion docs/examples/users/create.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ $result = $users->create(
userId: '<USER_ID>',
email: 'email@example.com', // optional
phone: '+12065550100', // optional
password: '', // optional
password: 'password', // optional
name: '<NAME>' // optional
);```
2 changes: 1 addition & 1 deletion docs/examples/users/update-password.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ $users = new Users($client);

$result = $users->updatePassword(
userId: '<USER_ID>',
password: ''
password: 'password'
);```
2 changes: 1 addition & 1 deletion docs/examples/webhooks/create.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ $result = $webhooks->create(
enabled: false, // optional
tls: false, // optional
authUsername: '<AUTH_USERNAME>', // optional
authPassword: '<AUTH_PASSWORD>', // optional
authPassword: 'password', // optional
secret: '<SECRET>' // optional
);```
2 changes: 1 addition & 1 deletion docs/examples/webhooks/update.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ $result = $webhooks->update(
enabled: false, // optional
tls: false, // optional
authUsername: '<AUTH_USERNAME>', // optional
authPassword: '<AUTH_PASSWORD>' // optional
authPassword: 'password' // optional
);```
23 changes: 21 additions & 2 deletions docs/project.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,16 @@ PUT https://cloud.appwrite.io/v1/project/oauth2-server
| enabled | boolean | Enable or disable the OAuth2 server. | |
| authorizationUrl | string | URL to your application with consent screen. | |
| scopes | array | List of allowed OAuth2 scopes. Maximum of 100 scopes are allowed, each up to 128 characters long. | [] |
| authorizationDetailsTypes | array | List of accepted `authorization_details` types. Maximum of 100 types are allowed, each up to 128 characters long. | [] |
| accessTokenDuration | integer | Access token duration in seconds for confidential clients (server-side apps that authenticate with a client secret). Leave empty to use default 8 hours. | |
| 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. | |
| 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. | |
| userCodeFormat | string | Character set for device flow user codes: `numeric` (digits only — best for numeric keypads and TV remotes), `alphabetic` (letters only), or `alphanumeric` (letters and digits — highest entropy per character). Defaults to `alphanumeric`. | alphanumeric |
| deviceCodeDuration | integer | Lifetime in seconds of device flow device codes and user codes. Device codes are intentionally short-lived. Leave empty to use default 600. | |


```http request
Expand Down Expand Up @@ -1110,6 +1115,19 @@ PATCH https://cloud.appwrite.io/v1/project/policies/deny-aliased-email
| enabled | boolean | Set whether or not to block aliased emails during signup and email updates. | |


```http request
PATCH https://cloud.appwrite.io/v1/project/policies/deny-corporate-email
```

** Configures if only corporate email addresses (non-free and non-disposable domains) are allowed during new user sign-ups and email updates. **

### Parameters

| Field Name | Type | Description | Default |
| --- | --- | --- | --- |
| enabled | boolean | Set whether or not to restrict sign-ups and email updates to corporate email addresses only. | |


```http request
PATCH https://cloud.appwrite.io/v1/project/policies/deny-disposable-email
```
Expand Down Expand Up @@ -1151,6 +1169,7 @@ PATCH https://cloud.appwrite.io/v1/project/policies/membership-privacy
| userPhone | boolean | Set to true if you want make user phone number visible to all team members, or false to hide it. | |
| userName | boolean | Set to true if you want make user name visible to all team members, or false to hide it. | |
| userMFA | boolean | Set to true if you want make user MFA status visible to all team members, or false to hide it. | |
| userAccessedAt | boolean | Set to true if you want make user last access time visible to all team members, or false to hide it. | |


```http request
Expand Down Expand Up @@ -1286,7 +1305,7 @@ GET https://cloud.appwrite.io/v1/project/policies/{policyId}

| Field Name | Type | Description | Default |
| --- | --- | --- | --- |
| policyId | string | **Required** Policy ID. Can be one of: password-dictionary, password-history, password-strength, password-personal-data, session-alert, session-duration, session-invalidation, session-limit, user-limit, membership-privacy, deny-aliased-email, deny-disposable-email, deny-free-email. | |
| policyId | string | **Required** Policy ID. Can be one of: password-dictionary, password-history, password-strength, password-personal-data, session-alert, session-duration, session-invalidation, session-limit, user-limit, membership-privacy, deny-aliased-email, deny-disposable-email, deny-free-email, deny-corporate-email. | |


```http request
Expand All @@ -1313,7 +1332,7 @@ PATCH https://cloud.appwrite.io/v1/project/services/{serviceId}

| Field Name | Type | Description | Default |
| --- | --- | --- | --- |
| serviceId | string | **Required** Service name. Can be one of: account, avatars, databases, tablesdb, locale, health, project, storage, teams, users, vcs, sites, functions, proxy, graphql, migrations, messaging, advisor | |
| serviceId | string | **Required** Service name. Can be one of: account, avatars, databases, tablesdb, locale, health, project, storage, teams, users, vcs, sites, functions, proxy, graphql, migrations, messaging, advisor, oauth2 | |
| enabled | boolean | Service status. | |


Expand Down
1 change: 1 addition & 0 deletions docs/tablesdb.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ POST https://cloud.appwrite.io/v1/tablesdb
| databaseId | 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. | |
| 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 |
| dedicatedDatabaseId | string | Optional dedicated database (compute) ID to attach this database to. Leave empty to create a database on the shared pool. | |


```http request
Expand Down
16 changes: 7 additions & 9 deletions src/Appwrite/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ class Client
*/
protected array $headers = [
'content-type' => '',
'user-agent' => 'AppwritePHPSDK/25.1.0 ()',
'user-agent' => 'AppwritePHPSDK/26.0.0 ()',
'x-sdk-name'=> 'PHP',
'x-sdk-platform'=> 'server',
'x-sdk-language'=> 'php',
'x-sdk-version'=> '25.1.0',
'x-sdk-version'=> '26.0.0',
];

/**
Expand Down Expand Up @@ -210,7 +210,7 @@ public function setCookie(string $value): Client
/**
* Set ImpersonateUserId
*
* Impersonate a user by ID on an already user-authenticated request. Requires the current request to be authenticated as a user with impersonator capability; X-Appwrite-Key alone is not sufficient. Impersonator users are intentionally granted users.read so they can discover a target before impersonation begins. Internal audit logs still attribute actions to the original impersonator and record the impersonated target only in internal audit payload data.
* Impersonate a user by ID
*
* @param string $value
*
Expand All @@ -227,7 +227,7 @@ public function setImpersonateUserId(string $value): Client
/**
* Set ImpersonateUserEmail
*
* Impersonate a user by email on an already user-authenticated request. Requires the current request to be authenticated as a user with impersonator capability; X-Appwrite-Key alone is not sufficient. Impersonator users are intentionally granted users.read so they can discover a target before impersonation begins. Internal audit logs still attribute actions to the original impersonator and record the impersonated target only in internal audit payload data.
* Impersonate a user by email
*
* @param string $value
*
Expand All @@ -244,7 +244,7 @@ public function setImpersonateUserEmail(string $value): Client
/**
* Set ImpersonateUserPhone
*
* Impersonate a user by phone on an already user-authenticated request. Requires the current request to be authenticated as a user with impersonator capability; X-Appwrite-Key alone is not sufficient. Impersonator users are intentionally granted users.read so they can discover a target before impersonation begins. Internal audit logs still attribute actions to the original impersonator and record the impersonated target only in internal audit payload data.
* Impersonate a user by phone
*
* @param string $value
*
Expand Down Expand Up @@ -427,10 +427,8 @@ public function call(
}
}

switch(substr($contentType, 0, strpos($contentType, ';'))) {
case 'application/json':
$responseBody = json_decode($responseBody, true);
break;
if (str_starts_with($contentType, 'application/json')) {
$responseBody = json_decode($responseBody, true);
}

if (curl_errno($ch)) {
Expand Down
9 changes: 9 additions & 0 deletions src/Appwrite/Enums/ProjectKeyScopes.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class ProjectKeyScopes implements JsonSerializable
private static ProjectKeyScopes $ARCHIVESWRITE;
private static ProjectKeyScopes $RESTORATIONSREAD;
private static ProjectKeyScopes $RESTORATIONSWRITE;
private static ProjectKeyScopes $DEDICATEDDATABASESEXECUTE;
private static ProjectKeyScopes $DOMAINSREAD;
private static ProjectKeyScopes $DOMAINSWRITE;
private static ProjectKeyScopes $EVENTSREAD;
Expand Down Expand Up @@ -750,6 +751,13 @@ public static function RESTORATIONSWRITE(): ProjectKeyScopes
}
return self::$RESTORATIONSWRITE;
}
public static function DEDICATEDDATABASESEXECUTE(): ProjectKeyScopes
{
if (!isset(self::$DEDICATEDDATABASESEXECUTE)) {
self::$DEDICATEDDATABASESEXECUTE = new ProjectKeyScopes('dedicatedDatabases.execute');
}
return self::$DEDICATEDDATABASESEXECUTE;
}
public static function DOMAINSREAD(): ProjectKeyScopes
{
if (!isset(self::$DOMAINSREAD)) {
Expand Down Expand Up @@ -886,6 +894,7 @@ public static function from(string $value): self
'archives.write' => self::ARCHIVESWRITE(),
'restorations.read' => self::RESTORATIONSREAD(),
'restorations.write' => self::RESTORATIONSWRITE(),
'dedicatedDatabases.execute' => self::DEDICATEDDATABASESEXECUTE(),
'domains.read' => self::DOMAINSREAD(),
'domains.write' => self::DOMAINSWRITE(),
'events.read' => self::EVENTSREAD(),
Expand Down
9 changes: 9 additions & 0 deletions src/Appwrite/Enums/ProjectPolicyId.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class ProjectPolicyId implements JsonSerializable
private static ProjectPolicyId $DENYALIASEDEMAIL;
private static ProjectPolicyId $DENYDISPOSABLEEMAIL;
private static ProjectPolicyId $DENYFREEEMAIL;
private static ProjectPolicyId $DENYCORPORATEEMAIL;

private string $value;

Expand Down Expand Up @@ -128,6 +129,13 @@ public static function DENYFREEEMAIL(): ProjectPolicyId
}
return self::$DENYFREEEMAIL;
}
public static function DENYCORPORATEEMAIL(): ProjectPolicyId
{
if (!isset(self::$DENYCORPORATEEMAIL)) {
self::$DENYCORPORATEEMAIL = new ProjectPolicyId('deny-corporate-email');
}
return self::$DENYCORPORATEEMAIL;
}

public static function from(string $value): self
{
Expand All @@ -145,6 +153,7 @@ public static function from(string $value): self
'deny-aliased-email' => self::DENYALIASEDEMAIL(),
'deny-disposable-email' => self::DENYDISPOSABLEEMAIL(),
'deny-free-email' => self::DENYFREEEMAIL(),
'deny-corporate-email' => self::DENYCORPORATEEMAIL(),
default => throw new \InvalidArgumentException('Unknown ProjectPolicyId value: ' . $value),
};
}
Expand Down
9 changes: 9 additions & 0 deletions src/Appwrite/Enums/ProjectServiceId.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class ProjectServiceId implements JsonSerializable
private static ProjectServiceId $MIGRATIONS;
private static ProjectServiceId $MESSAGING;
private static ProjectServiceId $ADVISOR;
private static ProjectServiceId $OAUTH2;

private string $value;

Expand Down Expand Up @@ -168,6 +169,13 @@ public static function ADVISOR(): ProjectServiceId
}
return self::$ADVISOR;
}
public static function OAUTH2(): ProjectServiceId
{
if (!isset(self::$OAUTH2)) {
self::$OAUTH2 = new ProjectServiceId('oauth2');
}
return self::$OAUTH2;
}

public static function from(string $value): self
{
Expand All @@ -190,6 +198,7 @@ public static function from(string $value): self
'migrations' => self::MIGRATIONS(),
'messaging' => self::MESSAGING(),
'advisor' => self::ADVISOR(),
'oauth2' => self::OAUTH2(),
default => throw new \InvalidArgumentException('Unknown ProjectServiceId value: ' . $value),
};
}
Expand Down
Loading