diff --git a/.env b/.env
index 2373b618c2..09abb07be2 100644
--- a/.env
+++ b/.env
@@ -4,6 +4,7 @@ _APP_WORKER_PER_CORE=6
_APP_CONSOLE_WHITELIST_ROOT=disabled
_APP_CONSOLE_WHITELIST_EMAILS=
_APP_CONSOLE_WHITELIST_IPS=
+_APP_CONSOLE_COUNTRIES_DENYLIST=AQ
_APP_CONSOLE_HOSTNAMES=localhost,appwrite.io,*.appwrite.io
_APP_SYSTEM_EMAIL_NAME=Appwrite
_APP_SYSTEM_EMAIL_ADDRESS=team@appwrite.io
@@ -86,7 +87,7 @@ _APP_LOGGING_PROVIDER=
_APP_LOGGING_CONFIG=
_APP_GRAPHQL_MAX_BATCH_SIZE=10
_APP_GRAPHQL_MAX_COMPLEXITY=250
-_APP_GRAPHQL_MAX_DEPTH=3
+_APP_GRAPHQL_MAX_DEPTH=4
_APP_DOCKER_HUB_USERNAME=
_APP_DOCKER_HUB_PASSWORD=
_APP_VCS_GITHUB_APP_NAME=
@@ -97,4 +98,9 @@ _APP_VCS_GITHUB_CLIENT_SECRET=
_APP_VCS_GITHUB_WEBHOOK_SECRET=
_APP_MIGRATIONS_FIREBASE_CLIENT_ID=
_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET=
-_APP_ASSISTANT_OPENAI_API_KEY=
\ No newline at end of file
+_APP_ASSISTANT_OPENAI_API_KEY=
+_APP_MESSAGE_SMS_TEST_DSN=
+_APP_MESSAGE_EMAIL_TEST_DSN=
+_APP_MESSAGE_PUSH_TEST_DSN=
+_APP_WEBHOOK_MAX_FAILED_ATTEMPTS=10
+_APP_PROJECT_REGIONS=default
\ No newline at end of file
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 2fb6840f6e..2cc4c700f7 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -123,6 +123,7 @@ jobs:
Users,
Webhooks,
VCS,
+ Messaging,
]
steps:
@@ -140,7 +141,7 @@ jobs:
run: |
docker load --input /tmp/${{ env.IMAGE }}.tar
docker compose up -d
- sleep 10
+ sleep 25
- name: Run ${{matrix.service}} Tests
run: docker compose exec -T appwrite test /usr/src/code/tests/e2e/Services/${{matrix.service}} --debug
diff --git a/.gitignore b/.gitignore
index 3151de5adb..ac88830b49 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,4 @@ debug/
app/sdks
dev/yasd_init.php
.phpunit.result.cache
+Makefile
diff --git a/.gitmodules b/.gitmodules
index 0c2321bcfa..89728a4028 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,4 +1,4 @@
[submodule "app/console"]
path = app/console
url = https://github.com/appwrite/console
- branch = 3.2.16
+ branch = 4.0.1
diff --git a/.gitpod.yml b/.gitpod.yml
index d740c467cb..478b62fc8d 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -17,7 +17,6 @@ tasks:
ports:
- port: 8080
- onOpen: open-preview
visibility: public
vscode:
diff --git a/CHANGES.md b/CHANGES.md
index 606a8ff1b7..5dd4ba8770 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -496,7 +496,7 @@
## Features
- Added Phone Authentication by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/3357
- Added Twilio Support
- - Added TextMagic Support
+ - Added Textmagic Support
- Added Telesign Support
- Added Endpoint to create Phone Session (`POST:/v1/account/sessions/phone`)
- Added Endpoint to confirm Phone Session (`PUT:/v1/account/sessions/phone`)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 0522e33da5..529f6103d1 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -344,13 +344,13 @@ Things to remember when releasing SDKs:
## Debug
-Appwrite uses [yasd](https://github.com/swoole/yasd) debugger, which can be made available during build of Appwrite. You can connect to the debugger using VS Code's [PHP Debug](https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug) extension.
+Appwrite uses [XDebug](https://github.com/xdebug/xdebug) debugger, which can be made available during build of Appwrite. You can connect to the debugger using VS Code's [PHP Debug](https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug) extension.
If you are in PHP Storm you don't need any plugin. Below are the settings required for remote debugger connection:
-1. Create an init file.
-2. Duplicate **dev/yasd_init.php.stub** file and name it **dev/yasd_init.php**.
-3. Set **DEBUG** build arg in **appwrite** service in **docker-compose.yml** file.
+1. Set **DEBUG** build arg in **appwrite** service in **docker-compose.yml** file.
+2. If needed edit the **dev/xdebug.ini** file to your needs.
+3. Launch your Appwrite instance while your debugger is listening for connections.
### VS Code Launch Configuration
diff --git a/Dockerfile b/Dockerfile
index 5d06d6c828..d7343dd71d 100755
--- a/Dockerfile
+++ b/Dockerfile
@@ -12,7 +12,7 @@ RUN composer install --ignore-platform-reqs --optimize-autoloader \
--no-plugins --no-scripts --prefer-dist \
`if [ "$TESTING" != "true" ]; then echo "--no-dev"; fi`
-FROM --platform=$BUILDPLATFORM node:16.14.2-alpine3.15 as node
+FROM --platform=$BUILDPLATFORM node:20.11.0-alpine3.19 as node
COPY app/console /usr/local/src/console
@@ -29,7 +29,7 @@ ENV VITE_APPWRITE_GROWTH_ENDPOINT=$VITE_APPWRITE_GROWTH_ENDPOINT
RUN npm ci
RUN npm run build
-FROM appwrite/base:0.4.3 as final
+FROM appwrite/base:0.9.0 as final
LABEL maintainer="team@appwrite.io"
@@ -56,6 +56,7 @@ COPY ./public /usr/src/code/public
COPY ./bin /usr/local/bin
COPY ./docs /usr/src/code/docs
COPY ./src /usr/src/code/src
+COPY ./dev /usr/src/code/dev
# Set Volumes
RUN mkdir -p /storage/uploads && \
@@ -71,43 +72,54 @@ RUN mkdir -p /storage/uploads && \
chown -Rf www-data.www-data /storage/functions && chmod -Rf 0755 /storage/functions && \
chown -Rf www-data.www-data /storage/debug && chmod -Rf 0755 /storage/debug
+# Development Executables
+RUN chmod +x /usr/local/bin/dev-generate-translations
+
# Executables
RUN chmod +x /usr/local/bin/doctor && \
- chmod +x /usr/local/bin/maintenance && \
chmod +x /usr/local/bin/install && \
- chmod +x /usr/local/bin/upgrade && \
+ chmod +x /usr/local/bin/maintenance && \
chmod +x /usr/local/bin/migrate && \
chmod +x /usr/local/bin/realtime && \
- chmod +x /usr/local/bin/schedule && \
+ chmod +x /usr/local/bin/schedule-functions && \
+ chmod +x /usr/local/bin/schedule-messages && \
chmod +x /usr/local/bin/sdks && \
chmod +x /usr/local/bin/specs && \
chmod +x /usr/local/bin/ssl && \
chmod +x /usr/local/bin/test && \
+ chmod +x /usr/local/bin/upgrade && \
chmod +x /usr/local/bin/vars && \
chmod +x /usr/local/bin/queue-retry && \
chmod +x /usr/local/bin/queue-count-failed && \
chmod +x /usr/local/bin/queue-count-processing && \
chmod +x /usr/local/bin/queue-count-success && \
chmod +x /usr/local/bin/worker-audits && \
+ chmod +x /usr/local/bin/worker-builds && \
chmod +x /usr/local/bin/worker-certificates && \
chmod +x /usr/local/bin/worker-databases && \
chmod +x /usr/local/bin/worker-deletes && \
chmod +x /usr/local/bin/worker-functions && \
- chmod +x /usr/local/bin/worker-builds && \
+ chmod +x /usr/local/bin/worker-hamster && \
chmod +x /usr/local/bin/worker-mails && \
chmod +x /usr/local/bin/worker-messaging && \
- chmod +x /usr/local/bin/worker-webhooks && \
chmod +x /usr/local/bin/worker-migrations && \
+ chmod +x /usr/local/bin/worker-webhooks && \
chmod +x /usr/local/bin/worker-hamster && \
chmod +x /usr/local/bin/worker-usage && \
chmod +x /usr/local/bin/worker-usage-dump
# Cloud Executabless
-RUN chmod +x /usr/local/bin/hamster && \
- chmod +x /usr/local/bin/volume-sync && \
+RUN chmod +x /usr/local/bin/calc-tier-stats && \
+ chmod +x /usr/local/bin/calc-users-stats && \
+ chmod +x /usr/local/bin/clear-card-cache && \
+ chmod +x /usr/local/bin/delete-orphaned-projects && \
+ chmod +x /usr/local/bin/get-migration-stats && \
+ chmod +x /usr/local/bin/hamster && \
+ chmod +x /usr/local/bin/patch-delete-project-collections && \
chmod +x /usr/local/bin/patch-delete-schedule-updated-at-attribute && \
chmod +x /usr/local/bin/patch-recreate-repositories-documents && \
+ chmod +x /usr/local/bin/volume-sync && \
chmod +x /usr/local/bin/patch-delete-project-collections && \
chmod +x /usr/local/bin/delete-orphaned-projects && \
chmod +x /usr/local/bin/clear-card-cache && \
@@ -120,16 +132,10 @@ RUN chmod +x /usr/local/bin/hamster && \
RUN mkdir -p /etc/letsencrypt/live/ && chmod -Rf 755 /etc/letsencrypt/live/
# Enable Extensions
-RUN if [ "$DEBUG" == "true" ]; then printf "zend_extension=yasd \nyasd.debug_mode=remote \nyasd.init_file=/usr/src/code/dev/yasd_init.php \nyasd.remote_port=9005 \nyasd.log_level=-1" >> /usr/local/etc/php/conf.d/yasd.ini; fi
-
-RUN if [ "$DEBUG" == "true" ]; then echo "opcache.enable=0" >> /usr/local/etc/php/conf.d/appwrite.ini; fi
-RUN echo "opcache.preload_user=www-data" >> /usr/local/etc/php/conf.d/appwrite.ini
-RUN echo "opcache.preload=/usr/src/code/app/preload.php" >> /usr/local/etc/php/conf.d/appwrite.ini
-RUN echo "opcache.enable_cli=1" >> /usr/local/etc/php/conf.d/appwrite.ini
-RUN echo "default_socket_timeout=-1" >> /usr/local/etc/php/conf.d/appwrite.ini
-RUN echo "opcache.jit_buffer_size=100M" >> /usr/local/etc/php/conf.d/appwrite.ini
-RUN echo "opcache.jit=1235" >> /usr/local/etc/php/conf.d/appwrite.ini
+RUN if [ "$DEBUG" == "true" ]; then cp /usr/src/code/dev/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini; fi
+RUN if [ "$DEBUG" = "false" ]; then rm -rf /usr/src/code/dev; fi
+RUN if [ "$DEBUG" = "false" ]; then rm -f /usr/local/lib/php/extensions/no-debug-non-zts-20220829/xdebug.so; fi
EXPOSE 80
-CMD [ "php", "app/http.php", "-dopcache.preload=opcache.preload=/usr/src/code/app/preload.php" ]
\ No newline at end of file
+CMD [ "php", "app/http.php" ]
\ No newline at end of file
diff --git a/app/assets/dbip/dbip-country-lite-2023-01.mmdb b/app/assets/dbip/dbip-country-lite-2023-01.mmdb
deleted file mode 100644
index dd98483fe5..0000000000
Binary files a/app/assets/dbip/dbip-country-lite-2023-01.mmdb and /dev/null differ
diff --git a/app/assets/dbip/dbip-country-lite-2024-02.mmdb b/app/assets/dbip/dbip-country-lite-2024-02.mmdb
new file mode 100644
index 0000000000..e02ba8af04
Binary files /dev/null and b/app/assets/dbip/dbip-country-lite-2024-02.mmdb differ
diff --git a/app/cli.php b/app/cli.php
index d7cc5fe414..1a8c785a30 100644
--- a/app/cli.php
+++ b/app/cli.php
@@ -3,29 +3,29 @@
require_once __DIR__ . '/init.php';
require_once __DIR__ . '/controllers/general.php';
-use Appwrite\Event\Delete;
use Appwrite\Event\Certificate;
+use Appwrite\Event\Delete;
use Appwrite\Event\Func;
use Appwrite\Event\Hamster;
use Appwrite\Platform\Appwrite;
-use Utopia\CLI\CLI;
-use Utopia\Database\Validator\Authorization;
-use Utopia\Platform\Service;
use Utopia\App;
-use Utopia\CLI\Console;
use Utopia\Cache\Adapter\Sharding;
use Utopia\Cache\Cache;
+use Utopia\CLI\CLI;
+use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Database\Database;
use Utopia\Database\Document;
+use Utopia\Database\Validator\Authorization;
use Utopia\Logger\Log;
+use Utopia\Platform\Service;
use Utopia\Pools\Group;
use Utopia\Queue\Connection;
use Utopia\Registry\Registry;
Authorization::disable();
-CLI::setResource('register', fn()=>$register);
+CLI::setResource('register', fn () => $register);
CLI::setResource('cache', function ($pools) {
$list = Config::getParam('pools-cache', []);
@@ -72,12 +72,12 @@ CLI::setResource('dbForConsole', function ($pools, $cache) {
$collections = Config::getParam('collections', [])['console'];
$last = \array_key_last($collections);
- if (!($dbForConsole->exists($dbForConsole->getDefaultDatabase(), $last))) { /** TODO cache ready variable using registry */
+ if (!($dbForConsole->exists($dbForConsole->getDatabase(), $last))) { /** TODO cache ready variable using registry */
throw new Exception('Tables not ready yet.');
}
$ready = true;
- } catch (\Exception $err) {
+ } catch (\Throwable $err) {
Console::warning($err->getMessage());
$pools->get('console')->reclaim();
sleep($sleep);
diff --git a/app/config/auth.php b/app/config/auth.php
index cf1d180aaa..2330fe75cf 100644
--- a/app/config/auth.php
+++ b/app/config/auth.php
@@ -7,21 +7,28 @@ return [
'name' => 'Email/Password',
'key' => 'emailPassword',
'icon' => '/images/users/email.png',
- 'docs' => 'https://appwrite.io/docs/client/account?sdk=web-default#accountCreateEmailSession',
+ 'docs' => 'https://appwrite.io/docs/references/cloud/client-web/account#accountCreateEmailPasswordSession',
'enabled' => true,
],
'magic-url' => [
'name' => 'Magic URL',
'key' => 'usersAuthMagicURL',
'icon' => '/images/users/magic-url.png',
- 'docs' => 'https://appwrite.io/docs/client/account?sdk=web-default#accountCreateMagicURLSession',
+ 'docs' => 'https://appwrite.io/docs/references/cloud/client-web/account#accountCreateMagicURLToken',
+ 'enabled' => true,
+ ],
+ 'email-otp' => [
+ 'name' => 'Email (OTP)',
+ 'key' => 'emailOtp',
+ 'icon' => '/images/users/email.png',
+ 'docs' => 'https://appwrite.io/docs/references/cloud/client-web/account#accountCreateEmailToken',
'enabled' => true,
],
'anonymous' => [
'name' => 'Anonymous',
'key' => 'anonymous',
'icon' => '/images/users/anonymous.png',
- 'docs' => 'https://appwrite.io/docs/client/account?sdk=web-default#accountCreateAnonymousSession',
+ 'docs' => 'https://appwrite.io/docs/references/cloud/client-web/account#accountCreateAnonymousSession',
'enabled' => true,
],
'invites' => [
@@ -42,7 +49,7 @@ return [
'name' => 'Phone',
'key' => 'phone',
'icon' => '/images/users/phone.png',
- 'docs' => 'https://appwrite.io/docs/client/account?sdk=web-default#accountCreatePhoneSession',
+ 'docs' => 'https://appwrite.io/docs/references/cloud/client-web/account#accountCreatePhoneToken',
'enabled' => true,
],
];
diff --git a/app/config/avatars/credit-cards.php b/app/config/avatars/credit-cards.php
index aaef17ee3f..1aa22c4174 100644
--- a/app/config/avatars/credit-cards.php
+++ b/app/config/avatars/credit-cards.php
@@ -17,4 +17,4 @@ return [
'visa' => ['name' => 'Visa', 'path' => __DIR__ . '/credit-cards/visa.png'],
'mir' => ['name' => 'MIR', 'path' => __DIR__ . '/credit-cards/mir.png'],
'maestro' => ['name' => 'Maestro', 'path' => __DIR__ . '/credit-cards/maestro.png']
- ];
+];
diff --git a/app/config/collections.php b/app/config/collections.php
index ffa0ad86c9..cd0d1b2ef5 100644
--- a/app/config/collections.php
+++ b/app/config/collections.php
@@ -5,7 +5,7 @@ use Utopia\Config\Config;
use Utopia\Database\Database;
use Utopia\Database\Helpers\ID;
-$providers = Config::getParam('providers', []);
+$providers = Config::getParam('oAuthProviders', []);
$auth = Config::getParam('auth', []);
/**
@@ -267,6 +267,39 @@ $commonCollections = [
'array' => false,
'filters' => [],
],
+ [
+ '$id' => ID::custom('mfa'),
+ 'type' => Database::VAR_BOOLEAN,
+ 'format' => '',
+ 'size' => 0,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('mfaRecoveryCodes'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 256,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => [],
+ 'array' => true,
+ 'filters' => ['encrypt'],
+ ],
+ [
+ '$id' => ID::custom('authenticators'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 16384,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => ['subQueryAuthenticators'],
+ ],
[
'$id' => ID::custom('sessions'),
'type' => Database::VAR_STRING,
@@ -289,6 +322,17 @@ $commonCollections = [
'array' => false,
'filters' => ['subQueryTokens'],
],
+ [
+ '$id' => ID::custom('challenges'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 16384,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => ['subQueryChallenges'],
+ ],
[
'$id' => ID::custom('memberships'),
'type' => Database::VAR_STRING,
@@ -300,6 +344,17 @@ $commonCollections = [
'array' => false,
'filters' => ['subQueryMemberships'],
],
+ [
+ '$id' => ID::custom('targets'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 16384,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => ['subQueryTargets'],
+ ],
[
'$id' => ID::custom('search'),
'type' => Database::VAR_STRING,
@@ -321,7 +376,7 @@ $commonCollections = [
'default' => null,
'array' => false,
'filters' => ['datetime'],
- ]
+ ],
],
'indexes' => [
[
@@ -491,6 +546,159 @@ $commonCollections = [
],
],
+ 'authenticators' => [
+ '$collection' => ID::custom(Database::METADATA),
+ '$id' => ID::custom('authenticators'),
+ 'name' => 'Authenticators',
+ 'attributes' => [
+ [
+ '$id' => ID::custom('userInternalId'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('userId'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('type'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('verified'),
+ 'type' => Database::VAR_BOOLEAN,
+ 'format' => '',
+ 'size' => 0,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => false,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('data'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 65535,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => [],
+ 'array' => false,
+ 'filters' => ['json', 'encrypt'],
+ ],
+ ],
+ 'indexes' => [
+ [
+ '$id' => ID::custom('_key_userInternalId'),
+ 'type' => Database::INDEX_KEY,
+ 'attributes' => ['userInternalId'],
+ 'lengths' => [Database::LENGTH_KEY],
+ 'orders' => [Database::ORDER_ASC],
+ ]
+ ],
+ ],
+
+ 'challenges' => [
+ '$collection' => ID::custom(Database::METADATA),
+ '$id' => ID::custom('challenges'),
+ 'name' => 'Challenges',
+ 'attributes' => [
+ [
+ '$id' => ID::custom('userInternalId'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('userId'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('type'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('token'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 512, // https://www.tutorialspoint.com/how-long-is-the-sha256-hash-in-mysql (512 for encryption)
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => ['encrypt'],
+ ], [
+ '$id' => ID::custom('code'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 512,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => ['encrypt'],
+ ], [
+ '$id' => ID::custom('expire'),
+ 'type' => Database::VAR_DATETIME,
+ 'format' => '',
+ 'size' => 0,
+ 'signed' => false,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => ['datetime'],
+ ]
+ ],
+ 'indexes' => [
+ [
+ '$id' => ID::custom('_key_user'),
+ 'type' => Database::INDEX_KEY,
+ 'attributes' => ['userInternalId'],
+ 'lengths' => [Database::LENGTH_KEY],
+ 'orders' => [Database::ORDER_ASC],
+ ]
+ ],
+ ],
+
'sessions' => [
'$collection' => ID::custom(Database::METADATA),
'$id' => ID::custom('sessions'),
@@ -749,6 +957,39 @@ $commonCollections = [
'array' => false,
'filters' => [],
],
+ [
+ '$id' => ID::custom('factors'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 256,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => [],
+ 'array' => true,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('expire'),
+ 'type' => Database::VAR_DATETIME,
+ 'format' => '',
+ 'size' => 0,
+ 'signed' => false,
+ 'required' => true,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => ['datetime'],
+ ],
+ [
+ '$id' => ID::custom('mfaUpdatedAt'),
+ 'type' => Database::VAR_DATETIME,
+ 'format' => '',
+ 'size' => 0,
+ 'signed' => false,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => ['datetime'],
+ ],
],
'indexes' => [
[
@@ -1352,7 +1593,7 @@ $commonCollections = [
'stats' => [
'$collection' => ID::custom(Database::METADATA),
'$id' => ID::custom('stats'),
- 'name' => 'stats',
+ 'name' => 'Stats',
'attributes' => [
[
'$id' => ID::custom('metric'),
@@ -1434,7 +1675,699 @@ $commonCollections = [
],
],
],
- ];
+
+ 'providers' => [
+ '$collection' => ID::custom(DATABASE::METADATA),
+ '$id' => ID::custom('providers'),
+ 'name' => 'Providers',
+ 'attributes' => [
+ [
+ '$id' => ID::custom('name'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 128,
+ 'signed' => true,
+ 'required' => true,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('provider'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => true,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('type'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 128,
+ 'signed' => true,
+ 'required' => true,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('enabled'),
+ 'type' => Database::VAR_BOOLEAN,
+ 'signed' => true,
+ 'size' => 0,
+ 'format' => '',
+ 'filters' => [],
+ 'required' => true,
+ 'default' => true,
+ 'array' => false,
+ ],
+ [
+ '$id' => ID::custom('credentials'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 16384,
+ 'signed' => true,
+ 'required' => true,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => ['json', 'encrypt'],
+ ],
+ [
+ '$id' => ID::custom('options'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 16384,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => [],
+ 'array' => false,
+ 'filters' => ['json'],
+ ],
+ [
+ '$id' => ID::custom('search'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 65535,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => '',
+ 'array' => false,
+ 'filters' => ['providerSearch'],
+ ],
+ ],
+ 'indexes' => [
+ [
+ '$id' => ID::custom('_key_provider'),
+ 'type' => Database::INDEX_KEY,
+ 'attributes' => ['provider'],
+ 'lengths' => [],
+ 'orders' => [Database::ORDER_ASC],
+ ],
+ [
+ '$id' => ID::custom('_key_name'),
+ 'type' => Database::INDEX_FULLTEXT,
+ 'attributes' => ['name'],
+ 'lengths' => [],
+ 'orders' => [Database::ORDER_ASC],
+ ],
+ [
+ '$id' => ID::custom('_key_type'),
+ 'type' => Database::INDEX_KEY,
+ 'attributes' => ['type'],
+ 'lengths' => [],
+ 'orders' => [Database::ORDER_ASC],
+ ],
+ [
+ '$id' => ID::custom('_key_enabled_type'),
+ 'type' => Database::INDEX_KEY,
+ 'attributes' => ['enabled', 'type'],
+ 'lengths' => [],
+ 'orders' => [Database::ORDER_ASC],
+ ],
+ [
+ '$id' => ID::custom('_key_search'),
+ 'type' => Database::INDEX_FULLTEXT,
+ 'attributes' => ['search'],
+ 'lengths' => [],
+ 'orders' => [],
+ ]
+ ],
+ ],
+
+ 'messages' => [
+ '$collection' => ID::custom(DATABASE::METADATA),
+ '$id' => ID::custom('messages'),
+ 'name' => 'Messages',
+ 'attributes' => [
+ [
+ '$id' => ID::custom('providerType'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => true,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('status'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => true,
+ 'default' => 'processing',
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('data'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 65535,
+ 'signed' => true,
+ 'required' => true,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => ['json'],
+ ],
+ [
+ '$id' => ID::custom('topics'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 21845,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => [],
+ 'array' => true,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('users'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 21845,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => [],
+ 'array' => true,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('targets'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 21845,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => [],
+ 'array' => true,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('scheduledAt'),
+ 'type' => Database::VAR_DATETIME,
+ 'format' => '',
+ 'size' => 0,
+ 'signed' => false,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => ['datetime'],
+ ],
+ [
+ '$id' => ID::custom('scheduleInternalId'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('scheduleId'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('deliveredAt'),
+ 'type' => Database::VAR_DATETIME,
+ 'format' => '',
+ 'size' => 0,
+ 'signed' => false,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => ['datetime'],
+ ],
+ [
+ '$id' => ID::custom('deliveryErrors'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 65535,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => true,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('deliveredTotal'),
+ 'type' => Database::VAR_INTEGER,
+ 'format' => '',
+ 'size' => 0,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => 0,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('search'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 16384,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => '',
+ 'array' => false,
+ 'filters' => ['messageSearch'],
+ ],
+ ],
+ 'indexes' => [
+ [
+ '$id' => ID::custom('_key_search'),
+ 'type' => Database::INDEX_FULLTEXT,
+ 'attributes' => ['search'],
+ 'lengths' => [],
+ 'orders' => [],
+ ],
+ ],
+ ],
+
+ 'topics' => [
+ '$collection' => ID::custom(DATABASE::METADATA),
+ '$id' => ID::custom('topics'),
+ 'name' => 'Topics',
+ 'attributes' => [
+ [
+ '$id' => ID::custom('name'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 128,
+ 'signed' => true,
+ 'required' => true,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('subscribe'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 128,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => true,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('emailTotal'),
+ 'type' => Database::VAR_INTEGER,
+ 'format' => '',
+ 'size' => 0,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => 0,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('smsTotal'),
+ 'type' => Database::VAR_INTEGER,
+ 'format' => '',
+ 'size' => 0,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => 0,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('pushTotal'),
+ 'type' => Database::VAR_INTEGER,
+ 'format' => '',
+ 'size' => 0,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => 0,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('targets'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 16384,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => ['subQueryTopicTargets'],
+ ],
+ [
+ '$id' => ID::custom('search'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 16384,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => '',
+ 'array' => false,
+ 'filters' => ['topicSearch'],
+ ],
+ ],
+ 'indexes' => [
+ [
+ '$id' => ID::custom('_key_name'),
+ 'type' => Database::INDEX_FULLTEXT,
+ 'attributes' => ['name'],
+ 'lengths' => [],
+ 'orders' => [],
+ ],
+ [
+ '$id' => ID::custom('_key_search'),
+ 'type' => Database::INDEX_FULLTEXT,
+ 'attributes' => ['search'],
+ 'lengths' => [],
+ 'orders' => [Database::ORDER_ASC],
+ ]
+ ],
+ ],
+
+ 'subscribers' => [
+ '$collection' => ID::custom(DATABASE::METADATA),
+ '$id' => ID::custom('subscribers'),
+ 'name' => 'Subscribers',
+ 'attributes' => [
+ [
+ '$id' => ID::custom('targetId'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => true,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('targetInternalId'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => true,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('userId'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => true,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('userInternalId'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => true,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('topicId'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => true,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('topicInternalId'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => true,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('providerType'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 128,
+ 'signed' => true,
+ 'required' => true,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('search'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 16384,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ ],
+ 'indexes' => [
+ [
+ '$id' => ID::custom('_key_targetId'),
+ 'type' => Database::INDEX_KEY,
+ 'attributes' => ['targetId'],
+ 'lengths' => [],
+ 'orders' => [],
+ ],
+ [
+ '$id' => ID::custom('_key_targetInternalId'),
+ 'type' => Database::INDEX_KEY,
+ 'attributes' => ['targetInternalId'],
+ 'lengths' => [],
+ 'orders' => [],
+ ],
+ [
+ '$id' => ID::custom('_key_userId'),
+ 'type' => Database::INDEX_KEY,
+ 'attributes' => ['userId'],
+ 'lengths' => [],
+ 'orders' => [],
+ ],
+ [
+ '$id' => ID::custom('_key_userInternalId'),
+ 'type' => Database::INDEX_KEY,
+ 'attributes' => ['userInternalId'],
+ 'lengths' => [],
+ 'orders' => [],
+ ],
+ [
+ '$id' => ID::custom('_key_topicId'),
+ 'type' => Database::INDEX_KEY,
+ 'attributes' => ['topicId'],
+ 'lengths' => [],
+ 'orders' => [],
+ ],
+ [
+ '$id' => ID::custom('_key_topicInternalId'),
+ 'type' => Database::INDEX_KEY,
+ 'attributes' => ['topicInternalId'],
+ 'lengths' => [],
+ 'orders' => [],
+ ],
+ [
+ '$id' => ID::custom('_unique_target_topic'),
+ 'type' => Database::INDEX_UNIQUE,
+ 'attributes' => ['targetInternalId', 'topicInternalId'],
+ 'lengths' => [],
+ 'orders' => [],
+ ],
+ [
+ '$id' => ID::custom('_fulltext_search'),
+ 'type' => Database::INDEX_FULLTEXT,
+ 'attributes' => ['search'],
+ 'lengths' => [],
+ 'orders' => [],
+ ],
+ ],
+ ],
+
+ 'targets' => [
+ '$collection' => ID::custom(DATABASE::METADATA),
+ '$id' => ID::custom('targets'),
+ 'name' => 'Targets',
+ 'attributes' => [
+ [
+ '$id' => ID::custom('userId'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => true,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('userInternalId'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => true,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('sessionId'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('sessionInternalId'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('providerType'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => true,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('providerId'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('providerInternalId'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('identifier'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => true,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('name'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => Database::LENGTH_KEY,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => null,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('expired'),
+ 'type' => Database::VAR_BOOLEAN,
+ 'format' => '',
+ 'size' => 0,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => false,
+ 'array' => false,
+ 'filters' => [],
+ ],
+ ],
+ 'indexes' => [
+ [
+ '$id' => ID::custom('_key_userId'),
+ 'type' => Database::INDEX_KEY,
+ 'attributes' => ['userId'],
+ 'lengths' => [],
+ 'orders' => [Database::ORDER_ASC],
+ ],
+ [
+ '$id' => ID::custom('_key_userInternalId'),
+ 'type' => Database::INDEX_KEY,
+ 'attributes' => ['userInternalId'],
+ 'lengths' => [],
+ 'orders' => [Database::ORDER_ASC],
+ ],
+ [
+ '$id' => ID::custom('_key_providerId'),
+ 'type' => Database::INDEX_KEY,
+ 'attributes' => ['providerId'],
+ 'lengths' => [],
+ 'orders' => [],
+ ],
+ [
+ '$id' => ID::custom('_key_providerInternalId'),
+ 'type' => Database::INDEX_KEY,
+ 'attributes' => ['providerInternalId'],
+ 'lengths' => [],
+ 'orders' => [],
+ ],
+ [
+ '$id' => ID::custom('_key_identifier'),
+ 'type' => Database::INDEX_UNIQUE,
+ 'attributes' => ['identifier'],
+ 'lengths' => [],
+ 'orders' => [],
+ ],
+ ],
+ ],
+];
$projectCollections = array_merge([
'databases' => [
@@ -3434,7 +4367,7 @@ $consoleCollections = array_merge([
'filters' => ['json'],
],
[
- '$id' => ID::custom('authProviders'),
+ '$id' => ID::custom('oAuthProviders'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16384,
@@ -3936,6 +4869,39 @@ $consoleCollections = array_merge([
'array' => false,
'filters' => [],
],
+ [
+ '$id' => ID::custom('enabled'),
+ 'type' => Database::VAR_BOOLEAN,
+ 'signed' => true,
+ 'size' => 0,
+ 'format' => '',
+ 'filters' => [],
+ 'required' => false,
+ 'default' => true,
+ 'array' => false,
+ ],
+ [
+ '$id' => ID::custom('logs'),
+ 'type' => Database::VAR_STRING,
+ 'format' => '',
+ 'size' => 1000000,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => '',
+ 'array' => false,
+ 'filters' => [],
+ ],
+ [
+ '$id' => ID::custom('attempts'),
+ 'type' => Database::VAR_INTEGER,
+ 'format' => '',
+ 'size' => 0,
+ 'signed' => true,
+ 'required' => false,
+ 'default' => 0,
+ 'array' => false,
+ 'filters' => [],
+ ],
],
'indexes' => [
[
diff --git a/app/config/errors.php b/app/config/errors.php
index 4241346cef..c999ddba58 100644
--- a/app/config/errors.php
+++ b/app/config/errors.php
@@ -5,6 +5,7 @@
*/
use Appwrite\Extend\Exception;
+use Appwrite\Messaging\Status as MessageStatus;
return [
/** General Errors */
@@ -108,6 +109,21 @@ return [
'description' => 'This method was not fully implemented yet. If you believe this is a mistake, please upgrade your Appwrite server version.',
'code' => 405,
],
+ Exception::GENERAL_INVALID_EMAIL => [
+ 'name' => Exception::GENERAL_INVALID_EMAIL,
+ 'description' => 'Value must be a valid email address.',
+ 'code' => 400,
+ ],
+ Exception::GENERAL_INVALID_PHONE => [
+ 'name' => Exception::GENERAL_INVALID_PHONE,
+ 'description' => 'Value must be a valid phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.',
+ 'code' => 400,
+ ],
+ Exception::GENERAL_REGION_ACCESS_DENIED => [
+ 'name' => Exception::GENERAL_REGION_ACCESS_DENIED,
+ 'description' => 'Your location is not supported due to legal requirements.',
+ 'code' => 451,
+ ],
Exception::GENERAL_BAD_REQUEST => [
'name' => Exception::GENERAL_BAD_REQUEST,
'description' => 'There was an error processing your request. Please check the inputs and try again.',
@@ -172,7 +188,7 @@ return [
],
Exception::USER_SESSION_ALREADY_EXISTS => [
'name' => Exception::USER_SESSION_ALREADY_EXISTS,
- 'description' => 'Creation of anonymous users is prohibited when a session is active.',
+ 'description' => 'Creation of a session is prohibited when a session is active.',
'code' => 401,
],
Exception::USER_NOT_FOUND => [
@@ -226,6 +242,26 @@ return [
'description' => 'A user with the same phone number already exists in the current project.',
'code' => 409,
],
+ Exception::USER_RECOVERY_CODES_ALREADY_EXISTS => [
+ 'name' => Exception::USER_RECOVERY_CODES_ALREADY_EXISTS,
+ 'description' => 'The current user already generated recovery codes and they can only be read once for security reasons.',
+ 'code' => 409,
+ ],
+ Exception::USER_AUTHENTICATOR_NOT_FOUND => [
+ 'name' => Exception::USER_AUTHENTICATOR_NOT_FOUND,
+ 'description' => 'Authenticator could not be found on the current user.',
+ 'code' => 404,
+ ],
+ Exception::USER_RECOVERY_CODES_NOT_FOUND => [
+ 'name' => Exception::USER_RECOVERY_CODES_NOT_FOUND,
+ 'description' => 'Recovery codes could not be found on the current user.',
+ 'code' => 404,
+ ],
+ Exception::USER_AUTHENTICATOR_ALREADY_VERIFIED => [
+ 'name' => Exception::USER_AUTHENTICATOR_ALREADY_VERIFIED,
+ 'description' => 'This authenticator is already verified on the current user.',
+ 'code' => 409,
+ ],
Exception::USER_PHONE_NOT_FOUND => [
'name' => Exception::USER_PHONE_NOT_FOUND,
'description' => 'The current user does not have a phone number associated with their account.',
@@ -236,6 +272,16 @@ return [
'description' => 'Missing ID from OAuth2 provider.',
'code' => 400,
],
+ Exception::USER_MORE_FACTORS_REQUIRED => [
+ 'name' => Exception::USER_MORE_FACTORS_REQUIRED,
+ 'description' => 'More factors are required to complete the sign in process.',
+ 'code' => 401,
+ ],
+ Exception::USER_CHALLENGE_REQUIRED => [
+ 'name' => Exception::USER_CHALLENGE_REQUIRED,
+ 'description' => 'A recently succeessful challenge is required to complete this action. A challenge is considered recent for 5 minutes.',
+ 'code' => 401,
+ ],
Exception::USER_OAUTH2_BAD_REQUEST => [
'name' => Exception::USER_OAUTH2_BAD_REQUEST,
'description' => 'OAuth2 provider rejected the bad request.',
@@ -266,6 +312,21 @@ return [
'description' => 'User deletion is not allowed for users with active memberships. Please delete all confirmed memberships before deleting the account.',
'code' => 400
],
+ Exception::USER_TARGET_NOT_FOUND => [
+ 'name' => Exception::USER_TARGET_NOT_FOUND,
+ 'description' => 'The target could not be found.',
+ 'code' => 404,
+ ],
+ Exception::USER_TARGET_ALREADY_EXISTS => [
+ 'name' => Exception::USER_TARGET_ALREADY_EXISTS,
+ 'description' => 'A target with the same ID already exists.',
+ 'code' => 409,
+ ],
+ Exception::USER_API_KEY_AND_SESSION_SET => [
+ 'name' => Exception::USER_API_KEY_AND_SESSION_SET,
+ 'description' => 'API key and session used in the same request. Use either `setSession` or `setKey`. Learn about which authentication method to use in the SSR docs: https://appwrite.io/docs/products/auth/server-side-rendering',
+ 'code' => 403,
+ ],
/** Teams */
Exception::TEAM_NOT_FOUND => [
@@ -404,6 +465,11 @@ return [
'description' => 'The value for x-appwrite-id header is invalid. Please check the value of the x-appwrite-id header is a valid id and not unique().',
'code' => 400,
],
+ Exception::STORAGE_FILE_NOT_PUBLIC => [
+ 'name' => Exception::STORAGE_FILE_NOT_PUBLIC,
+ 'description' => 'The requested file is not publicly readable.',
+ 'code' => 403,
+ ],
/** VCS */
Exception::INSTALLATION_NOT_FOUND => [
@@ -631,11 +697,6 @@ return [
'description' => 'Project with the requested ID already exists. Try again with a different ID or use ID.unique() to generate a unique ID.',
'code' => 409,
],
- Exception::PROJECT_UNKNOWN => [
- 'name' => Exception::PROJECT_UNKNOWN,
- 'description' => 'The project ID is either missing or not valid. Please check the value of the X-Appwrite-Project header to ensure the correct project ID is being used.',
- 'code' => 400,
- ],
Exception::PROJECT_PROVIDER_DISABLED => [
'name' => Exception::PROJECT_PROVIDER_DISABLED,
'description' => 'The chosen OAuth provider is disabled. You can enable the OAuth provider using the Appwrite console.',
@@ -707,6 +768,11 @@ return [
'description' => 'You can\'t delete default template. If you are trying to reset your template changes, you can ignore this error as it\'s already been reset.',
'code' => 401,
],
+ Exception::PROJECT_REGION_UNSUPPORTED => [
+ 'name' => Exception::PROJECT_REGION_UNSUPPORTED,
+ 'description' => 'The requested region is either inactive or unsupported. Please check the value of the _APP_REGIONS environment variable.',
+ 'code' => 400,
+ ],
Exception::WEBHOOK_NOT_FOUND => [
'name' => Exception::WEBHOOK_NOT_FOUND,
'description' => 'Webhook with the requested ID could not be found.',
@@ -801,4 +867,114 @@ return [
'description' => 'Failed to establish a connection to the specified domain. Please verify the domain name and ensure that the server is running and accessible.',
'code' => 404,
],
+
+ /** Providers */
+ Exception::PROVIDER_NOT_FOUND => [
+ 'name' => Exception::PROVIDER_NOT_FOUND,
+ 'description' => 'Provider with the requested ID could not be found.',
+ 'code' => 404,
+ ],
+ Exception::PROVIDER_ALREADY_EXISTS => [
+ 'name' => Exception::PROVIDER_ALREADY_EXISTS,
+ 'description' => 'Provider with the requested ID already exists.',
+ 'code' => 409,
+ ],
+ Exception::PROVIDER_INCORRECT_TYPE => [
+ 'name' => Exception::PROVIDER_INCORRECT_TYPE,
+ 'description' => 'Provider with the requested ID is of the incorrect type.',
+ 'code' => 400,
+ ],
+ Exception::PROVIDER_MISSING_CREDENTIALS => [
+ 'name' => Exception::PROVIDER_MISSING_CREDENTIALS,
+ 'description' => 'Provider with the requested ID is missing credentials.',
+ 'code' => 400,
+ ],
+
+ /** Topics */
+ Exception::TOPIC_NOT_FOUND => [
+ 'name' => Exception::TOPIC_NOT_FOUND,
+ 'description' => 'Topic with the request ID could not be found.',
+ 'code' => 404,
+ ],
+ Exception::TOPIC_ALREADY_EXISTS => [
+ 'name' => Exception::TOPIC_ALREADY_EXISTS,
+ 'description' => 'Topic with the request ID already exists.',
+ 'code' => 409,
+ ],
+
+ /** Subscribers */
+ Exception::SUBSCRIBER_NOT_FOUND => [
+ 'name' => Exception::SUBSCRIBER_NOT_FOUND,
+ 'description' => 'Subscriber with the request ID could not be found.',
+ 'code' => 404,
+ ],
+ Exception::SUBSCRIBER_ALREADY_EXISTS => [
+ 'name' => Exception::SUBSCRIBER_ALREADY_EXISTS,
+ 'description' => 'Subscriber with the request ID already exists.',
+ 'code' => 409,
+ ],
+
+ /** Messages */
+ Exception::MESSAGE_NOT_FOUND => [
+ 'name' => Exception::MESSAGE_NOT_FOUND,
+ 'description' => 'Message with the requested ID could not be found.',
+ 'code' => 404,
+ ],
+ Exception::MESSAGE_MISSING_TARGET => [
+ 'name' => Exception::MESSAGE_MISSING_TARGET,
+ 'description' => 'Message with the requested ID has no recipients (topics or users or targets).',
+ 'code' => 400,
+ ],
+ Exception::MESSAGE_ALREADY_SENT => [
+ 'name' => Exception::MESSAGE_ALREADY_SENT,
+ 'description' => 'Message with the requested ID has already been sent.',
+ 'code' => 400,
+ ],
+ Exception::MESSAGE_ALREADY_PROCESSING => [
+ 'name' => Exception::MESSAGE_ALREADY_PROCESSING,
+ 'description' => 'Message with the requested ID is already being processed.',
+ 'code' => 400,
+ ],
+ Exception::MESSAGE_ALREADY_FAILED => [
+ 'name' => Exception::MESSAGE_ALREADY_FAILED,
+ 'description' => 'Message with the requested ID has already failed.',
+ 'code' => 400,
+ ],
+ Exception::MESSAGE_ALREADY_SCHEDULED => [
+ 'name' => Exception::MESSAGE_ALREADY_SCHEDULED,
+ 'description' => 'Message with the requested ID has already been scheduled for delivery.',
+ 'code' => 400,
+ ],
+ Exception::MESSAGE_TARGET_NOT_EMAIL => [
+ 'name' => Exception::MESSAGE_TARGET_NOT_EMAIL,
+ 'description' => 'Message with the target ID is not an email target.',
+ 'code' => 400,
+ ],
+ Exception::MESSAGE_TARGET_NOT_SMS => [
+ 'name' => Exception::MESSAGE_TARGET_NOT_SMS,
+ 'description' => 'Message with the target ID is not an SMS target.',
+ 'code' => 400,
+ ],
+ Exception::MESSAGE_TARGET_NOT_PUSH => [
+ 'name' => Exception::MESSAGE_TARGET_NOT_PUSH,
+ 'description' => 'Message with the target ID is not a push target.',
+ 'code' => 400,
+ ],
+ Exception::MESSAGE_MISSING_SCHEDULE => [
+ 'name' => Exception::MESSAGE_MISSING_SCHEDULE,
+ 'description' => 'Message can not have status ' . MessageStatus::SCHEDULED . ' without a schedule.',
+ 'code' => 400,
+ ],
+ Exception::SCHEDULE_NOT_FOUND => [
+ 'name' => Exception::SCHEDULE_NOT_FOUND,
+ 'description' => 'Schedule with the requested ID could not be found.',
+ 'code' => 404,
+ ],
+
+ /** Targets */
+ Exception::TARGET_PROVIDER_INVALID_TYPE => [
+ 'name' => Exception::TARGET_PROVIDER_INVALID_TYPE,
+ 'description' => 'Target has an invalid provider type.',
+ 'code' => 400,
+ ],
];
diff --git a/app/config/events.php b/app/config/events.php
index c0b6cc3b41..5378502faf 100644
--- a/app/config/events.php
+++ b/app/config/events.php
@@ -44,6 +44,28 @@ return [
'$description' => 'This event triggers when a verification token for a user is validated.'
],
],
+ 'targets' => [
+ '$model' => Response::MODEL_TARGET,
+ '$resource' => true,
+ '$description' => 'This event triggers on any user\'s target event.',
+ 'create' => [
+ '$description' => 'This event triggers when a user\'s target is created.',
+ ],
+ 'update' => [
+ '$description' => 'This event triggers when a user\'s target is updated.',
+ ],
+ 'delete' => [
+ '$description' => 'This event triggers when a user\'s target is deleted.',
+ ],
+ ],
+ 'tokens' => [
+ '$model' => Response::MODEL_TOKEN,
+ '$resource' => true,
+ '$description' => 'This event triggers on any user\'s token event.',
+ 'create' => [
+ '$description' => 'This event triggers when a user\'s token is created.',
+ ],
+ ],
'create' => [
'$description' => 'This event triggers when a user is created.'
],
@@ -237,6 +259,56 @@ return [
'$description' => 'This event triggers when a function is updated.',
]
],
+ 'messages' => [
+ '$model' => Response::MODEL_MESSAGE,
+ '$resource' => true,
+ '$description' => 'This event triggers on any messaging event.',
+ 'create' => [
+ '$description' => 'This event triggers when a message is created.',
+ ],
+ 'update' => [
+ '$description' => 'This event triggers when a message is updated.',
+ ],
+ ],
+ 'topics' => [
+ '$model' => Response::MODEL_TOPIC,
+ '$resource' => true,
+ '$description' => 'This event triggers on any topic event.',
+ 'create' => [
+ '$description' => 'This event triggers when a topic is created.',
+ ],
+ 'update' => [
+ '$description' => 'This event triggers when a topic is updated.',
+ ],
+ 'delete' => [
+ '$description' => 'This event triggers when a topic is deleted.'
+ ],
+ 'subscribers' => [
+ '$model' => Response::MODEL_SUBSCRIBER,
+ '$resource' => true,
+ '$description' => 'This event triggers on any subscriber event.',
+ 'create' => [
+ '$description' => 'This event triggers when a subscriber is created.',
+ ],
+ 'delete' => [
+ '$description' => 'This event triggers when a subscriber is deleted.'
+ ],
+ ],
+ ],
+ 'providers' => [
+ '$model' => Response::MODEL_PROVIDER,
+ '$resource' => true,
+ '$description' => 'This event triggers on any provider event.',
+ 'create' => [
+ '$description' => 'This event triggers when a provider is created.',
+ ],
+ 'update' => [
+ '$description' => 'This event triggers when a provider is updated.',
+ ],
+ 'delete' => [
+ '$description' => 'This event triggers when a provider is deleted.'
+ ],
+ ],
'rules' => [
'$model' => Response::MODEL_PROXY_RULE,
'$resource' => true,
diff --git a/app/config/locale/languages.php b/app/config/locale/languages.php
index 6272bd02a6..eeea92e636 100644
--- a/app/config/locale/languages.php
+++ b/app/config/locale/languages.php
@@ -654,10 +654,15 @@ return [
"nativeName" => "پښتو"
],
[
- "code" => "pt",
+ "code" => "pt-pt",
"name" => "Portuguese",
"nativeName" => "Português"
],
+ [
+ "code" => "pt-br",
+ "name" => "Portuguese (Brazilian)",
+ "nativeName" => "Português"
+ ],
[
"code" => "qu",
"name" => "Quechua",
@@ -919,9 +924,14 @@ return [
"nativeName" => "Cuengh / Tôô / 壮语"
],
[
- "code" => "zh",
- "name" => "Chinese",
- "nativeName" => "中文"
+ "code" => "zh-cn",
+ "name" => "Chinese (Simplified)",
+ "nativeName" => "中国人"
+ ],
+ [
+ "code" => "zh-tw",
+ "name" => "Chinese (Traditional)",
+ "nativeName" => "中國人"
],
[
"code" => "zu",
diff --git a/app/config/locale/templates.php b/app/config/locale/templates.php
index f2672c04a0..ac5a2acf1d 100644
--- a/app/config/locale/templates.php
+++ b/app/config/locale/templates.php
@@ -6,10 +6,12 @@ return [
'magicSession',
'recovery',
'invitation',
+ 'mfaChallenge'
],
'sms' => [
'verification',
'login',
- 'invitation'
+ 'invitation',
+ 'mfaChallenge'
]
];
diff --git a/app/config/locale/templates/email-base-styled.tpl b/app/config/locale/templates/email-base-styled.tpl
new file mode 100644
index 0000000000..4d6972389e
--- /dev/null
+++ b/app/config/locale/templates/email-base-styled.tpl
@@ -0,0 +1,207 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+ © {{year}} Appwrite | 251 Little Falls Drive, Wilmington 19808,
+ Delaware, United States
+
+
+
+
\ No newline at end of file
diff --git a/app/config/locale/templates/email-base.tpl b/app/config/locale/templates/email-base.tpl
index f41a9530e1..13056fd5ae 100644
--- a/app/config/locale/templates/email-base.tpl
+++ b/app/config/locale/templates/email-base.tpl
@@ -1,5 +1,74 @@
+
+
+
+
+
+
@@ -8,13 +77,14 @@
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Poppins:wght@500;600&display=swap"
rel="stylesheet">