Resolve merge conflicts
This commit is contained in:
commit
36fcc6c293
19 changed files with 212 additions and 100 deletions
145
.github/workflows/tests.yml
vendored
145
.github/workflows/tests.yml
vendored
|
@ -4,57 +4,118 @@ concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
IMAGE: appwrite-dev
|
||||||
|
CACHE_KEY: appwrite-dev-${{ github.event.pull_request.head.sha }}
|
||||||
|
|
||||||
on: [pull_request]
|
on: [pull_request]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
tests:
|
setup:
|
||||||
name: Unit & E2E
|
name: Setup & Build Appwrite Image
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Build Appwrite
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: false
|
||||||
|
tags: ${{ env.IMAGE }}
|
||||||
|
load: true
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
outputs: type=docker,dest=/tmp/${{ env.IMAGE }}.tar
|
||||||
|
build-args: |
|
||||||
|
DEBUG=false
|
||||||
|
TESTING=true
|
||||||
|
VERSION=dev
|
||||||
|
|
||||||
|
- name: Cache Docker Image
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
key: ${{ env.CACHE_KEY }}
|
||||||
|
path: /tmp/${{ env.IMAGE }}.tar
|
||||||
|
|
||||||
|
unit_test:
|
||||||
|
name: Unit Test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: setup
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v2
|
||||||
with:
|
|
||||||
# We must fetch at least the immediate parents so that if this is
|
|
||||||
# a pull request then we can checkout the head.
|
|
||||||
fetch-depth: 2
|
|
||||||
# Fetch submodules
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
# If this run was triggered by a pull request event, then checkout
|
- name: Load Cache
|
||||||
# the head of the pull request instead of the merge commit.
|
uses: actions/cache@v3
|
||||||
- run: git checkout HEAD^2
|
with:
|
||||||
if: ${{ github.event_name == 'pull_request' }}
|
key: ${{ env.CACHE_KEY }}
|
||||||
|
path: /tmp/${{ env.IMAGE }}.tar
|
||||||
|
fail-on-cache-miss: true
|
||||||
|
|
||||||
# This is a separate action that sets up buildx runner
|
- name: Load and Start Appwrite
|
||||||
- name: Set up Docker Buildx
|
run: |
|
||||||
uses: docker/setup-buildx-action@v2
|
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||||
|
docker compose up -d
|
||||||
|
sleep 10
|
||||||
|
|
||||||
- name: Build Appwrite
|
- name: Doctor
|
||||||
uses: docker/build-push-action@v3
|
run: docker compose exec -T appwrite doctor
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
push: false
|
|
||||||
tags: appwrite-dev
|
|
||||||
load: true
|
|
||||||
cache-from: type=gha
|
|
||||||
cache-to: type=gha,mode=max
|
|
||||||
build-args: |
|
|
||||||
DEBUG=false
|
|
||||||
TESTING=true
|
|
||||||
VERSION=dev
|
|
||||||
|
|
||||||
- name: Start Appwrite
|
- name: Environment Variables
|
||||||
run: |
|
run: docker compose exec -T appwrite vars
|
||||||
docker compose up -d
|
|
||||||
sleep 30
|
|
||||||
|
|
||||||
- name: Doctor
|
- name: Run Unit Tests
|
||||||
run: |
|
run: docker compose exec appwrite test /usr/src/code/tests/unit
|
||||||
docker compose logs appwrite
|
|
||||||
docker compose exec -T appwrite doctor
|
|
||||||
|
|
||||||
- name: Environment Variables
|
e2e_test:
|
||||||
run: docker compose exec -T appwrite vars
|
name: E2E Test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: setup
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
service:
|
||||||
|
[
|
||||||
|
Account,
|
||||||
|
Avatars,
|
||||||
|
Console,
|
||||||
|
Databases,
|
||||||
|
Functions,
|
||||||
|
GraphQL,
|
||||||
|
Health,
|
||||||
|
Locale,
|
||||||
|
Projects,
|
||||||
|
Realtime,
|
||||||
|
Storage,
|
||||||
|
Teams,
|
||||||
|
Users,
|
||||||
|
Webhooks,
|
||||||
|
]
|
||||||
|
|
||||||
- name: Run Tests
|
steps:
|
||||||
run: docker compose exec -T appwrite test --debug
|
- name: checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Load Cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
key: ${{ env.CACHE_KEY }}
|
||||||
|
path: /tmp/${{ env.IMAGE }}.tar
|
||||||
|
fail-on-cache-miss: true
|
||||||
|
|
||||||
|
- name: Load and Start Appwrite
|
||||||
|
run: |
|
||||||
|
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||||
|
docker compose up -d
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
- name: Run ${{matrix.service}} Tests
|
||||||
|
run: docker compose exec -T appwrite test /usr/src/code/tests/e2e/Services/${{matrix.service}} --debug
|
2
.gitmodules
vendored
2
.gitmodules
vendored
|
@ -1,4 +1,4 @@
|
||||||
[submodule "app/console"]
|
[submodule "app/console"]
|
||||||
path = app/console
|
path = app/console
|
||||||
url = https://github.com/appwrite/console
|
url = https://github.com/appwrite/console
|
||||||
branch = 3.2.3
|
branch = 3.2.4
|
||||||
|
|
|
@ -8,7 +8,7 @@ tasks:
|
||||||
command: |
|
command: |
|
||||||
docker run --rm --interactive --tty \
|
docker run --rm --interactive --tty \
|
||||||
--volume $PWD:/app \
|
--volume $PWD:/app \
|
||||||
composer update \
|
composer install \
|
||||||
--ignore-platform-reqs \
|
--ignore-platform-reqs \
|
||||||
--optimize-autoloader \
|
--optimize-autoloader \
|
||||||
--no-plugins \
|
--no-plugins \
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
# Version 1.4.7
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fix missing body in async function execution in [#6988](https://github.com/appwrite/appwrite/pull/6988)
|
||||||
|
|
||||||
# Version 1.4.6
|
# Version 1.4.6
|
||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
|
|
|
@ -89,7 +89,7 @@ $ git push origin [name_of_your_new_branch]
|
||||||
|
|
||||||
To set up a working **development environment**, just fork the project git repository and install the backend and frontend dependencies using the proper package manager and create run the docker-compose stack.
|
To set up a working **development environment**, just fork the project git repository and install the backend and frontend dependencies using the proper package manager and create run the docker-compose stack.
|
||||||
|
|
||||||
> If you just want to install Appwrite for day-to-day use and not as a contributor, you can reference the [installation guide](https://github.com/appwrite/appwrite#installation), the [getting started guide](https://appwrite.io/docs/getting-started-for-web), or the main [README](README.md) file.
|
> If you just want to install Appwrite for day-to-day use and not as a contributor, you can reference the [installation guide](https://github.com/appwrite/appwrite#installation), the [getting started guide](https://appwrite.io/docs/quick-starts), or the main [README](README.md) file.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone git@github.com:[YOUR_FORK_HERE]/appwrite.git
|
git clone git@github.com:[YOUR_FORK_HERE]/appwrite.git
|
||||||
|
@ -454,7 +454,7 @@ From time to time, our team will add tutorials that will help contributors find
|
||||||
|
|
||||||
- [Adding Support for a New OAuth2 Provider](./docs/tutorials/add-oauth2-provider.md)
|
- [Adding Support for a New OAuth2 Provider](./docs/tutorials/add-oauth2-provider.md)
|
||||||
- [Appwrite Environment Variables](./docs/tutorials/add-environment-variable.md)
|
- [Appwrite Environment Variables](./docs/tutorials/add-environment-variable.md)
|
||||||
- [Running in Production](https://appwrite.io/docs/production)
|
- [Running in Production](https://appwrite.io/docs/advanced/self-hosting/production)
|
||||||
- [Adding Storage Adapter](./docs/tutorials/add-storage-adapter.md)
|
- [Adding Storage Adapter](./docs/tutorials/add-storage-adapter.md)
|
||||||
|
|
||||||
## Other Ways to Help
|
## Other Ways to Help
|
||||||
|
|
|
@ -66,7 +66,7 @@ docker run -it --rm \
|
||||||
--volume /var/run/docker.sock:/var/run/docker.sock \
|
--volume /var/run/docker.sock:/var/run/docker.sock \
|
||||||
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
|
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
|
||||||
--entrypoint="install" \
|
--entrypoint="install" \
|
||||||
appwrite/appwrite:1.4.6
|
appwrite/appwrite:1.4.7
|
||||||
```
|
```
|
||||||
|
|
||||||
### Windows
|
### Windows
|
||||||
|
@ -78,7 +78,7 @@ docker run -it --rm ^
|
||||||
--volume //var/run/docker.sock:/var/run/docker.sock ^
|
--volume //var/run/docker.sock:/var/run/docker.sock ^
|
||||||
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
|
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
|
||||||
--entrypoint="install" ^
|
--entrypoint="install" ^
|
||||||
appwrite/appwrite:1.4.6
|
appwrite/appwrite:1.4.7
|
||||||
```
|
```
|
||||||
|
|
||||||
#### PowerShell
|
#### PowerShell
|
||||||
|
@ -88,7 +88,7 @@ docker run -it --rm `
|
||||||
--volume /var/run/docker.sock:/var/run/docker.sock `
|
--volume /var/run/docker.sock:/var/run/docker.sock `
|
||||||
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw `
|
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw `
|
||||||
--entrypoint="install" `
|
--entrypoint="install" `
|
||||||
appwrite/appwrite:1.4.6
|
appwrite/appwrite:1.4.7
|
||||||
```
|
```
|
||||||
|
|
||||||
运行后,可以在浏览器上访问 http://localhost 找到 Appwrite 控制台。在非 Linux 的本机主机上完成安装后,服务器可能需要几分钟才能启动。
|
运行后,可以在浏览器上访问 http://localhost 找到 Appwrite 控制台。在非 Linux 的本机主机上完成安装后,服务器可能需要几分钟才能启动。
|
||||||
|
|
|
@ -65,7 +65,7 @@ Table of Contents:
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Appwrite is designed to run in a containerized environment. Running your server is as easy as running one command from your terminal. You can either run Appwrite on your localhost using docker-compose or on any other container orchestration tool, such as Kubernetes, Docker Swarm, or Rancher.
|
Appwrite is designed to run in a containerized environment. Running your server is as easy as running one command from your terminal. You can either run Appwrite on your localhost using docker-compose or on any other container orchestration tool, such as [Kubernetes](https://kubernetes.io/docs/home/), [Docker Swarm](https://docs.docker.com/engine/swarm/), or [Rancher](https://rancher.com/docs/).
|
||||||
|
|
||||||
The easiest way to start running your Appwrite server is by running our docker-compose file. Before running the installation command, make sure you have [Docker](https://www.docker.com/products/docker-desktop) installed on your machine:
|
The easiest way to start running your Appwrite server is by running our docker-compose file. Before running the installation command, make sure you have [Docker](https://www.docker.com/products/docker-desktop) installed on your machine:
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ docker run -it --rm \
|
||||||
--volume /var/run/docker.sock:/var/run/docker.sock \
|
--volume /var/run/docker.sock:/var/run/docker.sock \
|
||||||
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
|
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
|
||||||
--entrypoint="install" \
|
--entrypoint="install" \
|
||||||
appwrite/appwrite:1.4.6
|
appwrite/appwrite:1.4.7
|
||||||
```
|
```
|
||||||
|
|
||||||
### Windows
|
### Windows
|
||||||
|
@ -88,7 +88,7 @@ docker run -it --rm ^
|
||||||
--volume //var/run/docker.sock:/var/run/docker.sock ^
|
--volume //var/run/docker.sock:/var/run/docker.sock ^
|
||||||
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
|
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
|
||||||
--entrypoint="install" ^
|
--entrypoint="install" ^
|
||||||
appwrite/appwrite:1.4.6
|
appwrite/appwrite:1.4.7
|
||||||
```
|
```
|
||||||
|
|
||||||
#### PowerShell
|
#### PowerShell
|
||||||
|
@ -98,7 +98,7 @@ docker run -it --rm `
|
||||||
--volume /var/run/docker.sock:/var/run/docker.sock `
|
--volume /var/run/docker.sock:/var/run/docker.sock `
|
||||||
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw `
|
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw `
|
||||||
--entrypoint="install" `
|
--entrypoint="install" `
|
||||||
appwrite/appwrite:1.4.6
|
appwrite/appwrite:1.4.7
|
||||||
```
|
```
|
||||||
|
|
||||||
Once the Docker installation is complete, 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 completing the installation.
|
Once the Docker installation is complete, 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 completing the installation.
|
||||||
|
|
|
@ -86,7 +86,7 @@ return [
|
||||||
Exception::GENERAL_PROTOCOL_UNSUPPORTED => [
|
Exception::GENERAL_PROTOCOL_UNSUPPORTED => [
|
||||||
'name' => Exception::GENERAL_PROTOCOL_UNSUPPORTED,
|
'name' => Exception::GENERAL_PROTOCOL_UNSUPPORTED,
|
||||||
'description' => 'The request cannot be fulfilled with the current protocol. Please check the value of the _APP_OPTIONS_FORCE_HTTPS environment variable.',
|
'description' => 'The request cannot be fulfilled with the current protocol. Please check the value of the _APP_OPTIONS_FORCE_HTTPS environment variable.',
|
||||||
'code' => 500,
|
'code' => 426,
|
||||||
],
|
],
|
||||||
Exception::GENERAL_CODES_DISABLED => [
|
Exception::GENERAL_CODES_DISABLED => [
|
||||||
'name' => Exception::GENERAL_CODES_DISABLED,
|
'name' => Exception::GENERAL_CODES_DISABLED,
|
||||||
|
@ -732,4 +732,21 @@ return [
|
||||||
'description' => 'Migration is already in progress. You can check the status of the migration in your Appwrite Console\'s "Settings" > "Migrations".',
|
'description' => 'Migration is already in progress. You can check the status of the migration in your Appwrite Console\'s "Settings" > "Migrations".',
|
||||||
'code' => 409,
|
'code' => 409,
|
||||||
],
|
],
|
||||||
|
|
||||||
|
/** Realtime */
|
||||||
|
Exception::REALTIME_MESSAGE_FORMAT_INVALID => [
|
||||||
|
'name' => Exception::REALTIME_MESSAGE_FORMAT_INVALID,
|
||||||
|
'description' => 'Message format is not valid.',
|
||||||
|
'code' => 1003,
|
||||||
|
],
|
||||||
|
Exception::REALTIME_POLICY_VIOLATION => [
|
||||||
|
'name' => Exception::REALTIME_POLICY_VIOLATION,
|
||||||
|
'description' => 'Policy violation.',
|
||||||
|
'code' => 1008,
|
||||||
|
],
|
||||||
|
Exception::REALTIME_TOO_MANY_MESSAGES => [
|
||||||
|
'name' => Exception::REALTIME_TOO_MANY_MESSAGES,
|
||||||
|
'description' => 'Too many messages.',
|
||||||
|
'code' => 1013,
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
|
@ -110,7 +110,7 @@ const APP_KEY_ACCCESS = 24 * 60 * 60; // 24 hours
|
||||||
const APP_USER_ACCCESS = 24 * 60 * 60; // 24 hours
|
const APP_USER_ACCCESS = 24 * 60 * 60; // 24 hours
|
||||||
const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours
|
const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours
|
||||||
const APP_CACHE_BUSTER = 514;
|
const APP_CACHE_BUSTER = 514;
|
||||||
const APP_VERSION_STABLE = '1.4.6';
|
const APP_VERSION_STABLE = '1.4.7';
|
||||||
const APP_DATABASE_ATTRIBUTE_EMAIL = 'email';
|
const APP_DATABASE_ATTRIBUTE_EMAIL = 'email';
|
||||||
const APP_DATABASE_ATTRIBUTE_ENUM = 'enum';
|
const APP_DATABASE_ATTRIBUTE_ENUM = 'enum';
|
||||||
const APP_DATABASE_ATTRIBUTE_IP = 'ip';
|
const APP_DATABASE_ATTRIBUTE_IP = 'ip';
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Appwrite\Auth\Auth;
|
use Appwrite\Auth\Auth;
|
||||||
|
use Appwrite\Extend\Exception;
|
||||||
use Appwrite\Messaging\Adapter\Realtime;
|
use Appwrite\Messaging\Adapter\Realtime;
|
||||||
use Appwrite\Network\Validator\Origin;
|
use Appwrite\Network\Validator\Origin;
|
||||||
|
use Appwrite\Utopia\Request;
|
||||||
use Appwrite\Utopia\Response;
|
use Appwrite\Utopia\Response;
|
||||||
use Swoole\Http\Request as SwooleRequest;
|
use Swoole\Http\Request as SwooleRequest;
|
||||||
use Swoole\Http\Response as SwooleResponse;
|
use Swoole\Http\Response as SwooleResponse;
|
||||||
|
@ -20,7 +22,6 @@ use Utopia\Database\DateTime;
|
||||||
use Utopia\Database\Document;
|
use Utopia\Database\Document;
|
||||||
use Utopia\Database\Query;
|
use Utopia\Database\Query;
|
||||||
use Utopia\Database\Validator\Authorization;
|
use Utopia\Database\Validator\Authorization;
|
||||||
use Appwrite\Utopia\Request;
|
|
||||||
use Utopia\Cache\Adapter\Sharding;
|
use Utopia\Cache\Adapter\Sharding;
|
||||||
use Utopia\Cache\Cache;
|
use Utopia\Cache\Cache;
|
||||||
use Utopia\Config\Config;
|
use Utopia\Config\Config;
|
||||||
|
@ -28,6 +29,9 @@ use Utopia\Database\Database;
|
||||||
use Utopia\WebSocket\Server;
|
use Utopia\WebSocket\Server;
|
||||||
use Utopia\WebSocket\Adapter;
|
use Utopia\WebSocket\Adapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Utopia\Registry\Registry $register
|
||||||
|
*/
|
||||||
require_once __DIR__ . '/init.php';
|
require_once __DIR__ . '/init.php';
|
||||||
|
|
||||||
Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
|
Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
|
||||||
|
@ -122,12 +126,12 @@ $server = new Server($adapter);
|
||||||
$logError = function (Throwable $error, string $action) use ($register) {
|
$logError = function (Throwable $error, string $action) use ($register) {
|
||||||
$logger = $register->get('logger');
|
$logger = $register->get('logger');
|
||||||
|
|
||||||
if ($logger) {
|
if ($logger && !$error instanceof Exception) {
|
||||||
$version = App::getEnv('_APP_VERSION', 'UNKNOWN');
|
$version = App::getEnv('_APP_VERSION', 'UNKNOWN');
|
||||||
|
|
||||||
$log = new Log();
|
$log = new Log();
|
||||||
$log->setNamespace("realtime");
|
$log->setNamespace("realtime");
|
||||||
$log->setServer(\gethostname());
|
$log->setServer(gethostname());
|
||||||
$log->setVersion($version);
|
$log->setVersion($version);
|
||||||
$log->setType(Log::TYPE_ERROR);
|
$log->setType(Log::TYPE_ERROR);
|
||||||
$log->setMessage($error->getMessage());
|
$log->setMessage($error->getMessage());
|
||||||
|
@ -182,7 +186,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume
|
||||||
|
|
||||||
$statsDocument = Authorization::skip(fn () => $database->createDocument('realtime', $document));
|
$statsDocument = Authorization::skip(fn () => $database->createDocument('realtime', $document));
|
||||||
break;
|
break;
|
||||||
} catch (\Throwable $th) {
|
} catch (Throwable) {
|
||||||
Console::warning("Collection not ready. Retrying connection ({$attempts})...");
|
Console::warning("Collection not ready. Retrying connection ({$attempts})...");
|
||||||
sleep(DATABASE_RECONNECT_SLEEP);
|
sleep(DATABASE_RECONNECT_SLEEP);
|
||||||
}
|
}
|
||||||
|
@ -210,7 +214,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume
|
||||||
->setAttribute('value', json_encode($payload));
|
->setAttribute('value', json_encode($payload));
|
||||||
|
|
||||||
Authorization::skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument));
|
Authorization::skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument));
|
||||||
} catch (\Throwable $th) {
|
} catch (Throwable $th) {
|
||||||
call_user_func($logError, $th, "updateWorkerDocument");
|
call_user_func($logError, $th, "updateWorkerDocument");
|
||||||
} finally {
|
} finally {
|
||||||
$register->get('pools')->reclaim();
|
$register->get('pools')->reclaim();
|
||||||
|
@ -362,7 +366,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
|
||||||
$stats->incr($event['project'], 'messages', $num);
|
$stats->incr($event['project'], 'messages', $num);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (\Throwable $th) {
|
} catch (Throwable $th) {
|
||||||
call_user_func($logError, $th, "pubSubConnection");
|
call_user_func($logError, $th, "pubSubConnection");
|
||||||
|
|
||||||
Console::error('Pub/sub error: ' . $th->getMessage());
|
Console::error('Pub/sub error: ' . $th->getMessage());
|
||||||
|
@ -389,19 +393,19 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
||||||
App::setResource('response', fn() => $response);
|
App::setResource('response', fn() => $response);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
/** @var \Utopia\Database\Document $project */
|
/** @var Document $project */
|
||||||
$project = $app->getResource('project');
|
$project = $app->getResource('project');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Project Check
|
* Project Check
|
||||||
*/
|
*/
|
||||||
if (empty($project->getId())) {
|
if (empty($project->getId())) {
|
||||||
throw new Exception('Missing or unknown project ID', 1008);
|
throw new Exception(Exception::REALTIME_POLICY_VIOLATION, 'Missing or unknown project ID');
|
||||||
}
|
}
|
||||||
|
|
||||||
$dbForProject = getProjectDB($project);
|
$dbForProject = getProjectDB($project);
|
||||||
$console = $app->getResource('console'); /** @var \Utopia\Database\Document $console */
|
$console = $app->getResource('console'); /** @var Document $console */
|
||||||
$user = $app->getResource('user'); /** @var \Utopia\Database\Document $user */
|
$user = $app->getResource('user'); /** @var Document $user */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Abuse Check
|
* Abuse Check
|
||||||
|
@ -416,7 +420,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
||||||
$abuse = new Abuse($timeLimit);
|
$abuse = new Abuse($timeLimit);
|
||||||
|
|
||||||
if (App::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled' && $abuse->check()) {
|
if (App::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled' && $abuse->check()) {
|
||||||
throw new Exception('Too many requests', 1013);
|
throw new Exception(Exception::REALTIME_TOO_MANY_MESSAGES, 'Too many requests');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -425,10 +429,10 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
||||||
* Skip this check for non-web platforms which are not required to send an origin header.
|
* Skip this check for non-web platforms which are not required to send an origin header.
|
||||||
*/
|
*/
|
||||||
$origin = $request->getOrigin();
|
$origin = $request->getOrigin();
|
||||||
$originValidator = new Origin(\array_merge($project->getAttribute('platforms', []), $console->getAttribute('platforms', [])));
|
$originValidator = new Origin(array_merge($project->getAttribute('platforms', []), $console->getAttribute('platforms', [])));
|
||||||
|
|
||||||
if (!$originValidator->isValid($origin) && $project->getId() !== 'console') {
|
if (!$originValidator->isValid($origin) && $project->getId() !== 'console') {
|
||||||
throw new Exception($originValidator->getDescription(), 1008);
|
throw new Exception(Exception::REALTIME_POLICY_VIOLATION, $originValidator->getDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
$roles = Auth::getRoles($user);
|
$roles = Auth::getRoles($user);
|
||||||
|
@ -439,7 +443,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
||||||
* Channels Check
|
* Channels Check
|
||||||
*/
|
*/
|
||||||
if (empty($channels)) {
|
if (empty($channels)) {
|
||||||
throw new Exception('Missing channels', 1008);
|
throw new Exception(Exception::REALTIME_POLICY_VIOLATION, 'Missing channels');
|
||||||
}
|
}
|
||||||
|
|
||||||
$realtime->subscribe($project->getId(), $connection, $roles, $channels);
|
$realtime->subscribe($project->getId(), $connection, $roles, $channels);
|
||||||
|
@ -460,7 +464,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
||||||
]);
|
]);
|
||||||
$stats->incr($project->getId(), 'connections');
|
$stats->incr($project->getId(), 'connections');
|
||||||
$stats->incr($project->getId(), 'connectionsTotal');
|
$stats->incr($project->getId(), 'connectionsTotal');
|
||||||
} catch (\Throwable $th) {
|
} catch (Throwable $th) {
|
||||||
call_user_func($logError, $th, "initServer");
|
call_user_func($logError, $th, "initServer");
|
||||||
|
|
||||||
$response = [
|
$response = [
|
||||||
|
@ -486,7 +490,6 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
||||||
|
|
||||||
$server->onMessage(function (int $connection, string $message) use ($server, $register, $realtime, $containerId) {
|
$server->onMessage(function (int $connection, string $message) use ($server, $register, $realtime, $containerId) {
|
||||||
try {
|
try {
|
||||||
$app = new App('UTC');
|
|
||||||
$response = new Response(new SwooleResponse());
|
$response = new Response(new SwooleResponse());
|
||||||
$projectId = $realtime->connections[$connection]['projectId'];
|
$projectId = $realtime->connections[$connection]['projectId'];
|
||||||
$database = getConsoleDB();
|
$database = getConsoleDB();
|
||||||
|
@ -494,6 +497,8 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re
|
||||||
if ($projectId !== 'console') {
|
if ($projectId !== 'console') {
|
||||||
$project = Authorization::skip(fn() => $database->getDocument('projects', $projectId));
|
$project = Authorization::skip(fn() => $database->getDocument('projects', $projectId));
|
||||||
$database = getProjectDB($project);
|
$database = getProjectDB($project);
|
||||||
|
} else {
|
||||||
|
$project = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -510,22 +515,22 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re
|
||||||
$abuse = new Abuse($timeLimit);
|
$abuse = new Abuse($timeLimit);
|
||||||
|
|
||||||
if ($abuse->check() && App::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') {
|
if ($abuse->check() && App::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') {
|
||||||
throw new Exception('Too many messages', 1013);
|
throw new Exception(Exception::REALTIME_TOO_MANY_MESSAGES, 'Too many messages.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$message = json_decode($message, true);
|
$message = json_decode($message, true);
|
||||||
|
|
||||||
if (is_null($message) || (!array_key_exists('type', $message) && !array_key_exists('data', $message))) {
|
if (is_null($message) || (!array_key_exists('type', $message) && !array_key_exists('data', $message))) {
|
||||||
throw new Exception('Message format is not valid.', 1003);
|
throw new Exception(Exception::REALTIME_MESSAGE_FORMAT_INVALID, 'Message format is not valid.');
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($message['type']) {
|
switch ($message['type']) {
|
||||||
/**
|
/**
|
||||||
* This type is used to authenticate.
|
* This type is used to authenticate.
|
||||||
*/
|
*/
|
||||||
case 'authentication':
|
case 'authentication':
|
||||||
if (!array_key_exists('session', $message['data'])) {
|
if (!array_key_exists('session', $message['data'])) {
|
||||||
throw new Exception('Payload is not valid.', 1003);
|
throw new Exception(Exception::REALTIME_MESSAGE_FORMAT_INVALID, 'Payload is not valid.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$session = Auth::decodeSession($message['data']['session']);
|
$session = Auth::decodeSession($message['data']['session']);
|
||||||
|
@ -540,7 +545,7 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re
|
||||||
|| !Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret, $authDuration) // Validate user has valid login token
|
|| !Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret, $authDuration) // Validate user has valid login token
|
||||||
) {
|
) {
|
||||||
// cookie not valid
|
// cookie not valid
|
||||||
throw new Exception('Session is not valid.', 1003);
|
throw new Exception(Exception::REALTIME_MESSAGE_FORMAT_INVALID, 'Session is not valid.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$roles = Auth::getRoles($user);
|
$roles = Auth::getRoles($user);
|
||||||
|
@ -560,9 +565,9 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Exception('Message type is not valid.', 1003);
|
throw new Exception(Exception::REALTIME_MESSAGE_FORMAT_INVALID, 'Message type is not valid.');
|
||||||
}
|
}
|
||||||
} catch (\Throwable $th) {
|
} catch (Throwable $th) {
|
||||||
$response = [
|
$response = [
|
||||||
'type' => 'error',
|
'type' => 'error',
|
||||||
'data' => [
|
'data' => [
|
||||||
|
|
|
@ -36,7 +36,6 @@ use Utopia\Queue\Connection;
|
||||||
Authorization::disable();
|
Authorization::disable();
|
||||||
Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
|
Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
|
||||||
|
|
||||||
|
|
||||||
Server::setResource('register', fn () => $register);
|
Server::setResource('register', fn () => $register);
|
||||||
|
|
||||||
Server::setResource('dbForConsole', function (Cache $cache, Registry $register) {
|
Server::setResource('dbForConsole', function (Cache $cache, Registry $register) {
|
||||||
|
|
|
@ -64,7 +64,7 @@
|
||||||
"utopia-php/preloader": "0.2.*",
|
"utopia-php/preloader": "0.2.*",
|
||||||
"utopia-php/queue": "0.5.*",
|
"utopia-php/queue": "0.5.*",
|
||||||
"utopia-php/registry": "0.5.*",
|
"utopia-php/registry": "0.5.*",
|
||||||
"utopia-php/storage": "0.17.*",
|
"utopia-php/storage": "0.18.*",
|
||||||
"utopia-php/swoole": "0.5.*",
|
"utopia-php/swoole": "0.5.*",
|
||||||
"utopia-php/vcs": "0.6.*",
|
"utopia-php/vcs": "0.6.*",
|
||||||
"utopia-php/websocket": "0.1.*",
|
"utopia-php/websocket": "0.1.*",
|
||||||
|
|
30
composer.lock
generated
30
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "e1face7cebc5b79288c93a04e1f98521",
|
"content-hash": "06c2610579f319495ea7d2d28f42d376",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "adhocore/jwt",
|
"name": "adhocore/jwt",
|
||||||
|
@ -1906,16 +1906,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "utopia-php/database",
|
"name": "utopia-php/database",
|
||||||
"version": "0.44.2",
|
"version": "0.44.4",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/utopia-php/database.git",
|
"url": "https://github.com/utopia-php/database.git",
|
||||||
"reference": "591cadbc2c622a3304aae9a16ebfdbe75ef33a06"
|
"reference": "b0c3fd8ecfedc3646d7780f2d6b38955a66baf48"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/591cadbc2c622a3304aae9a16ebfdbe75ef33a06",
|
"url": "https://api.github.com/repos/utopia-php/database/zipball/b0c3fd8ecfedc3646d7780f2d6b38955a66baf48",
|
||||||
"reference": "591cadbc2c622a3304aae9a16ebfdbe75ef33a06",
|
"reference": "b0c3fd8ecfedc3646d7780f2d6b38955a66baf48",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -1928,7 +1928,7 @@
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fakerphp/faker": "^1.14",
|
"fakerphp/faker": "^1.14",
|
||||||
"laravel/pint": "1.4.*",
|
"laravel/pint": "1.13.*",
|
||||||
"pcov/clobber": "^2.0",
|
"pcov/clobber": "^2.0",
|
||||||
"phpstan/phpstan": "1.10.*",
|
"phpstan/phpstan": "1.10.*",
|
||||||
"phpunit/phpunit": "^9.4",
|
"phpunit/phpunit": "^9.4",
|
||||||
|
@ -1956,9 +1956,9 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/utopia-php/database/issues",
|
"issues": "https://github.com/utopia-php/database/issues",
|
||||||
"source": "https://github.com/utopia-php/database/tree/0.44.2"
|
"source": "https://github.com/utopia-php/database/tree/0.44.4"
|
||||||
},
|
},
|
||||||
"time": "2023-10-19T07:39:00+00:00"
|
"time": "2023-10-26T07:08:12+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "utopia-php/domains",
|
"name": "utopia-php/domains",
|
||||||
|
@ -2742,16 +2742,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "utopia-php/storage",
|
"name": "utopia-php/storage",
|
||||||
"version": "0.17.0",
|
"version": "0.18.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/utopia-php/storage.git",
|
"url": "https://github.com/utopia-php/storage.git",
|
||||||
"reference": "efec5376c02d3d8330f1beb1469e6d6e313e21ee"
|
"reference": "983e6dee137012f9f57f126d3c79aab54e4e8824"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/utopia-php/storage/zipball/efec5376c02d3d8330f1beb1469e6d6e313e21ee",
|
"url": "https://api.github.com/repos/utopia-php/storage/zipball/983e6dee137012f9f57f126d3c79aab54e4e8824",
|
||||||
"reference": "efec5376c02d3d8330f1beb1469e6d6e313e21ee",
|
"reference": "983e6dee137012f9f57f126d3c79aab54e4e8824",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -2791,9 +2791,9 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/utopia-php/storage/issues",
|
"issues": "https://github.com/utopia-php/storage/issues",
|
||||||
"source": "https://github.com/utopia-php/storage/tree/0.17.0"
|
"source": "https://github.com/utopia-php/storage/tree/0.18.1"
|
||||||
},
|
},
|
||||||
"time": "2023-08-21T11:28:36+00:00"
|
"time": "2023-10-24T14:44:19+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "utopia-php/swoole",
|
"name": "utopia-php/swoole",
|
||||||
|
@ -5822,5 +5822,5 @@
|
||||||
"platform-overrides": {
|
"platform-overrides": {
|
||||||
"php": "8.0"
|
"php": "8.0"
|
||||||
},
|
},
|
||||||
"plugin-api-version": "2.3.0"
|
"plugin-api-version": "2.6.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -225,8 +225,13 @@ class Exception extends \Exception
|
||||||
public const MIGRATION_ALREADY_EXISTS = 'migration_already_exists';
|
public const MIGRATION_ALREADY_EXISTS = 'migration_already_exists';
|
||||||
public const MIGRATION_IN_PROGRESS = 'migration_in_progress';
|
public const MIGRATION_IN_PROGRESS = 'migration_in_progress';
|
||||||
|
|
||||||
protected $type = '';
|
/** Realtime */
|
||||||
protected $errors = [];
|
public const REALTIME_MESSAGE_FORMAT_INVALID = 'realtime_message_format_invalid';
|
||||||
|
public const REALTIME_TOO_MANY_MESSAGES = 'realtime_too_many_messages';
|
||||||
|
public const REALTIME_POLICY_VIOLATION = 'realtime_policy_violation';
|
||||||
|
|
||||||
|
protected string $type = '';
|
||||||
|
protected array $errors = [];
|
||||||
|
|
||||||
public function __construct(string $type = Exception::GENERAL_UNKNOWN, string $message = null, int $code = null, \Throwable $previous = null)
|
public function __construct(string $type = Exception::GENERAL_UNKNOWN, string $message = null, int $code = null, \Throwable $previous = null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -71,6 +71,7 @@ abstract class Migration
|
||||||
'1.4.4' => 'V19',
|
'1.4.4' => 'V19',
|
||||||
'1.4.5' => 'V19',
|
'1.4.5' => 'V19',
|
||||||
'1.4.6' => 'V19',
|
'1.4.6' => 'V19',
|
||||||
|
'1.4.7' => 'V19',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -77,7 +77,7 @@ class Functions extends Action
|
||||||
|
|
||||||
$type = $payload['type'] ?? '';
|
$type = $payload['type'] ?? '';
|
||||||
$events = $payload['events'] ?? [];
|
$events = $payload['events'] ?? [];
|
||||||
$data = $payload['data'] ?? '';
|
$data = $payload['body'] ?? '';
|
||||||
$eventData = $payload['payload'] ?? '';
|
$eventData = $payload['payload'] ?? '';
|
||||||
$project = new Document($payload['project'] ?? []);
|
$project = new Document($payload['project'] ?? []);
|
||||||
$function = new Document($payload['function'] ?? []);
|
$function = new Document($payload['function'] ?? []);
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace Tests\E2E\Services\GraphQL;
|
namespace Tests\E2E\Services\GraphQL;
|
||||||
|
|
||||||
|
use Utopia\CLI\Console;
|
||||||
|
|
||||||
trait Base
|
trait Base
|
||||||
{
|
{
|
||||||
// Databases
|
// Databases
|
||||||
|
@ -1933,4 +1935,13 @@ trait Base
|
||||||
|
|
||||||
throw new \InvalidArgumentException('Invalid query type');
|
throw new \InvalidArgumentException('Invalid query type');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function-related methods
|
||||||
|
protected string $stdout = '';
|
||||||
|
protected string $stderr = '';
|
||||||
|
|
||||||
|
protected function packageCode($folder)
|
||||||
|
{
|
||||||
|
Console::execute('cd ' . realpath(__DIR__ . "/../../../resources/functions") . "/$folder && tar --exclude code.tar.gz -czf code.tar.gz .", '', $this->stdout, $this->stderr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,11 @@ class FunctionsClientTest extends Scope
|
||||||
{
|
{
|
||||||
$projectId = $this->getProject()['$id'];
|
$projectId = $this->getProject()['$id'];
|
||||||
$query = $this->getQuery(self::$CREATE_DEPLOYMENT);
|
$query = $this->getQuery(self::$CREATE_DEPLOYMENT);
|
||||||
$code = realpath(__DIR__ . '/../../../resources/functions') . "/php/code.tar.gz";
|
|
||||||
|
$folder = 'php';
|
||||||
|
$code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz";
|
||||||
|
$this->packageCode($folder);
|
||||||
|
|
||||||
$gqlPayload = [
|
$gqlPayload = [
|
||||||
'operations' => \json_encode([
|
'operations' => \json_encode([
|
||||||
'query' => $query,
|
'query' => $query,
|
||||||
|
|
|
@ -81,7 +81,11 @@ class FunctionsServerTest extends Scope
|
||||||
{
|
{
|
||||||
$projectId = $this->getProject()['$id'];
|
$projectId = $this->getProject()['$id'];
|
||||||
$query = $this->getQuery(self::$CREATE_DEPLOYMENT);
|
$query = $this->getQuery(self::$CREATE_DEPLOYMENT);
|
||||||
$code = realpath(__DIR__ . '/../../../resources/functions') . "/php/code.tar.gz";
|
|
||||||
|
$folder = 'php';
|
||||||
|
$code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz";
|
||||||
|
$this->packageCode($folder);
|
||||||
|
|
||||||
$gqlPayload = [
|
$gqlPayload = [
|
||||||
'operations' => \json_encode([
|
'operations' => \json_encode([
|
||||||
'query' => $query,
|
'query' => $query,
|
||||||
|
|
Loading…
Reference in a new issue