1
0
Fork 0
mirror of synced 2024-05-21 05:02:37 +12:00

Merge branch 'feat-console-rewrite' of https://github.com/appwrite/appwrite into feat-console-rewrite

This commit is contained in:
Torsten Dittmann 2022-11-09 15:06:32 +01:00
commit ab5ddc263b
69 changed files with 761 additions and 557 deletions

View file

@ -28,8 +28,8 @@ jobs:
export COMPOSE_DOCKER_CLI_BUILD=1
export BUILDKIT_PROGRESS=plain
docker pull composer:2.0
docker compose -f docker-compose.yml -f docker-compose.ci.yml build appwrite
docker compose -f docker-compose.yml -f docker-compose.ci.yml up -d
docker compose build appwrite
docker compose up -d
sleep 30
- name: Doctor
run: docker compose exec -T appwrite doctor

2
.gitmodules vendored
View file

@ -1,4 +1,4 @@
[submodule "app/console"]
path = app/console
url = https://github.com/appwrite/console.git
branch = feat-layout-endpoints
branch = main

View file

@ -1,3 +1,13 @@
# Version 1.1.0
## Bugs
- Fix license detection for Flutter and Dart SDKs [#4435](https://github.com/appwrite/appwrite/pull/4435)
# Version 1.0.3
## Bugs
- Fix document audit deletion [#4429](https://github.com/appwrite/appwrite/pull/4429)
- Fix attribute and index deletion when deleting a collection [#4429](https://github.com/appwrite/appwrite/pull/4429)
# Version 1.0.2
## Bugs
- Fixed nullable values in functions variables [#3885](https://github.com/appwrite/appwrite/pull/3885)

View file

@ -12,7 +12,7 @@ Help us keep Appwrite open and inclusive. Please read and follow our [Code of Co
## Submit a Pull Request 🚀
Branch naming convention is as following
Branch naming convention is as follows
`TYPE-ISSUE_ID-DESCRIPTION`
@ -30,7 +30,7 @@ When `TYPE` can be:
- **fix** - a bug fix
- **refactor** - code change that neither fixes a bug nor adds a feature
**All PRs must include a commit message with the changes description!**
**All PRs must include a commit message with the description of the changes made!**
For the initial start, fork the project and use git clone command to download the repository to your computer. A standard procedure for working on an issue would be to:
@ -48,7 +48,7 @@ $ git checkout -b [name_of_your_new_branch]
3. Work - commit - repeat ( be sure to be in your branch )
4. Before you push your changes, make sure your code follows the `PSR12` coding standards , which is the standard Appwrite follows currently. You can easily do this by running the formatter.
4. Before you push your changes, make sure your code follows the `PSR12` coding standards, which is the standard Appwrite follows currently. You can easily do this by running the formatter.
```bash
composer format <your file path>
@ -60,7 +60,7 @@ Now, go a step further by running the linter by the following command to manuall
composer lint <your file path>
```
This will give you a list of errors for you to rectify , if there is an instance you need more information on the errors being displayed you can pass in additional command line arguments. More list of available arguments can be found [here](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage). A very useful command line argument is `--report=diff`. This will give you the expected changes by the linter for easy fixing of formatting issues.
This will give you a list of errors for you to rectify, if there is an instance you need more information on the errors being displayed you can pass in additional command line arguments. More list of available arguments can be found [here](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage). A very useful command line argument is `--report=diff`. This will give you the expected changes by the linter for easy fixing of formatting issues.
```bash
composer lint --report=diff <your file path>
@ -93,6 +93,7 @@ git clone git@github.com:[YOUR_FORK_HERE]/appwrite.git
cd appwrite
docker compose build
docker compose up -d
```
@ -116,7 +117,7 @@ After finishing the installation process, you can start writing and editing code
#### Advanced Topics
We love to create issues that are good for beginners and label them as `good first issue` or `hacktoberfest`, but some more advanced topics might require extra knowledge. Below is a list of links you can use to learn more about some of the more advance topics that will help you master the Appwrite codebase.
We love to create issues that are good for beginners and label them as `good first issue` or `hacktoberfest`, but some more advanced topics might require extra knowledge. Below is a list of links you can use to learn more about some of the more advanced topics that will help you master the Appwrite codebase.
##### Tools and Libs
@ -338,7 +339,7 @@ Things to remember when releasing SDKs
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 [PHP Debug](https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug) extension or if you are in PHP Storm you don't need any plugin. Below are the settings required for remote debugger connection.
First, you need to create an init file. Duplicate **dev/yasd_init.php.stub** file and name it **dev/yasd_init.php** and there change the IP address to your development machine's IP. Without the proper IP address debugger won't connect. And you also need to set **DEBUG** build arg in **appwrite** service in **docker-compose.yml** file.
First, you need to create an init file. Duplicate **dev/yasd_init.php.stub** file and name it **dev/yasd_init.php** and then change the IP address to your development machine's IP. Without the proper IP address debugger won't connect. And you also need to set **DEBUG** build arg in **appwrite** service in **docker-compose.yml** file.
### VS Code Launch Configuration

View file

@ -14,7 +14,6 @@ RUN composer install --ignore-platform-reqs --optimize-autoloader \
FROM node:16.14.2-alpine3.15 as node
COPY app/console /usr/local/src/console
WORKDIR /usr/local/src/console
@ -311,7 +310,6 @@ COPY ./bin /usr/local/bin
COPY ./docs /usr/src/code/docs
COPY ./public/fonts /usr/src/code/public/fonts
COPY ./public/images /usr/src/code/public/images
COPY ./console /usr/src/code/console
COPY ./src /usr/src/code/src
# Set Volumes

View file

@ -21,6 +21,8 @@
[English](README.md) | 简体中文
[**我们发布了 Appwrite 1.0 版本!**](https://appwrite.io/1.0)
Appwrite是一个基于Docker的端到端开发者平台其容器化的微服务库可应用于网页端移动端以及后端。Appwrite 通过视觉化界面极简了从零编写 API 的繁琐过程,在保证软件安全的前提下为开发者创造了一个高效的开发环境。
Appwrite 可以提供给开发者用户验证,外部授权,用户数据读写检索,文件储存,图像处理,云函数计算,[等多种服务](https://appwrite.io/docs).
@ -62,7 +64,7 @@ docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
--entrypoint="install" \
appwrite/appwrite:1.0.2
appwrite/appwrite:1.0.3
```
### Windows
@ -74,7 +76,7 @@ docker run -it --rm ^
--volume //var/run/docker.sock:/var/run/docker.sock ^
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
--entrypoint="install" ^
appwrite/appwrite:1.0.2
appwrite/appwrite:1.0.3
```
#### PowerShell
@ -84,7 +86,7 @@ docker run -it --rm ,
--volume /var/run/docker.sock:/var/run/docker.sock ,
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw ,
--entrypoint="install" ,
appwrite/appwrite:1.0.2
appwrite/appwrite:1.0.3
```
运行后,可以在浏览器上访问 http://localhost 找到 Appwrite 控制台。在非 Linux 的本机主机上完成安装后,服务器可能需要几分钟才能启动。

View file

@ -75,7 +75,7 @@ docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
--entrypoint="install" \
appwrite/appwrite:1.0.2
appwrite/appwrite:1.0.3
```
### Windows
@ -87,7 +87,7 @@ docker run -it --rm ^
--volume //var/run/docker.sock:/var/run/docker.sock ^
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
--entrypoint="install" ^
appwrite/appwrite:1.0.2
appwrite/appwrite:1.0.3
```
#### PowerShell
@ -97,7 +97,7 @@ docker run -it --rm `
--volume /var/run/docker.sock:/var/run/docker.sock `
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw `
--entrypoint="install" `
appwrite/appwrite:1.0.2
appwrite/appwrite:1.0.3
```
Once the Docker installation completes, go to http://localhost to access the Appwrite console from your browser. Please note that on non-Linux native hosts, the server might take a few minutes to start after installation completes.
@ -145,7 +145,7 @@ Getting started with Appwrite is as easy as creating a new project, choosing you
### Services
- [**Account**](https://appwrite.io/docs/client/account) - Manage current user authentication and account. Track and manage the user sessions, devices, sign-in methods, and security logs.
- [**Users**](https://appwrite.io/docs/server/users) - Manage and list all project users when in admin mode.
- [**Users**](https://appwrite.io/docs/server/users) - Manage and list all project users when building backend integrations with Server SDKs.
- [**Teams**](https://appwrite.io/docs/client/teams) - Manage and group users in teams. Manage memberships, invites, and user roles within a team.
- [**Databases**](https://appwrite.io/docs/client/databases) - Manage databases, collections and documents. Read, create, update, and delete documents and filter lists of document collections using advanced filters.
- [**Storage**](https://appwrite.io/docs/client/storage) - Manage storage files. Read, create, delete, and preview files. Manipulate the preview of your files to fit your app perfectly. All files are scanned by ClamAV and stored in a secure and encrypted way.
@ -206,7 +206,7 @@ For security issues, kindly email us at [security@appwrite.io](mailto:security@a
## Follow Us
Join our growing community around the world! See our official [Blog](https://medium.com/appwrite-io). Follow us on [Twitter](https://twitter.com/appwrite), [Facebook Page](https://www.facebook.com/appwrite.io), [Facebook Group](https://www.facebook.com/groups/appwrite.developers/) , [Dev Community](https://dev.to/appwrite) or join our live [Discord server](https://discord.gg/GSeTUeA) for more help, ideas, and discussions.
Join our growing community around the world! See our official [Blog](https://medium.com/appwrite-io). Follow us on [Twitter](https://twitter.com/appwrite), [Facebook Page](https://www.facebook.com/appwrite.io), [Facebook Group](https://www.facebook.com/groups/appwrite.developers/), [Dev Community](https://dev.to/appwrite) or join our live [Discord server](https://discord.gg/GSeTUeA) for more help, ideas, and discussions.
## License

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
Subproject commit 4be303e3c754b7fba367669bd82b194c811836c0

View file

@ -1574,7 +1574,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes')
Query::equal('databaseInternalId', [$db->getInternalId()])
], 61);
$limit = 64 - MariaDB::getNumberOfDefaultIndexes();
$limit = 64 - MariaDB::getCountOfDefaultIndexes();
if ($count >= $limit) {
throw new Exception(Exception::INDEX_LIMIT_EXCEEDED, 'Index limit exceeded');

View file

@ -832,6 +832,7 @@ App::get('/v1/functions/:functionId/deployments')
$result->setAttribute('status', $build->getAttribute('status', 'processing'));
$result->setAttribute('buildStderr', $build->getAttribute('stderr', ''));
$result->setAttribute('buildStdout', $build->getAttribute('stdout', ''));
$result->setAttribute('buildTime', $build->getAttribute('duration', 0));
}
$response->dynamic(new Document([

View file

@ -444,12 +444,13 @@ App::patch('/v1/projects/:projectId/oauth2')
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_PROJECT)
->param('projectId', '', new UID(), 'Project unique ID.')
->param('provider', '', new WhiteList(\array_keys(Config::getParam('providers')), true), 'Provider Name', false)
->param('appId', '', new Text(256), 'Provider app ID. Max length: 256 chars.', true)
->param('secret', '', new text(512), 'Provider secret key. Max length: 512 chars.', true)
->param('provider', '', new WhiteList(\array_keys(Config::getParam('providers')), true), 'Provider Name')
->param('appId', null, new Text(256), 'Provider app ID. Max length: 256 chars.', true)
->param('secret', null, new text(512), 'Provider secret key. Max length: 512 chars.', true)
->param('enabled', null, new Boolean(), 'Provider status. Set to \'false\' to disable new session creation.', true)
->inject('response')
->inject('dbForConsole')
->action(function (string $projectId, string $provider, string $appId, string $secret, Response $response, Database $dbForConsole) {
->action(function (string $projectId, string $provider, ?string $appId, ?string $secret, ?bool $enabled, Response $response, Database $dbForConsole) {
$project = $dbForConsole->getDocument('projects', $projectId);
@ -458,8 +459,18 @@ App::patch('/v1/projects/:projectId/oauth2')
}
$providers = $project->getAttribute('authProviders', []);
$providers[$provider . 'Appid'] = $appId;
$providers[$provider . 'Secret'] = $secret;
if ($appId !== null) {
$providers[$provider . 'Appid'] = $appId;
}
if ($secret !== null) {
$providers[$provider . 'Secret'] = $secret;
}
if ($enabled !== null) {
$providers[$provider . 'Enabled'] = $enabled;
}
$project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('authProviders', $providers));
@ -563,10 +574,6 @@ App::delete('/v1/projects/:projectId')
->setDocument($project)
;
if (!$dbForConsole->deleteDocument('teams', $project->getAttribute('teamId', null))) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove project team from DB');
}
if (!$dbForConsole->deleteDocument('projects', $projectId)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove project from DB');
}

View file

@ -888,7 +888,7 @@ App::patch('/v1/users/:userId/phone')
try {
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
} catch (Duplicate $th) {
throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS);
throw new Exception(Exception::USER_PHONE_ALREADY_EXISTS);
}
$events->setParam('userId', $user->getId());

View file

@ -403,11 +403,6 @@ App::error()
$version = App::getEnv('_APP_VERSION', 'UNKNOWN');
$route = $utopia->match($request);
/** Delegate PDO exceptions to the global handler so the database connection can be returned to the pool */
if ($error instanceof PDOException) {
throw $error;
}
if ($logger) {
if ($error->getCode() >= 500 || $error->getCode() === 0) {
try {

View file

@ -3,50 +3,17 @@
use Appwrite\Utopia\Response;
use Utopia\App;
$fallbackRoute = function (Response $response) {
$fallback = file_get_contents(__DIR__ . '/../../../console/index.html');
$response->html($fallback);
};
App::get('/')
->groups(['web'])
->label('permission', 'public')
->label('scope', 'home')
->inject('response')
->action($fallbackRoute);
App::get('/console/*')
->alias('/')
->alias('/invite')
->alias('/login')
->alias('/recover')
->alias('/register')
->groups(['web'])
->label('permission', 'public')
->label('scope', 'home')
->inject('response')
->action($fallbackRoute);
App::get('/invite')
->groups(['web'])
->label('permission', 'public')
->label('scope', 'home')
->inject('response')
->action($fallbackRoute);
App::get('/login')
->groups(['web'])
->label('permission', 'public')
->label('scope', 'home')
->inject('response')
->action($fallbackRoute);
App::get('/recover')
->groups(['web'])
->label('permission', 'public')
->label('scope', 'home')
->inject('response')
->action($fallbackRoute);
App::get('/register')
->groups(['web'])
->label('permission', 'public')
->label('scope', 'home')
->inject('response')
->action($fallbackRoute);
->action(function (Response $response) {
$fallback = file_get_contents(__DIR__ . '/../../../console/index.html');
$response->html($fallback);
});

View file

@ -90,18 +90,11 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) {
/** @var array $collections */
$collections = Config::getParam('collections', []);
if (!$dbForConsole->exists(App::getEnv('_APP_DB_SCHEMA', 'appwrite'))) {
$redis->flushAll();
Console::success('[Setup] - Creating database: appwrite...');
$dbForConsole->create(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
}
try {
Console::success('[Setup] - Creating metadata table: appwrite...');
$dbForConsole->createMetadata();
} catch (\Throwable $th) {
$redis->flushAll();
Console::success('[Setup] - Creating database: appwrite...');
$dbForConsole->create(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
} catch (\Exception $e) {
Console::success('[Setup] - Skip: metadata table already exists');
}
@ -323,13 +316,6 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo
Console::error('[Error] File: ' . $th->getFile());
Console::error('[Error] Line: ' . $th->getLine());
/**
* Reset Database connection if PDOException was thrown.
*/
if ($th instanceof PDOException) {
$db = null;
}
$swooleResponse->setStatusCode(500);
$output = ((App::isDevelopment())) ? [

View file

@ -95,7 +95,7 @@ const APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT = 60; // Default maximum write rate pe
const APP_KEY_ACCCESS = 24 * 60 * 60; // 24 hours
const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours
const APP_CACHE_BUSTER = 501;
const APP_VERSION_STABLE = '1.0.2';
const APP_VERSION_STABLE = '1.0.3';
const APP_DATABASE_ATTRIBUTE_EMAIL = 'email';
const APP_DATABASE_ATTRIBUTE_ENUM = 'enum';
const APP_DATABASE_ATTRIBUTE_IP = 'ip';
@ -283,7 +283,7 @@ Database::addFilter(
->find('attributes', [
Query::equal('collectionInternalId', [$document->getInternalId()]),
Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]),
Query::limit($database->getAttributeLimit()),
Query::limit($database->getLimitForAttributes()),
]);
}
);

View file

@ -72,7 +72,7 @@ Redistribution and use in source and binary forms, with or without modification,
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name Appwrite nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.';

View file

@ -181,6 +181,10 @@ class BuildsV1 extends Worker
$build->setAttribute('stderr', $response['stderr']);
$build->setAttribute('stdout', $response['response']);
/* Also update the deployment buildTime */
$deployment->setAttribute('buildTime', $response['duration']);
$deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment);
Console::success("Build id: $buildId created");
/** Set auto deploy */

View file

@ -193,21 +193,24 @@ class DeletesV1 extends Worker
protected function deleteCollection(Document $document, string $projectId): void
{
$collectionId = $document->getId();
$databaseId = str_replace('database_', '', $document->getCollection());
$databaseId = $document->getAttribute('databaseId');
$databaseInternalId = $document->getAttribute('databaseInternalId');
$dbForProject = $this->getProjectDB($projectId);
$dbForProject->deleteCollection('database_' . $databaseId . '_collection_' . $document->getInternalId());
$dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $document->getInternalId());
$this->deleteByGroup('attributes', [
Query::equal('databaseId', [$databaseId]),
Query::equal('collectionId', [$collectionId])
], $dbForProject);
$this->deleteByGroup('indexes', [
Query::equal('databaseId', [$databaseId]),
Query::equal('collectionId', [$collectionId])
], $dbForProject);
$this->deleteAuditLogsByResource('collection/' . $collectionId, $projectId);
$this->deleteAuditLogsByResource('database/' . $databaseId . '/collection/' . $collectionId, $projectId);
}
/**

View file

@ -43,24 +43,24 @@
"ext-sockets": "*",
"appwrite/php-clamav": "1.1.*",
"appwrite/php-runtimes": "0.11.*",
"utopia-php/abuse": "0.13.*",
"utopia-php/abuse": "0.14.*",
"utopia-php/analytics": "0.2.*",
"utopia-php/audit": "0.14.*",
"utopia-php/audit": "0.15.*",
"utopia-php/cache": "0.6.*",
"utopia-php/cli": "0.13.*",
"utopia-php/config": "0.2.*",
"utopia-php/database": "0.25.*",
"utopia-php/database": "0.26.*",
"utopia-php/preloader": "0.2.*",
"utopia-php/domains": "1.1.*",
"utopia-php/framework": "0.21.*",
"utopia-php/framework": "dev-feat-multiple-aliases as 0.22.9",
"utopia-php/image": "0.5.*",
"utopia-php/locale": "0.4.*",
"utopia-php/logger": "0.3.*",
"utopia-php/messaging": "0.1.*",
"utopia-php/orchestration": "0.6.*",
"utopia-php/preloader": "0.2.*",
"utopia-php/registry": "0.5.*",
"utopia-php/storage": "0.11.*",
"utopia-php/swoole": "0.3.*",
"utopia-php/swoole": "0.4.*",
"utopia-php/websocket": "0.1.0",
"resque/php-resque": "1.3.6",
"matomo/device-detector": "6.0.0",
@ -93,4 +93,4 @@
"php": "8.0"
}
}
}
}

140
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "e81c5582d74cc867fbf80e9bdf4f4872",
"content-hash": "d8785bcc235caa7fe9312614f053d0cd",
"packages": [
{
"name": "adhocore/jwt",
@ -693,16 +693,16 @@
},
{
"name": "guzzlehttp/psr7",
"version": "2.4.1",
"version": "2.4.3",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "69568e4293f4fa993f3b0e51c9723e1e17c41379"
"reference": "67c26b443f348a51926030c83481b85718457d3d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/69568e4293f4fa993f3b0e51c9723e1e17c41379",
"reference": "69568e4293f4fa993f3b0e51c9723e1e17c41379",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/67c26b443f348a51926030c83481b85718457d3d",
"reference": "67c26b443f348a51926030c83481b85718457d3d",
"shasum": ""
},
"require": {
@ -792,7 +792,7 @@
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/2.4.1"
"source": "https://github.com/guzzle/psr7/tree/2.4.3"
},
"funding": [
{
@ -808,7 +808,7 @@
"type": "tidelift"
}
],
"time": "2022-08-28T14:45:39+00:00"
"time": "2022-10-26T14:07:24+00:00"
},
{
"name": "influxdb/influxdb-php",
@ -1741,23 +1741,23 @@
},
{
"name": "utopia-php/abuse",
"version": "0.13.1",
"version": "0.14.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/abuse.git",
"reference": "4c1b8fe742f17158c59550cdfd9074a94bf474ac"
"reference": "1a5da248e74c1bfc39bc440fa949de6935acceeb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/4c1b8fe742f17158c59550cdfd9074a94bf474ac",
"reference": "4c1b8fe742f17158c59550cdfd9074a94bf474ac",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/1a5da248e74c1bfc39bc440fa949de6935acceeb",
"reference": "1a5da248e74c1bfc39bc440fa949de6935acceeb",
"shasum": ""
},
"require": {
"ext-curl": "*",
"ext-pdo": "*",
"php": ">=8.0",
"utopia-php/database": "0.25.*"
"utopia-php/database": "0.26.*"
},
"require-dev": {
"phpunit/phpunit": "^9.4",
@ -1789,9 +1789,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/abuse/issues",
"source": "https://github.com/utopia-php/abuse/tree/0.13.1"
"source": "https://github.com/utopia-php/abuse/tree/0.14.0"
},
"time": "2022-09-07T16:02:58+00:00"
"time": "2022-10-14T11:26:39+00:00"
},
{
"name": "utopia-php/analytics",
@ -1850,22 +1850,22 @@
},
{
"name": "utopia-php/audit",
"version": "0.14.1",
"version": "0.15.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/audit.git",
"reference": "b011224ed9bfef7e5c849938e65619af28f7cf41"
"reference": "937ffd13e7a5ac9ad220b329247569ef2a4881d9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/b011224ed9bfef7e5c849938e65619af28f7cf41",
"reference": "b011224ed9bfef7e5c849938e65619af28f7cf41",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/937ffd13e7a5ac9ad220b329247569ef2a4881d9",
"reference": "937ffd13e7a5ac9ad220b329247569ef2a4881d9",
"shasum": ""
},
"require": {
"ext-pdo": "*",
"php": ">=8.0",
"utopia-php/database": "0.25.*"
"utopia-php/database": "0.26.*"
},
"require-dev": {
"phpunit/phpunit": "^9.3",
@ -1881,12 +1881,6 @@
"license": [
"MIT"
],
"authors": [
{
"name": "Eldad Fux",
"email": "eldad@appwrite.io"
}
],
"description": "A simple audit library to manage application users logs",
"keywords": [
"Audit",
@ -1897,9 +1891,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/audit/issues",
"source": "https://github.com/utopia-php/audit/tree/0.14.1"
"source": "https://github.com/utopia-php/audit/tree/0.15.0"
},
"time": "2022-09-07T16:03:16+00:00"
"time": "2022-10-14T11:39:18+00:00"
},
{
"name": "utopia-php/cache",
@ -2060,16 +2054,16 @@
},
{
"name": "utopia-php/database",
"version": "0.25.5",
"version": "0.26.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/database.git",
"reference": "6d1c1d46d66553154975a3e8e72d30b5bd2413d9"
"reference": "d172af2541137c83a86d066f82f48914b5a3a610"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/6d1c1d46d66553154975a3e8e72d30b5bd2413d9",
"reference": "6d1c1d46d66553154975a3e8e72d30b5bd2413d9",
"url": "https://api.github.com/repos/utopia-php/database/zipball/d172af2541137c83a86d066f82f48914b5a3a610",
"reference": "d172af2541137c83a86d066f82f48914b5a3a610",
"shasum": ""
},
"require": {
@ -2118,9 +2112,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/0.25.5"
"source": "https://github.com/utopia-php/database/tree/0.26.0"
},
"time": "2022-09-30T15:01:32+00:00"
"time": "2022-10-03T17:12:01+00:00"
},
{
"name": "utopia-php/domains",
@ -2178,24 +2172,24 @@
},
{
"name": "utopia-php/framework",
"version": "0.21.1",
"version": "dev-feat-multiple-aliases",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/framework.git",
"reference": "c81789b87a917da2daf336738170ebe01f50ea18"
"reference": "37637cb22a30e6660a0886befef4d6a5e657fc48"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/framework/zipball/c81789b87a917da2daf336738170ebe01f50ea18",
"reference": "c81789b87a917da2daf336738170ebe01f50ea18",
"url": "https://api.github.com/repos/utopia-php/framework/zipball/37637cb22a30e6660a0886befef4d6a5e657fc48",
"reference": "37637cb22a30e6660a0886befef4d6a5e657fc48",
"shasum": ""
},
"require": {
"php": ">=8.0.0"
},
"require-dev": {
"phpunit/phpunit": "^9.5.10",
"vimeo/psalm": "4.13.1"
"phpunit/phpunit": "^9.5.25",
"vimeo/psalm": "^4.27.0"
},
"type": "library",
"autoload": {
@ -2207,12 +2201,6 @@
"license": [
"MIT"
],
"authors": [
{
"name": "Eldad Fux",
"email": "eldad@appwrite.io"
}
],
"description": "A simple, light and advanced PHP framework",
"keywords": [
"framework",
@ -2221,9 +2209,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/framework/issues",
"source": "https://github.com/utopia-php/framework/tree/0.21.1"
"source": "https://github.com/utopia-php/framework/tree/feat-multiple-aliases"
},
"time": "2022-09-07T09:56:28+00:00"
"time": "2022-10-20T21:06:21+00:00"
},
{
"name": "utopia-php/image",
@ -2665,16 +2653,16 @@
},
{
"name": "utopia-php/swoole",
"version": "0.3.3",
"version": "0.4.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/swoole.git",
"reference": "8312df69233b5dcd3992de88f131f238002749de"
"reference": "536e1f3e78fc0197e4a8ed81b1bf2636a3bc4538"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/swoole/zipball/8312df69233b5dcd3992de88f131f238002749de",
"reference": "8312df69233b5dcd3992de88f131f238002749de",
"url": "https://api.github.com/repos/utopia-php/swoole/zipball/536e1f3e78fc0197e4a8ed81b1bf2636a3bc4538",
"reference": "536e1f3e78fc0197e4a8ed81b1bf2636a3bc4538",
"shasum": ""
},
"require": {
@ -2715,9 +2703,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/swoole/issues",
"source": "https://github.com/utopia-php/swoole/tree/0.3.3"
"source": "https://github.com/utopia-php/swoole/tree/0.4.0"
},
"time": "2022-01-20T09:58:43+00:00"
"time": "2022-10-08T14:32:43+00:00"
},
{
"name": "utopia-php/system",
@ -3473,25 +3461,30 @@
},
{
"name": "phpdocumentor/type-resolver",
"version": "1.6.1",
"version": "1.6.2",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "77a32518733312af16a44300404e945338981de3"
"reference": "48f445a408c131e38cab1c235aa6d2bb7a0bb20d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3",
"reference": "77a32518733312af16a44300404e945338981de3",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/48f445a408c131e38cab1c235aa6d2bb7a0bb20d",
"reference": "48f445a408c131e38cab1c235aa6d2bb7a0bb20d",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0",
"php": "^7.4 || ^8.0",
"phpdocumentor/reflection-common": "^2.0"
},
"require-dev": {
"ext-tokenizer": "*",
"psalm/phar": "^4.8"
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan-phpunit": "^1.1",
"phpunit/phpunit": "^9.5",
"rector/rector": "^0.13.9",
"vimeo/psalm": "^4.25"
},
"type": "library",
"extra": {
@ -3517,9 +3510,9 @@
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
"support": {
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1"
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.2"
},
"time": "2022-03-15T21:29:03+00:00"
"time": "2022-10-14T12:47:21+00:00"
},
{
"name": "phpspec/prophecy",
@ -3590,16 +3583,16 @@
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.17",
"version": "9.2.18",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8"
"reference": "12fddc491826940cf9b7e88ad9664cf51f0f6d0a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aa94dc41e8661fe90c7316849907cba3007b10d8",
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/12fddc491826940cf9b7e88ad9664cf51f0f6d0a",
"reference": "12fddc491826940cf9b7e88ad9664cf51f0f6d0a",
"shasum": ""
},
"require": {
@ -3655,7 +3648,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.17"
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.18"
},
"funding": [
{
@ -3663,7 +3656,7 @@
"type": "github"
}
],
"time": "2022-08-30T12:24:04+00:00"
"time": "2022-10-27T13:35:33+00:00"
},
{
"name": "phpunit/php-file-iterator",
@ -5412,9 +5405,18 @@
"time": "2022-09-28T08:42:51+00:00"
}
],
"aliases": [],
"aliases": [
{
"package": "utopia-php/framework",
"version": "dev-feat-multiple-aliases",
"alias": "0.22.9",
"alias_normalized": "0.22.9.0"
}
],
"minimum-stability": "stable",
"stability-flags": [],
"stability-flags": {
"utopia-php/framework": 20
},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {

View file

@ -1,48 +0,0 @@
services:
appwrite:
image: appwrite-dev
appwrite-realtime:
image: appwrite-dev
appwrite-worker-audits:
image: appwrite-dev
appwrite-worker-webhooks:
image: appwrite-dev
appwrite-worker-deletes:
image: appwrite-dev
appwrite-worker-databases:
image: appwrite-dev
appwrite-worker-builds:
image: appwrite-dev
appwrite-worker-certificates:
image: appwrite-dev
appwrite-worker-functions:
image: appwrite-dev
appwrite-executor:
image: appwrite-dev
appwrite-worker-mails:
image: appwrite-dev
appwrite-worker-messaging:
image: appwrite-dev
appwrite-maintenance:
image: appwrite-dev
appwrite-usage-timeseries:
image: appwrite-dev
appwrite-usage-database:
image: appwrite-dev
appwrite-schedule:
image: appwrite-dev

View file

@ -10,30 +10,6 @@ x-logging: &x-logging
max-file: '5'
max-size: '10m'
x-env-storage: &x-env-storage |-
_APP_STORAGE_DEVICE
_APP_STORAGE_S3_ACCESS_KEY
_APP_STORAGE_S3_SECRET
_APP_STORAGE_S3_REGION
_APP_STORAGE_S3_BUCKET
_APP_STORAGE_DO_SPACES_ACCESS_KEY
_APP_STORAGE_DO_SPACES_SECRET
_APP_STORAGE_DO_SPACES_REGION
_APP_STORAGE_DO_SPACES_BUCKET
_APP_STORAGE_BACKBLAZE_ACCESS_KEY
_APP_STORAGE_BACKBLAZE_SECRET
_APP_STORAGE_BACKBLAZE_REGION
_APP_STORAGE_BACKBLAZE_BUCKET
_APP_STORAGE_DO_SPACES_BUCKET
_APP_STORAGE_LINODE_ACCESS_KEY
_APP_STORAGE_LINODE_SECRET
_APP_STORAGE_LINODE_REGION
_APP_STORAGE_LINODE_BUCKET
_APP_STORAGE_WASABI_ACCESS_KEY
_APP_STORAGE_WASABI_SECRET
_APP_STORAGE_WASABI_REGION
_APP_STORAGE_WASABI_BUCKET
version: '3'
services:
@ -70,6 +46,7 @@ services:
appwrite:
container_name: appwrite
<<: *x-logging
image: appwrite-dev
build:
context: .
args:
@ -154,7 +131,27 @@ services:
- _APP_STORAGE_ANTIVIRUS
- _APP_STORAGE_ANTIVIRUS_HOST
- _APP_STORAGE_ANTIVIRUS_PORT
- *x-env-storage
- _APP_STORAGE_DEVICE
- _APP_STORAGE_S3_ACCESS_KEY
- _APP_STORAGE_S3_SECRET
- _APP_STORAGE_S3_REGION
- _APP_STORAGE_S3_BUCKET
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DO_SPACES_SECRET
- _APP_STORAGE_DO_SPACES_REGION
- _APP_STORAGE_DO_SPACES_BUCKET
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY
- _APP_STORAGE_BACKBLAZE_SECRET
- _APP_STORAGE_BACKBLAZE_REGION
- _APP_STORAGE_BACKBLAZE_BUCKET
- _APP_STORAGE_LINODE_ACCESS_KEY
- _APP_STORAGE_LINODE_SECRET
- _APP_STORAGE_LINODE_REGION
- _APP_STORAGE_LINODE_BUCKET
- _APP_STORAGE_WASABI_ACCESS_KEY
- _APP_STORAGE_WASABI_SECRET
- _APP_STORAGE_WASABI_REGION
- _APP_STORAGE_WASABI_BUCKET
- _APP_FUNCTIONS_SIZE_LIMIT
- _APP_FUNCTIONS_TIMEOUT
- _APP_FUNCTIONS_BUILD_TIMEOUT
@ -181,8 +178,7 @@ services:
entrypoint: realtime
<<: *x-logging
container_name: appwrite-realtime
build:
context: .
image: appwrite-dev
restart: unless-stopped
ports:
- 9505:80
@ -229,8 +225,7 @@ services:
entrypoint: worker-audits
<<: *x-logging
container_name: appwrite-worker-audits
build:
context: .
image: appwrite-dev
networks:
- appwrite
volumes:
@ -258,8 +253,7 @@ services:
entrypoint: worker-webhooks
<<: *x-logging
container_name: appwrite-worker-webhooks
build:
context: .
image: appwrite-dev
networks:
- appwrite
volumes:
@ -284,8 +278,7 @@ services:
entrypoint: worker-deletes
<<: *x-logging
container_name: appwrite-worker-deletes
build:
context: .
image: appwrite-dev
networks:
- appwrite
depends_on:
@ -311,7 +304,27 @@ services:
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- *x-env-storage
- _APP_STORAGE_DEVICE
- _APP_STORAGE_S3_ACCESS_KEY
- _APP_STORAGE_S3_SECRET
- _APP_STORAGE_S3_REGION
- _APP_STORAGE_S3_BUCKET
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DO_SPACES_SECRET
- _APP_STORAGE_DO_SPACES_REGION
- _APP_STORAGE_DO_SPACES_BUCKET
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY
- _APP_STORAGE_BACKBLAZE_SECRET
- _APP_STORAGE_BACKBLAZE_REGION
- _APP_STORAGE_BACKBLAZE_BUCKET
- _APP_STORAGE_LINODE_ACCESS_KEY
- _APP_STORAGE_LINODE_SECRET
- _APP_STORAGE_LINODE_REGION
- _APP_STORAGE_LINODE_BUCKET
- _APP_STORAGE_WASABI_ACCESS_KEY
- _APP_STORAGE_WASABI_SECRET
- _APP_STORAGE_WASABI_REGION
- _APP_STORAGE_WASABI_BUCKET
- _APP_LOGGING_PROVIDER
- _APP_LOGGING_CONFIG
- _APP_EXECUTOR_SECRET
@ -321,8 +334,7 @@ services:
entrypoint: worker-databases
<<: *x-logging
container_name: appwrite-worker-databases
build:
context: .
image: appwrite-dev
networks:
- appwrite
volumes:
@ -351,8 +363,7 @@ services:
entrypoint: worker-builds
<<: *x-logging
container_name: appwrite-worker-builds
build:
context: .
image: appwrite-dev
networks:
- appwrite
volumes:
@ -382,8 +393,7 @@ services:
entrypoint: worker-certificates
<<: *x-logging
container_name: appwrite-worker-certificates
build:
context: .
image: appwrite-dev
networks:
- appwrite
depends_on:
@ -416,8 +426,7 @@ services:
entrypoint: worker-functions
<<: *x-logging
container_name: appwrite-worker-functions
build:
context: .
image: appwrite-dev
networks:
- appwrite
volumes:
@ -451,12 +460,7 @@ services:
<<: *x-logging
entrypoint: executor
stop_signal: SIGINT
build:
context: .
args:
- DEBUG=false
- TESTING=true
- VERSION=dev
image: appwrite-dev
networks:
appwrite:
runtimes:
@ -488,7 +492,27 @@ services:
- OPEN_RUNTIMES_NETWORK
- _APP_LOGGING_PROVIDER
- _APP_LOGGING_CONFIG
- *x-env-storage
- _APP_STORAGE_DEVICE
- _APP_STORAGE_S3_ACCESS_KEY
- _APP_STORAGE_S3_SECRET
- _APP_STORAGE_S3_REGION
- _APP_STORAGE_S3_BUCKET
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DO_SPACES_SECRET
- _APP_STORAGE_DO_SPACES_REGION
- _APP_STORAGE_DO_SPACES_BUCKET
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY
- _APP_STORAGE_BACKBLAZE_SECRET
- _APP_STORAGE_BACKBLAZE_REGION
- _APP_STORAGE_BACKBLAZE_BUCKET
- _APP_STORAGE_LINODE_ACCESS_KEY
- _APP_STORAGE_LINODE_SECRET
- _APP_STORAGE_LINODE_REGION
- _APP_STORAGE_LINODE_BUCKET
- _APP_STORAGE_WASABI_ACCESS_KEY
- _APP_STORAGE_WASABI_SECRET
- _APP_STORAGE_WASABI_REGION
- _APP_STORAGE_WASABI_BUCKET
- DOCKERHUB_PULL_USERNAME
- DOCKERHUB_PULL_PASSWORD
@ -496,8 +520,7 @@ services:
entrypoint: worker-mails
<<: *x-logging
container_name: appwrite-worker-mails
build:
context: .
image: appwrite-dev
networks:
- appwrite
volumes:
@ -528,8 +551,7 @@ services:
entrypoint: worker-messaging
<<: *x-logging
container_name: appwrite-worker-messaging
build:
context: .
image: appwrite-dev
networks:
- appwrite
volumes:
@ -552,8 +574,7 @@ services:
entrypoint: maintenance
<<: *x-logging
container_name: appwrite-maintenance
build:
context: .
image: appwrite-dev
networks:
- appwrite
volumes:
@ -588,10 +609,7 @@ services:
- --type=timeseries
<<: *x-logging
container_name: appwrite-usage-timeseries
build:
context: .
args:
- DEBUG=false
image: appwrite-dev
networks:
- appwrite
volumes:
@ -626,10 +644,7 @@ services:
- --type=database
<<: *x-logging
container_name: appwrite-usage-database
build:
context: .
args:
- DEBUG=false
image: appwrite-dev
networks:
- appwrite
volumes:
@ -662,8 +677,7 @@ services:
entrypoint: schedule
<<: *x-logging
container_name: appwrite-schedule
build:
context: .
image: appwrite-dev
networks:
- appwrite
volumes:

View file

@ -1 +1 @@
Get a list of all the user's documents in a given collection. You can use the query params to filter your results. On admin mode, this endpoint will return a list of all of documents belonging to the provided collectionId. [Learn more about different API modes](/docs/admin).
Get a list of all the user's documents in a given collection. You can use the query params to filter your results.

View file

@ -1 +1 @@
Get a list of all the current user function execution logs. You can use the query params to filter your results. On admin mode, this endpoint will return a list of all of the project's executions. [Learn more about different API modes](/docs/admin).
Get a list of all the current user function execution logs. You can use the query params to filter your results.

View file

@ -1 +1 @@
Get a list of all the user files. You can use the query params to filter your results. On admin mode, this endpoint will return a list of all of the project's files. [Learn more about different API modes](/docs/admin).
Get a list of all the user files. You can use the query params to filter your results.

View file

@ -1,3 +1 @@
Get a list of all the teams in which the current user is a member. You can use the parameters to filter your results.
In admin mode, this endpoint returns a list of all the teams in the current project. [Learn more about different API modes](/docs/admin).
Get a list of all the teams in which the current user is a member. You can use the parameters to filter your results.

View file

@ -2,9 +2,9 @@ The Account service allows you to authenticate and manage a user account. You ca
Register new user accounts with the [Create Account](/docs/client/account#accountCreate), [Create Magic URL session](/docs/client/account#accountCreateMagicURLSession), or [Create Phone session](/docs/client/account#accountCreatePhoneSession) endpoint. You can authenticate the user account by using multiple sign-in methods available. Once the user is authenticated, a new session object will be created to allow the user to access his or her private data and settings.
This service also exposes an endpoint to save and read the [user preferences](/docs/client/account#accountUpdatePrefs) as a key-value object. This feature is handy if you want to allow extra customization in your app. Common usage for this feature may include saving the user preferred locale, timezone, or custom app theme.
This service also exposes an endpoint to save and read the [user preferences](/docs/client/account#accountUpdatePrefs) as a key-value object. This feature is handy if you want to allow extra customization in your app. Common usage for this feature may include saving the user's preferred locale, timezone, or custom app theme.
> ## Account API vs Users API
> While the Account API operates in the scope of the current logged-in user and usually using a client-side integration, the Users API is integrated from the server-side and operates in an admin scope with access to all your project users.
>
> Some of the Account API methods are available from the server SDK when you authenticate with JWT. This allows you to perform server-side actions on behalf of your project user.
> Some of the Account API methods are available from the server SDK when you authenticate with JWT. This allows you to perform server-side actions on behalf of your project user.

View file

@ -1,5 +1,5 @@
The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars.
The Avatars service allows you to fetch country flags, browser icons, payment methods logos, remote websites favicons, generate QR codes, and manipulate remote images URLs.
The Avatars service allows you to fetch country flags, browser icons, payment methods logos, remote websites favicons, generate QR codes, and manipulate remote image URLs.
All endpoints in this service allow you to resize, crop, and change the output image quality for maximum performance and visibility in your app.
All endpoints in this service allow you to resize, crop, and change the output image quality for maximum performance and visibility in your app.

View file

@ -5,12 +5,12 @@ This document is part of the Appwrite contributors' guide. Before you continue r
## Getting Started
### Agenda
Adding new features may require various configurations options to be set by the users. And for such options, we use environment variables in Appwrite.
Adding new features may require various configuration options to be set by the users. And for such options, we use environment variables in Appwrite.
This tutorial will cover how to properly add a new environment variable in Appwrite.
### Naming environment variable
The environment variables in Appwrite are prefixed with `_APP_`. If it belongs to a specific category, the category name is appended as `_APP_REDIS` for the Redis category. The available categories are General, Redis, MariaDB, InfluxDB, StatsD, SMTP, Storage and Functions. Finally, a properly describing name is given to the variable. For example, `_APP_REDIS_HOST` is an environment variable for Redis connection host. You can find more information on available categories and existing environment variables in the [environment variables doc](https://appwrite.io/docs/environment-variables).
The environment variables in Appwrite are prefixed with `_APP_`. If it belongs to a specific category, the category name is appended as `_APP_REDIS` for the Redis category. The available categories are General, Redis, MariaDB, InfluxDB, StatsD, SMTP, Storage, Functions and Maintenance. Finally, a properly describing name is given to the variable. For example, `_APP_REDIS_HOST` is an environment variable for the hostname of your Redis instance. You can find more information on available categories and existing environment variables in the [environment variables doc](https://appwrite.io/docs/environment-variables).
### Describe new environment variable
First of all, we add the new environment variable to `app/config/variables.php` in the designated category. If none of the categories fit, add it to the General category. Copy the existing variable description to create a new one so that you will not miss any required fields.

View file

@ -62,7 +62,7 @@ We maintain a [`locale branch`](https://github.com/appwrite/appwrite/tree/locale
2. **en.json**
[en.json]((https://github.com/appwrite/appwrite/blob/locale/app/config/locale/translations/en.json)) contains the English translation for all the terms that are present in **terms.json**. You can use this file as a reference when making a contribution for your language.
[en.json](https://github.com/appwrite/appwrite/blob/locale/app/config/locale/translations/en.json) contains the English translation for all the terms that are present in **terms.json**. You can use this file as a reference when making a contribution for your language.
```json
{

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -836,6 +836,7 @@ label.switch {
border-radius: 21px;
background: var(--config-color-fade);
display: inline-block;
overflow: visible;
margin: 0;
padding: 5px;
.func-padding-start(5px);

View file

@ -14,6 +14,7 @@ use Utopia\Database\Document;
use Utopia\Database\DateTime;
use Utopia\Database\Role;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\Roles;
class Auth
{
@ -427,11 +428,11 @@ class Auth
$phoneVerified = $user->getAttribute('phoneVerification', false);
if ($emailVerified || $phoneVerified) {
$roles[] = Role::user($user->getId(), Database::DIMENSION_VERIFIED)->toString();
$roles[] = Role::users(Database::DIMENSION_VERIFIED)->toString();
$roles[] = Role::user($user->getId(), Roles::DIMENSION_VERIFIED)->toString();
$roles[] = Role::users(Roles::DIMENSION_VERIFIED)->toString();
} else {
$roles[] = Role::user($user->getId(), Database::DIMENSION_UNVERIFIED)->toString();
$roles[] = Role::users(Database::DIMENSION_UNVERIFIED)->toString();
$roles[] = Role::user($user->getId(), Roles::DIMENSION_UNVERIFIED)->toString();
$roles[] = Role::users(Roles::DIMENSION_UNVERIFIED)->toString();
}
} else {
return [Role::guests()->toString()];

View file

@ -44,7 +44,7 @@ abstract class Migration
'1.0.0-RC1' => 'V15',
'1.0.0' => 'V15',
'1.0.1' => 'V15',
'1.0.2' => 'V15'
'1.0.3' => 'V15'
];
/**

View file

@ -229,7 +229,7 @@ abstract class Worker
throw new \Exception("Project does not exist: {$projectId}");
}
if ($type === self::DATABASE_CONSOLE && !$database->exists($database->getDefaultDatabase(), '_metadata')) {
if ($type === self::DATABASE_CONSOLE && !$database->exists($database->getDefaultDatabase(), Database::METADATA)) {
throw new \Exception('Console project not ready');
}

View file

@ -368,6 +368,11 @@ class OpenAPI3 extends Format
$node['schema']['format'] = 'password';
$node['schema']['x-example'] = 'password';
break;
case 'Appwrite\Auth\Validator\Phone':
$node['schema']['type'] = $validator->getType();
$node['schema']['format'] = 'phone';
$node['schema']['x-example'] = '+12065550100'; // In the US, 555 is reserved like example.com
break;
case 'Utopia\Validator\Range':
/** @var \Utopia\Validator\Range $validator */
$node['schema']['type'] = $validator->getType() === Validator::TYPE_FLOAT ? 'number' : $validator->getType();

View file

@ -365,6 +365,11 @@ class Swagger2 extends Format
$node['format'] = 'password';
$node['x-example'] = 'password';
break;
case 'Appwrite\Auth\Validator\Phone':
$node['type'] = $validator->getType();
$node['format'] = 'phone';
$node['x-example'] = '+12065550100';
break;
case 'Utopia\Validator\Range':
/** @var \Utopia\Validator\Range $validator */
$node['type'] = $validator->getType() === Validator::TYPE_FLOAT ? 'number' : $validator->getType();

View file

@ -70,6 +70,7 @@ use Appwrite\Utopia\Response\Model\HealthStatus;
use Appwrite\Utopia\Response\Model\HealthTime;
use Appwrite\Utopia\Response\Model\HealthVersion;
use Appwrite\Utopia\Response\Model\Mock; // Keep last
use Appwrite\Utopia\Response\Model\Provider;
use Appwrite\Utopia\Response\Model\Runtime;
use Appwrite\Utopia\Response\Model\UsageBuckets;
use Appwrite\Utopia\Response\Model\UsageCollection;
@ -194,6 +195,8 @@ class Response extends SwooleResponse
public const MODEL_WEBHOOK_LIST = 'webhookList';
public const MODEL_KEY = 'key';
public const MODEL_KEY_LIST = 'keyList';
public const MODEL_PROVIDER = 'provider';
public const MODEL_PROVIDER_LIST = 'providerList';
public const MODEL_PLATFORM = 'platform';
public const MODEL_PLATFORM_LIST = 'platformList';
public const MODEL_DOMAIN = 'domain';
@ -259,6 +262,7 @@ class Response extends SwooleResponse
->setModel(new BaseList('Projects List', self::MODEL_PROJECT_LIST, 'projects', self::MODEL_PROJECT, true, false))
->setModel(new BaseList('Webhooks List', self::MODEL_WEBHOOK_LIST, 'webhooks', self::MODEL_WEBHOOK, true, false))
->setModel(new BaseList('API Keys List', self::MODEL_KEY_LIST, 'keys', self::MODEL_KEY, true, false))
->setModel(new BaseList('Providers List', self::MODEL_PROVIDER_LIST, 'platforms', self::MODEL_PROVIDER, true, false))
->setModel(new BaseList('Platforms List', self::MODEL_PLATFORM_LIST, 'platforms', self::MODEL_PLATFORM, true, false))
->setModel(new BaseList('Domains List', self::MODEL_DOMAIN_LIST, 'domains', self::MODEL_DOMAIN, true, false))
->setModel(new BaseList('Countries List', self::MODEL_COUNTRY_LIST, 'countries', self::MODEL_COUNTRY))
@ -312,6 +316,7 @@ class Response extends SwooleResponse
->setModel(new Webhook())
->setModel(new Key())
->setModel(new Domain())
->setModel(new Provider())
->setModel(new Platform())
->setModel(new Variable())
->setModel(new Country())

View file

@ -82,6 +82,12 @@ class Deployment extends Model
'default' => '',
'example' => 'enabled',
])
->addRule('buildTime', [
'type' => self::TYPE_INTEGER,
'description' => 'The current build time in seconds.',
'default' => 0,
'example' => 128,
])
;
}

View file

@ -107,6 +107,13 @@ class Project extends Model
'default' => 0,
'example' => 100,
])
->addRule('providers', [
'type' => Response::MODEL_PROVIDER,
'description' => 'List of Providers.',
'default' => [],
'example' => new \stdClass(),
'array' => true,
])
->addRule('platforms', [
'type' => Response::MODEL_PLATFORM,
'description' => 'List of Platforms.',
@ -138,32 +145,8 @@ class Project extends Model
;
$services = Config::getParam('services', []);
$providers = Config::getParam('providers', []);
$auth = Config::getParam('auth', []);
foreach ($providers as $index => $provider) {
if (!$provider['enabled']) {
continue;
}
$name = (isset($provider['name'])) ? $provider['name'] : 'Unknown';
$this
->addRule('provider' . \ucfirst($index) . 'Appid', [
'type' => self::TYPE_STRING,
'description' => $name . ' OAuth app ID.',
'example' => '123247283472834787438',
'default' => '',
])
->addRule('provider' . \ucfirst($index) . 'Secret', [
'type' => self::TYPE_STRING,
'description' => $name . ' OAuth secret ID.',
'example' => 'djsgudsdsewe43434343dd34...',
'default' => '',
])
;
}
foreach ($auth as $index => $method) {
$name = $method['name'] ?? '';
$key = $method['key'] ?? '';
@ -224,6 +207,7 @@ class Project extends Model
*/
public function filter(Document $document): Document
{
// Services
$values = $document->getAttribute('services', []);
$services = Config::getParam('services', []);
@ -236,6 +220,7 @@ class Project extends Model
$document->setAttribute('serviceStatusFor' . ucfirst($key), $value);
}
// Auth
$authValues = $document->getAttribute('auths', []);
$auth = Config::getParam('auth', []);
@ -247,17 +232,27 @@ class Project extends Model
$document->setAttribute('auth' . ucfirst($key), $value);
}
// Providers
$providers = Config::getParam('providers', []);
$providerValues = $document->getAttribute('authProviders', []);
$projectProviders = [];
foreach ($providers as $key => $provider) {
if (!$provider['enabled']) {
// Disabled by Appwrite configuration, exclude from response
continue;
}
$appId = $providerValues[$key . 'Appid'] ?? '';
$secret = $providerValues[$key . 'Secret'] ?? '';
$document->setAttribute('provider' . ucfirst($key) . 'Appid', $appId)->setAttribute('provider' . ucfirst($key) . 'Secret', $secret);
$projectProviders[] = new Document([
'name' => ucfirst($key),
'appId' => $providerValues[$key . 'Appid'] ?? '',
'secret' => $providerValues[$key . 'Secret'] ?? '',
'enabled' => $providerValues[$key . 'Enabled'] ?? false,
]);
}
$document->setAttribute("providers", $projectProviders);
return $document;
}
}

View file

@ -0,0 +1,60 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
class Provider extends Model
{
protected bool $public = false;
public function __construct()
{
$this
->addRule('name', [
'type' => self::TYPE_STRING,
'description' => 'Provider name.',
'default' => '',
'example' => 'GitHub',
])
->addRule('appId', [
'type' => self::TYPE_STRING,
'description' => 'OAuth 2.0 application ID.',
'default' => '',
'example' => '259125845563242502',
])
->addRule('secret', [
'type' => self::TYPE_STRING,
'description' => 'OAuth 2.0 application secret. Might be JSON string if provider requires extra configuration.',
'default' => '',
'example' => 'Bpw_g9c2TGXxfgLshDbSaL8tsCcqgczQ',
])
->addRule('enabled', [
'type' => self::TYPE_BOOLEAN,
'description' => 'Provider is active and can be used to create session.',
'example' => '',
])
;
}
/**
* Get Name
*
* @return string
*/
public function getName(): string
{
return 'Provider';
}
/**
* Get Type
*
* @return string
*/
public function getType(): string
{
return Response::MODEL_PROVIDER;
}
}

View file

@ -17,45 +17,45 @@ class UsageBuckets extends Model
'example' => '30d',
])
->addRule('filesCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of files in this bucket.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesStorage', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total storage of files in this bucket.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for files created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for files read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for files updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for files deleted.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
;

View file

@ -17,38 +17,38 @@ class UsageCollection extends Model
'example' => '30d',
])
->addRule('documentsCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of documents.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents deleted.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
;

View file

@ -17,73 +17,73 @@ class UsageDatabase extends Model
'example' => '30d',
])
->addRule('documentsCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of documents.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of collections.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents deleted.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for collections created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for collections read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for collections updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for collections delete.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
;

View file

@ -17,108 +17,108 @@ class UsageDatabases extends Model
'example' => '30d',
])
->addRule('databasesCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of documents.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of documents.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of collections.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('databasesCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('databasesRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('databasesUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('databasesDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of collections.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documentsDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for documents deleted.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for collections created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for collections read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for collections updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collectionsDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for collections delete.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
;

View file

@ -17,59 +17,59 @@ class UsageFunction extends Model
'example' => '30d',
])
->addRule('executionsTotal', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for number of function executions.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('executionsFailure', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function execution failures.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('executionsSuccess', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function execution successes.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('executionsTime', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function execution duration.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('buildsTotal', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for number of function builds.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('buildsFailure', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function build failures.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('buildsSuccess', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function build successes.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('buildsTime', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function build duration.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
;

View file

@ -17,59 +17,59 @@ class UsageFunctions extends Model
'example' => '30d',
])
->addRule('executionsTotal', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for number of function executions.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('executionsFailure', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function execution failures.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('executionsSuccess', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function execution successes.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('executionsTime', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function execution duration.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('buildsTotal', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for number of function builds.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('buildsFailure', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function build failures.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('buildsSuccess', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function build successes.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('buildsTime', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function build duration.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
;

View file

@ -17,52 +17,52 @@ class UsageProject extends Model
'example' => '30d',
])
->addRule('requests', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for number of requests.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('network', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for consumed bandwidth.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('executions', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for function executions.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('documents', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for number of documents.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('collections', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for number of collections.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('users', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for number of users.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('storage', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for the occupied storage size (in bytes).',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
;

View file

@ -17,80 +17,80 @@ class UsageStorage extends Model
'example' => '30d',
])
->addRule('storage', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for the occupied storage size (in bytes).',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of files.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('bucketsCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of buckets.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('bucketsCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for buckets created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('bucketsRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for buckets read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('bucketsUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for buckets updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('bucketsDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for buckets deleted.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for files created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for files read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for files updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('filesDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for files deleted.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
;

View file

@ -17,59 +17,59 @@ class UsageUsers extends Model
'example' => '30d',
])
->addRule('usersCount', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for total number of users.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('usersCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for users created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('usersRead', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for users read.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('usersUpdate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for users updated.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('usersDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for users deleted.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('sessionsCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for sessions created.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('sessionsProviderCreate', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for sessions created for a provider ( email, anonymous or oauth2 ).',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
->addRule('sessionsDelete', [
'type' => Response::MODEL_METRIC_LIST,
'type' => Response::MODEL_METRIC,
'description' => 'Aggregated stats for sessions deleted.',
'default' => [],
'example' => new \stdClass(),
'example' => [],
'array' => true
])
;

View file

@ -124,56 +124,33 @@ class HTTPTest extends Scope
$this->client->setEndpoint($previousEndpoint);
}
// public function testSpecSwagger2()
// {
// $response = $this->client->call(Client::METHOD_GET, '/specs/swagger2?platform=client', [
// 'content-type' => 'application/json',
// ], []);
// if(!file_put_contents(__DIR__ . '/../../resources/swagger2.json', json_encode($response['body']))) {
// throw new Exception('Failed to save spec file');
// }
// $client = new Client();
// $client->setEndpoint('https://validator.swagger.io');
// /**
// * Test for SUCCESS
// */
// $response = $client->call(Client::METHOD_POST, '/validator/debug', [
// 'content-type' => 'application/json',
// ], json_decode(file_get_contents(realpath(__DIR__ . '/../../resources/swagger2.json')), true));
// $response['body'] = json_decode($response['body'], true);
// $this->assertEquals(200, $response['headers']['status-code']);
// $this->assertTrue(empty($response['body']));
// unlink(realpath(__DIR__ . '/../../resources/swagger2.json'));
// }
public function testSpecOpenAPI3()
public function testSpecs()
{
$response = $this->client->call(Client::METHOD_GET, '/specs/open-api3?platform=console', [
'content-type' => 'application/json',
], []);
$directory = __DIR__ . '/../../../app/config/specs/';
$files = scandir($directory);
$client = new Client();
$client->setEndpoint('https://validator.swagger.io');
$versions = [
'latest',
'0.15.x',
'0.14.x',
];
foreach ($files as $file) {
if (in_array($file, ['.', '..'])) {
continue;
}
if (
(strpos($file, 'latest') === false) &&
(strpos($file, '0.12.x') === false) &&
(strpos($file, '0.13.x') === false)
) {
$allowed = false;
foreach ($versions as $version) {
if (\str_contains($file, $version)) {
$allowed = true;
break;
}
}
if (!$allowed) {
continue;
}
@ -186,7 +163,7 @@ class HTTPTest extends Scope
$response['body'] = json_decode($response['body'], true);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertTrue(empty($response['body']));
$this->assertEmpty($response['body']['schemaValidationMessages']);
}
}

View file

@ -550,6 +550,7 @@ class FunctionsCustomServerTest extends Scope
$this->assertIsArray($function['body']['deployments']);
$this->assertCount(2, $function['body']['deployments']);
$this->assertEquals($function['body']['deployments'][0]['$id'], $data['deploymentId']);
$this->assertGreaterThanOrEqual(2, $function['body']['deployments'][0]['buildTime']);
return $data;
}
@ -568,6 +569,7 @@ class FunctionsCustomServerTest extends Scope
], $this->getHeaders()));
$this->assertEquals(200, $function['headers']['status-code']);
$this->assertEquals(0, $function['body']['buildTime']);
/**
* Test for FAILURE

View file

@ -447,8 +447,61 @@ class ProjectsConsoleClientTest extends Scope
$this->assertEquals($id, $response['body']['$id']);
foreach ($providers as $key => $provider) {
$this->assertEquals('AppId-' . ucfirst($key), $response['body']['provider' . ucfirst($key) . 'Appid']);
$this->assertEquals('Secret-' . ucfirst($key), $response['body']['provider' . ucfirst($key) . 'Secret']);
$asserted = false;
foreach ($response['body']['providers'] as $responseProvider) {
if ($responseProvider['name'] === ucfirst($key)) {
$this->assertEquals('AppId-' . ucfirst($key), $responseProvider['appId']);
$this->assertEquals('Secret-' . ucfirst($key), $responseProvider['secret']);
$this->assertFalse($responseProvider['enabled']);
$asserted = true;
break;
}
}
$this->assertTrue($asserted);
}
// Enable providers
$i = 0;
foreach ($providers as $key => $provider) {
$response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/oauth2', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'provider' => $key,
'enabled' => $i === 0 ? false : true // On first provider, test enabled=false
]);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);
$i++;
}
$response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']);
$this->assertEquals($id, $response['body']['$id']);
$i = 0;
foreach ($providers as $key => $provider) {
$asserted = false;
foreach ($response['body']['providers'] as $responseProvider) {
if ($responseProvider['name'] === ucfirst($key)) {
// On first provider, test enabled=false
$this->assertEquals($i !== 0, $responseProvider['enabled']);
$asserted = true;
break;
}
}
$this->assertTrue($asserted);
$i++;
}
/**
@ -2333,4 +2386,83 @@ class ProjectsConsoleClientTest extends Scope
return $data;
}
public function testDeleteProject(): array
{
$data = [];
// Create a team and a project
$team = $this->client->call(Client::METHOD_POST, '/teams', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'teamId' => ID::unique(),
'name' => 'Amating Team',
]);
$this->assertEquals(201, $team['headers']['status-code']);
$this->assertEquals('Amating Team', $team['body']['name']);
$this->assertNotEmpty($team['body']['$id']);
$teamId = $team['body']['$id'];
$project = $this->client->call(Client::METHOD_POST, '/projects', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'projectId' => ID::unique(),
'name' => 'Amazing Project',
'teamId' => $teamId,
'region' => 'default'
]);
$this->assertEquals(201, $project['headers']['status-code']);
$this->assertEquals('Amazing Project', $project['body']['name']);
$this->assertEquals($teamId, $project['body']['teamId']);
$this->assertNotEmpty($project['body']['$id']);
$projectId = $project['body']['$id'];
// Ensure I can get both team and project
$team = $this->client->call(Client::METHOD_GET, '/teams/' . $teamId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
$this->assertEquals(200, $team['headers']['status-code']);
$project = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
$this->assertEquals(200, $project['headers']['status-code']);
// Delete team
$team = $this->client->call(Client::METHOD_DELETE, '/projects/' . $projectId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'password' => 'password'
]);
$this->assertEquals(204, $team['headers']['status-code']);
// Ensure I can get team but not a project
$team = $this->client->call(Client::METHOD_GET, '/teams/' . $teamId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
$this->assertEquals(200, $team['headers']['status-code']);
$project = $this->client->call(Client::METHOD_GET, '/projects/' . $projectId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
$this->assertEquals(404, $project['headers']['status-code']);
return $data;
}
}

View file

@ -926,6 +926,81 @@ trait UsersBase
return $data;
}
/**
* @depends testGetUser
*/
public function testUpdateUserNumber(array $data): array
{
/**
* Test for SUCCESS
*/
$updatedNumber = "+910000000000"; //dummy number
$user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/phone', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'number' => $updatedNumber,
]);
$this->assertEquals($user['headers']['status-code'], 200);
$this->assertEquals($user['body']['phone'], $updatedNumber);
$user = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
$this->assertEquals($user['headers']['status-code'], 200);
$this->assertEquals($user['body']['phone'], $updatedNumber);
/**
* Test for FAILURE
*/
$errorType = "user_phone_already_exists";
$user1Id = "user1";
$statusCodeForUserPhoneAlredyExists = 409;
// adding same number ($updatedNumber) to different user i.e user1
$response = $this->client->call(Client::METHOD_PATCH, '/users/' . $user1Id . '/phone', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'number' => $updatedNumber,
]);
$this->assertEquals($response['headers']['status-code'], $statusCodeForUserPhoneAlredyExists);
$this->assertNotEmpty($response['body']);
$this->assertEquals($response['body']['type'], $errorType);
return $data;
}
/**
* @depends testUpdateUserNumber
*/
public function testUpdateUserNumberSearch($data): void
{
$id = $data['userId'] ?? '';
$newNumber = "+910000000000"; //dummy number
/**
* Test for SUCCESS
*/
$response = $this->client->call(Client::METHOD_GET, '/users', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'search' => $newNumber,
]);
$this->assertEquals($response['headers']['status-code'], 200);
$this->assertNotEmpty($response['body']);
$this->assertNotEmpty($response['body']['users']);
$this->assertCount(1, $response['body']['users']);
$this->assertEquals($response['body']['users'][0]['$id'], $id);
$this->assertEquals($response['body']['users'][0]['phone'], $newNumber);
}
/**
* @depends testGetUser

View file

@ -10,6 +10,7 @@ use Utopia\Database\Role;
use Utopia\Database\Validator\Authorization;
use PHPUnit\Framework\TestCase;
use Utopia\Database\Database;
use Utopia\Database\Validator\Roles;
class AuthTest extends TestCase
{
@ -379,8 +380,8 @@ class AuthTest extends TestCase
$this->assertCount(11, $roles);
$this->assertContains(Role::users()->toString(), $roles);
$this->assertContains(Role::user(ID::custom('123'))->toString(), $roles);
$this->assertContains(Role::users(Database::DIMENSION_VERIFIED)->toString(), $roles);
$this->assertContains(Role::user(ID::custom('123'), Database::DIMENSION_VERIFIED)->toString(), $roles);
$this->assertContains(Role::users(Roles::DIMENSION_VERIFIED)->toString(), $roles);
$this->assertContains(Role::user(ID::custom('123'), Roles::DIMENSION_VERIFIED)->toString(), $roles);
$this->assertContains(Role::team(ID::custom('abc'))->toString(), $roles);
$this->assertContains(Role::team(ID::custom('abc'), 'administrator')->toString(), $roles);
$this->assertContains(Role::team(ID::custom('abc'), 'moderator')->toString(), $roles);
@ -394,15 +395,15 @@ class AuthTest extends TestCase
$user['phoneVerification'] = false;
$roles = Auth::getRoles($user);
$this->assertContains(Role::users(Database::DIMENSION_UNVERIFIED)->toString(), $roles);
$this->assertContains(Role::user(ID::custom('123'), Database::DIMENSION_UNVERIFIED)->toString(), $roles);
$this->assertContains(Role::users(Roles::DIMENSION_UNVERIFIED)->toString(), $roles);
$this->assertContains(Role::user(ID::custom('123'), Roles::DIMENSION_UNVERIFIED)->toString(), $roles);
// Enable single verification type
$user['emailVerification'] = true;
$roles = Auth::getRoles($user);
$this->assertContains(Role::users(Database::DIMENSION_VERIFIED)->toString(), $roles);
$this->assertContains(Role::user(ID::custom('123'), Database::DIMENSION_VERIFIED)->toString(), $roles);
$this->assertContains(Role::users(Roles::DIMENSION_VERIFIED)->toString(), $roles);
$this->assertContains(Role::user(ID::custom('123'), Roles::DIMENSION_VERIFIED)->toString(), $roles);
}
public function testPrivilegedUserRoles(): void
@ -438,8 +439,8 @@ class AuthTest extends TestCase
$this->assertCount(7, $roles);
$this->assertNotContains(Role::users()->toString(), $roles);
$this->assertNotContains(Role::user(ID::custom('123'))->toString(), $roles);
$this->assertNotContains(Role::users(Database::DIMENSION_VERIFIED)->toString(), $roles);
$this->assertNotContains(Role::user(ID::custom('123'), Database::DIMENSION_VERIFIED)->toString(), $roles);
$this->assertNotContains(Role::users(Roles::DIMENSION_VERIFIED)->toString(), $roles);
$this->assertNotContains(Role::user(ID::custom('123'), Roles::DIMENSION_VERIFIED)->toString(), $roles);
$this->assertContains(Role::team(ID::custom('abc'))->toString(), $roles);
$this->assertContains(Role::team(ID::custom('abc'), 'administrator')->toString(), $roles);
$this->assertContains(Role::team(ID::custom('abc'), 'moderator')->toString(), $roles);