diff --git a/.env b/.env index 01e3d1616a..1f0e7a152e 100644 --- a/.env +++ b/.env @@ -32,6 +32,18 @@ _APP_STORAGE_DO_SPACES_ACCESS_KEY= _APP_STORAGE_DO_SPACES_SECRET= _APP_STORAGE_DO_SPACES_REGION=us-east-1 _APP_STORAGE_DO_SPACES_BUCKET= +_APP_STORAGE_BACKBLAZE_ACCESS_KEY= +_APP_STORAGE_BACKBLAZE_SECRET= +_APP_STORAGE_BACKBLAZE_REGION=us-west-004 +_APP_STORAGE_BACKBLAZE_BUCKET= +_APP_STORAGE_LINODE_ACCESS_KEY= +_APP_STORAGE_LINODE_SECRET= +_APP_STORAGE_LINODE_REGION=eu-central-1 +_APP_STORAGE_LINODE_BUCKET= +_APP_STORAGE_WASABI_ACCESS_KEY= +_APP_STORAGE_WASABI_SECRET= +_APP_STORAGE_WASABI_REGION=eu-central-1 +_APP_STORAGE_WASABI_BUCKET= _APP_STORAGE_ANTIVIRUS=disabled _APP_STORAGE_ANTIVIRUS_HOST=clamav _APP_STORAGE_ANTIVIRUS_PORT=3310 diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml new file mode 100644 index 0000000000..2c98d11b80 --- /dev/null +++ b/.github/workflows/linter.yml @@ -0,0 +1,34 @@ +name: "Linter" + +on: [pull_request] +jobs: + tests: + name: Linter + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + 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 + + # If this run was triggered by a pull request event, then checkout + # the head of the pull request instead of the merge commit. + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.0' + + - name: Install dependencies + uses: php-actions/composer@v6 + with: + php_version: '8.0' + args: --profile --ignore-platform-reqs + + - name: Run Linter + run: ./vendor/bin/phpcs -p diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile deleted file mode 100644 index 6634613b7e..0000000000 --- a/.gitpod.Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM gitpod/workspace-full - -# Disable current PHP installation -RUN sudo a2dismod php7.4 -RUN sudo a2dismod mpm_prefork - -# Install apache2 (PHP install requires to do this first) -RUN sudo apt --yes -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" install apache2 - -# Update to PHP 8.0 with unattended installation -RUN sudo apt --yes install software-properties-common && sudo add-apt-repository ppa:ondrej/php -y -RUN sudo apt update -RUN sudo apt --yes -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" install php8.0 diff --git a/.gitpod.yml b/.gitpod.yml index 32ccdb693f..dfc306c59f 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -1,10 +1,17 @@ -image: - file: .gitpod.Dockerfile - tasks: - - init: docker-compose pull && - docker-compose build && - docker run --rm --interactive --tty --volume $PWD:/app composer update --ignore-platform-reqs --optimize-autoloader --no-plugins --no-scripts --prefer-dist + - name: Run Appwrite Docker Stack + init: | + docker compose pull + docker compose build + command: | + docker run --rm --interactive --tty \ + --volume $PWD:/app \ + composer update \ + --ignore-platform-reqs \ + --optimize-autoloader \ + --no-plugins \ + --no-scripts \ + --prefer-dist ports: - port: 8080 diff --git a/CHANGES.md b/CHANGES.md index 9aab3afb80..30b5b1e7db 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,18 @@ +# Version 0.14.2 + +## Features + +- Support for Backblaze adapter in Storage +- Support for Linode adapter in Storage +- Support for Wasabi adapter in Storage +- New Cloud Function Runtimes: + - Dart 2.17 + - Deno 1.21 + - Java 18 + - Node 18 +- Improved overall Migration speed + + # Version 0.14.1 ## Bugs diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ae04e7732e..b8f13b3538 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,11 +12,12 @@ 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 following `TYPE-ISSUE_ID-DESCRIPTION` example: + ``` doc-548-submit-a-pull-request-section-to-contribution-guide ``` @@ -29,32 +30,55 @@ 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 changes description!** 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: 1. `git pull`, before creating a new branch, pull the changes from upstream. Your master needs to be up to date. + ``` $ git pull ``` + 2. Create new branch from `master` like: `doc-548-submit-a-pull-request-section-to-contribution-guide`
+ ``` $ git checkout -b [name_of_your_new_branch] ``` + 3. Work - commit - repeat ( be sure to be in your branch ) -4. Push changes to GitHub +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 +./vendor/bin/phpcbf +``` + +Now, go a step further by running the linter by the following command to manually fix the issues the formatter wasn't able to fix. + +```bash +./vendor/bin/phpcs +``` + +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 +./vendor/bin/phpcs --report=diff +``` + +5. Push changes to GitHub + ``` $ git push origin [name_of_your_new_branch] ``` -5. Submit your changes for review -If you go to your repository on GitHub, you'll see a `Compare & pull request` button. Click on that button. -6. Start a Pull Request -Now submit the pull request and click on `Create pull request`. -7. Get a code review approval/reject -8. After approval, merge your PR -9. GitHub will automatically delete the branch after the merge is done. (they can still be restored). +6. Submit your changes for review + If you go to your repository on GitHub, you'll see a `Compare & pull request` button. Click on that button. +7. Start a Pull Request + Now submit the pull request and click on `Create pull request`. +8. Get a code review approval/reject +9. After approval, merge your PR +10. GitHub will automatically delete the branch after the merge is done. (they can still be restored). ## Setup From Source @@ -90,18 +114,20 @@ Appwrite uses an internal micro-framework called Litespeed.js to build simple UI 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. ##### Tools and Libs + - [Docker](https://www.docker.com/get-started) -- [PHP FIG](https://www.php-fig.org/) - [PSR-1](https://www.php-fig.org/psr/psr-1/) and [PSR-4](https://www.php-fig.org/psr/psr-4/) +- [PHP FIG](https://www.php-fig.org/) - [PSR-12](https://www.php-fig.org/psr/psr-12/) - [PHP Swoole](https://www.swoole.co.uk/) Learn more at our [Technology Stack](#technology-stack) section. ##### Network and Protocols + - [OSI Model](https://en.wikipedia.org/wiki/OSI_model) - [TCP vs UDP](https://www.guru99.com/tcp-vs-udp-understanding-the-difference.html#:~:text=TCP%20is%20a%20connection%2Doriented,speed%20of%20UDP%20is%20faster&text=TCP%20does%20error%20checking%20and,but%20it%20discards%20erroneous%20packets.) - [HTTP](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol) @@ -110,10 +136,12 @@ Learn more at our [Technology Stack](#technology-stack) section. - [gRPC](https://en.wikipedia.org/wiki/GRPC) ##### Architecture + - [Microservices vs Monolithic](https://www.mulesoft.com/resources/api/microservices-vs-monolithic#:~:text=Microservices%20architecture%20vs%20monolithic%20architecture&text=A%20monolithic%20application%20is%20built%20as%20a%20single%20unit.&text=To%20make%20any%20alterations%20to,formally%20with%20business%2Doriented%20APIs.) - [MVVM](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel) - Appwrite console architecture ##### Security + - [Appwrite Auth and ACL](https://github.com/appwrite/appwrite/blob/0.7.x/docs/specs/authentication.drawio.svg) - [OAuth](https://en.wikipedia.org/wiki/OAuth) - [Encryption](https://medium.com/searchencrypt/what-is-encryption-how-does-it-work-e8f20e340537#:~:text=Encryption%20is%20a%20process%20that,%2C%20or%20decrypt%2C%20the%20information.) @@ -124,8 +152,8 @@ Learn more at our [Technology Stack](#technology-stack) section. Appwrite's current structure is a combination of both [Monolithic](https://en.wikipedia.org/wiki/Monolithic_application) and [Microservice](https://en.wikipedia.org/wiki/Microservices) architectures, but our final goal, as we grow, is to be using only microservices. --- -![Appwrite](docs/specs/overview.drawio.svg) ---- + +## ![Appwrite](docs/specs/overview.drawio.svg) ### File Structure @@ -204,15 +232,15 @@ Appwrite stack is combined from a variety of open-source technologies and tools. ### Other Technologies -* Redis - for managing cache and in-memory data (currently, we do not use Redis for persistent data) -* MariaDB - for database storage and queries -* InfluxDB - for managing stats and time-series based data -* Statsd - for sending data over UDP protocol (using Telegraf) -* ClamAV - for validating and scanning storage files -* Imagemagick - for manipulating and managing image media files. -* Webp - for better compression of images on supporting clients -* SMTP - for sending email messages and alerts -* Resque - for managing data queues and scheduled tasks over a Redis server +- Redis - for managing cache and in-memory data (currently, we do not use Redis for persistent data) +- MariaDB - for database storage and queries +- InfluxDB - for managing stats and time-series based data +- Statsd - for sending data over UDP protocol (using Telegraf) +- ClamAV - for validating and scanning storage files +- Imagemagick - for manipulating and managing image media files. +- Webp - for better compression of images on supporting clients +- SMTP - for sending email messages and alerts +- Resque - for managing data queues and scheduled tasks over a Redis server ## Package Managers @@ -224,7 +252,7 @@ Appwrite uses [PHP's Composer](https://getcomposer.org/) for managing dependenci ## Coding Standards -Appwrite is following the [PHP-FIG standards](https://www.php-fig.org/). Currently, we are using both PSR-0 and PSR-4 for coding standards and autoloading standards. Soon we will also review the project for support with PSR-12 (Extended Coding Style). +Appwrite is following the [PHP-FIG standards](https://www.php-fig.org/). Currently, we are using both PSR-0 and PSR-12 for coding standards and autoloading standards. We use prettier for our JS coding standards and auto-formatting our code. @@ -236,14 +264,14 @@ We wish Appwrite will be as easy to set up and in a single, localhost, and easy When contributing code, please take into account the following considerations: -* Response Time -* Throughput -* Requests per Seconds -* Network Usage -* Memory Usage -* Browser Rendering -* Background Jobs -* Task Execution Time +- Response Time +- Throughput +- Requests per Seconds +- Network Usage +- Memory Usage +- Browser Rendering +- Background Jobs +- Task Execution Time ## Security & Privacy @@ -280,6 +308,7 @@ Before running the command, make sure you have proper write permissions to the A ```bash docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x -t appwrite/appwrite:dev --push . ``` + **Build Functions Runtimes** The Runtimes for all supported cloud functions (multicore builds) can be found at the [open-runtimes/open-runtimes](https://github.com/open-runtimes/open-runtimes) repository. @@ -299,11 +328,11 @@ For generating a new console SDK follow the next steps: Things to remember when releasing SDKs -* Update the Changelogs in **docs/sdks** (right now only Dart and Flutter are using these) -* Update **GETTING_STARTED.md** in **docs/sdks** for each SDKs if any changes in the related APIs in there -* Update SDK versions as required on **app/config/platforms.php** -* Generate SDKs using the command `php app/cli.php sdks` and follow the instructions -* Release new tags on GitHub repository for each SDKs +- Update the Changelogs in **docs/sdks** (right now only Dart and Flutter are using these) +- Update **GETTING_STARTED.md** in **docs/sdks** for each SDKs if any changes in the related APIs in there +- Update SDK versions as required on **app/config/platforms.php** +- Generate SDKs using the command `php app/cli.php sdks` and follow the instructions +- Release new tags on GitHub repository for each SDKs ## Debug @@ -315,13 +344,13 @@ First, you need to create an init file. Duplicate **dev/yasd_init.php.stub** fil ```json { - "name": "Listen for Xdebug", - "type": "php", - "request": "launch", - "port": 9005, - "pathMappings": { - "/usr/src/code": "${workspaceRoot}" - }, + "name": "Listen for Xdebug", + "type": "php", + "request": "launch", + "port": 9005, + "pathMappings": { + "/usr/src/code": "${workspaceRoot}" + } } ``` @@ -354,65 +383,62 @@ To run end-2-end tests for a spcific service use: ```bash docker-compose exec appwrite test /usr/src/code/tests/e2e/Services/[ServiceName] ``` + ## Benchmarking You can use WRK Docker image to benchmark the server performance. Benchmarking is extremely useful when you want to compare how the server behaves before and after a change has been applied. Replace [APPWRITE_HOSTNAME_OR_IP] with your Appwrite server hostname or IP. Note that localhost is not accessible from inside the WRK container. ``` - Options: - -c, --connections Connections to keep open - -d, --duration Duration of test - -t, --threads Number of threads to use - - -s, --script Load Lua script file - -H, --header Add header to request - --latency Print latency statistics - --timeout Socket/request timeout - -v, --version Print version details -``` + Options: + -c, --connections Connections to keep open + -d, --duration Duration of test + -t, --threads Number of threads to use + + -s, --script Load Lua script file + -H, --header Add header to request + --latency Print latency statistics + --timeout Socket/request timeout + -v, --version Print version details +``` ```bash docker run --rm skandyla/wrk -t3 -c100 -d30 https://[APPWRITE_HOSTNAME_OR_IP] ``` -## Code Maintenance +## Code Maintenance We use some automation tools to help us keep a healthy codebase. -Improve PHP execution time by using [fully-qualified function calls](https://veewee.github.io/blog/optimizing-php-performance-by-fq-function-calls/): +**Run Formatter:** ```bash -php-cs-fixer fix src/ --rules=native_function_invocation --allow-risky=yes +# Run on all files +./vendor/bin/phpcbf +# Run on single file or folder +./vendor/bin/phpcbf ``` -Coding Standards: +**Run Linter:** ```bash -php-cs-fixer fix app/controllers --rules='{"braces": {"allow_single_line_closure": true}}' -``` - -```bash -php-cs-fixer fix src --rules='{"braces": {"allow_single_line_closure": true}}' -``` - -Static Code Analysis: - -```bash -docker-compose exec appwrite /usr/src/code/vendor/bin/psalm +# Run on all files +./vendor/bin/phpcs +# Run on single file or folder +./vendor/bin/phpcs ``` ## Tutorials From time to time, our team will add tutorials that will help contributors find their way in the Appwrite source code. Below is a list of currently available tutorials: -* [Adding Support for a New OAuth2 Provider](./docs/tutorials/add-oauth2-provider.md) -* [Appwrite Environment Variables](./docs/tutorials/environment-variables.md) -* [Running in Production](./docs/tutorials/running-in-production.md) -* [Adding Storage Adapter](./docs/tutorials/add-storage-adapter.md) +- [Adding Support for a New OAuth2 Provider](./docs/tutorials/add-oauth2-provider.md) +- [Appwrite Environment Variables](./docs/tutorials/environment-variables.md) +- [Running in Production](./docs/tutorials/running-in-production.md) +- [Adding Storage Adapter](./docs/tutorials/add-storage-adapter.md) ## Other Ways to Help -Pull requests are great, but there are many other areas where you can help Appwrite. +Pull requests are great, but there are many other areas where you can help Appwrite. ### Blogging & Speaking @@ -437,4 +463,3 @@ Submitting documentation updates, enhancements, designs, or bug fixes. Spelling ### Helping Someone Searching for Appwrite on Discord, GitHub, or StackOverflow and helping someone else who needs help. You can also help by teaching others how to contribute to Appwrite's repo! - diff --git a/Dockerfile b/Dockerfile index 7f5df76148..e2b991cf6a 100755 --- a/Dockerfile +++ b/Dockerfile @@ -162,6 +162,18 @@ ENV _APP_SERVER=swoole \ _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_REDIS_HOST=redis \ _APP_REDIS_PORT=6379 \ _APP_DB_HOST=mariadb \ diff --git a/README-CN.md b/README-CN.md index f95bd12f93..7a10dee770 100644 --- a/README-CN.md +++ b/README-CN.md @@ -59,7 +59,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:0.14.1 + appwrite/appwrite:0.14.2 ``` ### Windows @@ -71,7 +71,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:0.14.1 + appwrite/appwrite:0.14.2 ``` #### PowerShell @@ -81,7 +81,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:0.14.1 + appwrite/appwrite:0.14.2 ``` ่ฟ่กŒๅŽ๏ผŒๅฏไปฅๅœจๆต่งˆๅ™จไธŠ่ฎฟ้—ฎ http://localhost ๆ‰พๅˆฐ Appwrite ๆŽงๅˆถๅฐใ€‚ๅœจ้ž Linux ็š„ๆœฌๆœบไธปๆœบไธŠๅฎŒๆˆๅฎ‰่ฃ…ๅŽ๏ผŒๆœๅŠกๅ™จๅฏ่ƒฝ้œ€่ฆๅ‡ ๅˆ†้’Ÿๆ‰่ƒฝๅฏๅŠจใ€‚ diff --git a/README.md b/README.md index 5254547afa..e67e4f3bad 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,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:0.14.1 + appwrite/appwrite:0.14.2 ``` ### Windows @@ -74,7 +74,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:0.14.1 + appwrite/appwrite:0.14.2 ``` #### PowerShell @@ -84,7 +84,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:0.14.1 + appwrite/appwrite:0.14.2 ``` 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. diff --git a/app/cli.php b/app/cli.php index 8902aad886..09b3dc9413 100644 --- a/app/cli.php +++ b/app/cli.php @@ -1,6 +1,7 @@ run(); \ No newline at end of file +$cli->run(); diff --git a/app/config/auth.php b/app/config/auth.php index aab6833b65..451b8d2c2e 100644 --- a/app/config/auth.php +++ b/app/config/auth.php @@ -1,4 +1,4 @@ - '', 'enabled' => false, ], -]; \ No newline at end of file +]; diff --git a/app/config/avatars/browsers.php b/app/config/avatars/browsers.php index 2b065d165c..56e63853eb 100644 --- a/app/config/avatars/browsers.php +++ b/app/config/avatars/browsers.php @@ -2,20 +2,20 @@ return [ // Codes based on: https://github.com/matomo-org/device-detector/blob/master/Parser/Client/Browser.php - 'aa' => __DIR__.'/browsers/avant.png', - 'an' => __DIR__.'/browsers/android-webview-beta.png', - 'ch' => __DIR__.'/browsers/chrome.png', - 'ci' => __DIR__.'/browsers/chrome.png', //Chrome Mobile iOS - 'cm' => __DIR__.'/browsers/chrome.png', //Chrome Mobile - 'cr' => __DIR__.'/browsers/chromium.png', - 'ff' => __DIR__.'/browsers/firefox.png', - 'sf' => __DIR__.'/browsers/safari.png', - 'mf' => __DIR__.'/browsers/safari.png', - 'ps' => __DIR__.'/browsers/edge.png', - 'oi' => __DIR__.'/browsers/edge.png', - 'om' => __DIR__.'/browsers/opera-mini.png', - 'op' => __DIR__.'/browsers/opera.png', - 'on' => __DIR__.'/browsers/opera.png', + 'aa' => __DIR__ . '/browsers/avant.png', + 'an' => __DIR__ . '/browsers/android-webview-beta.png', + 'ch' => __DIR__ . '/browsers/chrome.png', + 'ci' => __DIR__ . '/browsers/chrome.png', //Chrome Mobile iOS + 'cm' => __DIR__ . '/browsers/chrome.png', //Chrome Mobile + 'cr' => __DIR__ . '/browsers/chromium.png', + 'ff' => __DIR__ . '/browsers/firefox.png', + 'sf' => __DIR__ . '/browsers/safari.png', + 'mf' => __DIR__ . '/browsers/safari.png', + 'ps' => __DIR__ . '/browsers/edge.png', + 'oi' => __DIR__ . '/browsers/edge.png', + 'om' => __DIR__ . '/browsers/opera-mini.png', + 'op' => __DIR__ . '/browsers/opera.png', + 'on' => __DIR__ . '/browsers/opera.png', /* '36' => '360 Phone Browser', diff --git a/app/config/avatars/credit-cards.php b/app/config/avatars/credit-cards.php index daa53a9056..67829537a1 100644 --- a/app/config/avatars/credit-cards.php +++ b/app/config/avatars/credit-cards.php @@ -1,20 +1,20 @@ __DIR__.'/credit-cards/amex.png', - 'argencard' => __DIR__.'/credit-cards/argencard.png', - 'cabal' => __DIR__.'/credit-cards/cabal.png', - 'censosud' => __DIR__.'/credit-cards/consosud.png', - 'diners' => __DIR__.'/credit-cards/diners.png', - 'discover' => __DIR__.'/credit-cards/discover.png', - 'elo' => __DIR__.'/credit-cards/elo.png', - 'hipercard' => __DIR__.'/credit-cards/hipercard.png', - 'jcb' => __DIR__.'/credit-cards/jcb.png', - 'mastercard' => __DIR__.'/credit-cards/mastercard.png', - 'naranja' => __DIR__.'/credit-cards/naranja.png', - 'targeta-shopping' => __DIR__.'/credit-cards/tarjeta-shopping.png', - 'union-china-pay' => __DIR__.'/credit-cards/union-china-pay.png', - 'visa' => __DIR__.'/credit-cards/visa.png', - 'mir' => __DIR__.'/credit-cards/mir.png', - 'maestro' => __DIR__.'/credit-cards/maestro.png', + 'amex' => __DIR__ . '/credit-cards/amex.png', + 'argencard' => __DIR__ . '/credit-cards/argencard.png', + 'cabal' => __DIR__ . '/credit-cards/cabal.png', + 'censosud' => __DIR__ . '/credit-cards/consosud.png', + 'diners' => __DIR__ . '/credit-cards/diners.png', + 'discover' => __DIR__ . '/credit-cards/discover.png', + 'elo' => __DIR__ . '/credit-cards/elo.png', + 'hipercard' => __DIR__ . '/credit-cards/hipercard.png', + 'jcb' => __DIR__ . '/credit-cards/jcb.png', + 'mastercard' => __DIR__ . '/credit-cards/mastercard.png', + 'naranja' => __DIR__ . '/credit-cards/naranja.png', + 'targeta-shopping' => __DIR__ . '/credit-cards/tarjeta-shopping.png', + 'union-china-pay' => __DIR__ . '/credit-cards/union-china-pay.png', + 'visa' => __DIR__ . '/credit-cards/visa.png', + 'mir' => __DIR__ . '/credit-cards/mir.png', + 'maestro' => __DIR__ . '/credit-cards/maestro.png', ]; diff --git a/app/config/avatars/flags.php b/app/config/avatars/flags.php index 7939e5ccf7..20f7e3701f 100644 --- a/app/config/avatars/flags.php +++ b/app/config/avatars/flags.php @@ -1,198 +1,198 @@ __DIR__.'/flags/af.png', - 'ao' => __DIR__.'/flags/ao.png', - 'al' => __DIR__.'/flags/al.png', - 'ad' => __DIR__.'/flags/ad.png', - 'ae' => __DIR__.'/flags/ae.png', - 'ar' => __DIR__.'/flags/ar.png', - 'am' => __DIR__.'/flags/am.png', - 'ag' => __DIR__.'/flags/ag.png', - 'au' => __DIR__.'/flags/au.png', - 'at' => __DIR__.'/flags/at.png', - 'az' => __DIR__.'/flags/az.png', - 'bi' => __DIR__.'/flags/bi.png', - 'be' => __DIR__.'/flags/be.png', - 'bj' => __DIR__.'/flags/bj.png', - 'bf' => __DIR__.'/flags/bf.png', - 'bd' => __DIR__.'/flags/bd.png', - 'bg' => __DIR__.'/flags/bg.png', - 'bh' => __DIR__.'/flags/bh.png', - 'bs' => __DIR__.'/flags/bs.png', - 'ba' => __DIR__.'/flags/ba.png', - 'by' => __DIR__.'/flags/by.png', - 'bz' => __DIR__.'/flags/bz.png', - 'bo' => __DIR__.'/flags/bo.png', - 'br' => __DIR__.'/flags/br.png', - 'bb' => __DIR__.'/flags/bb.png', - 'bn' => __DIR__.'/flags/bn.png', - 'bt' => __DIR__.'/flags/bt.png', - 'bw' => __DIR__.'/flags/bw.png', - 'cf' => __DIR__.'/flags/cf.png', - 'ca' => __DIR__.'/flags/ca.png', - 'ch' => __DIR__.'/flags/ch.png', - 'cl' => __DIR__.'/flags/cl.png', - 'cn' => __DIR__.'/flags/cn.png', - 'ci' => __DIR__.'/flags/ci.png', - 'cm' => __DIR__.'/flags/cm.png', - 'cd' => __DIR__.'/flags/cd.png', - 'cg' => __DIR__.'/flags/cg.png', - 'co' => __DIR__.'/flags/co.png', - 'km' => __DIR__.'/flags/km.png', - 'cv' => __DIR__.'/flags/cv.png', - 'cr' => __DIR__.'/flags/cr.png', - 'cu' => __DIR__.'/flags/cu.png', - 'cy' => __DIR__.'/flags/cy.png', - 'cz' => __DIR__.'/flags/cz.png', - 'de' => __DIR__.'/flags/de.png', - 'dj' => __DIR__.'/flags/dj.png', - 'dm' => __DIR__.'/flags/dm.png', - 'dk' => __DIR__.'/flags/dk.png', - 'do' => __DIR__.'/flags/do.png', - 'dz' => __DIR__.'/flags/dz.png', - 'ec' => __DIR__.'/flags/ec.png', - 'eg' => __DIR__.'/flags/eg.png', - 'er' => __DIR__.'/flags/er.png', - 'es' => __DIR__.'/flags/es.png', - 'ee' => __DIR__.'/flags/ee.png', - 'et' => __DIR__.'/flags/et.png', - 'fi' => __DIR__.'/flags/fi.png', - 'fj' => __DIR__.'/flags/fj.png', - 'fr' => __DIR__.'/flags/fr.png', - 'fm' => __DIR__.'/flags/fm.png', - 'ga' => __DIR__.'/flags/ga.png', - 'gb' => __DIR__.'/flags/gb.png', - 'ge' => __DIR__.'/flags/ge.png', - 'gh' => __DIR__.'/flags/gh.png', - 'gn' => __DIR__.'/flags/gn.png', - 'gm' => __DIR__.'/flags/gm.png', - 'gw' => __DIR__.'/flags/gw.png', - 'gq' => __DIR__.'/flags/gq.png', - 'gr' => __DIR__.'/flags/gr.png', - 'gd' => __DIR__.'/flags/gd.png', - 'gt' => __DIR__.'/flags/gt.png', - 'gy' => __DIR__.'/flags/gy.png', - 'hn' => __DIR__.'/flags/hn.png', - 'hr' => __DIR__.'/flags/hr.png', - 'ht' => __DIR__.'/flags/ht.png', - 'hu' => __DIR__.'/flags/hu.png', - 'id' => __DIR__.'/flags/id.png', - 'in' => __DIR__.'/flags/in.png', - 'ie' => __DIR__.'/flags/ie.png', - 'ir' => __DIR__.'/flags/ir.png', - 'iq' => __DIR__.'/flags/iq.png', - 'is' => __DIR__.'/flags/is.png', - 'il' => __DIR__.'/flags/il.png', - 'it' => __DIR__.'/flags/it.png', - 'jm' => __DIR__.'/flags/jm.png', - 'jo' => __DIR__.'/flags/jo.png', - 'jp' => __DIR__.'/flags/jp.png', - 'kz' => __DIR__.'/flags/kz.png', - 'ke' => __DIR__.'/flags/ke.png', - 'kg' => __DIR__.'/flags/kg.png', - 'kh' => __DIR__.'/flags/kh.png', - 'ki' => __DIR__.'/flags/ki.png', - 'kn' => __DIR__.'/flags/kn.png', - 'kr' => __DIR__.'/flags/kr.png', - 'kw' => __DIR__.'/flags/kw.png', - 'la' => __DIR__.'/flags/la.png', - 'lb' => __DIR__.'/flags/lb.png', - 'lr' => __DIR__.'/flags/lr.png', - 'ly' => __DIR__.'/flags/ly.png', - 'lc' => __DIR__.'/flags/lc.png', - 'li' => __DIR__.'/flags/li.png', - 'lk' => __DIR__.'/flags/lk.png', - 'ls' => __DIR__.'/flags/ls.png', - 'lt' => __DIR__.'/flags/ls.png', - 'lu' => __DIR__.'/flags/lu.png', - 'lv' => __DIR__.'/flags/lv.png', - 'ma' => __DIR__.'/flags/ma.png', - 'mc' => __DIR__.'/flags/mc.png', - 'md' => __DIR__.'/flags/md.png', - 'mg' => __DIR__.'/flags/mg.png', - 'mv' => __DIR__.'/flags/mv.png', - 'mx' => __DIR__.'/flags/mx.png', - 'mh' => __DIR__.'/flags/mh.png', - 'mk' => __DIR__.'/flags/mk.png', - 'ml' => __DIR__.'/flags/ml.png', - 'mt' => __DIR__.'/flags/mt.png', - 'mm' => __DIR__.'/flags/mm.png', - 'me' => __DIR__.'/flags/me.png', - 'mn' => __DIR__.'/flags/mn.png', - 'mz' => __DIR__.'/flags/mz.png', - 'mr' => __DIR__.'/flags/mr.png', - 'mu' => __DIR__.'/flags/mu.png', - 'mw' => __DIR__.'/flags/mw.png', - 'my' => __DIR__.'/flags/my.png', - 'na' => __DIR__.'/flags/na.png', - 'ne' => __DIR__.'/flags/ne.png', - 'ng' => __DIR__.'/flags/ng.png', - 'ni' => __DIR__.'/flags/ni.png', - 'nl' => __DIR__.'/flags/nl.png', - 'no' => __DIR__.'/flags/no.png', - 'np' => __DIR__.'/flags/np.png', - 'nr' => __DIR__.'/flags/nr.png', - 'nz' => __DIR__.'/flags/nz.png', - 'om' => __DIR__.'/flags/om.png', - 'pk' => __DIR__.'/flags/pk.png', - 'pa' => __DIR__.'/flags/pa.png', - 'pe' => __DIR__.'/flags/pe.png', - 'ph' => __DIR__.'/flags/ph.png', - 'pw' => __DIR__.'/flags/pw.png', - 'pg' => __DIR__.'/flags/pg.png', - 'pl' => __DIR__.'/flags/pl.png', - 'kp' => __DIR__.'/flags/kp.png', - 'pt' => __DIR__.'/flags/pt.png', - 'py' => __DIR__.'/flags/py.png', - 'qa' => __DIR__.'/flags/qa.png', - 'ro' => __DIR__.'/flags/ro.png', - 'ru' => __DIR__.'/flags/ru.png', - 'rw' => __DIR__.'/flags/rw.png', - 'sa' => __DIR__.'/flags/sa.png', - 'sd' => __DIR__.'/flags/sd.png', - 'sn' => __DIR__.'/flags/sn.png', - 'sg' => __DIR__.'/flags/sg.png', - 'sb' => __DIR__.'/flags/sb.png', - 'sl' => __DIR__.'/flags/sl.png', - 'sv' => __DIR__.'/flags/sv.png', - 'sm' => __DIR__.'/flags/sm.png', - 'so' => __DIR__.'/flags/so.png', - 'rs' => __DIR__.'/flags/rs.png', - 'ss' => __DIR__.'/flags/ss.png', - 'st' => __DIR__.'/flags/st.png', - 'sr' => __DIR__.'/flags/sr.png', - 'sk' => __DIR__.'/flags/sk.png', - 'si' => __DIR__.'/flags/si.png', - 'se' => __DIR__.'/flags/se.png', - 'sz' => __DIR__.'/flags/sz.png', - 'sc' => __DIR__.'/flags/sc.png', - 'sy' => __DIR__.'/flags/sy.png', - 'td' => __DIR__.'/flags/td.png', - 'tg' => __DIR__.'/flags/tg.png', - 'th' => __DIR__.'/flags/th.png', - 'tj' => __DIR__.'/flags/tj.png', - 'tm' => __DIR__.'/flags/tm.png', - 'tl' => __DIR__.'/flags/tl.png', - 'to' => __DIR__.'/flags/to.png', - 'tt' => __DIR__.'/flags/tt.png', - 'tn' => __DIR__.'/flags/tn.png', - 'tr' => __DIR__.'/flags/tr.png', - 'tv' => __DIR__.'/flags/tv.png', - 'tz' => __DIR__.'/flags/tz.png', - 'ug' => __DIR__.'/flags/ug.png', - 'ua' => __DIR__.'/flags/ua.png', - 'uy' => __DIR__.'/flags/uy.png', - 'us' => __DIR__.'/flags/us.png', - 'uz' => __DIR__.'/flags/uz.png', - 'va' => __DIR__.'/flags/va.png', - 'vc' => __DIR__.'/flags/vc.png', - 've' => __DIR__.'/flags/ve.png', - 'vn' => __DIR__.'/flags/vn.png', - 'vu' => __DIR__.'/flags/vu.png', - 'ws' => __DIR__.'/flags/ws.png', - 'ye' => __DIR__.'/flags/ye.png', - 'za' => __DIR__.'/flags/za.png', - 'zm' => __DIR__.'/flags/zm.png', - 'zw' => __DIR__.'/flags/zw.png', + 'af' => __DIR__ . '/flags/af.png', + 'ao' => __DIR__ . '/flags/ao.png', + 'al' => __DIR__ . '/flags/al.png', + 'ad' => __DIR__ . '/flags/ad.png', + 'ae' => __DIR__ . '/flags/ae.png', + 'ar' => __DIR__ . '/flags/ar.png', + 'am' => __DIR__ . '/flags/am.png', + 'ag' => __DIR__ . '/flags/ag.png', + 'au' => __DIR__ . '/flags/au.png', + 'at' => __DIR__ . '/flags/at.png', + 'az' => __DIR__ . '/flags/az.png', + 'bi' => __DIR__ . '/flags/bi.png', + 'be' => __DIR__ . '/flags/be.png', + 'bj' => __DIR__ . '/flags/bj.png', + 'bf' => __DIR__ . '/flags/bf.png', + 'bd' => __DIR__ . '/flags/bd.png', + 'bg' => __DIR__ . '/flags/bg.png', + 'bh' => __DIR__ . '/flags/bh.png', + 'bs' => __DIR__ . '/flags/bs.png', + 'ba' => __DIR__ . '/flags/ba.png', + 'by' => __DIR__ . '/flags/by.png', + 'bz' => __DIR__ . '/flags/bz.png', + 'bo' => __DIR__ . '/flags/bo.png', + 'br' => __DIR__ . '/flags/br.png', + 'bb' => __DIR__ . '/flags/bb.png', + 'bn' => __DIR__ . '/flags/bn.png', + 'bt' => __DIR__ . '/flags/bt.png', + 'bw' => __DIR__ . '/flags/bw.png', + 'cf' => __DIR__ . '/flags/cf.png', + 'ca' => __DIR__ . '/flags/ca.png', + 'ch' => __DIR__ . '/flags/ch.png', + 'cl' => __DIR__ . '/flags/cl.png', + 'cn' => __DIR__ . '/flags/cn.png', + 'ci' => __DIR__ . '/flags/ci.png', + 'cm' => __DIR__ . '/flags/cm.png', + 'cd' => __DIR__ . '/flags/cd.png', + 'cg' => __DIR__ . '/flags/cg.png', + 'co' => __DIR__ . '/flags/co.png', + 'km' => __DIR__ . '/flags/km.png', + 'cv' => __DIR__ . '/flags/cv.png', + 'cr' => __DIR__ . '/flags/cr.png', + 'cu' => __DIR__ . '/flags/cu.png', + 'cy' => __DIR__ . '/flags/cy.png', + 'cz' => __DIR__ . '/flags/cz.png', + 'de' => __DIR__ . '/flags/de.png', + 'dj' => __DIR__ . '/flags/dj.png', + 'dm' => __DIR__ . '/flags/dm.png', + 'dk' => __DIR__ . '/flags/dk.png', + 'do' => __DIR__ . '/flags/do.png', + 'dz' => __DIR__ . '/flags/dz.png', + 'ec' => __DIR__ . '/flags/ec.png', + 'eg' => __DIR__ . '/flags/eg.png', + 'er' => __DIR__ . '/flags/er.png', + 'es' => __DIR__ . '/flags/es.png', + 'ee' => __DIR__ . '/flags/ee.png', + 'et' => __DIR__ . '/flags/et.png', + 'fi' => __DIR__ . '/flags/fi.png', + 'fj' => __DIR__ . '/flags/fj.png', + 'fr' => __DIR__ . '/flags/fr.png', + 'fm' => __DIR__ . '/flags/fm.png', + 'ga' => __DIR__ . '/flags/ga.png', + 'gb' => __DIR__ . '/flags/gb.png', + 'ge' => __DIR__ . '/flags/ge.png', + 'gh' => __DIR__ . '/flags/gh.png', + 'gn' => __DIR__ . '/flags/gn.png', + 'gm' => __DIR__ . '/flags/gm.png', + 'gw' => __DIR__ . '/flags/gw.png', + 'gq' => __DIR__ . '/flags/gq.png', + 'gr' => __DIR__ . '/flags/gr.png', + 'gd' => __DIR__ . '/flags/gd.png', + 'gt' => __DIR__ . '/flags/gt.png', + 'gy' => __DIR__ . '/flags/gy.png', + 'hn' => __DIR__ . '/flags/hn.png', + 'hr' => __DIR__ . '/flags/hr.png', + 'ht' => __DIR__ . '/flags/ht.png', + 'hu' => __DIR__ . '/flags/hu.png', + 'id' => __DIR__ . '/flags/id.png', + 'in' => __DIR__ . '/flags/in.png', + 'ie' => __DIR__ . '/flags/ie.png', + 'ir' => __DIR__ . '/flags/ir.png', + 'iq' => __DIR__ . '/flags/iq.png', + 'is' => __DIR__ . '/flags/is.png', + 'il' => __DIR__ . '/flags/il.png', + 'it' => __DIR__ . '/flags/it.png', + 'jm' => __DIR__ . '/flags/jm.png', + 'jo' => __DIR__ . '/flags/jo.png', + 'jp' => __DIR__ . '/flags/jp.png', + 'kz' => __DIR__ . '/flags/kz.png', + 'ke' => __DIR__ . '/flags/ke.png', + 'kg' => __DIR__ . '/flags/kg.png', + 'kh' => __DIR__ . '/flags/kh.png', + 'ki' => __DIR__ . '/flags/ki.png', + 'kn' => __DIR__ . '/flags/kn.png', + 'kr' => __DIR__ . '/flags/kr.png', + 'kw' => __DIR__ . '/flags/kw.png', + 'la' => __DIR__ . '/flags/la.png', + 'lb' => __DIR__ . '/flags/lb.png', + 'lr' => __DIR__ . '/flags/lr.png', + 'ly' => __DIR__ . '/flags/ly.png', + 'lc' => __DIR__ . '/flags/lc.png', + 'li' => __DIR__ . '/flags/li.png', + 'lk' => __DIR__ . '/flags/lk.png', + 'ls' => __DIR__ . '/flags/ls.png', + 'lt' => __DIR__ . '/flags/ls.png', + 'lu' => __DIR__ . '/flags/lu.png', + 'lv' => __DIR__ . '/flags/lv.png', + 'ma' => __DIR__ . '/flags/ma.png', + 'mc' => __DIR__ . '/flags/mc.png', + 'md' => __DIR__ . '/flags/md.png', + 'mg' => __DIR__ . '/flags/mg.png', + 'mv' => __DIR__ . '/flags/mv.png', + 'mx' => __DIR__ . '/flags/mx.png', + 'mh' => __DIR__ . '/flags/mh.png', + 'mk' => __DIR__ . '/flags/mk.png', + 'ml' => __DIR__ . '/flags/ml.png', + 'mt' => __DIR__ . '/flags/mt.png', + 'mm' => __DIR__ . '/flags/mm.png', + 'me' => __DIR__ . '/flags/me.png', + 'mn' => __DIR__ . '/flags/mn.png', + 'mz' => __DIR__ . '/flags/mz.png', + 'mr' => __DIR__ . '/flags/mr.png', + 'mu' => __DIR__ . '/flags/mu.png', + 'mw' => __DIR__ . '/flags/mw.png', + 'my' => __DIR__ . '/flags/my.png', + 'na' => __DIR__ . '/flags/na.png', + 'ne' => __DIR__ . '/flags/ne.png', + 'ng' => __DIR__ . '/flags/ng.png', + 'ni' => __DIR__ . '/flags/ni.png', + 'nl' => __DIR__ . '/flags/nl.png', + 'no' => __DIR__ . '/flags/no.png', + 'np' => __DIR__ . '/flags/np.png', + 'nr' => __DIR__ . '/flags/nr.png', + 'nz' => __DIR__ . '/flags/nz.png', + 'om' => __DIR__ . '/flags/om.png', + 'pk' => __DIR__ . '/flags/pk.png', + 'pa' => __DIR__ . '/flags/pa.png', + 'pe' => __DIR__ . '/flags/pe.png', + 'ph' => __DIR__ . '/flags/ph.png', + 'pw' => __DIR__ . '/flags/pw.png', + 'pg' => __DIR__ . '/flags/pg.png', + 'pl' => __DIR__ . '/flags/pl.png', + 'kp' => __DIR__ . '/flags/kp.png', + 'pt' => __DIR__ . '/flags/pt.png', + 'py' => __DIR__ . '/flags/py.png', + 'qa' => __DIR__ . '/flags/qa.png', + 'ro' => __DIR__ . '/flags/ro.png', + 'ru' => __DIR__ . '/flags/ru.png', + 'rw' => __DIR__ . '/flags/rw.png', + 'sa' => __DIR__ . '/flags/sa.png', + 'sd' => __DIR__ . '/flags/sd.png', + 'sn' => __DIR__ . '/flags/sn.png', + 'sg' => __DIR__ . '/flags/sg.png', + 'sb' => __DIR__ . '/flags/sb.png', + 'sl' => __DIR__ . '/flags/sl.png', + 'sv' => __DIR__ . '/flags/sv.png', + 'sm' => __DIR__ . '/flags/sm.png', + 'so' => __DIR__ . '/flags/so.png', + 'rs' => __DIR__ . '/flags/rs.png', + 'ss' => __DIR__ . '/flags/ss.png', + 'st' => __DIR__ . '/flags/st.png', + 'sr' => __DIR__ . '/flags/sr.png', + 'sk' => __DIR__ . '/flags/sk.png', + 'si' => __DIR__ . '/flags/si.png', + 'se' => __DIR__ . '/flags/se.png', + 'sz' => __DIR__ . '/flags/sz.png', + 'sc' => __DIR__ . '/flags/sc.png', + 'sy' => __DIR__ . '/flags/sy.png', + 'td' => __DIR__ . '/flags/td.png', + 'tg' => __DIR__ . '/flags/tg.png', + 'th' => __DIR__ . '/flags/th.png', + 'tj' => __DIR__ . '/flags/tj.png', + 'tm' => __DIR__ . '/flags/tm.png', + 'tl' => __DIR__ . '/flags/tl.png', + 'to' => __DIR__ . '/flags/to.png', + 'tt' => __DIR__ . '/flags/tt.png', + 'tn' => __DIR__ . '/flags/tn.png', + 'tr' => __DIR__ . '/flags/tr.png', + 'tv' => __DIR__ . '/flags/tv.png', + 'tz' => __DIR__ . '/flags/tz.png', + 'ug' => __DIR__ . '/flags/ug.png', + 'ua' => __DIR__ . '/flags/ua.png', + 'uy' => __DIR__ . '/flags/uy.png', + 'us' => __DIR__ . '/flags/us.png', + 'uz' => __DIR__ . '/flags/uz.png', + 'va' => __DIR__ . '/flags/va.png', + 'vc' => __DIR__ . '/flags/vc.png', + 've' => __DIR__ . '/flags/ve.png', + 'vn' => __DIR__ . '/flags/vn.png', + 'vu' => __DIR__ . '/flags/vu.png', + 'ws' => __DIR__ . '/flags/ws.png', + 'ye' => __DIR__ . '/flags/ye.png', + 'za' => __DIR__ . '/flags/za.png', + 'zm' => __DIR__ . '/flags/zm.png', + 'zw' => __DIR__ . '/flags/zw.png', ]; diff --git a/app/config/avatars/os.php b/app/config/avatars/os.php index ba5ee0e1fc..f500eed759 100644 --- a/app/config/avatars/os.php +++ b/app/config/avatars/os.php @@ -2,9 +2,9 @@ return [ // Codes based on: https://github.com/matomo-org/device-detector/blob/master/Parser/Client/Browser.php - 'AND' => __DIR__.'/os/android.png', - 'ATV' => __DIR__.'/os/apple-tv.png', - 'COS' => __DIR__.'/os/chrome-os.png', + 'AND' => __DIR__ . '/os/android.png', + 'ATV' => __DIR__ . '/os/apple-tv.png', + 'COS' => __DIR__ . '/os/chrome-os.png', /* 'AIX' => 'AIX', diff --git a/app/config/collections.php b/app/config/collections.php index 0e2a558210..4c666caa33 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -232,7 +232,7 @@ $collections = [ 'size' => 16384, 'signed' => true, 'required' => false, - 'default' => new stdClass, + 'default' => new stdClass(), 'array' => false, 'filters' => ['json', 'range', 'enum'], ], @@ -931,6 +931,17 @@ $collections = [ 'array' => true, 'filters' => [], ], + [ + '$id' => 'signatureKey', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], ], 'indexes' => [ [ @@ -2055,7 +2066,7 @@ $collections = [ ], [ '$id' => 'status', - 'type' => Database::VAR_STRING, + 'type' => Database::VAR_STRING, 'format' => '', 'size' => 256, 'signed' => true, @@ -2099,7 +2110,7 @@ $collections = [ ], [ '$id' => 'sourceType', - 'type' => Database::VAR_STRING, + 'type' => Database::VAR_STRING, 'format' => '', 'size' => 2048, 'signed' => true, @@ -2110,7 +2121,7 @@ $collections = [ ], [ '$id' => 'source', - 'type' => Database::VAR_STRING, + 'type' => Database::VAR_STRING, 'format' => '', 'size' => 2048, 'signed' => true, diff --git a/app/config/errors.php b/app/config/errors.php index 8dadcf079c..b1e418e517 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -1,7 +1,7 @@ [ 'name' => Exception::GENERAL_UNKNOWN, 'description' => 'An unknown error has occured. Please check the logs for more information.', - 'code' => 500, + 'code' => 500, ], Exception::GENERAL_MOCK => [ 'name' => Exception::GENERAL_MOCK, 'description' => 'General errors thrown by the mock controller used for testing.', - 'code' => 400, + 'code' => 400, ], Exception::GENERAL_ACCESS_FORBIDDEN => [ 'name' => Exception::GENERAL_ACCESS_FORBIDDEN, 'description' => 'Access to this API is forbidden.', - 'code' => 401, + 'code' => 401, ], Exception::GENERAL_UNKNOWN_ORIGIN => [ 'name' => Exception::GENERAL_UNKNOWN_ORIGIN, @@ -81,7 +81,7 @@ return [ 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.', - 'code' => 500, + 'code' => 500, ], /** User Errors */ @@ -497,4 +497,4 @@ return [ 'description' => 'Domain verification for the requested domain has failed.', 'code' => 401, ] -]; \ No newline at end of file +]; diff --git a/app/config/locale/codes.php b/app/config/locale/codes.php index 00d5e90f84..feeebf975d 100644 --- a/app/config/locale/codes.php +++ b/app/config/locale/codes.php @@ -51,7 +51,7 @@ return [ 'or', // Oriya 'tl', // Filipino 'pl', // Polish - 'pt-br', // Portuguese - Brazil + 'pt-br', // Portuguese - Brazil 'pt-pt', // Portuguese - Portugal 'pa', // Punjabi 'ro', // Romanian diff --git a/app/config/locale/translations/en.json b/app/config/locale/translations/en.json index ab765fe47e..91cc2405b6 100644 --- a/app/config/locale/translations/en.json +++ b/app/config/locale/translations/en.json @@ -30,7 +30,7 @@ "emails.certificate.subject": "Certificate failure for %s", "emails.certificate.hello": "Hello", "emails.certificate.body": "Certificate for your domain '{{domain}}' could not be generated. This is attempt no. {{attempt}}, and the failure was caused by: {{error}}", - "emails.certificate.footer": "Your previous certificate willl be valid for 30 days since the first failure. We highly recommend investigating this case, otherwise your domain will end up without a valid SSL communication.", + "emails.certificate.footer": "Your previous certificate will be valid for 30 days since the first failure. We highly recommend investigating this case, otherwise your domain will end up without a valid SSL communication.", "emails.certificate.thanks": "Thanks", "emails.certificate.signature": "{{project}} team", "locale.country.unknown": "Unknown", @@ -235,4 +235,4 @@ "continents.na": "North America", "continents.oc": "Oceania", "continents.sa": "South America" -} \ No newline at end of file +} diff --git a/app/config/locale/translations/ml.json b/app/config/locale/translations/ml.json index dce555c1cb..4997d0dfcd 100644 --- a/app/config/locale/translations/ml.json +++ b/app/config/locale/translations/ml.json @@ -18,12 +18,12 @@ "emails.recovery.subject": "เดฐเดนเดธเตเดฏเดตเดพเด•เตเด•เต เดชเตเดจเด•เตเดฐเดฎเต€เด•เดฐเดฃเด‚", "emails.recovery.hello": "เดจเดฎเดธเตเด•เดพเดฐเด‚ {{name}}", "emails.recovery.body": "เดจเดฟเด™เตเด™เดณเตเดŸเต† {{Project}} เดฐเดนเดธเตเดฏเดตเดพเด•เตเด•เต เดชเตเดจเด•เตเดฐเดฎเต€เด•เดฐเดฟเด•เตเด•เตเดจเตเดจเดคเดฟเดจเต เดˆ เดฒเดฟเด™เตเด•เต เดชเดฟเดจเตเดคเตเดŸเดฐเตเด•.", - "emails.recovery.footer": "เดจเดฟเด™เตเด™เดณเตเดŸเต† เดชเดพเดธเตโ€Œเดตเต‡เดกเต เดชเตเดจเด•เตเดฐเดฎเต€เด•เดฐเดฟเด•เตเด•เดพเดจเตโ€ เดจเดฟเด™เตเด™เตพ เด†เดตเดถเตเดฏเดชเตเดชเต†เดŸเตเดŸเดฟเดฒเตเดฒเต†เด™เตเด•เดฟเตฝ, เดˆ เดธเดจเตเดฆเต‡เดถเด‚ เด…เดตเด—เดฃเดฟเด•เตเด•เดพเดตเตเดจเตเดจเดคเดพเดฃเต.", + "emails.recovery.footer": "เดจเดฟเด™เตเด™เดณเตเดŸเต† เดฐเดนเดธเตเดฏเดตเดพเด•เตเด•เต เดชเตเดจเด•เตเดฐเดฎเต€เด•เดฐเดฟเด•เตเด•เดพเดจเตโ€ เดจเดฟเด™เตเด™เตพ เด†เดตเดถเตเดฏเดชเตเดชเต†เดŸเตเดŸเดฟเดฒเตเดฒเต†เด™เตเด•เดฟเตฝ, เดˆ เดธเดจเตเดฆเต‡เดถเด‚ เด…เดตเด—เดฃเดฟเด•เตเด•เดพเดตเตเดจเตเดจเดคเดพเดฃเต.", "emails.recovery.thanks": "เดจเดจเตเดฆเดฟ", "emails.recovery.signature": "{{project}} เดŸเต€เด‚", "emails.invitation.subject": "%s -เดฒเต† %s เดŸเต€เดฎเดฟเดฒเต‡เด•เตเด•เตเดณเตเดณ เด•เตเดทเดฃเด‚", "emails.invitation.hello": "เดจเดฎเดธเตเด•เดพเดฐเด‚", - "emails.invitation.body": "เดจเดฟเด™เตเด™เดณเต† {{project}} -เดฒเต† {{team}} เดŸเต€เดฎเดฟเดฒเต† เด…เด‚เด—เดฎเดพเด•เตเดตเดพเดจเตโ€ เด•เตเดทเดฃเดฟเด•เตเด•เดพเตป {{owner}} เด†เด—เตเดฐเดนเดฟเด•เตเด•เตเดคเดฟเดจเดพเดฒเดพเดฃเต เดˆ เดฎเต†เดฏเดฟเตฝ เดจเดฟเด™เตเด™เตพเด•เตเด•เต เด…เดฏเด•เตเด•เตเดจเตเดจเดคเต.", + "emails.invitation.body": "เดจเดฟเด™เตเด™เดณเต† {{project}} -เดฒเต† {{team}} เดŸเต€เดฎเดฟเดฒเต† เด…เด‚เด—เดฎเดพเด•เตเดตเดพเดจเตโ€ เด•เตเดทเดฃเดฟเด•เตเด•เดพเตป {{owner}} เด†เด—เตเดฐเดนเดฟเด•เตเด•เตเดจเตเดจเดคเดฟเดจเดพเดฒเดพเดฃเต เดˆ เดฎเต†เดฏเดฟเตฝ เดจเดฟเด™เตเด™เตพเด•เตเด•เต เด…เดฏเด•เตเด•เตเดจเตเดจเดคเต.", "emails.invitation.footer": "เดจเดฟเด™เตเด™เตพเด•เตเด•เต เดคเดพเตฝเดชเตเดชเดฐเตเดฏเดฎเดฟเดฒเตเดฒเต†เด™เตเด•เดฟเตฝ, เดˆ เดธเดจเตเดฆเต‡เดถเด‚ เด…เดตเด—เดฃเดฟเด•เตเด•เดพเดตเตเดจเตเดจเดคเดพเดฃเต.", "emails.invitation.thanks": "เดจเดจเตเดฆเดฟ", "emails.invitation.signature": "{{project}} เดŸเต€เด‚", @@ -229,4 +229,4 @@ "continents.na": "เดตเดŸเด•เตเด•เต‡ เด…เดฎเต‡เดฐเดฟเด•เตเด•", "continents.oc": "เด“เดทเตเดฏเดพเดจเดฟเดฏ", "continents.sa": "เดคเต†เด•เตเด•เต‡ เด…เดฎเต‡เดฐเดฟเด•เตเด•" -} \ No newline at end of file +} diff --git a/app/config/platforms.php b/app/config/platforms.php index 53d64c34e4..3219ba06c3 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -15,7 +15,7 @@ return [ [ 'key' => 'web', 'name' => 'Web', - 'version' => '8.0.0', + 'version' => '8.0.1', 'url' => 'https://github.com/appwrite/sdk-for-web', 'package' => 'https://www.npmjs.com/package/appwrite', 'enabled' => true, @@ -180,7 +180,7 @@ return [ [ 'key' => 'cli', 'name' => 'Command Line', - 'version' => '0.17.0', + 'version' => '0.17.1', 'url' => 'https://github.com/appwrite/sdk-for-cli', 'package' => 'https://www.npmjs.com/package/appwrite-cli', 'enabled' => true, @@ -352,7 +352,7 @@ return [ [ 'key' => 'dart', 'name' => 'Dart', - 'version' => '5.0.0', + 'version' => '5.0.1', 'url' => 'https://github.com/appwrite/sdk-for-dart', 'package' => 'https://pub.dev/packages/dart_appwrite', 'enabled' => true, diff --git a/app/config/runtimes.php b/app/config/runtimes.php index 9002016aa0..03be3f07fc 100644 --- a/app/config/runtimes.php +++ b/app/config/runtimes.php @@ -1,15 +1,16 @@ getAll(true, $allowList); -return $runtimes; \ No newline at end of file +return $runtimes; diff --git a/app/config/scopes.php b/app/config/scopes.php index 45919e7cb0..0b9879b649 100644 --- a/app/config/scopes.php +++ b/app/config/scopes.php @@ -70,4 +70,4 @@ return [ // List of publicly visible scopes 'health.read' => [ 'description' => 'Access to read your project\'s health status', ], -];; \ No newline at end of file +]; diff --git a/app/config/services.php b/app/config/services.php index 17375c360a..2225112ea9 100644 --- a/app/config/services.php +++ b/app/config/services.php @@ -43,7 +43,7 @@ return [ 'avatars' => [ 'key' => 'avatars', 'name' => 'Avatars', - 'subtitle'=> 'The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars.', + 'subtitle' => 'The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars.', 'description' => '/docs/services/avatars.md', 'controller' => 'api/avatars.php', 'sdk' => true, diff --git a/app/config/storage/inputs.php b/app/config/storage/inputs.php index c580316c53..3b83269261 100644 --- a/app/config/storage/inputs.php +++ b/app/config/storage/inputs.php @@ -5,4 +5,4 @@ return [ // Accepted inputs files 'jpeg' => 'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png', -]; \ No newline at end of file +]; diff --git a/app/config/storage/logos.php b/app/config/storage/logos.php index 8816611edc..9db9096537 100644 --- a/app/config/storage/logos.php +++ b/app/config/storage/logos.php @@ -1,18 +1,22 @@ __DIR__.'/logos/none.png', - 'default_image' => __DIR__.'/logos/image.png', - + 'default' => __DIR__ . '/logos/none.png', + 'default_image' => __DIR__ . '/logos/image.png', + // Video Files - 'video/mp4' => __DIR__.'/logos/video.png', - 'video/x-flv' => __DIR__.'/logos/video.png', - 'application/x-mpegURL' => __DIR__.'/logos/video.png', - 'video/MP2T' => __DIR__.'/logos/video.png', - 'video/3gpp' => __DIR__.'/logos/video.png', - 'video/quicktime' => __DIR__.'/logos/video.png', - 'video/x-msvideo' => __DIR__.'/logos/video.png', - 'video/x-ms-wmv' => __DIR__.'/logos/video.png', + + 'video/mp4' => __DIR__ . '/logos/video.png', + 'video/x-flv' => __DIR__ . '/logos/video.png', + 'video/webm' => __DIR__ . '/logos/video.png', + 'application/x-mpegURL' => __DIR__ . '/logos/video.png', + 'video/MP2T' => __DIR__ . '/logos/video.png', + 'video/3gpp' => __DIR__ . '/logos/video.png', + 'video/quicktime' => __DIR__ . '/logos/video.png', + 'video/x-msvideo' => __DIR__ . '/logos/video.png', + 'video/x-ms-wmv' => __DIR__ . '/logos/video.png', + + // // Microsoft Word // 'application/msword' => __DIR__.'/logos/word.png', @@ -41,4 +45,4 @@ return [ // Based on this list @see http://stackoverflow.com/a/4212908/2299554 // Adobe PDF // 'application/pdf' => __DIR__.'/logos/pdf.png', -]; \ No newline at end of file +]; diff --git a/app/config/storage/mimes.php b/app/config/storage/mimes.php index 7995ef368a..3e3cad3698 100644 --- a/app/config/storage/mimes.php +++ b/app/config/storage/mimes.php @@ -10,6 +10,7 @@ return [ // Video Files 'video/mp4', 'video/x-flv', + 'video/webm', 'application/x-mpegURL', 'video/MP2T', 'video/3gpp', @@ -30,7 +31,7 @@ return [ 'audio/ogg', // Ogg Vorbis RFC 5334 'audio/vorbis', // Vorbis RFC 5215 'audio/vnd.wav', // wav RFC 2361 - + // Microsoft Word 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', @@ -61,4 +62,4 @@ return [ // Adobe PDF 'application/pdf', -]; \ No newline at end of file +]; diff --git a/app/config/storage/outputs.php b/app/config/storage/outputs.php index dc521df9e4..507a9ce667 100644 --- a/app/config/storage/outputs.php +++ b/app/config/storage/outputs.php @@ -6,4 +6,4 @@ return [ // Accepted outputs files 'gif' => 'image/gif', 'png' => 'image/png', 'webp' => 'image/webp', -]; \ No newline at end of file +]; diff --git a/app/config/variables.php b/app/config/variables.php index 49f2d7cfee..df9b3c76c3 100644 --- a/app/config/variables.php +++ b/app/config/variables.php @@ -1,6 +1,7 @@ 'General', @@ -439,7 +440,7 @@ return [ ], [ 'name' => '_APP_STORAGE_DEVICE', - 'description' => 'Select default storage device. The default value is \'Local\'. List of supported adapters are \'Local\', \'S3\' and \'DOSpaces\'.', + 'description' => 'Select default storage device. The default value is \'Local\'. List of supported adapters are \'Local\', \'S3\', \'DOSpaces\', \'Backblaze\', \'Linode\' and \'Wasabi\'.', 'introduction' => '0.13.0', 'default' => 'Local', 'required' => false, @@ -509,6 +510,102 @@ return [ 'required' => false, 'question' => '', ], + [ + 'name' => '_APP_STORAGE_BACKBLAZE_ACCESS_KEY', + 'description' => 'Backblaze access key. Required when the storage adapter is set to Backblaze. Your Backblaze keyID will be your access key. You can get your keyID from your Backblaze console.', + 'introduction' => '0.14.2', + 'default' => '', + 'required' => false, + 'question' => '', + ], + [ + 'name' => '_APP_STORAGE_BACKBLAZE_SECRET', + 'description' => 'Backblaze secret key. Required when the storage adapter is set to Backblaze. Your Backblaze applicationKey will be your secret key. You can get your applicationKey from your Backblaze console.', + 'introduction' => '0.14.2', + 'default' => '', + 'required' => false, + 'question' => '', + ], + [ + 'name' => '_APP_STORAGE_BACKBLAZE_REGION', + 'description' => 'Backblaze region. Required when storage adapter is set to Backblaze. You can find your region info from your Backblaze console.', + 'introduction' => '0.14.2', + 'default' => 'us-west-004', + 'required' => false, + 'question' => '', + ], + [ + 'name' => '_APP_STORAGE_BACKBLAZE_BUCKET', + 'description' => 'Backblaze bucket. Required when storage adapter is set to Backblaze. You can create your bucket from your Backblaze console.', + 'introduction' => '0.14.2', + 'default' => '', + 'required' => false, + 'question' => '', + ], + [ + 'name' => '_APP_STORAGE_LINODE_ACCESS_KEY', + 'description' => 'Linode object storage access key. Required when the storage adapter is set to Linode. You can get your access key from your Linode console.', + 'introduction' => '0.14.2', + 'default' => '', + 'required' => false, + 'question' => '', + ], + [ + 'name' => '_APP_STORAGE_LINODE_SECRET', + 'description' => 'Linode object storage secret key. Required when the storage adapter is set to Linode. You can get your secret key from your Linode console.', + 'introduction' => '0.14.2', + 'default' => '', + 'required' => false, + 'question' => '', + ], + [ + 'name' => '_APP_STORAGE_LINODE_REGION', + 'description' => 'Linode object storage region. Required when storage adapter is set to Linode. You can find your region info from your Linode console.', + 'introduction' => '0.14.2', + 'default' => 'eu-central-1', + 'required' => false, + 'question' => '', + ], + [ + 'name' => '_APP_STORAGE_LINODE_BUCKET', + 'description' => 'Linode object storage bucket. Required when storage adapter is set to Linode. You can create buckets in your Linode console.', + 'introduction' => '0.14.2', + 'default' => '', + 'required' => false, + 'question' => '', + ], + [ + 'name' => '_APP_STORAGE_WASABI_ACCESS_KEY', + 'description' => 'Wasabi access key. Required when the storage adapter is set to Wasabi. You can get your access key from your Wasabi console.', + 'introduction' => '0.14.2', + 'default' => '', + 'required' => false, + 'question' => '', + ], + [ + 'name' => '_APP_STORAGE_WASABI_SECRET', + 'description' => 'Wasabi secret key. Required when the storage adapter is set to Wasabi. You can get your secret key from your Wasabi console.', + 'introduction' => '0.14.2', + 'default' => '', + 'required' => false, + 'question' => '', + ], + [ + 'name' => '_APP_STORAGE_WASABI_REGION', + 'description' => 'Wasabi region. Required when storage adapter is set to Wasabi. You can find your region info from your Wasabi console.', + 'introduction' => '0.14.2', + 'default' => 'eu-central-1', + 'required' => false, + 'question' => '', + ], + [ + 'name' => '_APP_STORAGE_WASABI_BUCKET', + 'description' => 'Wasabi bucket. Required when storage adapter is set to Wasabi. You can create buckets in your Wasabi console.', + 'introduction' => '0.14.2', + 'default' => '', + 'required' => false, + 'question' => '', + ], ], ], [ diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 29d0ccc8a5..10c9789882 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -4,22 +4,30 @@ use Ahc\Jwt\JWT; use Appwrite\Auth\Auth; use Appwrite\Auth\Validator\Password; use Appwrite\Detector\Detector; +use Appwrite\Event\Event; +use Appwrite\Event\Mail; use Appwrite\Network\Validator\Email; use Appwrite\Network\Validator\Host; use Appwrite\Network\Validator\URL; use Appwrite\OpenSSL\OpenSSL; +use Appwrite\Stats\Stats; use Appwrite\Template\Template; use Appwrite\URL\URL as URLParser; +use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Appwrite\Utopia\Database\Validator\CustomId; +use MaxMind\Db\Reader; use Utopia\App; -use Utopia\Audit\Audit; +use Appwrite\Event\Audit; +use Utopia\Audit\Audit as EventAudit; use Utopia\Config\Config; +use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Exception\Duplicate; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; +use Utopia\Locale\Locale; use Appwrite\Extend\Exception; use Utopia\Validator\ArrayList; use Utopia\Validator\Assoc; @@ -55,14 +63,7 @@ App::post('/v1/account') ->inject('audits') ->inject('usage') ->inject('events') - ->action(function ($userId, $email, $password, $name, $request, $response, $project, $dbForProject, $audits, $usage, $events) { - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $project */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $userId, string $email, string $password, string $name, Request $request, Response $response, Document $project, Database $dbForProject, Audit $audits, Stats $usage, Event $events) { $email = \strtolower($email); if ('console' === $project->getId()) { @@ -117,7 +118,7 @@ App::post('/v1/account') Authorization::setRole('role:' . Auth::USER_ROLE_MEMBER); $audits - ->setResource('user/'.$user->getId()) + ->setResource('user/' . $user->getId()) ->setUser($user) ; @@ -153,22 +154,13 @@ App::post('/v1/account/sessions') ->inject('audits') ->inject('usage') ->inject('events') - ->action(function ($email, $password, $request, $response, $dbForProject, $locale, $geodb, $audits, $usage, $events) { - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Locale\Locale $locale */ - /** @var MaxMind\Db\Reader $geodb */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $email, string $password, Request $request, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Audit $audits, Stats $usage, Event $events) { $email = \strtolower($email); $protocol = $request->getProtocol(); $profile = $dbForProject->findOne('users', [ - new Query('email', Query::TYPE_EQUAL, [$email])] - ); + new Query('email', Query::TYPE_EQUAL, [$email])]); if (!$profile || !Auth::passwordVerify($password, $profile->getAttribute('password'))) { throw new Exception('Invalid credentials', 401, Exception::USER_INVALID_CREDENTIALS); // Wrong password or username @@ -193,20 +185,22 @@ App::post('/v1/account/sessions') 'userAgent' => $request->getUserAgent('UNKNOWN'), 'ip' => $request->getIP(), 'countryCode' => ($record) ? \strtolower($record['country']['iso_code']) : '--', - ], $detector->getOS(), $detector->getClient(), $detector->getDevice() + ], + $detector->getOS(), + $detector->getClient(), + $detector->getDevice() )); Authorization::setRole('user:' . $profile->getId()); $session = $dbForProject->createDocument('sessions', $session ->setAttribute('$read', ['user:' . $profile->getId()]) - ->setAttribute('$write', ['user:' . $profile->getId()]) - ); + ->setAttribute('$write', ['user:' . $profile->getId()])); $dbForProject->deleteCachedDocument('users', $profile->getId()); $audits - ->setResource('user/'.$profile->getId()) + ->setResource('user/' . $profile->getId()) ->setUser($profile) ; @@ -222,7 +216,7 @@ App::post('/v1/account/sessions') ->setStatusCode(Response::STATUS_CODE_CREATED) ; - $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session ->setAttribute('current', true) @@ -257,22 +251,19 @@ App::get('/v1/account/sessions/oauth2/:provider') ->label('sdk.methodType', 'webAuth') ->label('abuse-limit', 50) ->label('abuse-key', 'ip:{ip}') - ->param('provider', '', new WhiteList(\array_keys(Config::getParam('providers')), true), 'OAuth2 Provider. Currently, supported providers are: ' . \implode(', ', \array_keys(\array_filter(Config::getParam('providers'), function($node) {return (!$node['mock']);}))).'.') - ->param('success', '', function ($clients) { return new Host($clients); }, 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) - ->param('failure', '', function ($clients) { return new Host($clients); }, 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) + ->param('provider', '', new WhiteList(\array_keys(Config::getParam('providers')), true), 'OAuth2 Provider. Currently, supported providers are: ' . \implode(', ', \array_keys(\array_filter(Config::getParam('providers'), fn($node) => (!$node['mock'])))) . '.') + ->param('success', '', fn($clients) => new Host($clients), 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) + ->param('failure', '', fn($clients) => new Host($clients), 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) ->param('scopes', [], new ArrayList(new Text(128), APP_LIMIT_ARRAY_PARAMS_SIZE), 'A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed, each 128 characters long.', true) ->inject('request') ->inject('response') ->inject('project') - ->action(function ($provider, $success, $failure, $scopes, $request, $response, $project) use ($oauthDefaultSuccess, $oauthDefaultFailure) { - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $project */ + ->action(function (string $provider, string $success, string $failure, array $scopes, Request $request, Response $response, Document $project) use ($oauthDefaultSuccess, $oauthDefaultFailure) { $protocol = $request->getProtocol(); - $callback = $protocol.'://'.$request->getHostname().'/v1/account/sessions/oauth2/callback/'.$provider.'/'.$project->getId(); - $appId = $project->getAttribute('authProviders', [])[$provider.'Appid'] ?? ''; - $appSecret = $project->getAttribute('authProviders', [])[$provider.'Secret'] ?? '{}'; + $callback = $protocol . '://' . $request->getHostname() . '/v1/account/sessions/oauth2/callback/' . $provider . '/' . $project->getId(); + $appId = $project->getAttribute('authProviders', [])[$provider . 'Appid'] ?? ''; + $appSecret = $project->getAttribute('authProviders', [])[$provider . 'Secret'] ?? '{}'; if (!empty($appSecret) && isset($appSecret['version'])) { $key = App::getEnv('_APP_OPENSSL_KEY_V' . $appSecret['version']); @@ -283,17 +274,17 @@ App::get('/v1/account/sessions/oauth2/:provider') throw new Exception('This provider is disabled. Please configure the provider app ID and app secret key from your ' . APP_NAME . ' console to continue.', 412, Exception::PROJECT_PROVIDER_DISABLED); } - $className = 'Appwrite\\Auth\\OAuth2\\'.\ucfirst($provider); + $className = 'Appwrite\\Auth\\OAuth2\\' . \ucfirst($provider); if (!\class_exists($className)) { throw new Exception('Provider is not supported', 501, Exception::PROJECT_PROVIDER_UNSUPPORTED); } - if(empty($success)) { + if (empty($success)) { $success = $protocol . '://' . $request->getHostname() . $oauthDefaultSuccess; } - if(empty($failure)) { + if (empty($failure)) { $failure = $protocol . '://' . $request->getHostname() . $oauthDefaultFailure; } @@ -317,9 +308,7 @@ App::get('/v1/account/sessions/oauth2/callback/:provider/:projectId') ->param('state', '', new Text(2048), 'Login state params.', true) ->inject('request') ->inject('response') - ->action(function ($projectId, $provider, $code, $state, $request, $response) { - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ + ->action(function (string $projectId, string $provider, string $code, string $state, Request $request, Response $response) { $domain = $request->getHostname(); $protocol = $request->getProtocol(); @@ -344,9 +333,7 @@ App::post('/v1/account/sessions/oauth2/callback/:provider/:projectId') ->param('state', '', new Text(2048), 'Login state params.', true) ->inject('request') ->inject('response') - ->action(function ($projectId, $provider, $code, $state, $request, $response) { - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ + ->action(function (string $projectId, string $provider, string $code, string $state, Request $request, Response $response) { $domain = $request->getHostname(); $protocol = $request->getProtocol(); @@ -379,23 +366,14 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') ->inject('audits') ->inject('events') ->inject('usage') - ->action(function ($provider, $code, $state, $request, $response, $project, $user, $dbForProject, $geodb, $audits, $events, $usage) use ($oauthDefaultSuccess) { - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $project */ - /** @var Utopia\Database\Document $user */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var MaxMind\Db\Reader $geodb */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Event\Event $events */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (string $provider, string $code, string $state, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Reader $geodb, Audit $audits, Event $events, Stats $usage) use ($oauthDefaultSuccess) { $protocol = $request->getProtocol(); $callback = $protocol . '://' . $request->getHostname() . '/v1/account/sessions/oauth2/callback/' . $provider . '/' . $project->getId(); $defaultState = ['success' => $project->getAttribute('url', ''), 'failure' => '']; $validateURL = new URL(); - $appId = $project->getAttribute('authProviders', [])[$provider.'Appid'] ?? ''; - $appSecret = $project->getAttribute('authProviders', [])[$provider.'Secret'] ?? '{}'; + $appId = $project->getAttribute('authProviders', [])[$provider . 'Appid'] ?? ''; + $appSecret = $project->getAttribute('authProviders', [])[$provider . 'Secret'] ?? '{}'; if (!empty($appSecret) && isset($appSecret['version'])) { $key = App::getEnv('_APP_OPENSSL_KEY_V' . $appSecret['version']); @@ -431,7 +409,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $state['failure'] = null; $accessToken = $oauth2->getAccessToken($code); - $refreshToken =$oauth2->getRefreshToken($code); + $refreshToken = $oauth2->getRefreshToken($code); $accessTokenExpiry = $oauth2->getAccessTokenExpiry($code); if (empty($accessToken)) { @@ -457,7 +435,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') if ($current) { // Delete current session of new one. $currentDocument = $dbForProject->getDocument('sessions', $current); - if(!$currentDocument->isEmpty()) { + if (!$currentDocument->isEmpty()) { $dbForProject->deleteDocument('sessions', $currentDocument->getId()); $dbForProject->deleteCachedDocument('users', $user->getId()); } @@ -478,8 +456,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $isVerified = $oauth2->isEmailVerified($accessToken); $user = $dbForProject->findOne('users', [ - new Query('email', Query::TYPE_EQUAL, [$email])] - ); + new Query('email', Query::TYPE_EQUAL, [$email])]); if ($user === false || $user->isEmpty()) { // Last option -> create the user, generate random password $limit = $project->getAttribute('auths', [])['limit'] ?? 0; @@ -561,20 +538,19 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $session = $dbForProject->createDocument('sessions', $session ->setAttribute('$read', ['user:' . $user->getId()]) - ->setAttribute('$write', ['user:' . $user->getId()]) - ); + ->setAttribute('$write', ['user:' . $user->getId()])); $dbForProject->deleteCachedDocument('users', $user->getId()); $audits - ->setResource('user/'.$user->getId()) + ->setResource('user/' . $user->getId()) ->setUser($user) ; $usage ->setParam('users.sessions.create', 1) ->setParam('projectId', $project->getId()) - ->setParam('provider', 'oauth2-'.$provider) + ->setParam('provider', 'oauth2-' . $provider) ; $events @@ -625,7 +601,7 @@ App::post('/v1/account/sessions/magic-url') ->label('abuse-key', 'url:{url},email:{param-email}') ->param('userId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string "unique()" to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') ->param('email', '', new Email(), 'User email.') - ->param('url', '', function ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) + ->param('url', '', fn($clients) => new Host($clients), 'URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) ->inject('request') ->inject('response') ->inject('project') @@ -634,17 +610,9 @@ App::post('/v1/account/sessions/magic-url') ->inject('audits') ->inject('events') ->inject('mails') - ->action(function ($userId, $email, $url, $request, $response, $project, $dbForProject, $locale, $audits, $events, $mails) { - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $project */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Locale\Locale $locale */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Event\Event $events */ - /** @var Appwrite\Event\Mail $mails */ + ->action(function (string $userId, string $email, string $url, Request $request, Response $response, Document $project, Database $dbForProject, Locale $locale, Audit $audits, Event $events, Mail $mails) { - if(empty(App::getEnv('_APP_SMTP_HOST'))) { + if (empty(App::getEnv('_APP_SMTP_HOST'))) { throw new Exception('SMTP Disabled', 503, Exception::GENERAL_SMTP_DISABLED); } @@ -700,17 +668,16 @@ App::post('/v1/account/sessions/magic-url') 'ip' => $request->getIP(), ]); - Authorization::setRole('user:'.$user->getId()); + Authorization::setRole('user:' . $user->getId()); $token = $dbForProject->createDocument('tokens', $token - ->setAttribute('$read', ['user:'.$user->getId()]) - ->setAttribute('$write', ['user:'.$user->getId()]) - ); + ->setAttribute('$read', ['user:' . $user->getId()]) + ->setAttribute('$write', ['user:' . $user->getId()])); $dbForProject->deleteCachedDocument('users', $user->getId()); - if(empty($url)) { - $url = $request->getProtocol().'://'.$request->getHostname().'/auth/magic-url'; + if (empty($url)) { + $url = $request->getProtocol() . '://' . $request->getHostname() . '/auth/magic-url'; } $url = Template::parseURL($url); @@ -736,7 +703,7 @@ App::post('/v1/account/sessions/magic-url') $token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $loginSecret : ''); $audits - ->setResource('user/'.$user->getId()) + ->setResource('user/' . $user->getId()) ->setUser($user) ; @@ -769,16 +736,7 @@ App::put('/v1/account/sessions/magic-url') ->inject('geodb') ->inject('audits') ->inject('events') - ->action(function ($userId, $secret, $request, $response, $dbForProject, $locale, $geodb, $audits, $events) { - /** @var string $userId */ - /** @var string $secret */ - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Locale\Locale $locale */ - /** @var MaxMind\Db\Reader $geodb */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $userId, string $secret, Request $request, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Audit $audits, Event $events) { $user = Authorization::skip(fn() => $dbForProject->getDocument('users', $userId)); @@ -816,8 +774,7 @@ App::put('/v1/account/sessions/magic-url') $session = $dbForProject->createDocument('sessions', $session ->setAttribute('$read', ['user:' . $user->getId()]) - ->setAttribute('$write', ['user:' . $user->getId()]) - ); + ->setAttribute('$write', ['user:' . $user->getId()])); $dbForProject->deleteCachedDocument('users', $user->getId()); @@ -838,7 +795,7 @@ App::put('/v1/account/sessions/magic-url') throw new Exception('Failed saving user to DB', 500, Exception::GENERAL_SERVER_ERROR); } - $audits->setResource('user/'.$user->getId()); + $audits->setResource('user/' . $user->getId()); $events ->setParam('userId', $user->getId()) @@ -852,12 +809,12 @@ App::put('/v1/account/sessions/magic-url') $protocol = $request->getProtocol(); $response - ->addCookie(Auth::$cookieName.'_legacy', Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->addCookie(Auth::$cookieName . '_legacy', Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) ->addCookie(Auth::$cookieName, Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite')) ->setStatusCode(Response::STATUS_CODE_CREATED) ; - $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session ->setAttribute('current', true) @@ -892,17 +849,7 @@ App::post('/v1/account/sessions/anonymous') ->inject('audits') ->inject('usage') ->inject('events') - ->action(function ($request, $response, $locale, $user, $project, $dbForProject, $geodb, $audits, $usage, $events) { - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Locale\Locale $locale */ - /** @var Utopia\Database\Document $user */ - /** @var Utopia\Database\Document $project */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var MaxMind\Db\Reader $geodb */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Stats\Stats $events */ + ->action(function (Request $request, Response $response, Locale $locale, Document $user, Document $project, Database $dbForProject, Reader $geodb, Audit $audits, Stats $usage, Event $events) { $protocol = $request->getProtocol(); @@ -970,12 +917,11 @@ App::post('/v1/account/sessions/anonymous') $session = $dbForProject->createDocument('sessions', $session ->setAttribute('$read', ['user:' . $user->getId()]) - ->setAttribute('$write', ['user:' . $user->getId()]) - ); + ->setAttribute('$write', ['user:' . $user->getId()])); $dbForProject->deleteCachedDocument('users', $user->getId()); - $audits->setResource('user/'.$user->getId()); + $audits->setResource('user/' . $user->getId()); $usage ->setParam('users.sessions.create', 1) @@ -997,7 +943,7 @@ App::post('/v1/account/sessions/anonymous') ->setStatusCode(Response::STATUS_CODE_CREATED) ; - $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session ->setAttribute('current', true) @@ -1024,10 +970,7 @@ App::post('/v1/account/jwt') ->inject('response') ->inject('user') ->inject('dbForProject') - ->action(function ($response, $user, $dbForProject) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $user */ - /** @var Utopia\Database\Database $dbForProject */ + ->action(function (Response $response, Document $user, Database $dbForProject) { $sessions = $user->getAttribute('sessions', []); @@ -1070,10 +1013,7 @@ App::get('/v1/account') ->inject('response') ->inject('user') ->inject('usage') - ->action(function ($response, $user, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $user */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (Response $response, Document $user, Stats $usage) { $usage->setParam('users.read', 1); @@ -1094,10 +1034,7 @@ App::get('/v1/account/prefs') ->inject('response') ->inject('user') ->inject('usage') - ->action(function ($response, $user, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $user */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (Response $response, Document $user, Stats $usage) { $prefs = $user->getAttribute('prefs', new \stdClass()); @@ -1121,17 +1058,13 @@ App::get('/v1/account/sessions') ->inject('user') ->inject('locale') ->inject('usage') - ->action(function ($response, $user, $locale, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $user */ - /** @var Utopia\Locale\Locale $locale */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (Response $response, Document $user, Locale $locale, Stats $usage) { $sessions = $user->getAttribute('sessions', []); $current = Auth::sessionVerify($sessions, Auth::$secret); foreach ($sessions as $key => $session) {/** @var Document $session */ - $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session->setAttribute('countryName', $countryName); $session->setAttribute('current', ($current == $session->getId()) ? true : false); @@ -1166,16 +1099,9 @@ App::get('/v1/account/logs') ->inject('geodb') ->inject('dbForProject') ->inject('usage') - ->action(function ($limit, $offset, $response, $user, $locale, $geodb, $dbForProject, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $project */ - /** @var Utopia\Database\Document $user */ - /** @var Utopia\Locale\Locale $locale */ - /** @var MaxMind\Db\Reader $geodb */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (int $limit, int $offset, Response $response, Document $user, Locale $locale, Reader $geodb, Database $dbForProject, Stats $usage) { - $audit = new Audit($dbForProject); + $audit = new EventAudit($dbForProject); $logs = $audit->getLogsByUser($user->getId(), $limit, $offset); @@ -1197,13 +1123,12 @@ App::get('/v1/account/logs') $record = $geodb->get($log['ip']); if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); } else { $output[$i]['countryCode'] = '--'; $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); } - } $usage->setParam('users.read', 1); @@ -1231,12 +1156,7 @@ App::get('/v1/account/sessions/:sessionId') ->inject('locale') ->inject('dbForProject') ->inject('usage') - ->action(function ($sessionId, $response, $user, $locale, $dbForProject, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $user */ - /** @var Utopia\Locale\Locale $locale */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (?string $sessionId, Response $response, Document $user, Locale $locale, Database $dbForProject, Stats $usage) { $sessions = $user->getAttribute('sessions', []); $sessionId = ($sessionId === 'current') @@ -1245,7 +1165,7 @@ App::get('/v1/account/sessions/:sessionId') foreach ($sessions as $session) {/** @var Document $session */ if ($sessionId == $session->getId()) { - $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session ->setAttribute('current', ($session->getAttribute('secret') == Auth::hash(Auth::$secret))) @@ -1280,21 +1200,14 @@ App::patch('/v1/account/name') ->inject('audits') ->inject('usage') ->inject('events') - ->action(function ($name, $response, $user, $dbForProject, $audits, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $user */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Stats\Stats $events */ + ->action(function (string $name, Response $response, Document $user, Database $dbForProject, Audit $audits, Stats $usage, Event $events) { $user = $dbForProject->updateDocument('users', $user->getId(), $user ->setAttribute('name', $name) - ->setAttribute('search', implode(' ', [$user->getId(), $name, $user->getAttribute('email')])) - ); + ->setAttribute('search', implode(' ', [$user->getId(), $name, $user->getAttribute('email')]))); $audits - ->setResource('user/'.$user->getId()) + ->setResource('user/' . $user->getId()) ->setUser($user) ; @@ -1324,13 +1237,7 @@ App::patch('/v1/account/password') ->inject('audits') ->inject('usage') ->inject('events') - ->action(function ($password, $oldPassword, $response, $user, $dbForProject, $audits, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $user */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Stats\Stats $events */ + ->action(function (string $password, string $oldPassword, Response $response, Document $user, Database $dbForProject, Audit $audits, Stats $usage, Event $events) { // Check old password only if its an existing user. if ($user->getAttribute('passwordUpdate') !== 0 && !Auth::passwordVerify($oldPassword, $user->getAttribute('password'))) { // Double check user password @@ -1346,7 +1253,7 @@ App::patch('/v1/account/password') ); $audits - ->setResource('user/'.$user->getId()) + ->setResource('user/' . $user->getId()) ->setUser($user) ; @@ -1376,13 +1283,7 @@ App::patch('/v1/account/email') ->inject('audits') ->inject('usage') ->inject('events') - ->action(function ($email, $password, $response, $user, $dbForProject, $audits, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $user */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Stats\Stats $events */ + ->action(function (string $email, string $password, Response $response, Document $user, Database $dbForProject, Audit $audits, Stats $usage, Event $events) { $isAnonymousUser = is_null($user->getAttribute('email')) && is_null($user->getAttribute('password')); // Check if request is from an anonymous account for converting @@ -1405,14 +1306,13 @@ App::patch('/v1/account/email') ->setAttribute('password', $isAnonymousUser ? Auth::passwordHash($password) : $user->getAttribute('password', '')) ->setAttribute('email', $email) ->setAttribute('emailVerification', false) // After this user needs to confirm mail again - ->setAttribute('search', implode(' ', [$user->getId(), $user->getAttribute('name'), $user->getAttribute('email')])) - ); - } catch(Duplicate $th) { + ->setAttribute('search', implode(' ', [$user->getId(), $user->getAttribute('name'), $user->getAttribute('email')]))); + } catch (Duplicate $th) { throw new Exception('Email already exists', 409, Exception::USER_EMAIL_ALREADY_EXISTS); } $audits - ->setResource('user/'.$user->getId()) + ->setResource('user/' . $user->getId()) ->setUser($user) ; @@ -1441,17 +1341,11 @@ App::patch('/v1/account/prefs') ->inject('audits') ->inject('usage') ->inject('events') - ->action(function ($prefs, $response, $user, $dbForProject, $audits, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $user */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ + ->action(function (array $prefs, Response $response, Document $user, Database $dbForProject, Audit $audits, Stats $usage, Event $events) { $user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('prefs', $prefs)); - $audits->setResource('user/'.$user->getId()); + $audits->setResource('user/' . $user->getId()); $usage->setParam('users.update', 1); $events->setParam('userId', $user->getId()); @@ -1477,14 +1371,7 @@ App::patch('/v1/account/status') ->inject('audits') ->inject('events') ->inject('usage') - ->action(function ($request, $response, $user, $dbForProject, $audits, $events, $usage) { - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $user */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Event\Event $events */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Audit $audits, Event $events, Stats $usage) { $user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('status', false)); @@ -1526,15 +1413,7 @@ App::delete('/v1/account/sessions/:sessionId') ->inject('audits') ->inject('events') ->inject('usage') - ->action(function ($sessionId, $request, $response, $user, $dbForProject, $locale, $audits, $events, $usage) { - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $user */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Locale\Locale $locale */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Event\Event $events */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (?string $sessionId, Request $request, Response $response, Document $user, Database $dbForProject, Locale $locale, Audit $audits, Event $events, Stats $usage) { $protocol = $request->getProtocol(); $sessionId = ($sessionId === 'current') @@ -1556,7 +1435,7 @@ App::delete('/v1/account/sessions/:sessionId') if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too $session ->setAttribute('current', true) - ->setAttribute('countryName', $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown'))) + ->setAttribute('countryName', $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown'))) ; if (!Config::getParam('domainVerification')) { @@ -1570,7 +1449,7 @@ App::delete('/v1/account/sessions/:sessionId') ->addCookie(Auth::$cookieName, '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite')) ; } - + $dbForProject->deleteCachedDocument('users', $user->getId()); $events @@ -1613,17 +1492,7 @@ App::patch('/v1/account/sessions/:sessionId') ->inject('audits') ->inject('events') ->inject('usage') - ->action(function ($sessionId, $request, $response, $user, $dbForProject, $project, $locale, $audits, $events, $usage) { - /** @var Appwrite\Utopia\Request $request */ - /** @var boolean $force */ - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $user */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Database\Document $project */ - /** @var Utopia\Locale\Locale $locale */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Event\Event $events */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (?string $sessionId, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Audit $audits, Event $events, Stats $usage) { $sessionId = ($sessionId === 'current') ? Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret) @@ -1633,7 +1502,6 @@ App::patch('/v1/account/sessions/:sessionId') foreach ($sessions as $key => $session) {/** @var Document $session */ if ($sessionId == $session->getId()) { - // Comment below would skip re-generation if token is still valid // We decided to not include this because developer can get expiration date from the session // I kept code in comment because it might become relevant in the future @@ -1646,10 +1514,10 @@ App::patch('/v1/account/sessions/:sessionId') $provider = $session->getAttribute('provider'); $refreshToken = $session->getAttribute('providerRefreshToken'); - $appId = $project->getAttribute('authProviders', [])[$provider.'Appid'] ?? ''; - $appSecret = $project->getAttribute('authProviders', [])[$provider.'Secret'] ?? '{}'; + $appId = $project->getAttribute('authProviders', [])[$provider . 'Appid'] ?? ''; + $appSecret = $project->getAttribute('authProviders', [])[$provider . 'Secret'] ?? '{}'; - $className = 'Appwrite\\Auth\\OAuth2\\'.\ucfirst($provider); + $className = 'Appwrite\\Auth\\OAuth2\\' . \ucfirst($provider); if (!\class_exists($className)) { throw new Exception('Provider is not supported', 501, Exception::PROJECT_PROVIDER_UNSUPPORTED); @@ -1709,15 +1577,7 @@ App::delete('/v1/account/sessions') ->inject('audits') ->inject('events') ->inject('usage') - ->action(function ($request, $response, $user, $dbForProject, $locale, $audits, $events, $usage) { - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $user */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Locale\Locale $locale */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Event\Event $events */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Locale $locale, Audit $audits, Event $events, Stats $usage) { $protocol = $request->getProtocol(); $sessions = $user->getAttribute('sessions', []); @@ -1733,7 +1593,7 @@ App::delete('/v1/account/sessions') $session ->setAttribute('current', false) - ->setAttribute('countryName', $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown'))) + ->setAttribute('countryName', $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown'))) ; if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { @@ -1780,7 +1640,7 @@ App::post('/v1/account/recovery') ->label('abuse-limit', 10) ->label('abuse-key', ['url:{url},email:{param-email}', 'ip:{ip}']) ->param('email', '', new Email(), 'User email.') - ->param('url', '', function ($clients) {return new Host($clients);}, 'URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) + ->param('url', '', fn ($clients) => new Host($clients), 'URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) ->inject('request') ->inject('response') ->inject('dbForProject') @@ -1790,18 +1650,9 @@ App::post('/v1/account/recovery') ->inject('audits') ->inject('events') ->inject('usage') - ->action(function ($email, $url, $request, $response, $dbForProject, $project, $locale, $mails, $audits, $events, $usage) { - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Database\Document $project */ - /** @var Utopia\Locale\Locale $locale */ - /** @var Appwrite\Event\Mail $mails */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Event\Event $events */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (string $email, string $url, Request $request, Response $response, Database $dbForProject, Document $project, Locale $locale, Mail $mails, Audit $audits, Event $events, Stats $usage) { - if(empty(App::getEnv('_APP_SMTP_HOST'))) { + if (empty(App::getEnv('_APP_SMTP_HOST'))) { throw new Exception('SMTP Disabled', 503, Exception::GENERAL_SMTP_DISABLED); } @@ -1839,9 +1690,8 @@ App::post('/v1/account/recovery') Authorization::setRole('user:' . $profile->getId()); $recovery = $dbForProject->createDocument('tokens', $recovery - ->setAttribute('$read', ['user:'.$profile->getId()]) - ->setAttribute('$write', ['user:'.$profile->getId()]) - ); + ->setAttribute('$read', ['user:' . $profile->getId()]) + ->setAttribute('$write', ['user:' . $profile->getId()])); $dbForProject->deleteCachedDocument('users', $profile->getId()); @@ -1901,12 +1751,7 @@ App::put('/v1/account/recovery') ->inject('audits') ->inject('usage') ->inject('events') - ->action(function ($userId, $secret, $password, $passwordAgain, $response, $dbForProject, $audits, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $userId, string $secret, string $password, string $passwordAgain, Response $response, Database $dbForProject, Audit $audits, Stats $usage, Event $events) { if ($password !== $passwordAgain) { throw new Exception('Passwords must match', 400, Exception::USER_PASSWORD_MISMATCH); @@ -1930,8 +1775,7 @@ App::put('/v1/account/recovery') $profile = $dbForProject->updateDocument('users', $profile->getId(), $profile ->setAttribute('password', Auth::passwordHash($password)) ->setAttribute('passwordUpdate', \time()) - ->setAttribute('emailVerification', true) - ); + ->setAttribute('emailVerification', true)); $recoveryDocument = $dbForProject->getDocument('tokens', $recovery); @@ -1968,7 +1812,7 @@ App::post('/v1/account/verification') ->label('sdk.response.model', Response::MODEL_TOKEN) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},userId:{userId}') - ->param('url', '', function ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add built-in confirm page + ->param('url', '', fn($clients) => new Host($clients), 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add built-in confirm page ->inject('request') ->inject('response') ->inject('project') @@ -1979,19 +1823,9 @@ App::post('/v1/account/verification') ->inject('events') ->inject('mails') ->inject('usage') - ->action(function ($url, $request, $response, $project, $user, $dbForProject, $locale, $audits, $events, $mails, $usage) { - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $project */ - /** @var Utopia\Database\Document $user */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Locale\Locale $locale */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Event\Event $events */ - /** @var Appwrite\Event\Mail $mails */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (string $url, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Audit $audits, Event $events, Mail $mails, Stats $usage) { - if(empty(App::getEnv('_APP_SMTP_HOST'))) { + if (empty(App::getEnv('_APP_SMTP_HOST'))) { throw new Exception('SMTP Disabled', 503, Exception::GENERAL_SMTP_DISABLED); } @@ -2016,9 +1850,8 @@ App::post('/v1/account/verification') Authorization::setRole('user:' . $user->getId()); $verification = $dbForProject->createDocument('tokens', $verification - ->setAttribute('$read', ['user:'.$user->getId()]) - ->setAttribute('$write', ['user:'.$user->getId()]) - ); + ->setAttribute('$read', ['user:' . $user->getId()]) + ->setAttribute('$write', ['user:' . $user->getId()])); $dbForProject->deleteCachedDocument('users', $user->getId()); @@ -2076,13 +1909,7 @@ App::put('/v1/account/verification') ->inject('audits') ->inject('usage') ->inject('events') - ->action(function ($userId, $secret, $response, $user, $dbForProject, $audits, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $user */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Audit $audits, Stats $usage, Event $events) { $profile = Authorization::skip(fn() => $dbForProject->getDocument('users', $userId)); diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index d9ff247911..f31d02f8d4 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -193,7 +193,7 @@ App::get('/v1/avatars/image') ->setContentType('image/png') ->addHeader('Expires', $date) ->addHeader('X-Appwrite-Cache', 'miss') - ->send($data);; + ->send($data); unset($image); }); diff --git a/app/controllers/api/database.php b/app/controllers/api/database.php index d002f95e07..358da9a527 100644 --- a/app/controllers/api/database.php +++ b/app/controllers/api/database.php @@ -1,6 +1,7 @@ getAttribute('type', ''); $size = $attribute->getAttribute('size', 0); $required = $attribute->getAttribute('required', true); - $signed = $attribute->getAttribute('signed', true); // integers are signed by default + $signed = $attribute->getAttribute('signed', true); // integers are signed by default $array = $attribute->getAttribute('array', false); $format = $attribute->getAttribute('format', ''); $formatOptions = $attribute->getAttribute('formatOptions', []); - $filters = $attribute->getAttribute('filters', []); // filters are hidden from the endpoint + $filters = $attribute->getAttribute('filters', []); // filters are hidden from the endpoint $default = $attribute->getAttribute('default'); $collection = $dbForProject->getDocument('collections', $collectionId); @@ -88,7 +84,7 @@ function createAttribute(string $collectionId, Document $attribute, Response $re try { $attribute = new Document([ - '$id' => $collectionId.'_'.$key, + '$id' => $collectionId . '_' . $key, 'key' => $key, 'collectionId' => $collectionId, 'type' => $type, @@ -105,11 +101,9 @@ function createAttribute(string $collectionId, Document $attribute, Response $re $dbForProject->checkAttribute($collection, $attribute); $attribute = $dbForProject->createDocument('attributes', $attribute); - } - catch (DuplicateException $exception) { + } catch (DuplicateException $exception) { throw new Exception('Attribute already exists', 409, Exception::ATTRIBUTE_ALREADY_EXISTS); - } - catch (LimitException $exception) { + } catch (LimitException $exception) { throw new Exception('Attribute limit exceeded', 400, Exception::ATTRIBUTE_LIMIT_EXCEEDED); } @@ -131,14 +125,14 @@ function createAttribute(string $collectionId, Document $attribute, Response $re ; $audits - ->setResource('collection/'.$collectionId) + ->setResource('collection/' . $collectionId) ->setPayload($attribute->getArrayCopy()) ; $response->setStatusCode(Response::STATUS_CODE_CREATED); return $attribute; -}; +} App::post('/v1/database/collections') ->desc('Create Collection') @@ -162,12 +156,7 @@ App::post('/v1/database/collections') ->inject('audits') ->inject('usage') ->inject('events') - ->action(function ($collectionId, $name, $permission, $read, $write, $response, $dbForProject, $audits, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject*/ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $collectionId, string $name, ?string $permission, ?array $read, ?array $write, Response $response, Database $dbForProject, EventAudit $audits, Stats $usage, Event $events) { $collectionId = $collectionId == 'unique()' ? $dbForProject->getId() : $collectionId; @@ -193,7 +182,7 @@ App::post('/v1/database/collections') } $audits - ->setResource('collection/'.$collectionId) + ->setResource('collection/' . $collectionId) ->setPayload($collection->getArrayCopy()) ; @@ -224,9 +213,7 @@ App::get('/v1/database/collections') ->inject('response') ->inject('dbForProject') ->inject('usage') - ->action(function ($search, $limit, $offset, $cursor, $cursorDirection, $orderType, $response, $dbForProject, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ + ->action(function (string $search, int $limit, int $offset, string $cursor, string $cursorDirection, string $orderType, Response $response, Database $dbForProject, Stats $usage) { if (!empty($cursor)) { $cursorCollection = $dbForProject->getDocument('collections', $cursor); @@ -265,9 +252,7 @@ App::get('/v1/database/collections/:collectionId') ->inject('response') ->inject('dbForProject') ->inject('usage') - ->action(function ($collectionId, $response, $dbForProject, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ + ->action(function (string $collectionId, Response $response, Database $dbForProject, Stats $usage) { $collection = $dbForProject->getDocument('collections', $collectionId); @@ -293,11 +278,7 @@ App::get('/v1/database/usage') ->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->action(function ($range, $response, $dbForProject) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForConsole */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Registry\Registry $register */ + ->action(function (string $range, Response $response, Database $dbForProject) { $usage = []; if (App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') { @@ -335,7 +316,7 @@ App::get('/v1/database/usage') $stats = []; - Authorization::skip(function() use ($dbForProject, $periods, $range, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $periods, $range, $metrics, &$stats) { foreach ($metrics as $metric) { $limit = $periods[$range]['limit']; $period = $periods[$range]['period']; @@ -357,7 +338,7 @@ App::get('/v1/database/usage') $backfill = $limit - \count($requestDocs); while ($backfill > 0) { $last = $limit - $backfill - 1; // array index of last added metric - $diff = match($period) { // convert period to seconds for unix timestamp math + $diff = match ($period) { // convert period to seconds for unix timestamp math '30m' => 1800, '1d' => 86400, }; @@ -404,10 +385,7 @@ App::get('/v1/database/:collectionId/usage') ->param('collectionId', '', new UID(), 'Collection ID.') ->inject('response') ->inject('dbForProject') - ->action(function ($range, $collectionId, $response, $dbForProject) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Registry\Registry $register */ + ->action(function (string $range, string $collectionId, Response $response, Database $dbForProject) { $collectionDocument = $dbForProject->getDocument('collections', $collectionId); $collection = $dbForProject->getCollection('collection_' . $collectionDocument->getInternalId()); @@ -417,7 +395,7 @@ App::get('/v1/database/:collectionId/usage') } $usage = []; - if(App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') { + if (App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') { $periods = [ '24h' => [ 'period' => '30m', @@ -447,7 +425,7 @@ App::get('/v1/database/:collectionId/usage') $stats = []; - Authorization::skip(function() use ($dbForProject, $periods, $range, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $periods, $range, $metrics, &$stats) { foreach ($metrics as $metric) { $limit = $periods[$range]['limit']; $period = $periods[$range]['period']; @@ -469,7 +447,7 @@ App::get('/v1/database/:collectionId/usage') $backfill = $limit - \count($requestDocs); while ($backfill > 0) { $last = $limit - $backfill - 1; // array index of last added metric - $diff = match($period) { // convert period to seconds for unix timestamp math + $diff = match ($period) { // convert period to seconds for unix timestamp math '30m' => 1800, '1d' => 86400, }; @@ -514,12 +492,7 @@ App::get('/v1/database/collections/:collectionId/logs') ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->action(function ($collectionId, $limit, $offset, $response, $dbForProject, $locale, $geodb) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $project */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Locale\Locale $locale */ - /** @var MaxMind\Db\Reader $geodb */ + ->action(function (string $collectionId, int $limit, int $offset, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { $collectionDocument = $dbForProject->getDocument('collections', $collectionId); $collection = $dbForProject->getCollection('collection_' . $collectionDocument->getInternalId()); @@ -529,7 +502,7 @@ App::get('/v1/database/collections/:collectionId/logs') } $audit = new Audit($dbForProject); - $resource = 'collection/'.$collectionId; + $resource = 'collection/' . $collectionId; $logs = $audit->getLogsByResource($resource, $limit, $offset); $output = []; @@ -569,8 +542,8 @@ App::get('/v1/database/collections/:collectionId/logs') $record = $geodb->get($log['ip']); if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); } else { $output[$i]['countryCode'] = '--'; $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); @@ -606,12 +579,7 @@ App::put('/v1/database/collections/:collectionId') ->inject('audits') ->inject('usage') ->inject('events') - ->action(function ($collectionId, $name, $permission, $read, $write, $enabled, $response, $dbForProject, $audits, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $collectionId, string $name, string $permission, ?array $read, ?array $write, bool $enabled, Response $response, Database $dbForProject, EventAudit $audits, Stats $usage, Event $events) { $collection = $dbForProject->getDocument('collections', $collectionId); @@ -631,18 +599,15 @@ App::put('/v1/database/collections/:collectionId') ->setAttribute('permission', $permission) ->setAttribute('dateUpdated', time()) ->setAttribute('enabled', $enabled) - ->setAttribute('search', implode(' ', [$collectionId, $name])) - ); - } - catch (AuthorizationException $exception) { + ->setAttribute('search', implode(' ', [$collectionId, $name]))); + } catch (AuthorizationException $exception) { throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED); - } - catch (StructureException $exception) { - throw new Exception('Bad structure. '.$exception->getMessage(), 400, Exception::DOCUMENT_INVALID_STRUCTURE); + } catch (StructureException $exception) { + throw new Exception('Bad structure. ' . $exception->getMessage(), 400, Exception::DOCUMENT_INVALID_STRUCTURE); } $audits - ->setResource('collection/'.$collectionId) + ->setResource('collection/' . $collectionId) ->setPayload($collection->getArrayCopy()) ; @@ -670,13 +635,7 @@ App::delete('/v1/database/collections/:collectionId') ->inject('audits') ->inject('deletes') ->inject('usage') - ->action(function ($collectionId, $response, $dbForProject, $events, $audits, $deletes, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Event $events */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Event\Delete $deletes */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (string $collectionId, Response $response, Database $dbForProject, Event $events, EventAudit $audits, Delete $deletes, Stats $usage) { $collection = $dbForProject->getDocument('collections', $collectionId); @@ -701,7 +660,7 @@ App::delete('/v1/database/collections/:collectionId') ; $audits - ->setResource('collection/'.$collectionId) + ->setResource('collection/' . $collectionId) ->setPayload($collection->getArrayCopy()) ; @@ -734,13 +693,7 @@ App::post('/v1/database/collections/:collectionId/attributes/string') ->inject('audits') ->inject('usage') ->inject('events') - ->action(function ($collectionId, $key, $size, $required, $default, $array, $response, $dbForProject, $database, $audits, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject*/ - /** @var Appwrite\Event\Database $database */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, EventAudit $audits, Stats $usage, Event $events) { // Ensure attribute default is within required size $validator = new Text($size); @@ -783,12 +736,7 @@ App::post('/v1/database/collections/:collectionId/attributes/email') ->inject('audits') ->inject('usage') ->inject('events') - ->action(function ($collectionId, $key, $required, $default, $array, $response, $dbForProject, $database, $audits, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject*/ - /** @var Appwrite\Event\Database $database */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $audits, Stats $usage, Event $events) { $attribute = createAttribute($collectionId, new Document([ 'key' => $key, @@ -827,13 +775,7 @@ App::post('/v1/database/collections/:collectionId/attributes/enum') ->inject('audits') ->inject('usage') ->inject('events') - ->action(function ($collectionId, $key, $elements, $required, $default, $array, $response, $dbForProject, $database, $audits, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject*/ - /** @var Appwrite\Event\Database $database */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, EventAudit $audits, Stats $usage, Event $events) { // use length of longest string as attribute size $size = 0; @@ -841,7 +783,6 @@ App::post('/v1/database/collections/:collectionId/attributes/enum') $length = \strlen($element); if ($length === 0) { throw new Exception('Each enum element must not be empty', 400, Exception::ATTRIBUTE_VALUE_INVALID); - } $size = ($length > $size) ? $length : $size; } @@ -887,12 +828,7 @@ App::post('/v1/database/collections/:collectionId/attributes/ip') ->inject('audits') ->inject('usage') ->inject('events') - ->action(function ($collectionId, $key, $required, $default, $array, $response, $dbForProject, $database, $audits, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject*/ - /** @var Appwrite\Event\Database $database */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, EventAudit $audits, Stats $usage, Event $events) { $attribute = createAttribute($collectionId, new Document([ 'key' => $key, @@ -930,12 +866,7 @@ App::post('/v1/database/collections/:collectionId/attributes/url') ->inject('audits') ->inject('usage') ->inject('events') - ->action(function ($collectionId, $key, $required, $default, $array, $response, $dbForProject, $database, $audits, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Appwrite\Event\Database $database */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, EventAudit $audits, Stats $usage, Event $events) { $attribute = createAttribute($collectionId, new Document([ 'key' => $key, @@ -975,13 +906,7 @@ App::post('/v1/database/collections/:collectionId/attributes/integer') ->inject('audits') ->inject('usage') ->inject('events') - ->action(function ($collectionId, $key, $required, $min, $max, $default, $array, $response, $dbForProject, $database, $audits, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject*/ - /** @var Appwrite\Event\Database $database */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, EventAudit $audits, Stats $usage, Event $events) { // Ensure attribute default is within range $min = (is_null($min)) ? PHP_INT_MIN : \intval($min); @@ -1048,13 +973,7 @@ App::post('/v1/database/collections/:collectionId/attributes/float') ->inject('audits') ->inject('events') ->inject('usage') - ->action(function ($collectionId, $key, $required, $min, $max, $default, $array, $response, $dbForProject, $database, $audits, $events, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject*/ - /** @var Appwrite\Event\Database $database */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, EventAudit $audits, Event $events, Stats $usage) { // Ensure attribute default is within range $min = (is_null($min)) ? -PHP_FLOAT_MAX : \floatval($min); @@ -1122,13 +1041,7 @@ App::post('/v1/database/collections/:collectionId/attributes/boolean') ->inject('audits') ->inject('usage') ->inject('events') - ->action(function ($collectionId, $key, $required, $default, $array, $response, $dbForProject, $database, $audits, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject*/ - /** @var Appwrite\Event\Database $database */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, EventAudit $audits, Stats $usage, Event $events) { $attribute = createAttribute($collectionId, new Document([ 'key' => $key, @@ -1157,9 +1070,7 @@ App::get('/v1/database/collections/:collectionId/attributes') ->inject('response') ->inject('dbForProject') ->inject('usage') - ->action(function ($collectionId, $response, $dbForProject, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ + ->action(function (string $collectionId, Response $response, Database $dbForProject, Stats $usage) { $collection = $dbForProject->getDocument('collections', $collectionId); @@ -1201,9 +1112,7 @@ App::get('/v1/database/collections/:collectionId/attributes/:key') ->inject('response') ->inject('dbForProject') ->inject('usage') - ->action(function ($collectionId, $key, $response, $dbForProject, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ + ->action(function (string $collectionId, string $key, Response $response, Database $dbForProject, Stats $usage) { $collection = $dbForProject->getDocument('collections', $collectionId); @@ -1211,7 +1120,7 @@ App::get('/v1/database/collections/:collectionId/attributes/:key') throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $collectionId.'_'.$key); + $attribute = $dbForProject->getDocument('attributes', $collectionId . '_' . $key); if ($attribute->isEmpty()) { throw new Exception('Attribute not found', 404, Exception::ATTRIBUTE_NOT_FOUND); @@ -1221,11 +1130,11 @@ App::get('/v1/database/collections/:collectionId/attributes/:key') $type = $attribute->getAttribute('type'); $format = $attribute->getAttribute('format'); - $model = match($type) { + $model = match ($type) { Database::VAR_BOOLEAN => Response::MODEL_ATTRIBUTE_BOOLEAN, Database::VAR_INTEGER => Response::MODEL_ATTRIBUTE_INTEGER, Database::VAR_FLOAT => Response::MODEL_ATTRIBUTE_FLOAT, - Database::VAR_STRING => match($format) { + Database::VAR_STRING => match ($format) { APP_DATABASE_ATTRIBUTE_EMAIL => Response::MODEL_ATTRIBUTE_EMAIL, APP_DATABASE_ATTRIBUTE_ENUM => Response::MODEL_ATTRIBUTE_ENUM, APP_DATABASE_ATTRIBUTE_IP => Response::MODEL_ATTRIBUTE_IP, @@ -1259,13 +1168,7 @@ App::delete('/v1/database/collections/:collectionId/attributes/:key') ->inject('events') ->inject('audits') ->inject('usage') - ->action(function ($collectionId, $key, $response, $dbForProject, $database, $events, $audits, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Database $database */ - /** @var Appwrite\Event\Event $events */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $database, Event $events, EventAudit $audits, Stats $usage) { $collection = $dbForProject->getDocument('collections', $collectionId); @@ -1273,7 +1176,7 @@ App::delete('/v1/database/collections/:collectionId/attributes/:key') throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $collectionId.'_'.$key); + $attribute = $dbForProject->getDocument('attributes', $collectionId . '_' . $key); if ($attribute->isEmpty()) { throw new Exception('Attribute not found', 404, Exception::ATTRIBUTE_NOT_FOUND); @@ -1299,11 +1202,11 @@ App::delete('/v1/database/collections/:collectionId/attributes/:key') $type = $attribute->getAttribute('type'); $format = $attribute->getAttribute('format'); - $model = match($type) { + $model = match ($type) { Database::VAR_BOOLEAN => Response::MODEL_ATTRIBUTE_BOOLEAN, Database::VAR_INTEGER => Response::MODEL_ATTRIBUTE_INTEGER, Database::VAR_FLOAT => Response::MODEL_ATTRIBUTE_FLOAT, - Database::VAR_STRING => match($format) { + Database::VAR_STRING => match ($format) { APP_DATABASE_ATTRIBUTE_EMAIL => Response::MODEL_ATTRIBUTE_EMAIL, APP_DATABASE_ATTRIBUTE_ENUM => Response::MODEL_ATTRIBUTE_ENUM, APP_DATABASE_ATTRIBUTE_IP => Response::MODEL_ATTRIBUTE_IP, @@ -1321,7 +1224,7 @@ App::delete('/v1/database/collections/:collectionId/attributes/:key') ; $audits - ->setResource('collection/'.$collectionId) + ->setResource('collection/' . $collectionId) ->setPayload($attribute->getArrayCopy()) ; @@ -1351,13 +1254,7 @@ App::post('/v1/database/collections/:collectionId/indexes') ->inject('audits') ->inject('usage') ->inject('events') - ->action(function ($collectionId, $key, $type, $attributes, $orders, $response, $dbForProject, $database, $audits, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Database $database */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $collectionId, string $key, string $type, array $attributes, array $orders, Response $response, Database $dbForProject, EventDatabase $database, EventAudit $audits, Stats $usage, Event $events) { $collection = $dbForProject->getDocument('collections', $collectionId); @@ -1395,7 +1292,7 @@ App::post('/v1/database/collections/:collectionId/indexes') // ensure attribute is available if ($attributeStatus !== 'available') { - throw new Exception ('Attribute not available: ' . $oldAttributes[$attributeIndex]['key'], 400, Exception::ATTRIBUTE_NOT_AVAILABLE); + throw new Exception('Attribute not available: ' . $oldAttributes[$attributeIndex]['key'], 400, Exception::ATTRIBUTE_NOT_AVAILABLE); } // set attribute size as index length only for strings @@ -1404,7 +1301,7 @@ App::post('/v1/database/collections/:collectionId/indexes') try { $index = $dbForProject->createDocument('indexes', new Document([ - '$id' => $collectionId.'_'.$key, + '$id' => $collectionId . '_' . $key, 'key' => $key, 'status' => 'processing', // processing, available, failed, deleting, stuck 'collectionId' => $collectionId, @@ -1434,7 +1331,7 @@ App::post('/v1/database/collections/:collectionId/indexes') ; $audits - ->setResource('collection/'.$collection->getId()) + ->setResource('collection/' . $collection->getId()) ->setPayload($index->getArrayCopy()) ; @@ -1457,9 +1354,7 @@ App::get('/v1/database/collections/:collectionId/indexes') ->inject('response') ->inject('dbForProject') ->inject('usage') - ->action(function ($collectionId, $response, $dbForProject, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ + ->action(function (string $collectionId, Response $response, Database $dbForProject, Stats $usage) { $collection = $dbForProject->getDocument('collections', $collectionId); @@ -1493,9 +1388,7 @@ App::get('/v1/database/collections/:collectionId/indexes/:key') ->inject('response') ->inject('dbForProject') ->inject('usage') - ->action(function ($collectionId, $key, $response, $dbForProject, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ + ->action(function (string $collectionId, string $key, Response $response, Database $dbForProject, Stats $usage) { $collection = $dbForProject->getDocument('collections', $collectionId); @@ -1540,13 +1433,7 @@ App::delete('/v1/database/collections/:collectionId/indexes/:key') ->inject('events') ->inject('audits') ->inject('usage') - ->action(function ($collectionId, $key, $response, $dbForProject, $database, $events, $audits, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Database $database */ - /** @var Appwrite\Event\Event $events */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $database, Event $events, EventAudit $audits, Stats $usage) { $collection = $dbForProject->getDocument('collections', $collectionId); @@ -1554,7 +1441,7 @@ App::delete('/v1/database/collections/:collectionId/indexes/:key') throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND); } - $index = $dbForProject->getDocument('indexes', $collectionId.'_'.$key); + $index = $dbForProject->getDocument('indexes', $collectionId . '_' . $key); if (empty($index->getId())) { throw new Exception('Index not found', 404, Exception::INDEX_NOT_FOUND); @@ -1583,7 +1470,7 @@ App::delete('/v1/database/collections/:collectionId/indexes/:key') ; $audits - ->setResource('collection/'.$collection->getId()) + ->setResource('collection/' . $collection->getId()) ->setPayload($index->getArrayCopy()) ; @@ -1614,14 +1501,7 @@ App::post('/v1/database/collections/:collectionId/documents') ->inject('usage') ->inject('events') ->inject('mode') - ->action(function ($documentId, $collectionId, $data, $read, $write, $response, $dbForProject, $user, $audits, $usage, $events, $mode) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Database\Document $user */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ - /** @var string $mode */ + ->action(function (string $documentId, string $collectionId, string|array $data, ?array $read, ?array $write, Response $response, Database $dbForProject, Document $user, EventAudit $audits, Stats $usage, Event $events, string $mode) { $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array @@ -1635,7 +1515,7 @@ App::post('/v1/database/collections/:collectionId/documents') /** * Skip Authorization to get the collection. Needed in case of empty permissions for document level permissions. - * + * * @var Document $collection */ $collection = Authorization::skip(fn() => $dbForProject->getDocument('collections', $collectionId)); @@ -1656,8 +1536,8 @@ App::post('/v1/database/collections/:collectionId/documents') $data['$collection'] = $collection->getId(); // Adding this param to make API easier for developers $data['$id'] = $documentId == 'unique()' ? $dbForProject->getId() : $documentId; - $data['$read'] = (is_null($read) && !$user->isEmpty()) ? ['user:'.$user->getId()] : $read ?? []; // By default set read permissions for user - $data['$write'] = (is_null($write) && !$user->isEmpty()) ? ['user:'.$user->getId()] : $write ?? []; // By default set write permissions for user + $data['$read'] = (is_null($read) && !$user->isEmpty()) ? ['user:' . $user->getId()] : $read ?? []; // By default set read permissions for user + $data['$write'] = (is_null($write) && !$user->isEmpty()) ? ['user:' . $user->getId()] : $write ?? []; // By default set write permissions for user // Users can only add their roles to documents, API keys and Admin users can add any $roles = Authorization::getRoles(); @@ -1665,13 +1545,13 @@ App::post('/v1/database/collections/:collectionId/documents') if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles)) { foreach ($data['$read'] as $read) { if (!Authorization::isRole($read)) { - // TODO: Isn't this a 401: Unauthorized Error ? - throw new Exception('Read permissions must be one of: ('.\implode(', ', $roles).')', 400, Exception::USER_UNAUTHORIZED); + // TODO: Isn't this a 401: Unauthorized Error ? + throw new Exception('Read permissions must be one of: (' . \implode(', ', $roles) . ')', 400, Exception::USER_UNAUTHORIZED); } } foreach ($data['$write'] as $write) { if (!Authorization::isRole($write)) { - throw new Exception('Write permissions must be one of: ('.\implode(', ', $roles).')', 400, Exception::USER_UNAUTHORIZED); + throw new Exception('Write permissions must be one of: (' . \implode(', ', $roles) . ')', 400, Exception::USER_UNAUTHORIZED); } } } @@ -1684,11 +1564,9 @@ App::post('/v1/database/collections/:collectionId/documents') $document = $dbForProject->createDocument('collection_' . $collection->getInternalId(), new Document($data)); } $document->setAttribute('$collection', $collectionId); - } - catch (StructureException $exception) { + } catch (StructureException $exception) { throw new Exception($exception->getMessage(), 400, Exception::DOCUMENT_INVALID_STRUCTURE); - } - catch (DuplicateException $exception) { + } catch (DuplicateException $exception) { throw new Exception('Document already exists', 409, Exception::DOCUMENT_ALREADY_EXISTS); } @@ -1704,7 +1582,7 @@ App::post('/v1/database/collections/:collectionId/documents') ; $audits - ->setResource('document/'.$document->getId()) + ->setResource('document/' . $document->getId()) ->setPayload($document->getArrayCopy()) ; @@ -1724,7 +1602,7 @@ App::get('/v1/database/collections/:collectionId/documents') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_DOCUMENT_LIST) ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).') - ->param('queries', [], new ArrayList(new Text(128), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/database#querying-documents). Maximum of 100 queries are allowed, each 128 characters long.', true) + ->param('queries', [], new ArrayList(new Text(128), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/database#querying-documents). Maximum of 100 queries are allowed, each 128 characters long.', true) ->param('limit', 25, new Range(0, 100), 'Maximum number of documents to return in response. By default will return maximum 25 results. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' results allowed per request.', true) ->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this value to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true) ->param('cursor', '', new UID(), 'ID of the document used as the starting point for the query, excluding the document itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true) @@ -1735,11 +1613,7 @@ App::get('/v1/database/collections/:collectionId/documents') ->inject('dbForProject') ->inject('usage') ->inject('mode') - ->action(function ($collectionId, $queries, $limit, $offset, $cursor, $cursorDirection, $orderAttributes, $orderTypes, $response, $dbForProject, $usage, $mode) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var string $mode */ + ->action(function (string $collectionId, array $queries, int $limit, int $offset, string $cursor, string $cursorDirection, array $orderAttributes, array $orderTypes, Response $response, Database $dbForProject, Stats $usage, string $mode) { /** * Skip Authorization to get the collection. Needed in case of empty permissions for document level permissions. @@ -1772,13 +1646,13 @@ App::get('/v1/database/collections/:collectionId/documents') return $query; }, $queries); - if(!empty($orderAttributes)) { + if (!empty($orderAttributes)) { $validator = new OrderAttributes($collection->getAttribute('attributes', []), $collection->getAttribute('indexes', []), true); if (!$validator->isValid($orderAttributes)) { throw new Exception($validator->getDescription(), 400, Exception::GENERAL_QUERY_INVALID); } } - + if (!empty($queries)) { $validator = new QueriesValidator(new QueryValidator($collection->getAttribute('attributes', [])), $collection->getAttribute('indexes', []), true); if (!$validator->isValid($queries)) { @@ -1839,10 +1713,7 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId') ->inject('dbForProject') ->inject('usage') ->inject('mode') - ->action(function ($collectionId, $documentId, $response, $dbForProject, $usage, $mode) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var string $mode */ + ->action(function (string $collectionId, string $documentId, Response $response, Database $dbForProject, Stats $usage, string $mode) { /** * Skip Authorization to get the collection. Needed in case of empty permissions for document level permissions. @@ -1906,12 +1777,7 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId/logs') ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->action(function ($collectionId, $documentId, $limit, $offset, $response, $dbForProject, $locale, $geodb) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $project */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Locale\Locale $locale */ - /** @var MaxMind\Db\Reader $geodb */ + ->action(function (string $collectionId, string $documentId, int $limit, int $offset, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { $collection = $dbForProject->getDocument('collections', $collectionId); @@ -1926,7 +1792,7 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId/logs') } $audit = new Audit($dbForProject); - $resource = 'document/'.$document->getId(); + $resource = 'document/' . $document->getId(); $logs = $audit->getLogsByResource($resource, $limit, $offset); $output = []; @@ -1966,8 +1832,8 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId/logs') $record = $geodb->get($log['ip']); if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); } else { $output[$i]['countryCode'] = '--'; $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); @@ -2002,13 +1868,7 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId') ->inject('usage') ->inject('events') ->inject('mode') - ->action(function ($collectionId, $documentId, $data, $read, $write, $response, $dbForProject, $audits, $usage, $events, $mode) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ - /** @var string $mode */ + ->action(function (string $collectionId, string $documentId, string|array $data, ?array $read, ?array $write, Response $response, Database $dbForProject, EventAudit $audits, Stats $usage, Event $events, string $mode) { /** * Skip Authorization to get the collection. Needed in case of empty permissions for document level permissions. @@ -2059,14 +1919,14 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId') $roles = Authorization::getRoles(); if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles)) { - if(!is_null($read)) { + if (!is_null($read)) { foreach ($data['$read'] as $read) { if (!Authorization::isRole($read)) { - throw new Exception('Read permissions must be one of: ('.\implode(', ', $roles).')', 400, Exception::USER_UNAUTHORIZED); + throw new Exception('Read permissions must be one of: (' . \implode(', ', $roles) . ')', 400, Exception::USER_UNAUTHORIZED); } } } - if(!is_null($write)) { + if (!is_null($write)) { foreach ($data['$write'] as $write) { if (!Authorization::isRole($write)) { throw new Exception('Write permissions must be one of: (' . \implode(', ', $roles) . ')', 400, Exception::USER_UNAUTHORIZED); @@ -2086,14 +1946,11 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId') * Reset $collection attribute to remove prefix. */ $document->setAttribute('$collection', $collectionId); - } - catch (AuthorizationException $exception) { + } catch (AuthorizationException $exception) { throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED); - } - catch (DuplicateException $exception) { + } catch (DuplicateException $exception) { throw new Exception('Document already exists', 409, Exception::DOCUMENT_ALREADY_EXISTS); - } - catch (StructureException $exception) { + } catch (StructureException $exception) { throw new Exception($exception->getMessage(), 400, Exception::DOCUMENT_INVALID_STRUCTURE); } @@ -2109,7 +1966,7 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId') ; $audits - ->setResource('document/'.$document->getId()) + ->setResource('document/' . $document->getId()) ->setPayload($document->getArrayCopy()) ; @@ -2136,14 +1993,7 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId') ->inject('deletes') ->inject('usage') ->inject('mode') - ->action(function ($collectionId, $documentId, $response, $dbForProject, $events, $audits, $deletes, $usage, $mode) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Event $events */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Event\Delete $deletes */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var string $mode */ + ->action(function (string $collectionId, string $documentId, Response $response, Database $dbForProject, Event $events, EventAudit $audits, Delete $deletes, Stats $usage, string $mode) { /** * Skip Authorization to get the collection. Needed in case of empty permissions for document level permissions. @@ -2206,7 +2056,7 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId') ; $audits - ->setResource('document/'.$document->getId()) + ->setResource('document/' . $document->getId()) ->setPayload($document->getArrayCopy()) ; diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 069a576e12..6b07c97045 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -3,16 +3,21 @@ use Ahc\Jwt\JWT; use Appwrite\Auth\Auth; use Appwrite\Event\Build; +use Appwrite\Event\Delete; +use Appwrite\Event\Event; use Appwrite\Event\Func; use Appwrite\Event\Validator\Event as ValidatorEvent; use Appwrite\Extend\Exception; use Appwrite\Utopia\Database\Validator\CustomId; use Utopia\Database\Validator\UID; +use Appwrite\Stats\Stats; +use Utopia\Storage\Device; use Utopia\Storage\Validator\File; use Utopia\Storage\Validator\FileExt; use Utopia\Storage\Validator\FileSize; use Utopia\Storage\Validator\Upload; use Appwrite\Utopia\Response; +use Utopia\Swoole\Request; use Appwrite\Task\Validator\Cron; use Utopia\App; use Utopia\Database\Database; @@ -55,10 +60,7 @@ App::post('/v1/functions') ->inject('response') ->inject('dbForProject') ->inject('events') - ->action(function ($functionId, $name, $execute, $runtime, $vars, $events, $schedule, $timeout, $response, $dbForProject, $eventsInstance) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Event $eventsInstance */ + ->action(function (string $functionId, string $name, array $execute, string $runtime, array $vars, array $events, string $schedule, int $timeout, Response $response, Database $dbForProject, Event $eventsInstance) { $functionId = ($functionId == 'unique()') ? $dbForProject->getId() : $functionId; $function = $dbForProject->createDocument('functions', new Document([ @@ -104,9 +106,7 @@ App::get('/v1/functions') ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForProject') - ->action(function ($search, $limit, $offset, $cursor, $cursorDirection, $orderType, $response, $dbForProject) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ + ->action(function (string $search, int $limit, int $offset, string $cursor, string $cursorDirection, string $orderType, Response $response, Database $dbForProject) { if (!empty($cursor)) { $cursorFunction = $dbForProject->getDocument('functions', $cursor); @@ -140,8 +140,7 @@ App::get('/v1/functions/runtimes') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_RUNTIME_LIST) ->inject('response') - ->action(function ($response) { - /** @var Appwrite\Utopia\Response $response */ + ->action(function (Response $response) { $runtimes = Config::getParam('runtimes'); @@ -170,10 +169,7 @@ App::get('/v1/functions/:functionId') ->param('functionId', '', new UID(), 'Function ID.') ->inject('response') ->inject('dbForProject') - ->action(function ($functionId, $response, $dbForProject) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - + ->action(function (string $functionId, Response $response, Database $dbForProject) { $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { @@ -197,11 +193,7 @@ App::get('/v1/functions/:functionId/usage') ->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d']), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->action(function ($functionId, $range, $response, $dbForProject) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $project */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Registry\Registry $register */ + ->action(function (string $functionId, string $range, Response $response, Database $dbForProject) { $function = $dbForProject->getDocument('functions', $functionId); @@ -309,12 +301,7 @@ App::put('/v1/functions/:functionId') ->inject('project') ->inject('user') ->inject('events') - ->action(function ($functionId, $name, $execute, $vars, $events, $schedule, $timeout, $response, $dbForProject, $project, $user, $eventsInstance) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Database\Document $project */ - /** @var Utopia\Database\Document $user */ - /** @var Appwrite\Event\Event $eventsInstance */ + ->action(function (string $functionId, string $name, array $execute, array $vars, array $events, string $schedule, int $timeout, Response $response, Database $dbForProject, Document $project, Document $user, Event $eventsInstance) { $function = $dbForProject->getDocument('functions', $functionId); @@ -373,11 +360,7 @@ App::patch('/v1/functions/:functionId/deployments/:deploymentId') ->inject('dbForProject') ->inject('project') ->inject('events') - ->action(function ($functionId, $deploymentId, $response, $dbForProject, $project, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Database\Document $project */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject, Document $project, Event $events) { $function = $dbForProject->getDocument('functions', $functionId); $deployment = $dbForProject->getDocument('deployments', $deploymentId); @@ -440,11 +423,7 @@ App::delete('/v1/functions/:functionId') ->inject('dbForProject') ->inject('deletes') ->inject('events') - ->action(function ($functionId, $response, $dbForProject, $deletes, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Delete $deletes */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $functionId, Response $response, Database $dbForProject, Delete $deletes, Event $events) { $function = $dbForProject->getDocument('functions', $functionId); @@ -491,15 +470,7 @@ App::post('/v1/functions/:functionId/deployments') ->inject('project') ->inject('deviceFunctions') ->inject('deviceLocal') - ->action(function ($functionId, $entrypoint, $file, $activate, $request, $response, $dbForProject, $usage, $events, $project, $deviceFunctions, $deviceLocal) { - /** @var Utopia\Swoole\Request $request */ - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Event $usage */ - /** @var Appwrite\Event\Event $events */ - /** @var Utopia\Database\Document $project */ - /** @var Utopia\Storage\Device $deviceFunctions */ - /** @var Utopia\Storage\Device $deviceLocal */ + ->action(function (string $functionId, string $entrypoint, array $file, bool $activate, Request $request, Response $response, Database $dbForProject, Stats $usage, Event $events, Document $project, Device $deviceFunctions, Device $deviceLocal) { $function = $dbForProject->getDocument('functions', $functionId); @@ -679,9 +650,7 @@ App::get('/v1/functions/:functionId/deployments') ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForProject') - ->action(function ($functionId, $search, $limit, $offset, $cursor, $cursorDirection, $orderType, $response, $dbForProject) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ + ->action(function (string $functionId, string $search, int $limit, int $offset, string $cursor, string $cursorDirection, string $orderType, Response $response, Database $dbForProject) { $function = $dbForProject->getDocument('functions', $functionId); @@ -737,9 +706,7 @@ App::get('/v1/functions/:functionId/deployments/:deploymentId') ->param('deploymentId', '', new UID(), 'Deployment ID.') ->inject('response') ->inject('dbForProject') - ->action(function ($functionId, $deploymentId, $response, $dbForProject) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ + ->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject) { $function = $dbForProject->getDocument('functions', $functionId); @@ -779,13 +746,7 @@ App::delete('/v1/functions/:functionId/deployments/:deploymentId') ->inject('deletes') ->inject('events') ->inject('deviceFunctions') - ->action(function ($functionId, $deploymentId, $response, $dbForProject, $usage, $deletes, $events, $deviceFunctions) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Event $usage */ - /** @var Appwrite\Event\Delete $deletes */ - /** @var Appwrite\Event\Event $events */ - /** @var Utopia\Storage\Device $deviceFunctions */ + ->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject, Stats $usage, Delete $deletes, Event $events, Device $deviceFunctions) { $function = $dbForProject->getDocument('functions', $functionId); if ($function->isEmpty()) { @@ -849,12 +810,7 @@ App::post('/v1/functions/:functionId/executions') ->inject('dbForProject') ->inject('user') ->inject('events') - ->action(function ($functionId, $data, $async, $response, $project, $dbForProject, $user, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $project */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Database\Document $user */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $functionId, string $data, bool $async, Response $response, Document $project, Database $dbForProject, Document $user, Event $events) { $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); @@ -916,7 +872,6 @@ App::post('/v1/functions/:functionId/executions') $jwt = ''; // initialize if (!$user->isEmpty()) { // If userId exists, generate a JWT for function - $sessions = $user->getAttribute('sessions', []); $current = new Document(); @@ -1031,9 +986,7 @@ App::get('/v1/functions/:functionId/executions') ->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor.', true) ->inject('response') ->inject('dbForProject') - ->action(function ($functionId, $limit, $offset, $search, $cursor, $cursorDirection, $response, $dbForProject) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ + ->action(function (string $functionId, int $limit, int $offset, string $search, string $cursor, string $cursorDirection, Response $response, Database $dbForProject) { $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); @@ -1081,9 +1034,7 @@ App::get('/v1/functions/:functionId/executions/:executionId') ->param('executionId', '', new UID(), 'Execution ID.') ->inject('response') ->inject('dbForProject') - ->action(function ($functionId, $executionId, $response, $dbForProject) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ + ->action(function (string $functionId, string $executionId, Response $response, Database $dbForProject) { $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); @@ -1122,11 +1073,7 @@ App::post('/v1/functions/:functionId/deployments/:deploymentId/builds/:buildId') ->inject('dbForProject') ->inject('project') ->inject('events') - ->action(function ($functionId, $deploymentId, $buildId, $response, $dbForProject, $project, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Database\Document $project */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $functionId, string $deploymentId, string $buildId, Response $response, Database $dbForProject, Document $project, Event $events) { $function = $dbForProject->getDocument('functions', $functionId); $deployment = $dbForProject->getDocument('deployments', $deploymentId); diff --git a/app/controllers/api/graphql.php b/app/controllers/api/graphql.php index dcaff9725b..e89ae17961 100644 --- a/app/controllers/api/graphql.php +++ b/app/controllers/api/graphql.php @@ -1,8 +1,5 @@ desc('GraphQL Endpoint') ->groups(['api', 'graphql']) diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index 1fc24fd0b2..9eb9ca580e 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -9,7 +9,7 @@ use Utopia\Database\Document; use Utopia\Registry\Registry; use Utopia\Storage\Device; use Utopia\Storage\Device\Local; -use Utopia\Storage\Storage; +use Utopia\Storage\Storage; App::get('/v1/health') ->desc('Get HTTP') @@ -68,9 +68,9 @@ App::get('/v1/health/db') // Run a small test to check the connection $statement = $db->prepare("SELECT 1;"); - + $statement->closeCursor(); - + $statement->execute(); } catch (Exception $_e) { throw new Exception('Database is not available', 500, Exception::GENERAL_SERVER_ERROR); @@ -141,7 +141,7 @@ App::get('/v1/health/time') \socket_connect($sock, $host, 123); /* Send request */ - $msg = "\010".\str_repeat("\0", 47); + $msg = "\010" . \str_repeat("\0", 47); \socket_send($sock, $msg, \strlen($msg), 0); @@ -256,20 +256,22 @@ App::get('/v1/health/storage/local') $checkStart = \microtime(true); - foreach ([ + foreach ( + [ 'Uploads' => APP_STORAGE_UPLOADS, 'Cache' => APP_STORAGE_CACHE, 'Config' => APP_STORAGE_CONFIG, 'Certs' => APP_STORAGE_CERTIFICATES - ] as $key => $volume) { + ] as $key => $volume + ) { $device = new Local($volume); if (!\is_readable($device->getRoot())) { - throw new Exception('Device '.$key.' dir is not readable', 500, Exception::GENERAL_SERVER_ERROR); + throw new Exception('Device ' . $key . ' dir is not readable', 500, Exception::GENERAL_SERVER_ERROR); } if (!\is_writable($device->getRoot())) { - throw new Exception('Device '.$key.' dir is not writable', 500, Exception::GENERAL_SERVER_ERROR); + throw new Exception('Device ' . $key . ' dir is not writable', 500, Exception::GENERAL_SERVER_ERROR); } } @@ -304,13 +306,15 @@ App::get('/v1/health/anti-virus') $output['status'] = 'disabled'; $output['version'] = ''; } else { - $antivirus = new Network(App::getEnv('_APP_STORAGE_ANTIVIRUS_HOST', 'clamav'), - (int) App::getEnv('_APP_STORAGE_ANTIVIRUS_PORT', 3310)); + $antivirus = new Network( + App::getEnv('_APP_STORAGE_ANTIVIRUS_HOST', 'clamav'), + (int) App::getEnv('_APP_STORAGE_ANTIVIRUS_PORT', 3310) + ); try { $output['version'] = @$antivirus->version(); $output['status'] = (@$antivirus->ping()) ? 'pass' : 'fail'; - } catch( \Exception $e) { + } catch (\Exception $e) { throw new Exception('Antivirus is not available', 500, Exception::GENERAL_SERVER_ERROR); } } @@ -338,7 +342,7 @@ App::get('/v1/health/stats') // Currently only used internally $response ->json([ 'storage' => [ - 'used' => Storage::human($deviceFiles->getDirectorySize($deviceFiles->getRoot().'/')), + 'used' => Storage::human($deviceFiles->getDirectorySize($deviceFiles->getRoot() . '/')), 'partitionTotal' => Storage::human($deviceFiles->getPartitionTotalSpace()), 'partitionFree' => Storage::human($deviceFiles->getPartitionFreeSpace()), ], diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 7e730513f7..1c98983bea 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -77,7 +77,7 @@ App::post('/v1/projects') } $projectId = ($projectId == 'unique()') ? $dbForConsole->getId() : $projectId; - if($projectId === 'console') { + if ($projectId === 'console') { throw new Exception("'console' is a reserved project.", 400, Exception::PROJECT_RESERVED_PROJECT); } $project = $dbForConsole->createDocument('projects', new Document([ @@ -106,7 +106,7 @@ App::post('/v1/projects') 'search' => implode(' ', [$projectId, $name]), ])); /** @var array $collections */ - $collections = Config::getParam('collections', []); + $collections = Config::getParam('collections', []); $dbForProject->setNamespace("_{$project->getId()}"); $dbForProject->create('appwrite'); @@ -118,7 +118,7 @@ App::post('/v1/projects') $adapter->setup(); foreach ($collections as $key => $collection) { - if(($collection['$collection'] ?? '') !== Database::METADATA) { + if (($collection['$collection'] ?? '') !== Database::METADATA) { continue; } $attributes = []; @@ -281,7 +281,7 @@ App::get('/v1/projects/:projectId/usage') $stats = []; - Authorization::skip(function() use ($dbForProject, $periods, $range, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $periods, $range, $metrics, &$stats) { foreach ($metrics as $metric) { $limit = $periods[$range]['limit']; $period = $periods[$range]['period']; @@ -303,7 +303,7 @@ App::get('/v1/projects/:projectId/usage') $backfill = $limit - \count($requestDocs); while ($backfill > 0) { $last = $limit - $backfill - 1; // array index of last added metric - $diff = match($period) { // convert period to seconds for unix timestamp math + $diff = match ($period) { // convert period to seconds for unix timestamp math '30m' => 1800, '1d' => 86400, }; @@ -374,8 +374,7 @@ App::patch('/v1/projects/:projectId') ->setAttribute('legalCity', $legalCity) ->setAttribute('legalAddress', $legalAddress) ->setAttribute('legalTaxId', $legalTaxId) - ->setAttribute('search', implode(' ', [$projectId, $name])) - ); + ->setAttribute('search', implode(' ', [$projectId, $name]))); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -391,7 +390,7 @@ App::patch('/v1/projects/:projectId/service') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_PROJECT) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('service', '', new WhiteList(array_keys(array_filter(Config::getParam('services'), function ($element) {return $element['optional'];})), true), 'Service name.') + ->param('service', '', new WhiteList(array_keys(array_filter(Config::getParam('services'), fn($element) => $element['optional'])), true), 'Service name.') ->param('status', null, new Boolean(), 'Service status.') ->inject('response') ->inject('dbForConsole') @@ -470,8 +469,7 @@ App::patch('/v1/projects/:projectId/auth/limit') $auths['limit'] = $limit; $dbForConsole->updateDocument('projects', $project->getId(), $project - ->setAttribute('auths', $auths) - ); + ->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -584,6 +582,8 @@ App::post('/v1/projects/:projectId/webhooks') $security = (bool) filter_var($security, FILTER_VALIDATE_BOOLEAN); + + $webhook = new Document([ '$id' => $dbForConsole->getId(), '$read' => ['role:all'], @@ -595,6 +595,7 @@ App::post('/v1/projects/:projectId/webhooks') 'security' => $security, 'httpUser' => $httpUser, 'httpPass' => $httpPass, + 'signatureKey' => \bin2hex(\random_bytes(64)), ]); $webhook = $dbForConsole->createDocument('webhooks', $webhook); @@ -688,9 +689,10 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') ->param('security', false, new Boolean(true), 'Certificate verification, false for disabled or true for enabled.') ->param('httpUser', '', new Text(256), 'Webhook HTTP user. Max length: 256 chars.', true) ->param('httpPass', '', new Text(256), 'Webhook HTTP password. Max length: 256 chars.', true) + ->param('signatureKey', null, new Text(256), 'Webhook signature key. Max length: 256 chars.', true) ->inject('response') ->inject('dbForConsole') - ->action(function (string $projectId, string $webhookId, string $name, array $events, string $url, bool $security, string $httpUser, string $httpPass, Response $response, Database $dbForConsole) { + ->action(function (string $projectId, string $webhookId, string $name, array $events, string $url, bool $security, string $httpUser, string $httpPass, string $signatureKey, Response $response, Database $dbForConsole) { $project = $dbForConsole->getDocument('projects', $projectId); @@ -718,8 +720,11 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') ->setAttribute('httpPass', $httpPass) ; - $dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook); + if (!empty($signatureKey)) { + $webhook->setAttribute('signatureKey', $signatureKey); + } + $dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook); $dbForConsole->deleteCachedDocument('projects', $project->getId()); $response->dynamic($webhook, Response::MODEL_WEBHOOK); @@ -751,7 +756,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); - if($webhook === false || $webhook->isEmpty()) { + if ($webhook === false || $webhook->isEmpty()) { throw new Exception('Webhook not found', 404, Exception::WEBHOOK_NOT_FOUND); } @@ -941,7 +946,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId') new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]) ]); - if($key === false || $key->isEmpty()) { + if ($key === false || $key->isEmpty()) { throw new Exception('Key not found', 404, Exception::KEY_NOT_FOUND); } diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index c2d6c3452e..2f55d97205 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -39,7 +39,7 @@ use Utopia\Validator\Integer; use Utopia\Validator\Range; use Utopia\Validator\Text; use Utopia\Validator\WhiteList; -use Utopia\Swoole\Request; +use Utopia\Swoole\Request; App::post('/v1/storage/buckets') ->desc('Create bucket') @@ -262,8 +262,7 @@ App::put('/v1/storage/buckets/:bucketId') ->setAttribute('enabled', (bool) filter_var($enabled, FILTER_VALIDATE_BOOLEAN)) ->setAttribute('encryption', (bool) filter_var($encryption, FILTER_VALIDATE_BOOLEAN)) ->setAttribute('permission', $permission) - ->setAttribute('antivirus', (bool) filter_var($antivirus, FILTER_VALIDATE_BOOLEAN)) - ); + ->setAttribute('antivirus', (bool) filter_var($antivirus, FILTER_VALIDATE_BOOLEAN))); $audits ->setResource('storage/buckets/' . $bucket->getId()) @@ -360,8 +359,10 @@ App::post('/v1/storage/buckets/:bucketId/files') ->action(function (string $bucketId, string $fileId, array $file, ?array $read, ?array $write, Request $request, Response $response, Database $dbForProject, Document $user, Audit $audits, Stats $usage, Event $events, string $mode, Device $deviceFiles, Device $deviceLocal) { $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() - || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ( + $bucket->isEmpty() + || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN) + ) { throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -462,7 +463,7 @@ App::post('/v1/storage/buckets/:bucketId/files') } // Save to storage - $fileSize??=$deviceLocal->getFileSize($fileTmpName); + $fileSize ??= $deviceLocal->getFileSize($fileTmpName); $path = $deviceFiles->getPath($fileId . '.' . \pathinfo($fileName, PATHINFO_EXTENSION)); $path = str_ireplace($deviceFiles->getRoot(), $deviceFiles->getRoot() . DIRECTORY_SEPARATOR . $bucket->getId(), $path); // Add bucket id to path after root @@ -492,8 +493,10 @@ App::post('/v1/storage/buckets/:bucketId/files') $write = (is_null($write) && !$user->isEmpty()) ? ['user:' . $user->getId()] : $write ?? []; if ($chunksUploaded === $chunks) { if (App::getEnv('_APP_STORAGE_ANTIVIRUS') === 'enabled' && $bucket->getAttribute('antivirus', true) && $fileSize <= APP_LIMIT_ANTIVIRUS && App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL) === Storage::DEVICE_LOCAL) { - $antivirus = new Network(App::getEnv('_APP_STORAGE_ANTIVIRUS_HOST', 'clamav'), - (int) App::getEnv('_APP_STORAGE_ANTIVIRUS_PORT', 3310)); + $antivirus = new Network( + App::getEnv('_APP_STORAGE_ANTIVIRUS_HOST', 'clamav'), + (int) App::getEnv('_APP_STORAGE_ANTIVIRUS_PORT', 3310) + ); if (!$antivirus->fileScan($path)) { $deviceFiles->delete($path); @@ -587,7 +590,6 @@ App::post('/v1/storage/buckets/:bucketId/files') } else { $file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file); } - } } catch (StructureException $exception) { throw new Exception($exception->getMessage(), 400, Exception::DOCUMENT_INVALID_STRUCTURE); @@ -604,7 +606,6 @@ App::post('/v1/storage/buckets/:bucketId/files') ->setParam('storage.files.create', 1) ->setParam('bucketId', $bucketId) ; - } else { try { if ($file->isEmpty()) { @@ -689,8 +690,10 @@ App::get('/v1/storage/buckets/:bucketId/files') $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() - || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ( + $bucket->isEmpty() + || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN) + ) { throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -765,8 +768,10 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId') $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() - || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ( + $bucket->isEmpty() + || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN) + ) { throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -837,8 +842,10 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() - || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ( + $bucket->isEmpty() + || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN) + ) { throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -879,7 +886,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $mime = $file->getAttribute('mimeType'); if (!\in_array($mime, $inputs) || $file->getAttribute('sizeActual') > (int) App::getEnv('_APP_STORAGE_PREVIEW_LIMIT', 20000000)) { - if(!\in_array($mime, $inputs)) { + if (!\in_array($mime, $inputs)) { $path = (\array_key_exists($mime, $fileLogos)) ? $fileLogos[$mime] : $fileLogos['default']; } else { // it was an image but the file size exceeded the limit @@ -904,7 +911,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $cache = new Cache(new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId() . DIRECTORY_SEPARATOR . $bucketId . DIRECTORY_SEPARATOR . $fileId)); // Limit file number or size $data = $cache->load($key, 60 * 60 * 24 * 30 * 3/* 3 months */); - if(empty($output)) { + if (empty($output)) { // when file extension is not provided and the mime type is not one of our supported outputs // we fallback to `jpg` output format $output = empty($type) ? (array_search($mime, $outputs) ?? 'jpg') : $type; @@ -1003,8 +1010,10 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() - || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ( + $bucket->isEmpty() + || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN) + ) { throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -1140,8 +1149,10 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() - || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ( + $bucket->isEmpty() + || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN) + ) { throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -1311,8 +1322,10 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') } } - if ($bucket->isEmpty() - || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ( + $bucket->isEmpty() + || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN) + ) { throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -1386,8 +1399,10 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') ->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, Event $events, Audit $audits, Stats $usage, string $mode, Device $deviceFiles, Document $project) { $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - if ($bucket->isEmpty() - || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)) { + if ( + $bucket->isEmpty() + || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN) + ) { throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -1527,10 +1542,10 @@ App::get('/v1/storage/usage') } // backfill metrics with empty values for graphs - $backfill = $limit-\count($requestDocs); + $backfill = $limit - \count($requestDocs); while ($backfill > 0) { $last = $limit - $backfill - 1; // array index of last added metric - $diff = match($period) { // convert period to seconds for unix timestamp math + $diff = match ($period) { // convert period to seconds for unix timestamp math '30m' => 1800, '1d' => 86400, }; @@ -1636,10 +1651,10 @@ App::get('/v1/storage/:bucketId/usage') } // backfill metrics with empty values for graphs - $backfill = $limit-\count($requestDocs); + $backfill = $limit - \count($requestDocs); while ($backfill > 0) { $last = $limit - $backfill - 1; // array index of last added metric - $diff = match($period) { // convert period to seconds for unix timestamp math + $diff = match ($period) { // convert period to seconds for unix timestamp math '30m' => 1800, '1d' => 86400, }; diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index e18e87886d..a983745a95 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -59,8 +59,8 @@ App::post('/v1/teams') $teamId = $teamId == 'unique()' ? $dbForProject->getId() : $teamId; $team = Authorization::skip(fn() => $dbForProject->createDocument('teams', new Document([ '$id' => $teamId , - '$read' => ['team:'.$teamId], - '$write' => ['team:'.$teamId .'/owner'], + '$read' => ['team:' . $teamId], + '$write' => ['team:' . $teamId . '/owner'], 'name' => $name, 'total' => ($isPrivilegedUser || $isAppUser) ? 0 : 1, 'dateCreated' => \time(), @@ -71,8 +71,8 @@ App::post('/v1/teams') $membershipId = $dbForProject->getId(); $membership = new Document([ '$id' => $membershipId, - '$read' => ['user:'.$user->getId(), 'team:'.$team->getId()], - '$write' => ['user:'.$user->getId(), 'team:'.$team->getId().'/owner'], + '$read' => ['user:' . $user->getId(), 'team:' . $team->getId()], + '$write' => ['user:' . $user->getId(), 'team:' . $team->getId() . '/owner'], 'userId' => $user->getId(), 'teamId' => $team->getId(), 'roles' => $roles, @@ -95,7 +95,7 @@ App::post('/v1/teams') $audits ->setParam('event', 'teams.create') - ->setParam('resource', 'team/'.$teamId) + ->setParam('resource', 'team/' . $teamId) ->setParam('data', $team->getArrayCopy()) ; @@ -198,10 +198,9 @@ App::put('/v1/teams/:teamId') throw new Exception('Team not found', 404, Exception::TEAM_NOT_FOUND); } - $team = $dbForProject->updateDocument('teams', $team->getId(),$team + $team = $dbForProject->updateDocument('teams', $team->getId(), $team ->setAttribute('name', $name) - ->setAttribute('search', implode(' ', [$teamId, $name])) - ); + ->setAttribute('search', implode(' ', [$teamId, $name]))); $events->setParam('teamId', $team->getId()); $audits->setResource('team/' . $team->getId()); @@ -260,7 +259,7 @@ App::delete('/v1/teams/:teamId') $audits ->setParam('event', 'teams.delete') - ->setParam('resource', 'team/'.$teamId) + ->setParam('resource', 'team/' . $teamId) ->setParam('data', $team->getArrayCopy()) ; @@ -284,7 +283,7 @@ App::post('/v1/teams/:teamId/memberships') ->param('teamId', '', new UID(), 'Team ID.') ->param('email', '', new Email(), 'Email of the new team member.') ->param('roles', [], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.') - ->param('url', '', function ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the invitation email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add our own built-in confirm page + ->param('url', '', fn($clients) => new Host($clients), 'URL to redirect the user back to your app from the invitation email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add our own built-in confirm page ->param('name', '', new Text(128), 'Name of the new team member. Max length: 128 chars.', true) ->inject('response') ->inject('project') @@ -296,13 +295,13 @@ App::post('/v1/teams/:teamId/memberships') ->inject('events') ->action(function (string $teamId, string $email, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, EventAudit $audits, Mail $mails, Event $events) { - if(empty(App::getEnv('_APP_SMTP_HOST'))) { - throw new Exception('SMTP Disabled', 503, Exception::GENERAL_SMTP_DISABLED); - } - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); $isAppUser = Auth::isAppUser(Authorization::getRoles()); + if (!$isPrivilegedUser && !$isAppUser && empty(App::getEnv('_APP_SMTP_HOST'))) { + throw new Exception('SMTP Disabled', 503, Exception::GENERAL_SMTP_DISABLED); + } + $email = \strtolower($email); $name = (empty($name)) ? $email : $name; $team = $dbForProject->getDocument('teams', $teamId); @@ -314,13 +313,12 @@ App::post('/v1/teams/:teamId/memberships') $invitee = $dbForProject->findOne('users', [new Query('email', Query::TYPE_EQUAL, [$email])]); // Get user by email address if (empty($invitee)) { // Create new user if no user with same email found - $limit = $project->getAttribute('auths', [])['limit'] ?? 0; if ($limit !== 0 && $project->getId() !== 'console') { // check users limit, console invites are allways allowed. $total = $dbForProject->count('users', [], APP_LIMIT_USERS); - if($total >= $limit) { + if ($total >= $limit) { throw new Exception('Project registration is restricted. Contact your administrator for more information.', 501, Exception::USER_COUNT_EXCEEDED); } } @@ -329,16 +327,16 @@ App::post('/v1/teams/:teamId/memberships') $userId = $dbForProject->getId(); $invitee = Authorization::skip(fn() => $dbForProject->createDocument('users', new Document([ '$id' => $userId, - '$read' => ['user:'.$userId, 'role:all'], - '$write' => ['user:'.$userId], + '$read' => ['user:' . $userId, 'role:all'], + '$write' => ['user:' . $userId], 'email' => $email, 'emailVerification' => false, 'status' => true, 'password' => Auth::passwordHash(Auth::passwordGenerator()), - /** - * Set the password update time to 0 for users created using - * team invite and OAuth to allow password updates without an - * old password + /** + * Set the password update time to 0 for users created using + * team invite and OAuth to allow password updates without an + * old password */ 'passwordUpdate' => 0, 'registration' => \time(), @@ -355,7 +353,7 @@ App::post('/v1/teams/:teamId/memberships') } } - $isOwner = Authorization::isRole('team:'.$team->getId().'/owner');; + $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner'); if (!$isOwner && !$isPrivilegedUser && !$isAppUser) { // Not owner, not admin, not app (server) throw new Exception('User is not allowed to send invitations for this team', 401, Exception::USER_UNAUTHORIZED); @@ -367,7 +365,7 @@ App::post('/v1/teams/:teamId/memberships') $membership = new Document([ '$id' => $membershipId, '$read' => ['role:all'], - '$write' => ['user:'.$invitee->getId(), 'team:'.$team->getId().'/owner'], + '$write' => ['user:' . $invitee->getId(), 'team:' . $team->getId() . '/owner'], 'userId' => $invitee->getId(), 'teamId' => $team->getId(), 'roles' => $roles, @@ -382,7 +380,7 @@ App::post('/v1/teams/:teamId/memberships') try { $membership = Authorization::skip(fn() => $dbForProject->createDocument('memberships', $membership)); } catch (Duplicate $th) { - throw new Exception('User has already been invited or is already a member of this team', 409, Exception::TEAM_INVITE_ALREADY_EXISTS); + throw new Exception('User is already a member of this team', 409, Exception::TEAM_INVITE_ALREADY_EXISTS); } $team->setAttribute('total', $team->getAttribute('total', 0) + 1); $team = Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team)); @@ -414,7 +412,7 @@ App::post('/v1/teams/:teamId/memberships') } $audits - ->setResource('team/'.$teamId) + ->setResource('team/' . $teamId) ; $events @@ -423,11 +421,13 @@ App::post('/v1/teams/:teamId/memberships') ; $response->setStatusCode(Response::STATUS_CODE_CREATED); - $response->dynamic($membership + $response->dynamic( + $membership ->setAttribute('teamName', $team->getAttribute('name')) ->setAttribute('userName', $user->getAttribute('name')) - ->setAttribute('userEmail', $user->getAttribute('email')) - , Response::MODEL_MEMBERSHIP); + ->setAttribute('userEmail', $user->getAttribute('email')), + Response::MODEL_MEMBERSHIP + ); }); App::get('/v1/teams/:teamId/memberships') @@ -490,7 +490,7 @@ App::get('/v1/teams/:teamId/memberships') $memberships = array_filter($memberships, fn(Document $membership) => !empty($membership->getAttribute('userId'))); - $memberships = array_map(function($membership) use ($dbForProject, $team) { + $memberships = array_map(function ($membership) use ($dbForProject, $team) { $user = $dbForProject->getDocument('users', $membership->getAttribute('userId')); $membership @@ -533,7 +533,7 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') $membership = $dbForProject->getDocument('memberships', $membershipId); - if($membership->isEmpty() || empty($membership->getAttribute('userId'))) { + if ($membership->isEmpty() || empty($membership->getAttribute('userId'))) { throw new Exception('Membership not found', 404, Exception::MEMBERSHIP_NOT_FOUND); } @@ -545,7 +545,7 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') ->setAttribute('userEmail', $user->getAttribute('email')) ; - $response->dynamic($membership, Response::MODEL_MEMBERSHIP ); + $response->dynamic($membership, Response::MODEL_MEMBERSHIP); }); App::patch('/v1/teams/:teamId/memberships/:membershipId') @@ -588,7 +588,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); $isAppUser = Auth::isAppUser(Authorization::getRoles()); - $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner');; + $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner'); if (!$isOwner && !$isPrivilegedUser && !$isAppUser) { // Not owner, not admin, not app (server) throw new Exception('User is not allowed to modify roles', 401, Exception::USER_UNAUTHORIZED); @@ -667,7 +667,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') } if ($userId !== $membership->getAttribute('userId')) { - throw new Exception('Invite does not belong to current user ('.$user->getAttribute('email').')', 401, Exception::TEAM_INVITE_MISMATCH); + throw new Exception('Invite does not belong to current user (' . $user->getAttribute('email') . ')', 401, Exception::TEAM_INVITE_MISMATCH); } if ($user->isEmpty()) { @@ -675,7 +675,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') } if ($membership->getAttribute('userId') !== $user->getId()) { - throw new Exception('Invite does not belong to current user ('.$user->getAttribute('email').')', 401, Exception::TEAM_INVITE_MISMATCH); + throw new Exception('Invite does not belong to current user (' . $user->getAttribute('email') . ')', 401, Exception::TEAM_INVITE_MISMATCH); } if ($membership->getAttribute('confirm') === true) { @@ -693,7 +693,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') // Log user in - Authorization::setRole('user:'.$user->getId()); + Authorization::setRole('user:' . $user->getId()); $detector = new Detector($request->getUserAgent('UNKNOWN')); $record = $geodb->get($request->getIP()); @@ -712,13 +712,12 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') ], $detector->getOS(), $detector->getClient(), $detector->getDevice())); $session = $dbForProject->createDocument('sessions', $session - ->setAttribute('$read', ['user:'.$user->getId()]) - ->setAttribute('$write', ['user:'.$user->getId()]) - ); + ->setAttribute('$read', ['user:' . $user->getId()]) + ->setAttribute('$write', ['user:' . $user->getId()])); $dbForProject->deleteCachedDocument('users', $user->getId()); - Authorization::setRole('user:'.$userId); + Authorization::setRole('user:' . $userId); $membership = $dbForProject->updateDocument('memberships', $membership->getId(), $membership); @@ -726,7 +725,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $team = Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team->setAttribute('total', $team->getAttribute('total', 0) + 1))); - $audits->setResource('team/'.$teamId); + $audits->setResource('team/' . $teamId); $events ->setParam('teamId', $team->getId()) @@ -740,15 +739,17 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') } $response - ->addCookie(Auth::$cookieName.'_legacy', Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->addCookie(Auth::$cookieName . '_legacy', Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) ->addCookie(Auth::$cookieName, Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite')) ; - $response->dynamic($membership + $response->dynamic( + $membership ->setAttribute('teamName', $team->getAttribute('name')) ->setAttribute('userName', $user->getAttribute('name')) - ->setAttribute('userEmail', $user->getAttribute('email')) - , Response::MODEL_MEMBERSHIP); + ->setAttribute('userEmail', $user->getAttribute('email')), + Response::MODEL_MEMBERSHIP + ); }); App::delete('/v1/teams/:teamId/memberships/:membershipId') @@ -807,7 +808,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team)); } - $audits->setResource('team/'.$teamId); + $audits->setResource('team/' . $teamId); $events ->setParam('teamId', $team->getId()) @@ -850,7 +851,7 @@ App::get('/v1/teams/:teamId/logs') } $audit = new Audit($dbForProject); - $resource = 'team/'.$team->getId(); + $resource = 'team/' . $team->getId(); $logs = $audit->getLogsByResource($resource, $limit, $offset); $output = []; @@ -890,8 +891,8 @@ App::get('/v1/teams/:teamId/logs') $record = $geodb->get($log['ip']); if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); } else { $output[$i]['countryCode'] = '--'; $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 95df53ad3a..569a9ab58f 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -3,12 +3,17 @@ use Appwrite\Auth\Auth; use Appwrite\Auth\Validator\Password; use Appwrite\Detector\Detector; +use Appwrite\Event\Delete; +use Appwrite\Event\Event; +use Appwrite\Event\Audit as EventAudit; use Appwrite\Network\Validator\Email; +use Appwrite\Stats\Stats; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Response; use Utopia\App; use Utopia\Audit\Audit; use Utopia\Config\Config; +use Utopia\Locale\Locale; use Appwrite\Extend\Exception; use Utopia\Database\Document; use Utopia\Database\Exception\Duplicate; @@ -21,6 +26,7 @@ use Utopia\Validator\WhiteList; use Utopia\Validator\Text; use Utopia\Validator\Range; use Utopia\Validator\Boolean; +use MaxMind\Db\Reader; App::post('/v1/users') ->desc('Create User') @@ -42,11 +48,7 @@ App::post('/v1/users') ->inject('dbForProject') ->inject('usage') ->inject('events') - ->action(function ($userId, $email, $password, $name, $response, $dbForProject, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $userId, string $email, string $password, string $name, Response $response, Database $dbForProject, Stats $usage, Event $events) { $email = \strtolower($email); @@ -55,7 +57,7 @@ App::post('/v1/users') $user = $dbForProject->createDocument('users', new Document([ '$id' => $userId, '$read' => ['role:all'], - '$write' => ['user:'.$userId], + '$write' => ['user:' . $userId], 'email' => $email, 'emailVerification' => false, 'status' => true, @@ -106,10 +108,7 @@ App::get('/v1/users') ->inject('response') ->inject('dbForProject') ->inject('usage') - ->action(function ($search, $limit, $offset, $cursor, $cursorDirection, $orderType, $response, $dbForProject, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (string $search, int $limit, int $offset, string $cursor, string $cursorDirection, string $orderType, Response $response, Database $dbForProject, Stats $usage) { if (!empty($cursor)) { $cursorUser = $dbForProject->getDocument('users', $cursor); @@ -150,10 +149,7 @@ App::get('/v1/users/:userId') ->inject('response') ->inject('dbForProject') ->inject('usage') - ->action(function ($userId, $response, $dbForProject, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (string $userId, Response $response, Database $dbForProject, Stats $usage) { $user = $dbForProject->getDocument('users', $userId); @@ -182,10 +178,7 @@ App::get('/v1/users/:userId/prefs') ->inject('response') ->inject('dbForProject') ->inject('usage') - ->action(function ($userId, $response, $dbForProject, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (string $userId, Response $response, Database $dbForProject, Stats $usage) { $user = $dbForProject->getDocument('users', $userId); @@ -217,11 +210,7 @@ App::get('/v1/users/:userId/sessions') ->inject('dbForProject') ->inject('locale') ->inject('usage') - ->action(function ($userId, $response, $dbForProject, $locale, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Locale\Locale $locale */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (string $userId, Response $response, Database $dbForProject, Locale $locale, Stats $usage) { $user = $dbForProject->getDocument('users', $userId); @@ -231,10 +220,10 @@ App::get('/v1/users/:userId/sessions') $sessions = $user->getAttribute('sessions', []); - foreach ($sessions as $key => $session) { + foreach ($sessions as $key => $session) { /** @var Document $session */ - $countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); + $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session->setAttribute('countryName', $countryName); $session->setAttribute('current', false); @@ -264,10 +253,7 @@ App::get('/v1/users/:userId/memberships') ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') - ->action(function ($userId, $response, $dbForProject) { - /** @var string $userId */ - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ + ->action(function (string $userId, Response $response, Database $dbForProject) { $user = $dbForProject->getDocument('users', $userId); @@ -275,7 +261,7 @@ App::get('/v1/users/:userId/memberships') throw new Exception('User not found', 404, Exception::USER_NOT_FOUND); } - $memberships = array_map(function($membership) use ($dbForProject, $user) { + $memberships = array_map(function ($membership) use ($dbForProject, $user) { $team = $dbForProject->getDocument('teams', $membership->getAttribute('teamId')); $membership @@ -311,13 +297,7 @@ App::get('/v1/users/:userId/logs') ->inject('locale') ->inject('geodb') ->inject('usage') - ->action(function ($userId, $limit, $offset, $response, $dbForProject, $locale, $geodb, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $project */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Locale\Locale $locale */ - /** @var MaxMind\Db\Reader $geodb */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (string $userId, int $limit, int $offset, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Stats $usage) { $user = $dbForProject->getDocument('users', $userId); @@ -362,8 +342,8 @@ App::get('/v1/users/:userId/logs') $record = $geodb->get($log['ip']); if ($record) { - $output[$i]['countryCode'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; - $output[$i]['countryName'] = $locale->getText('countries.'.strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); + $output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--'; + $output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown')); } else { $output[$i]['countryCode'] = '--'; $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); @@ -398,11 +378,7 @@ App::patch('/v1/users/:userId/status') ->inject('dbForProject') ->inject('usage') ->inject('events') - ->action(function ($userId, $status, $response, $dbForProject, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $userId, bool $status, Response $response, Database $dbForProject, Stats $usage, Event $events) { $user = $dbForProject->getDocument('users', $userId); @@ -441,11 +417,7 @@ App::patch('/v1/users/:userId/verification') ->inject('dbForProject') ->inject('usage') ->inject('events') - ->action(function ($userId, $emailVerification, $response, $dbForProject, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $userId, bool $emailVerification, Response $response, Database $dbForProject, Stats $usage, Event $events) { $user = $dbForProject->getDocument('users', $userId); @@ -484,11 +456,7 @@ App::patch('/v1/users/:userId/name') ->inject('dbForProject') ->inject('audits') ->inject('events') - ->action(function ($userId, $name, $response, $dbForProject, $audits, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $userId, string $name, Response $response, Database $dbForProject, EventAudit $audits, Event $events) { $user = $dbForProject->getDocument('users', $userId); @@ -504,7 +472,7 @@ App::patch('/v1/users/:userId/name') $user = $dbForProject->updateDocument('users', $user->getId(), $user); $audits - ->setResource('user/'.$user->getId()) + ->setResource('user/' . $user->getId()) ; $events @@ -532,11 +500,7 @@ App::patch('/v1/users/:userId/password') ->inject('dbForProject') ->inject('audits') ->inject('events') - ->action(function ($userId, $password, $response, $dbForProject, $audits, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $userId, string $password, Response $response, Database $dbForProject, EventAudit $audits, Event $events) { $user = $dbForProject->getDocument('users', $userId); @@ -551,7 +515,7 @@ App::patch('/v1/users/:userId/password') $user = $dbForProject->updateDocument('users', $user->getId(), $user); $audits - ->setResource('user/'.$user->getId()) + ->setResource('user/' . $user->getId()) ; $events @@ -579,11 +543,7 @@ App::patch('/v1/users/:userId/email') ->inject('dbForProject') ->inject('audits') ->inject('events') - ->action(function ($userId, $email, $response, $dbForProject, $audits, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $userId, string $email, Response $response, Database $dbForProject, EventAudit $audits, Event $events) { $user = $dbForProject->getDocument('users', $userId); @@ -605,13 +565,13 @@ App::patch('/v1/users/:userId/email') try { $user = $dbForProject->updateDocument('users', $user->getId(), $user); - } catch(Duplicate $th) { + } catch (Duplicate $th) { throw new Exception('Email already exists', 409, Exception::USER_EMAIL_ALREADY_EXISTS); } $audits - ->setResource('user/'.$user->getId()) + ->setResource('user/' . $user->getId()) ; $events @@ -639,11 +599,7 @@ App::patch('/v1/users/:userId/prefs') ->inject('dbForProject') ->inject('usage') ->inject('events') - ->action(function ($userId, $prefs, $response, $dbForProject, $usage, $events) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Event $events */ + ->action(function (string $userId, array $prefs, Response $response, Database $dbForProject, Stats $usage, Event $events) { $user = $dbForProject->getDocument('users', $userId); @@ -681,11 +637,7 @@ App::delete('/v1/users/:userId/sessions/:sessionId') ->inject('dbForProject') ->inject('events') ->inject('usage') - ->action(function ($userId, $sessionId, $response, $dbForProject, $events, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Event $events */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (string $userId, string $sessionId, Response $response, Database $dbForProject, Event $events, Stats $usage) { $user = $dbForProject->getDocument('users', $userId); @@ -695,7 +647,7 @@ App::delete('/v1/users/:userId/sessions/:sessionId') $session = $dbForProject->getDocument('sessions', $sessionId); - if($session->isEmpty()) { + if ($session->isEmpty()) { throw new Exception('Session not found', 404, Exception::USER_SESSION_NOT_FOUND); } @@ -732,11 +684,7 @@ App::delete('/v1/users/:userId/sessions') ->inject('dbForProject') ->inject('events') ->inject('usage') - ->action(function ($userId, $response, $dbForProject, $events, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Event $events */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (string $userId, Response $response, Database $dbForProject, Event $events, Stats $usage) { $user = $dbForProject->getDocument('users', $userId); @@ -777,18 +725,13 @@ App::delete('/v1/users/:userId') ->label('sdk.description', '/docs/references/users/delete.md') ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) ->label('sdk.response.model', Response::MODEL_NONE) - ->param('userId', '', function () {return new UID();}, 'User ID.') + ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') ->inject('events') ->inject('deletes') ->inject('usage') - ->action(function ($userId, $response, $dbForProject, $events, $deletes, $usage) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Appwrite\Event\Event $events */ - /** @var Appwrite\Event\Delete $deletes */ - /** @var Appwrite\Stats\Stats $usage */ + ->action(function (string $userId, Response $response, Database $dbForProject, Event $events, Delete $deletes, Stats $usage) { $user = $dbForProject->getDocument('users', $userId); @@ -829,13 +772,11 @@ App::get('/v1/users/usage') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_USAGE_USERS) ->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d'], true), 'Date range.', true) - ->param('provider', '', new WhiteList(\array_merge(['email', 'anonymous'], \array_map(fn($value) => "oauth-".$value, \array_keys(Config::getParam('providers', [])))), true), 'Provider Name.', true) + ->param('provider', '', new WhiteList(\array_merge(['email', 'anonymous'], \array_map(fn($value) => "oauth-" . $value, \array_keys(Config::getParam('providers', [])))), true), 'Provider Name.', true) ->inject('response') ->inject('dbForProject') ->inject('register') - ->action(function ($range, $provider, $response, $dbForProject) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ + ->action(function (string $range, string $provider, Response $response, Database $dbForProject) { $usage = []; if (App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') { @@ -871,7 +812,7 @@ App::get('/v1/users/usage') $stats = []; - Authorization::skip(function() use ($dbForProject, $periods, $range, $metrics, &$stats) { + Authorization::skip(function () use ($dbForProject, $periods, $range, $metrics, &$stats) { foreach ($metrics as $metric) { $limit = $periods[$range]['limit']; $period = $periods[$range]['period']; @@ -880,7 +821,7 @@ App::get('/v1/users/usage') new Query('period', Query::TYPE_EQUAL, [$period]), new Query('metric', Query::TYPE_EQUAL, [$metric]), ], $limit, 0, ['time'], [Database::ORDER_DESC]); - + $stats[$metric] = []; foreach ($requestDocs as $requestDoc) { $stats[$metric][] = [ @@ -892,9 +833,8 @@ App::get('/v1/users/usage') // backfill metrics with empty values for graphs $backfill = $limit - \count($requestDocs); while ($backfill > 0) { - $last = $limit - $backfill - 1; // array index of last added metric - $diff = match($period) { // convert period to seconds for unix timestamp math + $diff = match ($period) { // convert period to seconds for unix timestamp math '30m' => 1800, '1d' => 86400, }; @@ -905,7 +845,7 @@ App::get('/v1/users/usage') $backfill--; } $stats[$metric] = array_reverse($stats[$metric]); - } + } }); $usage = new Document([ @@ -919,8 +859,7 @@ App::get('/v1/users/usage') 'sessionsProviderCreate' => $stats["users.sessions.$provider.create"], 'sessionsDelete' => $stats["users.sessions.delete"] ]); - } $response->dynamic($usage, Response::MODEL_USAGE_USERS); - }); \ No newline at end of file + }); diff --git a/app/controllers/general.php b/app/controllers/general.php index 8cd4553e33..747799e369 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1,14 +1,16 @@ getHeader('x-appwrite-response-format', App::getEnv('_APP_SYSTEM_RESPONSE_FORMAT', '')); if ($requestFormat) { - switch($requestFormat) { - case version_compare ($requestFormat , '0.12.0', '<') : + switch ($requestFormat) { + case version_compare($requestFormat, '0.12.0', '<'): Request::setFilter(new RequestV12()); break; - case version_compare ($requestFormat , '0.13.0', '<') : + case version_compare($requestFormat, '0.13.0', '<'): Request::setFilter(new RequestV13()); break; - case version_compare ($requestFormat , '0.14.0', '<') : + case version_compare($requestFormat, '0.14.0', '<'): Request::setFilter(new RequestV14()); break; default: @@ -75,21 +69,21 @@ App::init(function ($utopia, $request, $response, $console, $project, $dbForCons if (empty($domain->get()) || !$domain->isKnown() || $domain->isTest()) { $domains[$domain->get()] = false; Console::warning($domain->get() . ' is not a publicly accessible domain. Skipping SSL certificate generation.'); - } elseif(str_starts_with($request->getURI(), '/.well-known/acme-challenge')) { + } elseif (str_starts_with($request->getURI(), '/.well-known/acme-challenge')) { Console::warning('Skipping SSL certificates generation on ACME challenge.'); } else { Authorization::disable(); $envDomain = App::getEnv('_APP_DOMAIN', ''); $mainDomain = null; - if(!empty($envDomain) && $envDomain !== 'localhost') { + if (!empty($envDomain) && $envDomain !== 'localhost') { $mainDomain = $envDomain; } else { $domainDocument = $dbForConsole->findOne('domains', [], 0, ['_id'], ['ASC']); $mainDomain = $domainDocument ? $domainDocument->getAttribute('domain') : $domain->get(); } - if($mainDomain !== $domain->get()) { + if ($mainDomain !== $domain->get()) { Console::warning($domain->get() . ' is not a main domain. Skipping SSL certificate generation.'); } else { $domainDocument = $dbForConsole->findOne('domains', [ @@ -127,11 +121,11 @@ App::init(function ($utopia, $request, $response, $console, $project, $dbForCons } if ($project->isEmpty()) { - throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND); + throw new AppwriteException('Project not found', 404, AppwriteException::PROJECT_NOT_FOUND); } if (!empty($route->getLabel('sdk.auth', [])) && $project->isEmpty() && ($route->getLabel('scope', '') !== 'public')) { - throw new Exception('Missing or unknown project ID', 400, Exception::PROJECT_UNKNOWN); + throw new AppwriteException('Missing or unknown project ID', 400, AppwriteException::PROJECT_UNKNOWN); } $referrer = $request->getReferer(); @@ -149,37 +143,38 @@ App::init(function ($utopia, $request, $response, $console, $project, $dbForCons $refDomain = (!$route->getLabel('origin', false)) // This route is publicly accessible ? $refDomain - : (!empty($protocol) ? $protocol : $request->getProtocol()).'://'.$origin.(!empty($port) ? ':'.$port : ''); + : (!empty($protocol) ? $protocol : $request->getProtocol()) . '://' . $origin . (!empty($port) ? ':' . $port : ''); $selfDomain = new Domain($request->getHostname()); $endDomain = new Domain((string)$origin); - Config::setParam('domainVerification', + Config::setParam( + 'domainVerification', ($selfDomain->getRegisterable() === $endDomain->getRegisterable()) && - $endDomain->getRegisterable() !== ''); + $endDomain->getRegisterable() !== '' + ); Config::setParam('cookieDomain', ( $request->getHostname() === 'localhost' || - $request->getHostname() === 'localhost:'.$request->getPort() || + $request->getHostname() === 'localhost:' . $request->getPort() || (\filter_var($request->getHostname(), FILTER_VALIDATE_IP) !== false) ) ? null - : '.'.$request->getHostname() - ); + : '.' . $request->getHostname()); - /* + /* * Response format */ $responseFormat = $request->getHeader('x-appwrite-response-format', App::getEnv('_APP_SYSTEM_RESPONSE_FORMAT', '')); if ($responseFormat) { - switch($responseFormat) { - case version_compare ($responseFormat , '0.11.2', '<=') : + switch ($responseFormat) { + case version_compare($responseFormat, '0.11.2', '<='): Response::setFilter(new ResponseV11()); break; - case version_compare ($responseFormat , '0.12.4', '<='): + case version_compare($responseFormat, '0.12.4', '<='): Response::setFilter(new ResponseV12()); break; - case version_compare ($responseFormat , '0.13.4', '<='): + case version_compare($responseFormat, '0.13.4', '<='): Response::setFilter(new ResponseV13()); break; default: @@ -197,14 +192,14 @@ App::init(function ($utopia, $request, $response, $console, $project, $dbForCons */ if (App::getEnv('_APP_OPTIONS_FORCE_HTTPS', 'disabled') === 'enabled') { // Force HTTPS if ($request->getProtocol() !== 'https') { - if($request->getMethod() !== Request::METHOD_GET) { - throw new Exception('Method unsupported over HTTP.', 500, Exception::GENERAL_PROTOCOL_UNSUPPORTED); + if ($request->getMethod() !== Request::METHOD_GET) { + throw new AppwriteException('Method unsupported over HTTP.', 500, AppwriteException::GENERAL_PROTOCOL_UNSUPPORTED); } - return $response->redirect('https://'.$request->getHostname().$request->getURI()); + return $response->redirect('https://' . $request->getHostname() . $request->getURI()); } - $response->addHeader('Strict-Transport-Security', 'max-age='.(60 * 60 * 24 * 126)); // 126 days + $response->addHeader('Strict-Transport-Security', 'max-age=' . (60 * 60 * 24 * 126)); // 126 days } $response @@ -225,11 +220,13 @@ App::init(function ($utopia, $request, $response, $console, $project, $dbForCons $origin = $request->getOrigin($request->getReferer('')); $originValidator = new Origin(\array_merge($project->getAttribute('platforms', []), $console->getAttribute('platforms', []))); - if (!$originValidator->isValid($origin) + if ( + !$originValidator->isValid($origin) && \in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_PATCH, Request::METHOD_DELETE]) && $route->getLabel('origin', false) !== '*' - && empty($request->getHeader('x-appwrite-key', ''))) { - throw new Exception($originValidator->getDescription(), 403, Exception::GENERAL_UNKNOWN_ORIGIN); + && empty($request->getHeader('x-appwrite-key', '')) + ) { + throw new AppwriteException($originValidator->getDescription(), 403, AppwriteException::GENERAL_UNKNOWN_ORIGIN); } /* @@ -274,7 +271,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $dbForCons $user = new Document([ '$id' => '', 'status' => true, - 'email' => 'app.'.$project->getId().'@service.'.$request->getHostname(), + 'email' => 'app.' . $project->getId() . '@service.' . $request->getHostname(), 'password' => '', 'name' => $project->getAttribute('name', 'Untitled'), ]); @@ -282,47 +279,47 @@ App::init(function ($utopia, $request, $response, $console, $project, $dbForCons $role = Auth::USER_ROLE_APP; $scopes = \array_merge($roles[$role]['scopes'], $key->getAttribute('scopes', [])); - Authorization::setRole('role:'.Auth::USER_ROLE_APP); + Authorization::setRole('role:' . Auth::USER_ROLE_APP); Authorization::setDefaultStatus(false); // Cancel security segmentation for API keys. } } - Authorization::setRole('role:'.$role); + Authorization::setRole('role:' . $role); foreach (Auth::getRoles($user) as $authRole) { Authorization::setRole($authRole); } - $service = $route->getLabel('sdk.namespace',''); - if(!empty($service)) { - if(array_key_exists($service, $project->getAttribute('services',[])) - && !$project->getAttribute('services',[])[$service] - && !Auth::isPrivilegedUser(Authorization::getRoles())) { - throw new Exception('Service is disabled', 503, Exception::GENERAL_SERVICE_DISABLED); + $service = $route->getLabel('sdk.namespace', ''); + if (!empty($service)) { + $roles = Authorization::getRoles(); + if ( + array_key_exists($service, $project->getAttribute('services', [])) + && !$project->getAttribute('services', [])[$service] + && !(Auth::isPrivilegedUser($roles) || Auth::isAppUser($roles)) + ) { + throw new AppwriteException('Service is disabled', 503, AppwriteException::GENERAL_SERVICE_DISABLED); } } if (!\in_array($scope, $scopes)) { if ($project->isEmpty()) { // Check if permission is denied because project is missing - throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND); + throw new AppwriteException('Project not found', 404, AppwriteException::PROJECT_NOT_FOUND); } - throw new Exception($user->getAttribute('email', 'User').' (role: '.\strtolower($roles[$role]['label']).') missing scope ('.$scope.')', 401, Exception::GENERAL_UNAUTHORIZED_SCOPE); + throw new AppwriteException($user->getAttribute('email', 'User') . ' (role: ' . \strtolower($roles[$role]['label']) . ') missing scope (' . $scope . ')', 401, AppwriteException::GENERAL_UNAUTHORIZED_SCOPE); } if (false === $user->getAttribute('status')) { // Account is blocked - throw new Exception('Invalid credentials. User is blocked', 401, Exception::USER_BLOCKED); + throw new AppwriteException('Invalid credentials. User is blocked', 401, AppwriteException::USER_BLOCKED); } if ($user->getAttribute('reset')) { - throw new Exception('Password reset is required', 412, Exception::USER_PASSWORD_RESET_REQUIRED); + throw new AppwriteException('Password reset is required', 412, AppwriteException::USER_PASSWORD_RESET_REQUIRED); } - }, ['utopia', 'request', 'response', 'console', 'project', 'dbForConsole', 'user', 'locale', 'clients']); -App::options(function ($request, $response) { - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ +App::options(function (Request $request, Response $response) { $origin = $request->getOrigin(); @@ -336,15 +333,7 @@ App::options(function ($request, $response) { ->noContent(); }, ['request', 'response']); -App::error(function ($error, $utopia, $request, $response, $layout, $project, $logger, $loggerBreadcrumbs) { - /** @var Exception $error */ - /** @var Utopia\App $utopia */ - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ - /** @var Appwrite\Utopia\View $layout */ - /** @var Utopia\Database\Document $project */ - /** @var Utopia\Logger\Logger $logger */ - /** @var Utopia\Logger\Log\Breadcrumb[] $loggerBreadcrumbs */ +App::error(function (Throwable $error, App $utopia, Request $request, Response $response, View $layout, Document $project, ?Logger $logger, array $loggerBreadcrumbs) { $version = App::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->match($request); @@ -354,18 +343,18 @@ App::error(function ($error, $utopia, $request, $response, $layout, $project, $l throw $error; } - if($logger) { - if($error->getCode() >= 500 || $error->getCode() === 0) { + if ($logger) { + if ($error->getCode() >= 500 || $error->getCode() === 0) { try { /** @var Utopia\Database\Document $user */ $user = $utopia->getResource('user'); - } catch(\Throwable $th) { + } catch (\Throwable $th) { // All good, user is optional information for logger } $log = new Utopia\Logger\Log(); - if(isset($user) && !$user->isEmpty()) { + if (isset($user) && !$user->isEmpty()) { $log->setUser(new User($user->getId())); } @@ -376,7 +365,7 @@ App::error(function ($error, $utopia, $request, $response, $layout, $project, $l $log->setMessage($error->getMessage()); $log->addTag('method', $route->getMethod()); - $log->addTag('url', $route->getPath()); + $log->addTag('url', $route->getPath()); $log->addTag('verboseType', get_class($error)); $log->addTag('code', $error->getCode()); $log->addTag('projectId', $project->getId()); @@ -395,12 +384,12 @@ App::error(function ($error, $utopia, $request, $response, $layout, $project, $l $isProduction = App::getEnv('_APP_ENV', 'development') === 'production'; $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); - foreach($loggerBreadcrumbs as $loggerBreadcrumb) { + foreach ($loggerBreadcrumbs as $loggerBreadcrumb) { $log->addBreadcrumb($loggerBreadcrumb); } $responseCode = $logger->addLog($log); - Console::info('Log pushed with status code: '.$responseCode); + Console::info('Log pushed with status code: ' . $responseCode); } } @@ -411,35 +400,35 @@ App::error(function ($error, $utopia, $request, $response, $layout, $project, $l $trace = $error->getTrace(); if (php_sapi_name() === 'cli') { - Console::error('[Error] Timestamp: '.date('c', time())); + Console::error('[Error] Timestamp: ' . date('c', time())); - if($route) { - Console::error('[Error] Method: '.$route->getMethod()); - Console::error('[Error] URL: '.$route->getPath()); + if ($route) { + Console::error('[Error] Method: ' . $route->getMethod()); + Console::error('[Error] URL: ' . $route->getPath()); } - Console::error('[Error] Type: '.get_class($error)); - Console::error('[Error] Message: '.$message); - Console::error('[Error] File: '.$file); - Console::error('[Error] Line: '.$line); + Console::error('[Error] Type: ' . get_class($error)); + Console::error('[Error] Message: ' . $message); + Console::error('[Error] File: ' . $file); + Console::error('[Error] Line: ' . $line); } /** Handle Utopia Errors */ if ($error instanceof Utopia\Exception) { - $error = new Exception($message, $code, Exception::GENERAL_UNKNOWN, $error); - switch($code) { + $error = new AppwriteException($message, $code, AppwriteException::GENERAL_UNKNOWN, $error); + switch ($code) { case 400: - $error->setType(Exception::GENERAL_ARGUMENT_INVALID); + $error->setType(AppwriteException::GENERAL_ARGUMENT_INVALID); break; case 404: - $error->setType(Exception::GENERAL_ROUTE_NOT_FOUND); + $error->setType(AppwriteException::GENERAL_ROUTE_NOT_FOUND); break; } } /** Wrap all exceptions inside Appwrite\Extend\Exception */ - if (!($error instanceof Exception)) { - $error = new Exception($message, $code, Exception::GENERAL_UNKNOWN, $error); + if (!($error instanceof AppwriteException)) { + $error = new AppwriteException($message, $code, AppwriteException::GENERAL_UNKNOWN, $error); } switch ($code) { // Don't show 500 errors! @@ -501,7 +490,7 @@ App::error(function ($error, $utopia, $request, $response, $layout, $project, $l ; $layout - ->setParam('title', $project->getAttribute('name').' - Error') + ->setParam('title', $project->getAttribute('name') . ' - Error') ->setParam('description', 'No Description') ->setParam('body', $comp) ->setParam('version', $version) @@ -511,8 +500,10 @@ App::error(function ($error, $utopia, $request, $response, $layout, $project, $l $response->html($layout->render()); } - $response->dynamic(new Document($output), - $utopia->isDevelopment() ? Response::MODEL_ERROR_DEV : Response::MODEL_ERROR); + $response->dynamic( + new Document($output), + $utopia->isDevelopment() ? Response::MODEL_ERROR_DEV : Response::MODEL_ERROR + ); }, ['error', 'utopia', 'request', 'response', 'layout', 'project', 'logger', 'loggerBreadcrumbs']); App::get('/manifest.json') @@ -520,8 +511,7 @@ App::get('/manifest.json') ->label('scope', 'public') ->label('docs', false) ->inject('response') - ->action(function ($response) { - /** @var Appwrite\Utopia\Response $response */ + ->action(function (Response $response) { $response->json([ 'name' => APP_NAME, @@ -547,8 +537,8 @@ App::get('/robots.txt') ->label('scope', 'public') ->label('docs', false) ->inject('response') - ->action(function ($response) { - $template = new View(__DIR__.'/../views/general/robots.phtml'); + ->action(function (Response $response) { + $template = new View(__DIR__ . '/../views/general/robots.phtml'); $response->text($template->render(false)); }); @@ -557,8 +547,8 @@ App::get('/humans.txt') ->label('scope', 'public') ->label('docs', false) ->inject('response') - ->action(function ($response) { - $template = new View(__DIR__.'/../views/general/humans.phtml'); + ->action(function (Response $response) { + $template = new View(__DIR__ . '/../views/general/humans.phtml'); $response->text($template->render(false)); }); @@ -568,7 +558,7 @@ App::get('/.well-known/acme-challenge') ->label('docs', false) ->inject('request') ->inject('response') - ->action(function ($request, $response) { + ->action(function (Request $request, Response $response) { $uriChunks = \explode('/', $request->getURI()); $token = $uriChunks[\count($uriChunks) - 1]; @@ -581,32 +571,32 @@ App::get('/.well-known/acme-challenge') ]); if (!$validator->isValid($token) || \count($uriChunks) !== 4) { - throw new Exception('Invalid challenge token.', 400); + throw new AppwriteException('Invalid challenge token.', 400); } $base = \realpath(APP_STORAGE_CERTIFICATES); - $absolute = \realpath($base.'/.well-known/acme-challenge/'.$token); + $absolute = \realpath($base . '/.well-known/acme-challenge/' . $token); if (!$base) { - throw new Exception('Storage error', 500, Exception::GENERAL_SERVER_ERROR); + throw new AppwriteException('Storage error', 500, AppwriteException::GENERAL_SERVER_ERROR); } if (!$absolute) { - throw new Exception('Unknown path', 404); + throw new AppwriteException('Unknown path', 404); } if (!\substr($absolute, 0, \strlen($base)) === $base) { - throw new Exception('Invalid path', 401); + throw new AppwriteException('Invalid path', 401); } if (!\file_exists($absolute)) { - throw new Exception('Unknown path', 404); + throw new AppwriteException('Unknown path', 404); } $content = @\file_get_contents($absolute); if (!$content) { - throw new Exception('Failed to get contents', 500, Exception::GENERAL_SERVER_ERROR); + throw new AppwriteException('Failed to get contents', 500, AppwriteException::GENERAL_SERVER_ERROR); } $response->text($content); diff --git a/app/controllers/mock.php b/app/controllers/mock.php index 4346a7a8fa..fb3369efc7 100644 --- a/app/controllers/mock.php +++ b/app/controllers/mock.php @@ -5,6 +5,7 @@ global $utopia, $request, $response; use Appwrite\Extend\Exception; use Utopia\Database\Document; use Appwrite\Network\Validator\Host; +use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Utopia\App; use Utopia\Validator\ArrayList; @@ -206,13 +207,12 @@ App::get('/v1/mock/tests/general/download') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.mock', true) ->inject('response') - ->action(function ($response) { - /** @var Appwrite\Utopia\Request $request */ - + ->action(function (Response $response) { + $response ->setContentType('text/plain') ->addHeader('Content-Disposition', 'attachment; filename="test.txt"') - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache ->addHeader('X-Peak', \memory_get_peak_usage()) ->send("Download test passed.") ; @@ -237,54 +237,52 @@ App::post('/v1/mock/tests/general/upload') ->param('file', [], new File(), 'Sample file param', false) ->inject('request') ->inject('response') - ->action(function ($x, $y, $z, $file, $request, $response) { - /** @var Appwrite\Utopia\Request $request */ - /** @var Utopia\Swoole\Response $response */ - + ->action(function (string $x, int $y, array $z, array $file, Request $request, Response $response) { + $file = $request->getFiles('file'); - + $contentRange = $request->getHeader('content-range'); - $chunkSize = 5*1024*1024; // 5MB + $chunkSize = 5 * 1024 * 1024; // 5MB - if(!empty($contentRange)) { + if (!empty($contentRange)) { $start = $request->getContentRangeStart(); $end = $request->getContentRangeEnd(); $size = $request->getContentRangeSize(); $id = $request->getHeader('x-appwrite-id', ''); $file['size'] = (\is_array($file['size'])) ? $file['size'][0] : $file['size']; - if(is_null($start) || is_null($end) || is_null($size)) { + if (is_null($start) || is_null($end) || is_null($size)) { throw new Exception('Invalid content-range header', 400, Exception::GENERAL_MOCK); } - if($start > $end || $end > $size) { + if ($start > $end || $end > $size) { throw new Exception('Invalid content-range header', 400, Exception::GENERAL_MOCK); } - if($start === 0 && !empty($id)) { + if ($start === 0 && !empty($id)) { throw new Exception('First chunked request cannot have id header', 400, Exception::GENERAL_MOCK); } - if($start !== 0 && $id !== 'newfileid') { + if ($start !== 0 && $id !== 'newfileid') { throw new Exception('All chunked request must have id header (except first)', 400, Exception::GENERAL_MOCK); } - if($end !== $size && $end-$start+1 !== $chunkSize) { + if ($end !== $size && $end - $start + 1 !== $chunkSize) { throw new Exception('Chunk size must be 5MB (except last chunk)', 400, Exception::GENERAL_MOCK); } if ($end !== $size && $file['size'] !== $chunkSize) { throw new Exception('Wrong chunk size', 400, Exception::GENERAL_MOCK); } - - if($file['size'] > $chunkSize) { + + if ($file['size'] > $chunkSize) { throw new Exception('Chunk size must be 5MB or less', 400, Exception::GENERAL_MOCK); } - if($end !== $size) { + if ($end !== $size) { $response->json([ - '$id'=> 'newfileid', + '$id' => 'newfileid', 'chunksTotal' => $file['size'] / $chunkSize, 'chunksUploaded' => $start / $chunkSize ]); @@ -293,11 +291,11 @@ App::post('/v1/mock/tests/general/upload') $file['tmp_name'] = (\is_array($file['tmp_name'])) ? $file['tmp_name'][0] : $file['tmp_name']; $file['name'] = (\is_array($file['name'])) ? $file['name'][0] : $file['name']; $file['size'] = (\is_array($file['size'])) ? $file['size'][0] : $file['size']; - + if ($file['name'] !== 'file.png') { throw new Exception('Wrong file name', 400, Exception::GENERAL_MOCK); } - + if ($file['size'] !== 38756) { throw new Exception('Wrong file size', 400, Exception::GENERAL_MOCK); } @@ -321,8 +319,7 @@ App::get('/v1/mock/tests/general/redirect') ->label('sdk.response.model', Response::MODEL_MOCK) ->label('sdk.mock', true) ->inject('response') - ->action(function ($response) { - /** @var Appwrite\Utopia\Response $response */ + ->action(function (Response $response) { $response->redirect('/v1/mock/tests/general/redirect/done'); }); @@ -356,9 +353,7 @@ App::get('/v1/mock/tests/general/set-cookie') ->label('sdk.mock', true) ->inject('response') ->inject('request') - ->action(function ($response, $request) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Appwrite\Utopia\Request $request */ + ->action(function (Response $response, Request $request) { $response->addCookie('cookieName', 'cookieValue', \time() + 31536000, '/', $request->getHostname(), true, true); }); @@ -376,8 +371,7 @@ App::get('/v1/mock/tests/general/get-cookie') ->label('sdk.response.model', Response::MODEL_MOCK) ->label('sdk.mock', true) ->inject('request') - ->action(function ($request) { - /** @var Appwrite\Utopia\Request $request */ + ->action(function (Request $request) { if ($request->getCookie('cookieName', '') !== 'cookieValue') { throw new Exception('Missing cookie value', 400, Exception::GENERAL_MOCK); @@ -396,8 +390,7 @@ App::get('/v1/mock/tests/general/empty') ->label('sdk.response.model', Response::MODEL_NONE) ->label('sdk.mock', true) ->inject('response') - ->action(function ($response) { - /** @var Appwrite\Utopia\Response $response */ + ->action(function (Response $response) { $response->noContent(); }); @@ -447,8 +440,7 @@ App::get('/v1/mock/tests/general/502-error') ->label('sdk.response.model', Response::MODEL_ANY) ->label('sdk.mock', true) ->inject('response') - ->action(function ($response) { - /** @var Appwrite\Utopia\Response $response */ + ->action(function (Response $response) { $response ->setStatusCode(502) @@ -467,10 +459,9 @@ App::get('/v1/mock/tests/general/oauth2') ->param('scope', '', new Text(100), 'OAuth2 scope list.') ->param('state', '', new Text(1024), 'OAuth2 state.') ->inject('response') - ->action(function ($client_id, $redirectURI, $scope, $state, $response) { - /** @var Appwrite\Utopia\Response $response */ + ->action(function (string $client_id, string $redirectURI, string $scope, string $state, Response $response) { - $response->redirect($redirectURI.'?'.\http_build_query(['code' => 'abcdef', 'state' => $state])); + $response->redirect($redirectURI . '?' . \http_build_query(['code' => 'abcdef', 'state' => $state])); }); App::get('/v1/mock/tests/general/oauth2/token') @@ -486,8 +477,7 @@ App::get('/v1/mock/tests/general/oauth2/token') ->param('code', '', new Text(100), 'OAuth2 state.', true) ->param('refresh_token', '', new Text(100), 'OAuth2 refresh token.', true) ->inject('response') - ->action(function ($client_id, $client_secret, $grantType, $redirectURI, $code, $refreshToken, $response) { - /** @var Appwrite\Utopia\Response $response */ + ->action(function (string $client_id, string $client_secret, string $grantType, string $redirectURI, string $code, string $refreshToken, Response $response) { if ($client_id != '1') { throw new Exception('Invalid client ID', 400, Exception::GENERAL_MOCK); @@ -503,13 +493,13 @@ App::get('/v1/mock/tests/general/oauth2/token') 'expires_in' => 14400 ]; - if($grantType === 'authorization_code') { + if ($grantType === 'authorization_code') { if ($code !== 'abcdef') { throw new Exception('Invalid token', 400, Exception::GENERAL_MOCK); } $response->json($responseJson); - } else if($grantType === 'refresh_token') { + } elseif ($grantType === 'refresh_token') { if ($refreshToken !== 'tuvwxyz') { throw new Exception('Invalid refresh token', 400, Exception::GENERAL_MOCK); } @@ -527,8 +517,7 @@ App::get('/v1/mock/tests/general/oauth2/user') ->label('docs', false) ->param('token', '', new Text(100), 'OAuth2 Access Token.') ->inject('response') - ->action(function ($token, $response) { - /** @var Appwrite\Utopia\Response $response */ + ->action(function (string $token, Response $response) { if ($token != '123456') { throw new Exception('Invalid token', 400, Exception::GENERAL_MOCK); @@ -547,8 +536,7 @@ App::get('/v1/mock/tests/general/oauth2/success') ->label('scope', 'public') ->label('docs', false) ->inject('response') - ->action(function ($response) { - /** @var Appwrite\Utopia\Response $response */ + ->action(function (Response $response) { $response->json([ 'result' => 'success', @@ -561,8 +549,7 @@ App::get('/v1/mock/tests/general/oauth2/failure') ->label('scope', 'public') ->label('docs', false) ->inject('response') - ->action(function ($response) { - /** @var Appwrite\Utopia\Response $response */ + ->action(function (Response $response) { $response ->setStatusCode(Response::STATUS_CODE_BAD_REQUEST) @@ -571,16 +558,13 @@ App::get('/v1/mock/tests/general/oauth2/failure') ]); }); -App::shutdown(function($utopia, $response, $request) { - /** @var Utopia\App $utopia */ - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ +App::shutdown(function (App $utopia, Response $response, Request $request) { $result = []; $route = $utopia->match($request); - $path = APP_STORAGE_CACHE.'/tests.json'; + $path = APP_STORAGE_CACHE . '/tests.json'; $tests = (\file_exists($path)) ? \json_decode(\file_get_contents($path), true) : []; - + if (!\is_array($tests)) { throw new Exception('Failed to read results', 500, Exception::GENERAL_MOCK); } @@ -594,4 +578,4 @@ App::shutdown(function($utopia, $response, $request) { } $response->dynamic(new Document(['result' => $route->getMethod() . ':' . $route->getPath() . ':passed']), Response::MODEL_MOCK); -}, ['utopia', 'response', 'request'], 'mock'); \ No newline at end of file +}, ['utopia', 'response', 'request'], 'mock'); diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index e4ab00c04b..8ed7d2659b 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -1,30 +1,24 @@ match($request); @@ -46,7 +40,7 @@ App::init(function ($utopia, $request, $response, $project, $user, $events, $aud ->setParam('{userId}', $user->getId()) ->setParam('{userAgent}', $request->getUserAgent('')) ->setParam('{ip}', $request->getIP()) - ->setParam('{url}', $request->getHostname().$route->getPath()); + ->setParam('{url}', $request->getHostname() . $route->getPath()); $timeLimitArray[] = $timeLimit; } @@ -58,8 +52,8 @@ App::init(function ($utopia, $request, $response, $project, $user, $events, $aud foreach ($timeLimitArray as $timeLimit) { foreach ($request->getParams() as $key => $value) { // Set request params as potential abuse keys - if(!empty($value)) { - $timeLimit->setParam('{param-'.$key.'}', (\is_array($value)) ? \json_encode($value) : $value); + if (!empty($value)) { + $timeLimit->setParam('{param-' . $key . '}', (\is_array($value)) ? \json_encode($value) : $value); } } @@ -74,10 +68,11 @@ App::init(function ($utopia, $request, $response, $project, $user, $events, $aud ; } - if ((App::getEnv('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled' // Route is rate-limited - && $abuse->check()) // Abuse is not disabled - && (!$isAppUser && !$isPrivilegedUser)) // User is not an admin or API key - { + if ( + (App::getEnv('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled' // Route is rate-limited + && $abuse->check()) // Abuse is not disabled + && (!$isAppUser && !$isPrivilegedUser) + ) { // User is not an admin or API key throw new Exception('Too many requests', 429, Exception::GENERAL_RATE_LIMIT_EXCEEDED); } } @@ -108,7 +103,7 @@ App::init(function ($utopia, $request, $response, $project, $user, $events, $aud $usage ->setParam('projectId', $project->getId()) ->setParam('httpRequest', 1) - ->setParam('httpUrl', $request->getHostname().$request->getURI()) + ->setParam('httpUrl', $request->getHostname() . $request->getURI()) ->setParam('httpMethod', $request->getMethod()) ->setParam('httpPath', $route->getPath()) ->setParam('networkRequestSize', 0) @@ -120,48 +115,45 @@ App::init(function ($utopia, $request, $response, $project, $user, $events, $aud $database->setProject($project); }, ['utopia', 'request', 'response', 'project', 'user', 'events', 'audits', 'mails', 'usage', 'deletes', 'database', 'dbForProject', 'mode'], 'api'); -App::init(function ($utopia, $request, $project) { - /** @var Utopia\App $utopia */ - /** @var Appwrite\Utopia\Request $request */ - /** @var Utopia\Database\Document $project */ +App::init(function (App $utopia, Request $request, Document $project) { $route = $utopia->match($request); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); $isAppUser = Auth::isAppUser(Authorization::getRoles()); - if($isAppUser || $isPrivilegedUser) { // Skip limits for app and console devs + if ($isAppUser || $isPrivilegedUser) { // Skip limits for app and console devs return; } $auths = $project->getAttribute('auths', []); switch ($route->getLabel('auth.type', '')) { case 'emailPassword': - if(($auths['emailPassword'] ?? true) === false) { + if (($auths['emailPassword'] ?? true) === false) { throw new Exception('Email / Password authentication is disabled for this project', 501, Exception::USER_AUTH_METHOD_UNSUPPORTED); } break; case 'magic-url': - if($project->getAttribute('usersAuthMagicURL', true) === false) { + if ($project->getAttribute('usersAuthMagicURL', true) === false) { throw new Exception('Magic URL authentication is disabled for this project', 501, Exception::USER_AUTH_METHOD_UNSUPPORTED); } break; case 'anonymous': - if(($auths['anonymous'] ?? true) === false) { + if (($auths['anonymous'] ?? true) === false) { throw new Exception('Anonymous authentication is disabled for this project', 501, Exception::USER_AUTH_METHOD_UNSUPPORTED); } break; case 'invites': - if(($auths['invites'] ?? true) === false) { + if (($auths['invites'] ?? true) === false) { throw new Exception('Invites authentication is disabled for this project', 501, Exception::USER_AUTH_METHOD_UNSUPPORTED); } break; case 'jwt': - if(($auths['JWT'] ?? true) === false) { + if (($auths['JWT'] ?? true) === false) { throw new Exception('JWT authentication is disabled for this project', 501, Exception::USER_AUTH_METHOD_UNSUPPORTED); } break; @@ -170,21 +162,9 @@ App::init(function ($utopia, $request, $project) { throw new Exception('Unsupported authentication route', 501, Exception::USER_AUTH_METHOD_UNSUPPORTED); break; } - }, ['utopia', 'request', 'project'], 'auth'); -App::shutdown(function ($utopia, $request, $response, $project, $events, $audits, $usage, $deletes, $database, $mode, $dbForProject) { - /** @var Utopia\App $utopia */ - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $project */ - /** @var Appwrite\Event\Event $events */ - /** @var Appwrite\Event\Audit $audits */ - /** @var Appwrite\Stats\Stats $usage */ - /** @var Appwrite\Event\Delete $deletes */ - /** @var Appwrite\Event\Database $database */ - /** @var bool $mode */ - /** @var Utopia\Database\Database $dbForProject */ +App::shutdown(function (App $utopia, Request $request, Response $response, Document $project, Event $events, Audit $audits, Stats $usage, Delete $deletes, Event $database, string $mode, Database $dbForProject) { if (!empty($events->getEvent())) { if (empty($events->getPayload())) { @@ -233,7 +213,7 @@ App::shutdown(function ($utopia, $request, $response, $project, $events, $audits channels: $target['channels'], roles: $target['roles'], options: [ - 'permissionsChanged' => $target['permissionsChanged'], + 'permissionsChanged' => $target['permissionsChanged'], 'userId' => $events->getParam('userId') ] ); @@ -256,15 +236,15 @@ App::shutdown(function ($utopia, $request, $response, $project, $events, $audits } $route = $utopia->match($request); - if (App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled' + if ( + App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled' && $project->getId() && $mode !== APP_MODE_ADMIN // TODO: add check to make sure user is admin - && !empty($route->getLabel('sdk.namespace', null))) { // Don't calculate console usage on admin mode - + && !empty($route->getLabel('sdk.namespace', null)) + ) { // Don't calculate console usage on admin mode $usage ->setParam('networkRequestSize', $request->getSize() + $usage->getParam('storage')) ->setParam('networkResponseSize', $response->getSize()) ->submit(); } - -}, ['utopia', 'request', 'response', 'project', 'events', 'audits', 'usage', 'deletes', 'database', 'mode', 'dbForProject'], 'api'); \ No newline at end of file +}, ['utopia', 'request', 'response', 'project', 'events', 'audits', 'usage', 'deletes', 'database', 'mode', 'dbForProject'], 'api'); diff --git a/app/controllers/shared/web.php b/app/controllers/shared/web.php index e45333808a..a3f2df012c 100644 --- a/app/controllers/shared/web.php +++ b/app/controllers/shared/web.php @@ -2,12 +2,11 @@ use Utopia\App; use Utopia\Config\Config; +use Appwrite\Utopia\Response; +use Appwrite\Utopia\Request; +use Appwrite\Utopia\View; -App::init(function ($utopia, $request, $response, $layout) { - /** @var Utopia\App $utopia */ - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ - /** @var Appwrite\Utopia\View $layout */ +App::init(function (App $utopia, Request $request, Response $response, View $layout) { /* AJAX check */ if (!empty($request->getQuery('version', ''))) { @@ -48,10 +47,10 @@ App::init(function ($utopia, $request, $response, $layout) { $route = $utopia->match($request); - $route->label('error', __DIR__.'/../../views/general/error.phtml'); + $route->label('error', __DIR__ . '/../../views/general/error.phtml'); $scope = $route->getLabel('scope', ''); - + $layout ->setParam('version', App::getEnv('_APP_VERSION', 'UNKNOWN')) ->setParam('isDev', App::isDevelopment()) diff --git a/app/controllers/web/console.php b/app/controllers/web/console.php index 4ec54c1ded..194f6e3069 100644 --- a/app/controllers/web/console.php +++ b/app/controllers/web/console.php @@ -1,6 +1,7 @@ setParam('description', 'Appwrite Console allows you to easily manage, monitor, and control your entire backend API and tools.') @@ -17,12 +17,10 @@ App::init(function ($layout) { ; }, ['layout'], 'console'); -App::shutdown(function ($response, $layout) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Appwrite\Utopia\View $layout */ +App::shutdown(function (Response $response, View $layout) { - $header = new View(__DIR__.'/../../views/console/comps/header.phtml'); - $footer = new View(__DIR__.'/../../views/console/comps/footer.phtml'); + $header = new View(__DIR__ . '/../../views/console/comps/header.phtml'); + $footer = new View(__DIR__ . '/../../views/console/comps/footer.phtml'); $footer ->setParam('home', App::getEnv('_APP_HOME', '')) @@ -43,17 +41,16 @@ App::get('/error/:code') ->label('scope', 'home') ->param('code', null, new \Utopia\Validator\Numeric(), 'Valid status code number', false) ->inject('layout') - ->action(function ($code, $layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (int $code, View $layout) { - $page = new View(__DIR__.'/../../views/error.phtml'); + $page = new View(__DIR__ . '/../../views/error.phtml'); $page ->setParam('code', $code) ; $layout - ->setParam('title', APP_NAME.' - Error') + ->setParam('title', APP_NAME . ' - Error') ->setParam('body', $page); }); @@ -62,17 +59,16 @@ App::get('/console') ->label('permission', 'public') ->label('scope', 'console') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { - $page = new View(__DIR__.'/../../views/console/index.phtml'); + $page = new View(__DIR__ . '/../../views/console/index.phtml'); $page ->setParam('home', App::getEnv('_APP_HOME', '')) ; $layout - ->setParam('title', APP_NAME.' - Console') + ->setParam('title', APP_NAME . ' - Console') ->setParam('body', $page); }); @@ -81,19 +77,18 @@ App::get('/console/account') ->label('permission', 'public') ->label('scope', 'console') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { - $page = new View(__DIR__.'/../../views/console/account/index.phtml'); + $page = new View(__DIR__ . '/../../views/console/account/index.phtml'); - $cc = new View(__DIR__.'/../../views/console/forms/credit-card.phtml'); + $cc = new View(__DIR__ . '/../../views/console/forms/credit-card.phtml'); $page ->setParam('cc', $cc) ; $layout - ->setParam('title', 'Account - '.APP_NAME) + ->setParam('title', 'Account - ' . APP_NAME) ->setParam('body', $page); }); @@ -102,13 +97,12 @@ App::get('/console/notifications') ->label('permission', 'public') ->label('scope', 'console') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { - $page = new View(__DIR__.'/../../views/v1/console/notifications/index.phtml'); + $page = new View(__DIR__ . '/../../views/v1/console/notifications/index.phtml'); $layout - ->setParam('title', APP_NAME.' - Notifications') + ->setParam('title', APP_NAME . ' - Notifications') ->setParam('body', $page); }); @@ -117,14 +111,13 @@ App::get('/console/home') ->label('permission', 'public') ->label('scope', 'console') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { - $page = new View(__DIR__.'/../../views/console/home/index.phtml'); + $page = new View(__DIR__ . '/../../views/console/home/index.phtml'); $page - ->setParam('usageStatsEnabled',App::getEnv('_APP_USAGE_STATS','enabled') == 'enabled'); + ->setParam('usageStatsEnabled', App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled'); $layout - ->setParam('title', APP_NAME.' - Console') + ->setParam('title', APP_NAME . ' - Console') ->setParam('body', $page); }); @@ -133,22 +126,20 @@ App::get('/console/settings') ->label('permission', 'public') ->label('scope', 'console') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { $target = new Domain(App::getEnv('_APP_DOMAIN_TARGET', '')); - $page = new View(__DIR__.'/../../views/console/settings/index.phtml'); + $page = new View(__DIR__ . '/../../views/console/settings/index.phtml'); - $page - ->setParam('services', array_filter(Config::getParam('services'), function($element) {return $element['optional'];})) + $page->setParam('services', array_filter(Config::getParam('services'), fn($element) => $element['optional'])) ->setParam('customDomainsEnabled', ($target->isKnown() && !$target->isTest())) ->setParam('customDomainsTarget', $target->get()) ->setParam('smtpEnabled', (!empty(App::getEnv('_APP_SMTP_HOST')))) ; $layout - ->setParam('title', APP_NAME.' - Settings') + ->setParam('title', APP_NAME . ' - Settings') ->setParam('body', $page); }); @@ -157,15 +148,14 @@ App::get('/console/webhooks') ->label('permission', 'public') ->label('scope', 'console') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { - $page = new View(__DIR__.'/../../views/console/webhooks/index.phtml'); + $page = new View(__DIR__ . '/../../views/console/webhooks/index.phtml'); $page->setParam('events', Config::getParam('events', [])); $layout - ->setParam('title', APP_NAME.' - Webhooks') + ->setParam('title', APP_NAME . ' - Webhooks') ->setParam('body', $page); }); @@ -175,10 +165,9 @@ App::get('/console/webhooks/webhook') ->label('scope', 'console') ->param('id', '', new UID(), 'Webhook unique ID.') ->inject('layout') - ->action(function ($id, $layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (string $id, View $layout) { - $page = new View(__DIR__.'/../../views/console/webhooks/webhook.phtml'); + $page = new View(__DIR__ . '/../../views/console/webhooks/webhook.phtml'); $page ->setParam('events', Config::getParam('events', [])) @@ -186,7 +175,7 @@ App::get('/console/webhooks/webhook') ; $layout - ->setParam('title', APP_NAME.' - Webhooks') + ->setParam('title', APP_NAME . ' - Webhooks') ->setParam('body', $page); }); @@ -195,10 +184,9 @@ App::get('/console/webhooks/webhook/new') ->label('permission', 'public') ->label('scope', 'console') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { - $page = new View(__DIR__.'/../../views/console/webhooks/webhook.phtml'); + $page = new View(__DIR__ . '/../../views/console/webhooks/webhook.phtml'); $page ->setParam('events', Config::getParam('events', [])) @@ -206,7 +194,7 @@ App::get('/console/webhooks/webhook/new') ; $layout - ->setParam('title', APP_NAME.' - Webhooks') + ->setParam('title', APP_NAME . ' - Webhooks') ->setParam('body', $page); }); @@ -215,16 +203,15 @@ App::get('/console/keys') ->label('permission', 'public') ->label('scope', 'console') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { $scopes = array_keys(Config::getParam('scopes')); - $page = new View(__DIR__.'/../../views/console/keys/index.phtml'); + $page = new View(__DIR__ . '/../../views/console/keys/index.phtml'); $page->setParam('scopes', $scopes); $layout - ->setParam('title', APP_NAME.' - API Keys') + ->setParam('title', APP_NAME . ' - API Keys') ->setParam('body', $page); }); @@ -233,13 +220,12 @@ App::get('/console/database') ->label('permission', 'public') ->label('scope', 'console') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { - $page = new View(__DIR__.'/../../views/console/database/index.phtml'); + $page = new View(__DIR__ . '/../../views/console/database/index.phtml'); $layout - ->setParam('title', APP_NAME.' - Database') + ->setParam('title', APP_NAME . ' - Database') ->setParam('body', $page); }); @@ -250,11 +236,9 @@ App::get('/console/database/collection') ->param('id', '', new UID(), 'Collection unique ID.') ->inject('response') ->inject('layout') - ->action(function ($id, $response, $layout) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Appwrite\Utopia\View $layout */ + ->action(function (string $id, Response $response, View $layout) { - $logs = new View(__DIR__.'/../../views/console/comps/logs.phtml'); + $logs = new View(__DIR__ . '/../../views/console/comps/logs.phtml'); $logs ->setParam('interval', App::getEnv('_APP_MAINTENANCE_RETENTION_AUDIT', 0)) @@ -264,12 +248,12 @@ App::get('/console/database/collection') ]) ; - $page = new View(__DIR__.'/../../views/console/database/collection.phtml'); - + $page = new View(__DIR__ . '/../../views/console/database/collection.phtml'); + $page->setParam('logs', $logs); - + $layout - ->setParam('title', APP_NAME.' - Database Collection') + ->setParam('title', APP_NAME . ' - Database Collection') ->setParam('body', $page) ; @@ -286,10 +270,9 @@ App::get('/console/database/document') ->label('scope', 'console') ->param('collection', '', new UID(), 'Collection unique ID.') ->inject('layout') - ->action(function ($collection, $layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (string $collection, View $layout) { - $logs = new View(__DIR__.'/../../views/console/comps/logs.phtml'); + $logs = new View(__DIR__ . '/../../views/console/comps/logs.phtml'); $logs ->setParam('interval', App::getEnv('_APP_MAINTENANCE_RETENTION_AUDIT', 0)) @@ -300,7 +283,7 @@ App::get('/console/database/document') ]) ; - $page = new View(__DIR__.'/../../views/console/database/document.phtml'); + $page = new View(__DIR__ . '/../../views/console/database/document.phtml'); $page ->setParam('new', false) @@ -309,7 +292,7 @@ App::get('/console/database/document') ; $layout - ->setParam('title', APP_NAME.' - Database Document') + ->setParam('title', APP_NAME . ' - Database Document') ->setParam('body', $page); }); @@ -319,10 +302,9 @@ App::get('/console/database/document/new') ->label('scope', 'console') ->param('collection', '', new UID(), 'Collection unique ID.') ->inject('layout') - ->action(function ($collection, $layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (string $collection, View $layout) { - $page = new View(__DIR__.'/../../views/console/database/document.phtml'); + $page = new View(__DIR__ . '/../../views/console/database/document.phtml'); $page ->setParam('new', true) @@ -331,7 +313,7 @@ App::get('/console/database/document/new') ; $layout - ->setParam('title', APP_NAME.' - Database Document') + ->setParam('title', APP_NAME . ' - Database Document') ->setParam('body', $page); }); @@ -340,10 +322,10 @@ App::get('/console/storage') ->label('permission', 'public') ->label('scope', 'console') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ - $page = new View(__DIR__.'/../../views/console/storage/index.phtml'); - + ->action(function (View $layout) { + + $page = new View(__DIR__ . '/../../views/console/storage/index.phtml'); + $page ->setParam('home', App::getEnv('_APP_HOME', 0)) ->setParam('fileLimit', App::getEnv('_APP_STORAGE_LIMIT', 0)) @@ -351,7 +333,7 @@ App::get('/console/storage') ; $layout - ->setParam('title', APP_NAME.' - Storage') + ->setParam('title', APP_NAME . ' - Storage') ->setParam('body', $page); }); @@ -362,19 +344,17 @@ App::get('/console/storage/bucket') ->param('id', '', new UID(), 'Bucket unique ID.') ->inject('response') ->inject('layout') - ->action(function ($id, $response, $layout) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\View $layout */ + ->action(function (string $id, Response $response, View $layout) { - $page = new View(__DIR__.'/../../views/console/storage/bucket.phtml'); + $page = new View(__DIR__ . '/../../views/console/storage/bucket.phtml'); $page ->setParam('home', App::getEnv('_APP_HOME', 0)) ->setParam('fileLimit', App::getEnv('_APP_STORAGE_LIMIT', 0)) ->setParam('fileLimitHuman', Storage::human(App::getEnv('_APP_STORAGE_LIMIT', 0))) ; - + $layout - ->setParam('title', APP_NAME.' - Storage Buckets') + ->setParam('title', APP_NAME . ' - Storage Buckets') ->setParam('body', $page) ; @@ -390,10 +370,9 @@ App::get('/console/users') ->label('permission', 'public') ->label('scope', 'console') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { - $page = new View(__DIR__.'/../../views/console/users/index.phtml'); + $page = new View(__DIR__ . '/../../views/console/users/index.phtml'); $page ->setParam('auth', Config::getParam('auth')) @@ -402,7 +381,7 @@ App::get('/console/users') ; $layout - ->setParam('title', APP_NAME.' - Users') + ->setParam('title', APP_NAME . ' - Users') ->setParam('body', $page); }); @@ -411,13 +390,12 @@ App::get('/console/users/user') ->label('permission', 'public') ->label('scope', 'console') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { - $page = new View(__DIR__.'/../../views/console/users/user.phtml'); + $page = new View(__DIR__ . '/../../views/console/users/user.phtml'); $layout - ->setParam('title', APP_NAME.' - User') + ->setParam('title', APP_NAME . ' - User') ->setParam('body', $page); }); @@ -426,13 +404,12 @@ App::get('/console/users/teams/team') ->label('permission', 'public') ->label('scope', 'console') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { - $page = new View(__DIR__.'/../../views/console/users/team.phtml'); + $page = new View(__DIR__ . '/../../views/console/users/team.phtml'); $layout - ->setParam('title', APP_NAME.' - Team') + ->setParam('title', APP_NAME . ' - Team') ->setParam('body', $page); }); @@ -442,15 +419,15 @@ App::get('/console/functions') ->label('permission', 'public') ->label('scope', 'console') ->inject('layout') - ->action(function ($layout) { - $page = new View(__DIR__.'/../../views/console/functions/index.phtml'); + ->action(function (View $layout) { + $page = new View(__DIR__ . '/../../views/console/functions/index.phtml'); $page ->setParam('runtimes', Config::getParam('runtimes')) ; $layout - ->setParam('title', APP_NAME.' - Functions') + ->setParam('title', APP_NAME . ' - Functions') ->setParam('body', $page); }); @@ -460,19 +437,19 @@ App::get('/console/functions/function') ->label('permission', 'public') ->label('scope', 'console') ->inject('layout') - ->action(function ($layout) { - $page = new View(__DIR__.'/../../views/console/functions/function.phtml'); + ->action(function (View $layout) { + $page = new View(__DIR__ . '/../../views/console/functions/function.phtml'); $page ->setParam('events', Config::getParam('events', [])) ->setParam('fileLimit', App::getEnv('_APP_STORAGE_LIMIT', 0)) ->setParam('fileLimitHuman', Storage::human(App::getEnv('_APP_STORAGE_LIMIT', 0))) ->setParam('timeout', (int) App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900)) - ->setParam('usageStatsEnabled',App::getEnv('_APP_USAGE_STATS','enabled') == 'enabled'); + ->setParam('usageStatsEnabled', App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled'); ; $layout - ->setParam('title', APP_NAME.' - Function') + ->setParam('title', APP_NAME . ' - Function') ->setParam('body', $page); }); @@ -484,8 +461,8 @@ App::get('/console/version') ->inject('response') ->action(function ($response) { try { - $version = \json_decode(@\file_get_contents(App::getEnv('_APP_HOME', 'http://localhost').'/v1/health/version'), true); - + $version = \json_decode(@\file_get_contents(App::getEnv('_APP_HOME', 'http://localhost') . '/v1/health/version'), true); + if ($version && isset($version['version'])) { return $response->json(['version' => $version['version']]); } else { @@ -494,4 +471,4 @@ App::get('/console/version') } catch (\Throwable $th) { throw new Exception('Failed to check for a newer version', 500, Exception::GENERAL_SERVER_ERROR); } - }); \ No newline at end of file + }); diff --git a/app/controllers/web/home.php b/app/controllers/web/home.php index 30e629a02f..b5bf366066 100644 --- a/app/controllers/web/home.php +++ b/app/controllers/web/home.php @@ -1,14 +1,16 @@ setParam('version', App::getEnv('_APP_VERSION', 'UNKNOWN')) @@ -24,9 +26,7 @@ App::init(function ($layout) { ; }, ['layout'], 'home'); -App::shutdown(function ($response, $layout) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Appwrite\Utopia\View $layout */ +App::shutdown(function (Response $response, View $layout) { $response->html($layout->render()); }, ['response', 'layout'], 'home'); @@ -38,10 +38,7 @@ App::get('/') ->inject('response') ->inject('dbForConsole') ->inject('project') - ->action(function ($response, $dbForConsole, $project) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForConsole */ - /** @var Utopia\Database\Document $project */ + ->action(function (Response $response, Database $dbForConsole, Document $project) { $response ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') @@ -52,10 +49,10 @@ App::get('/') if ('console' === $project->getId() || $project->isEmpty()) { $whitelistRoot = App::getEnv('_APP_CONSOLE_WHITELIST_ROOT', 'enabled'); - if($whitelistRoot !== 'disabled') { + if ($whitelistRoot !== 'disabled') { $count = $dbForConsole->count('users', [], 1); - if($count !== 0) { + if ($count !== 0) { return $response->redirect('/auth/signin'); } } @@ -69,17 +66,16 @@ App::get('/auth/signin') ->label('permission', 'public') ->label('scope', 'home') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { - $page = new View(__DIR__.'/../../views/home/auth/signin.phtml'); + $page = new View(__DIR__ . '/../../views/home/auth/signin.phtml'); $page ->setParam('root', App::getEnv('_APP_CONSOLE_WHITELIST_ROOT', 'enabled')) ; $layout - ->setParam('title', 'Sign In - '.APP_NAME) + ->setParam('title', 'Sign In - ' . APP_NAME) ->setParam('body', $page); }); @@ -88,16 +84,16 @@ App::get('/auth/signup') ->label('permission', 'public') ->label('scope', 'home') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ - $page = new View(__DIR__.'/../../views/home/auth/signup.phtml'); + ->action(function (View $layout) { + + $page = new View(__DIR__ . '/../../views/home/auth/signup.phtml'); $page ->setParam('root', App::getEnv('_APP_CONSOLE_WHITELIST_ROOT', 'enabled')) ; $layout - ->setParam('title', 'Sign Up - '.APP_NAME) + ->setParam('title', 'Sign Up - ' . APP_NAME) ->setParam('body', $page); }); @@ -106,17 +102,16 @@ App::get('/auth/recovery') ->label('permission', 'public') ->label('scope', 'home') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { - $page = new View(__DIR__.'/../../views/home/auth/recovery.phtml'); + $page = new View(__DIR__ . '/../../views/home/auth/recovery.phtml'); $page ->setParam('smtpEnabled', (!empty(App::getEnv('_APP_SMTP_HOST')))) ; $layout - ->setParam('title', 'Password Recovery - '.APP_NAME) + ->setParam('title', 'Password Recovery - ' . APP_NAME) ->setParam('body', $page); }); @@ -125,13 +120,12 @@ App::get('/auth/confirm') ->label('permission', 'public') ->label('scope', 'home') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { - $page = new View(__DIR__.'/../../views/home/auth/confirm.phtml'); + $page = new View(__DIR__ . '/../../views/home/auth/confirm.phtml'); $layout - ->setParam('title', 'Account Confirmation - '.APP_NAME) + ->setParam('title', 'Account Confirmation - ' . APP_NAME) ->setParam('body', $page); }); @@ -140,13 +134,12 @@ App::get('/auth/join') ->label('permission', 'public') ->label('scope', 'home') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { - $page = new View(__DIR__.'/../../views/home/auth/join.phtml'); + $page = new View(__DIR__ . '/../../views/home/auth/join.phtml'); $layout - ->setParam('title', 'Invitation - '.APP_NAME) + ->setParam('title', 'Invitation - ' . APP_NAME) ->setParam('body', $page); }); @@ -155,13 +148,12 @@ App::get('/auth/recovery/reset') ->label('permission', 'public') ->label('scope', 'home') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { - $page = new View(__DIR__.'/../../views/home/auth/recovery/reset.phtml'); + $page = new View(__DIR__ . '/../../views/home/auth/recovery/reset.phtml'); $layout - ->setParam('title', 'Password Reset - '.APP_NAME) + ->setParam('title', 'Password Reset - ' . APP_NAME) ->setParam('body', $page); }); @@ -170,10 +162,9 @@ App::get('/auth/oauth2/success') ->label('permission', 'public') ->label('scope', 'home') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { - $page = new View(__DIR__.'/../../views/home/auth/oauth2.phtml'); + $page = new View(__DIR__ . '/../../views/home/auth/oauth2.phtml'); $layout ->setParam('title', APP_NAME) @@ -188,10 +179,9 @@ App::get('/auth/magic-url') ->label('permission', 'public') ->label('scope', 'home') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { - $page = new View(__DIR__.'/../../views/home/auth/magicURL.phtml'); + $page = new View(__DIR__ . '/../../views/home/auth/magicURL.phtml'); $layout ->setParam('title', APP_NAME) @@ -206,10 +196,9 @@ App::get('/auth/oauth2/failure') ->label('permission', 'public') ->label('scope', 'home') ->inject('layout') - ->action(function ($layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (View $layout) { - $page = new View(__DIR__.'/../../views/home/auth/oauth2.phtml'); + $page = new View(__DIR__ . '/../../views/home/auth/oauth2.phtml'); $layout ->setParam('title', APP_NAME) @@ -225,17 +214,16 @@ App::get('/error/:code') ->label('scope', 'home') ->param('code', null, new \Utopia\Validator\Numeric(), 'Valid status code number', false) ->inject('layout') - ->action(function ($code, $layout) { - /** @var Appwrite\Utopia\View $layout */ + ->action(function (int $code, View $layout) { - $page = new View(__DIR__.'/../../views/error.phtml'); + $page = new View(__DIR__ . '/../../views/error.phtml'); $page ->setParam('code', $code) ; $layout - ->setParam('title', 'Error'.' - '.APP_NAME) + ->setParam('title', 'Error' . ' - ' . APP_NAME) ->setParam('body', $page); }); @@ -244,8 +232,7 @@ App::get('/versions') ->groups(['web', 'home']) ->label('scope', 'public') ->inject('response') - ->action(function ($response) { - /** @var Appwrite\Utopia\Response $response */ + ->action(function (Response $response) { $platforms = Config::getParam('platforms'); @@ -253,15 +240,15 @@ App::get('/versions') 'server' => APP_VERSION_STABLE, ]; - foreach($platforms as $platform) { + foreach ($platforms as $platform) { $languages = $platform['languages'] ?? []; foreach ($languages as $key => $language) { - if(isset($language['dev']) && $language['dev']) { + if (isset($language['dev']) && $language['dev']) { continue; } - if(isset($language['enabled']) && !$language['enabled']) { + if (isset($language['enabled']) && !$language['enabled']) { continue; } diff --git a/app/executor.php b/app/executor.php index 2e957c624c..73fddc9680 100644 --- a/app/executor.php +++ b/app/executor.php @@ -1,4 +1,5 @@ column('id', Swoole\Table::TYPE_STRING, 256); @@ -64,8 +68,8 @@ $providerName = App::getEnv('_APP_LOGGING_PROVIDER', ''); $providerConfig = App::getEnv('_APP_LOGGING_CONFIG', ''); $logger = null; -if(!empty($providerName) && !empty($providerConfig) && Logger::hasProvider($providerName)) { - $classname = '\\Utopia\\Logger\\Adapter\\'.\ucfirst($providerName); +if (!empty($providerName) && !empty($providerConfig) && Logger::hasProvider($providerName)) { + $classname = '\\Utopia\\Logger\\Adapter\\' . \ucfirst($providerName); $adapter = new $classname($providerConfig); $logger = new Logger($adapter); } @@ -86,7 +90,7 @@ function logError(Throwable $error, string $action, Utopia\Route $route = null) if ($route) { $log->addTag('method', $route->getMethod()); - $log->addTag('url', $route->getPath()); + $log->addTag('url', $route->getPath()); } $log->addTag('code', $error->getCode()); @@ -110,11 +114,13 @@ function logError(Throwable $error, string $action, Utopia\Route $route = null) Console::error('[Error] Message: ' . $error->getMessage()); Console::error('[Error] File: ' . $error->getFile()); Console::error('[Error] Line: ' . $error->getLine()); -}; +} -function getStorageDevice($root): Device { +function getStorageDevice($root): Device +{ switch (App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL)) { - case Storage::DEVICE_LOCAL:default: + case Storage::DEVICE_LOCAL: + default: return new Local($root); case Storage::DEVICE_S3: $s3AccessKey = App::getEnv('_APP_STORAGE_S3_ACCESS_KEY', ''); @@ -130,6 +136,27 @@ function getStorageDevice($root): Device { $doSpacesBucket = App::getEnv('_APP_STORAGE_DO_SPACES_BUCKET', ''); $doSpacesAcl = 'private'; return new DOSpaces($root, $doSpacesAccessKey, $doSpacesSecretKey, $doSpacesBucket, $doSpacesRegion, $doSpacesAcl); + case Storage::DEVICE_BACKBLAZE: + $backblazeAccessKey = App::getEnv('_APP_STORAGE_BACKBLAZE_ACCESS_KEY', ''); + $backblazeSecretKey = App::getEnv('_APP_STORAGE_BACKBLAZE_SECRET', ''); + $backblazeRegion = App::getEnv('_APP_STORAGE_BACKBLAZE_REGION', ''); + $backblazeBucket = App::getEnv('_APP_STORAGE_BACKBLAZE_BUCKET', ''); + $backblazeAcl = 'private'; + return new Backblaze($root, $backblazeAccessKey, $backblazeSecretKey, $backblazeBucket, $backblazeRegion, $backblazeAcl); + case Storage::DEVICE_LINODE: + $linodeAccessKey = App::getEnv('_APP_STORAGE_LINODE_ACCESS_KEY', ''); + $linodeSecretKey = App::getEnv('_APP_STORAGE_LINODE_SECRET', ''); + $linodeRegion = App::getEnv('_APP_STORAGE_LINODE_REGION', ''); + $linodeBucket = App::getEnv('_APP_STORAGE_LINODE_BUCKET', ''); + $linodeAcl = 'private'; + return new Linode($root, $linodeAccessKey, $linodeSecretKey, $linodeBucket, $linodeRegion, $linodeAcl); + case Storage::DEVICE_WASABI: + $wasabiAccessKey = App::getEnv('_APP_STORAGE_WASABI_ACCESS_KEY', ''); + $wasabiSecretKey = App::getEnv('_APP_STORAGE_WASABI_SECRET', ''); + $wasabiRegion = App::getEnv('_APP_STORAGE_WASABI_REGION', ''); + $wasabiBucket = App::getEnv('_APP_STORAGE_WASABI_BUCKET', ''); + $wasabiAcl = 'private'; + return new Wasabi($root, $wasabiAccessKey, $wasabiSecretKey, $wasabiBucket, $wasabiRegion, $wasabiAcl); } } @@ -163,9 +190,9 @@ App::post('/v1/runtimes') try { Console::info('Building container : ' . $runtimeId); - - /** - * Temporary file paths in the executor + + /** + * Temporary file paths in the executor */ $tmpSource = "/tmp/$runtimeId/src/code.tar.gz"; $tmpBuild = "/tmp/$runtimeId/builds/code.tar.gz"; @@ -176,7 +203,7 @@ App::post('/v1/runtimes') $sourceDevice = getStorageDevice("/"); $localDevice = new Local(); $buffer = $sourceDevice->read($source); - if(!$localDevice->write($tmpSource, $buffer)) { + if (!$localDevice->write($tmpSource, $buffer)) { throw new Exception('Failed to copy source code to temporary directory', 500); }; @@ -202,7 +229,7 @@ App::post('/v1/runtimes') ->setCpus((int) App::getEnv('_APP_FUNCTIONS_CPUS', 0)) ->setMemory((int) App::getEnv('_APP_FUNCTIONS_MEMORY', 0)) ->setSwap((int) App::getEnv('_APP_FUNCTIONS_MEMORY_SWAP', 0)); - + /** Keep the container alive if we have commands to be executed */ $entrypoint = !empty($commands) ? [ 'tail', @@ -224,8 +251,8 @@ App::post('/v1/runtimes') ], workdir: $workdir, volumes: [ - \dirname($tmpSource). ':/tmp:rw', - \dirname($tmpBuild). ':/usr/code:rw' + \dirname($tmpSource) . ':/tmp:rw', + \dirname($tmpBuild) . ':/usr/code:rw' ] ); @@ -235,7 +262,7 @@ App::post('/v1/runtimes') $orchestration->networkConnect($runtimeId, App::getEnv('OPEN_RUNTIMES_NETWORK', 'appwrite_runtimes')); - /** + /** * Execute any commands if they were provided */ if (!empty($commands)) { @@ -265,7 +292,7 @@ App::post('/v1/runtimes') $outputPath = $destinationDevice->getPath(\uniqid() . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION)); $buffer = $localDevice->read($tmpBuild); - if(!$destinationDevice->write($outputPath, $buffer, $localDevice->getFileMimeType($tmpBuild))) { + if (!$destinationDevice->write($outputPath, $buffer, $localDevice->getFileMimeType($tmpBuild))) { throw new Exception('Failed to move built code to storage', 500); }; @@ -298,13 +325,12 @@ App::post('/v1/runtimes') } Console::success('Build Stage completed in ' . ($endTime - $startTime) . ' seconds'); - } catch (Throwable $th) { Console::error('Build failed: ' . $th->getMessage() . $stdout); throw new Exception($th->getMessage() . $stdout, 500); } finally { // Container cleanup - if($remove) { + if ($remove) { if (!empty($containerId)) { // If container properly created $orchestration->remove($containerId, true); @@ -337,7 +363,7 @@ App::get('/v1/runtimes') ->action(function ($activeRuntimes, Response $response) { $runtimes = []; - foreach($activeRuntimes as $runtime) { + foreach ($activeRuntimes as $runtime) { $runtimes[] = $runtime; } @@ -353,7 +379,7 @@ App::get('/v1/runtimes/:runtimeId') ->inject('response') ->action(function ($runtimeId, $activeRuntimes, Response $response) { - if(!$activeRuntimes->exists($runtimeId)) { + if (!$activeRuntimes->exists($runtimeId)) { throw new Exception('Runtime not found', 404); } @@ -372,7 +398,7 @@ App::delete('/v1/runtimes/:runtimeId') ->inject('response') ->action(function (string $runtimeId, $orchestrationPool, $activeRuntimes, Response $response) { - if(!$activeRuntimes->exists($runtimeId)) { + if (!$activeRuntimes->exists($runtimeId)) { throw new Exception('Runtime not found', 404); } @@ -408,7 +434,7 @@ App::post('/v1/execution') ->desc('Create an execution') ->param('runtimeId', '', new Text(64), 'The runtimeID to execute.') ->param('vars', [], new Assoc(), 'Environment variables required for the build.') - ->param('data', '{}', new Text(8192), 'Data to be forwarded to the function, this is user specified.', true) + ->param('data', '', new Text(8192), 'Data to be forwarded to the function, this is user specified.', true) ->param('timeout', 15, new Range(1, (int) App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900)), 'Function maximum execution time in seconds.') ->inject('activeRuntimes') ->inject('response') @@ -449,33 +475,33 @@ App::post('/v1/execution') \curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); \curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); \curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); - + \curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', 'Content-Length: ' . \strlen($body), 'x-internal-challenge: ' . $secret, 'host: null' ]); - + $executorResponse = \curl_exec($ch); - + $statusCode = \curl_getinfo($ch, CURLINFO_HTTP_CODE); - + $error = \curl_error($ch); - + $errNo = \curl_errno($ch); - + \curl_close($ch); switch (true) { /** No Error. */ - case $errNo === 0: + case $errNo === 0: break; /** Runtime not ready for requests yet. 111 is the swoole error code for Connection Refused - see https://openswoole.com/docs/swoole-error-code */ case $errNo === 111: throw new Exception('An internal curl error has occurred within the executor! Error Msg: ' . $error, 406); /** Any other CURL error */ - default: + default: throw new Exception('An internal curl error has occurred within the executor! Error Msg: ' . $error, 500); } @@ -527,7 +553,7 @@ App::setResource('activeRuntimes', fn() => $activeRuntimes); App::error(function ($utopia, $error, $request, $response) { $route = $utopia->match($request); logError($error, "httpError", $route); - + switch ($error->getCode()) { case 400: // Error allowed publicly case 401: // Error allowed publicly @@ -546,7 +572,7 @@ App::error(function ($utopia, $error, $request, $response) { default: $code = 500; // All other errors get the generic 500 server error status code } - + $output = [ 'message' => $error->getMessage(), 'code' => $error->getCode(), @@ -567,13 +593,13 @@ App::error(function ($utopia, $error, $request, $response) { App::init(function ($request, $response) { $secretKey = $request->getHeader('x-appwrite-executor-key', ''); - if (empty($secretKey)) { - throw new Exception('Missing executor key', 401); - } - - if ($secretKey !== App::getEnv('_APP_EXECUTOR_SECRET', '')) { + if (empty($secretKey)) { throw new Exception('Missing executor key', 401); - } + } + + if ($secretKey !== App::getEnv('_APP_EXECUTOR_SECRET', '')) { + throw new Exception('Missing executor key', 401); + } }, ['request', 'response']); @@ -581,7 +607,7 @@ $http->on('start', function ($http) { global $orchestrationPool; global $activeRuntimes; - /** + /** * Warmup: make sure images are ready to run fast ๐Ÿš€ */ $runtimes = new Runtimes('v1'); @@ -672,11 +698,10 @@ $http->on('start', function ($http) { } } }); - }); -$http->on('beforeShutdown', function() { +$http->on('beforeShutdown', function () { global $orchestrationPool; Console::info('Cleaning up containers before shutdown...'); @@ -685,7 +710,7 @@ $http->on('beforeShutdown', function() { $orchestrationPool->put($orchestration); foreach ($functionsToRemove as $container) { - go(function () use ($orchestrationPool, $container) { + go(function () use ($orchestrationPool, $container) { try { $orchestration = $orchestrationPool->get(); $orchestration->remove($container->getId(), true); @@ -711,7 +736,7 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo logError($th, "serverError"); $swooleResponse->setStatusCode(500); $output = [ - 'message' => 'Error: '. $th->getMessage(), + 'message' => 'Error: ' . $th->getMessage(), 'code' => 500, 'file' => $th->getFile(), 'line' => $th->getLine(), diff --git a/app/http.php b/app/http.php index d36c59b296..a7d10b9e0a 100644 --- a/app/http.php +++ b/app/http.php @@ -1,6 +1,6 @@ on('WorkerStart', function($server, $workerId) { - Console::success('Worker '.++$workerId.' started successfully'); +$http->on('WorkerStart', function ($server, $workerId) { + Console::success('Worker ' . ++$workerId . ' started successfully'); }); -$http->on('BeforeReload', function($server, $workerId) { +$http->on('BeforeReload', function ($server, $workerId) { Console::success('Starting reload...'); }); -$http->on('AfterReload', function($server, $workerId) { +$http->on('AfterReload', function ($server, $workerId) { Console::success('Reload completed...'); }); @@ -57,7 +57,7 @@ include __DIR__ . '/controllers/general.php'; $http->on('start', function (Server $http) use ($payloadSize, $register) { $app = new App('UTC'); - go(function() use ($register, $app) { + go(function () use ($register, $app) { // wait for database to be ready $attempts = 0; $max = 10; @@ -69,10 +69,10 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { $db = $register->get('dbPool')->get(); $redis = $register->get('redisPool')->get(); break; // leave the do-while if successful - } catch(\Exception $e) { + } catch (\Exception $e) { Console::warning("Database not ready. Retrying connection ({$attempts})..."); if ($attempts >= $max) { - throw new \Exception('Failed to connect to database: '. $e->getMessage()); + throw new \Exception('Failed to connect to database: ' . $e->getMessage()); } sleep($sleep); } @@ -86,7 +86,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { Console::success('[Setup] - Server database init started...'); $collections = Config::getParam('collections', []); /** @var array $collections */ - if(!$dbForConsole->exists(App::getEnv('_APP_DB_SCHEMA', 'appwrite'))) { + if (!$dbForConsole->exists(App::getEnv('_APP_DB_SCHEMA', 'appwrite'))) { $redis->flushAll(); Console::success('[Setup] - Creating database: appwrite...'); @@ -101,7 +101,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { Console::success('[Setup] - Skip: metadata table already exists'); } - if($dbForConsole->getCollection(Audit::COLLECTION)->isEmpty()) { + if ($dbForConsole->getCollection(Audit::COLLECTION)->isEmpty()) { $audit = new Audit($dbForConsole); $audit->setup(); } @@ -112,10 +112,10 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { } foreach ($collections as $key => $collection) { - if(($collection['$collection'] ?? '') !== Database::METADATA) { + if (($collection['$collection'] ?? '') !== Database::METADATA) { continue; } - if(!$dbForConsole->getCollection($key)->isEmpty()) { + if (!$dbForConsole->getCollection($key)->isEmpty()) { continue; } Console::success('[Setup] - Creating collection: ' . $collection['$id'] . '...'); @@ -150,7 +150,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { $dbForConsole->createCollection($key, $attributes, $indexes); } - if($dbForConsole->getDocument('buckets', 'default')->isEmpty()) { + if ($dbForConsole->getDocument('buckets', 'default')->isEmpty()) { Console::success('[Setup] - Creating default bucket...'); $dbForConsole->createDocument('buckets', new Document([ '$id' => 'default', @@ -170,16 +170,16 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { ])); $bucket = $dbForConsole->getDocument('buckets', 'default'); - + Console::success('[Setup] - Creating files collection for default bucket...'); $files = $collections['files'] ?? []; - if(empty($files)) { + if (empty($files)) { throw new Exception('Files collection is not configured.'); } - + $attributes = []; $indexes = []; - + foreach ($files['attributes'] as $attribute) { $attributes[] = new Document([ '$id' => $attribute['$id'], @@ -193,7 +193,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { 'format' => $attribute['format'] ?? '' ]); } - + foreach ($files['indexes'] as $index) { $indexes[] = new Document([ '$id' => $index['$id'], @@ -203,15 +203,14 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) { 'orders' => $index['orders'], ]); } - + $dbForConsole->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes); } Console::success('[Setup] - Server database init completed...'); }); - Console::success('Server started successfully (max payload is '.number_format($payloadSize).' bytes)'); - + Console::success('Server started successfully (max payload is ' . number_format($payloadSize) . ' bytes)'); Console::info("Master pid {$http->master_pid}, manager pid {$http->manager_pid}"); // listen ctrl + c @@ -225,13 +224,13 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo $request = new Request($swooleRequest); $response = new Response($swooleResponse); - if(Files::isFileLoaded($request->getURI())) { + if (Files::isFileLoaded($request->getURI())) { $time = (60 * 60 * 24 * 365 * 2); // 45 days cache $response ->setContentType(Files::getFileMimeType($request->getURI())) - ->addHeader('Cache-Control', 'public, max-age='.$time) - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time).' GMT') // 45 days cache + ->addHeader('Cache-Control', 'public, max-age=' . $time) + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time) . ' GMT') // 45 days cache ->send(Files::getFileContents($request->getURI())) ; @@ -255,11 +254,11 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo $version = App::getEnv('_APP_VERSION', 'UNKNOWN'); $logger = $app->getResource("logger"); - if($logger) { + if ($logger) { try { /** @var Utopia\Database\Document $user */ $user = $app->getResource('user'); - } catch(\Throwable $_th) { + } catch (\Throwable $_th) { // All good, user is optional information for logger } @@ -268,7 +267,7 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo $log = new Utopia\Logger\Log(); - if(isset($user) && !$user->isEmpty()) { + if (isset($user) && !$user->isEmpty()) { $log->setUser(new User($user->getId())); } @@ -279,7 +278,7 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo $log->setMessage($th->getMessage()); $log->addTag('method', $route->getMethod()); - $log->addTag('url', $route->getPath()); + $log->addTag('url', $route->getPath()); $log->addTag('verboseType', get_class($th)); $log->addTag('code', $th->getCode()); // $log->addTag('projectId', $project->getId()); // TODO: Figure out how to get ProjectID, if it becomes relevant @@ -298,18 +297,18 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo $isProduction = App::getEnv('_APP_ENV', 'development') === 'production'; $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); - foreach($loggerBreadcrumbs as $loggerBreadcrumb) { + foreach ($loggerBreadcrumbs as $loggerBreadcrumb) { $log->addBreadcrumb($loggerBreadcrumb); } $responseCode = $logger->addLog($log); - Console::info('Log pushed with status code: '.$responseCode); + Console::info('Log pushed with status code: ' . $responseCode); } - Console::error('[Error] Type: '.get_class($th)); - Console::error('[Error] Message: '.$th->getMessage()); - Console::error('[Error] File: '.$th->getFile()); - Console::error('[Error] Line: '.$th->getLine()); + Console::error('[Error] Type: ' . get_class($th)); + Console::error('[Error] Message: ' . $th->getMessage()); + Console::error('[Error] File: ' . $th->getFile()); + Console::error('[Error] Line: ' . $th->getLine()); /** * Reset Database connection if PDOException was thrown. @@ -321,7 +320,7 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo $swooleResponse->setStatusCode(500); $output = ((App::isDevelopment())) ? [ - 'message' => 'Error: '. $th->getMessage(), + 'message' => 'Error: ' . $th->getMessage(), 'code' => 500, 'file' => $th->getFile(), 'line' => $th->getLine(), @@ -345,4 +344,4 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo } }); -$http->start(); \ No newline at end of file +$http->start(); diff --git a/app/init.php b/app/init.php index 7583897d0a..0e1848b2c3 100644 --- a/app/init.php +++ b/app/init.php @@ -2,16 +2,17 @@ /** * Init - * + * * Initializes both Appwrite API entry point, queue workers, and CLI tasks. * Set configuration, framework resources & app constants - * + * */ -if (\file_exists(__DIR__.'/../vendor/autoload.php')) { - require_once __DIR__.'/../vendor/autoload.php'; + +if (\file_exists(__DIR__ . '/../vendor/autoload.php')) { + require_once __DIR__ . '/../vendor/autoload.php'; } -ini_set('memory_limit','512M'); +ini_set('memory_limit', '512M'); ini_set('display_errors', 1); ini_set('display_startup_errors', 1); ini_set('default_socket_timeout', -1); @@ -56,15 +57,18 @@ use Swoole\Database\RedisPool; use Utopia\Database\Query; use Utopia\Storage\Device; use Utopia\Storage\Storage; +use Utopia\Storage\Device\Backblaze; +use Utopia\Storage\Device\DOSpaces; use Utopia\Storage\Device\Local; use Utopia\Storage\Device\S3; -use Utopia\Storage\Device\DOSpaces; +use Utopia\Storage\Device\Linode; +use Utopia\Storage\Device\Wasabi; const APP_NAME = 'Appwrite'; const APP_DOMAIN = 'appwrite.io'; const APP_EMAIL_TEAM = 'team@localhost.test'; // Default email address const APP_EMAIL_SECURITY = ''; // Default security email address -const APP_USERAGENT = APP_NAME.'-Server v%s. Please report abuse at %s'; +const APP_USERAGENT = APP_NAME . '-Server v%s. Please report abuse at %s'; const APP_MODE_DEFAULT = 'default'; const APP_MODE_ADMIN = 'admin'; const APP_PAGING_LIMIT = 12; @@ -74,8 +78,9 @@ const APP_LIMIT_ANTIVIRUS = 20000000; //20MB const APP_LIMIT_ENCRYPTION = 20000000; //20MB const APP_LIMIT_COMPRESSION = 20000000; //20MB const APP_LIMIT_ARRAY_PARAMS_SIZE = 100; // Default maximum of how many elements can there be in API parameter that expects array value +const APP_LIMIT_SUBQUERY = 1000; const APP_CACHE_BUSTER = 305; -const APP_VERSION_STABLE = '0.14.1'; +const APP_VERSION_STABLE = '0.14.2'; const APP_DATABASE_ATTRIBUTE_EMAIL = 'email'; const APP_DATABASE_ATTRIBUTE_ENUM = 'enum'; const APP_DATABASE_ATTRIBUTE_IP = 'ip'; @@ -99,7 +104,7 @@ const APP_SOCIAL_GITHUB = 'https://github.com/appwrite'; const APP_SOCIAL_DISCORD = 'https://appwrite.io/discord'; const APP_SOCIAL_DISCORD_CHANNEL = '564160730845151244'; const APP_SOCIAL_DEV = 'https://dev.to/appwrite'; -const APP_SOCIAL_STACKSHARE = 'https://stackshare.io/appwrite'; +const APP_SOCIAL_STACKSHARE = 'https://stackshare.io/appwrite'; const APP_SOCIAL_YOUTUBE = 'https://www.youtube.com/c/appwrite?sub_confirmation=1'; // Database Reconnect const DATABASE_RECONNECT_SLEEP = 2; @@ -119,7 +124,7 @@ const DELETE_TYPE_PROJECTS = 'projects'; const DELETE_TYPE_FUNCTIONS = 'functions'; const DELETE_TYPE_DEPLOYMENTS = 'deployments'; const DELETE_TYPE_USERS = 'users'; -const DELETE_TYPE_TEAMS= 'teams'; +const DELETE_TYPE_TEAMS = 'teams'; const DELETE_TYPE_EXECUTIONS = 'executions'; const DELETE_TYPE_AUDIT = 'audit'; const DELETE_TYPE_ABUSE = 'abuse'; @@ -139,7 +144,7 @@ const APP_AUTH_TYPE_JWT = 'JWT'; const APP_AUTH_TYPE_KEY = 'Key'; const APP_AUTH_TYPE_ADMIN = 'Admin'; // Response related -const MAX_OUTPUT_CHUNK_SIZE = 2*1024*1024; // 2MB +const MAX_OUTPUT_CHUNK_SIZE = 2 * 1024 * 1024; // 2MB $register = new Registry(); @@ -148,82 +153,89 @@ App::setMode(App::getEnv('_APP_ENV', App::MODE_TYPE_PRODUCTION)); /* * ENV vars */ -Config::load('events', __DIR__.'/config/events.php'); -Config::load('auth', __DIR__.'/config/auth.php'); -Config::load('errors', __DIR__.'/config/errors.php'); -Config::load('providers', __DIR__.'/config/providers.php'); -Config::load('platforms', __DIR__.'/config/platforms.php'); -Config::load('collections', __DIR__.'/config/collections.php'); -Config::load('runtimes', __DIR__.'/config/runtimes.php'); -Config::load('roles', __DIR__.'/config/roles.php'); // User roles and scopes -Config::load('scopes', __DIR__.'/config/scopes.php'); // User roles and scopes -Config::load('services', __DIR__.'/config/services.php'); // List of services -Config::load('variables', __DIR__.'/config/variables.php'); // List of env variables -Config::load('avatar-browsers', __DIR__.'/config/avatars/browsers.php'); -Config::load('avatar-credit-cards', __DIR__.'/config/avatars/credit-cards.php'); -Config::load('avatar-flags', __DIR__.'/config/avatars/flags.php'); -Config::load('locale-codes', __DIR__.'/config/locale/codes.php'); -Config::load('locale-currencies', __DIR__.'/config/locale/currencies.php'); -Config::load('locale-eu', __DIR__.'/config/locale/eu.php'); -Config::load('locale-languages', __DIR__.'/config/locale/languages.php'); -Config::load('locale-phones', __DIR__.'/config/locale/phones.php'); -Config::load('locale-countries', __DIR__.'/config/locale/countries.php'); -Config::load('locale-continents', __DIR__.'/config/locale/continents.php'); -Config::load('storage-logos', __DIR__.'/config/storage/logos.php'); -Config::load('storage-mimes', __DIR__.'/config/storage/mimes.php'); -Config::load('storage-inputs', __DIR__.'/config/storage/inputs.php'); -Config::load('storage-outputs', __DIR__.'/config/storage/outputs.php'); +Config::load('events', __DIR__ . '/config/events.php'); +Config::load('auth', __DIR__ . '/config/auth.php'); +Config::load('errors', __DIR__ . '/config/errors.php'); +Config::load('providers', __DIR__ . '/config/providers.php'); +Config::load('platforms', __DIR__ . '/config/platforms.php'); +Config::load('collections', __DIR__ . '/config/collections.php'); +Config::load('runtimes', __DIR__ . '/config/runtimes.php'); +Config::load('roles', __DIR__ . '/config/roles.php'); // User roles and scopes +Config::load('scopes', __DIR__ . '/config/scopes.php'); // User roles and scopes +Config::load('services', __DIR__ . '/config/services.php'); // List of services +Config::load('variables', __DIR__ . '/config/variables.php'); // List of env variables +Config::load('avatar-browsers', __DIR__ . '/config/avatars/browsers.php'); +Config::load('avatar-credit-cards', __DIR__ . '/config/avatars/credit-cards.php'); +Config::load('avatar-flags', __DIR__ . '/config/avatars/flags.php'); +Config::load('locale-codes', __DIR__ . '/config/locale/codes.php'); +Config::load('locale-currencies', __DIR__ . '/config/locale/currencies.php'); +Config::load('locale-eu', __DIR__ . '/config/locale/eu.php'); +Config::load('locale-languages', __DIR__ . '/config/locale/languages.php'); +Config::load('locale-phones', __DIR__ . '/config/locale/phones.php'); +Config::load('locale-countries', __DIR__ . '/config/locale/countries.php'); +Config::load('locale-continents', __DIR__ . '/config/locale/continents.php'); +Config::load('storage-logos', __DIR__ . '/config/storage/logos.php'); +Config::load('storage-mimes', __DIR__ . '/config/storage/mimes.php'); +Config::load('storage-inputs', __DIR__ . '/config/storage/inputs.php'); +Config::load('storage-outputs', __DIR__ . '/config/storage/outputs.php'); -$user = App::getEnv('_APP_REDIS_USER',''); -$pass = App::getEnv('_APP_REDIS_PASS',''); -if(!empty($user) || !empty($pass)) { - Resque::setBackend('redis://'.$user.':'.$pass.'@'.App::getEnv('_APP_REDIS_HOST', '').':'.App::getEnv('_APP_REDIS_PORT', '')); +$user = App::getEnv('_APP_REDIS_USER', ''); +$pass = App::getEnv('_APP_REDIS_PASS', ''); +if (!empty($user) || !empty($pass)) { + Resque::setBackend('redis://' . $user . ':' . $pass . '@' . App::getEnv('_APP_REDIS_HOST', '') . ':' . App::getEnv('_APP_REDIS_PORT', '')); } else { - Resque::setBackend(App::getEnv('_APP_REDIS_HOST', '').':'.App::getEnv('_APP_REDIS_PORT', '')); + Resque::setBackend(App::getEnv('_APP_REDIS_HOST', '') . ':' . App::getEnv('_APP_REDIS_PORT', '')); } /** * New DB Filters */ -Database::addFilter('casting', - function($value) { +Database::addFilter( + 'casting', + function (mixed $value) { return json_encode(['value' => $value], JSON_PRESERVE_ZERO_FRACTION); }, - function($value) { + function (mixed $value) { if (is_null($value)) { return null; } + return json_decode($value, true)['value']; } ); -Database::addFilter('enum', - function($value, Document $attribute) { +Database::addFilter( + 'enum', + function (mixed $value, Document $attribute) { if ($attribute->isSet('elements')) { $attribute->removeAttribute('elements'); } + return $value; }, - function($value, Document $attribute) { + function (mixed $value, Document $attribute) { $formatOptions = json_decode($attribute->getAttribute('formatOptions', '[]'), true); if (isset($formatOptions['elements'])) { $attribute->setAttribute('elements', $formatOptions['elements']); } + return $value; } ); -Database::addFilter('range', - function($value, Document $attribute) { +Database::addFilter( + 'range', + function (mixed $value, Document $attribute) { if ($attribute->isSet('min')) { $attribute->removeAttribute('min'); } if ($attribute->isSet('max')) { $attribute->removeAttribute('max'); } + return $value; }, - function($value, Document $attribute) { + function (mixed $value, Document $attribute) { $formatOptions = json_decode($attribute->getAttribute('formatOptions', '[]'), true); if (isset($formatOptions['min']) || isset($formatOptions['max'])) { $attribute @@ -231,124 +243,134 @@ Database::addFilter('range', ->setAttribute('max', $formatOptions['max']) ; } + return $value; } ); -Database::addFilter('subQueryAttributes', - function($value) { +Database::addFilter( + 'subQueryAttributes', + function (mixed $value) { return null; }, - function($value, Document $document, Database $database) { + function (mixed $value, Document $document, Database $database) { return $database ->find('attributes', [ new Query('collectionId', Query::TYPE_EQUAL, [$document->getId()]) - ], $database->getAttributeLimit(), 0, []); + ], $database->getAttributeLimit()); } ); -Database::addFilter('subQueryIndexes', - function($value) { +Database::addFilter( + 'subQueryIndexes', + function (mixed $value) { return null; }, - function($value, Document $document, Database $database) { + function (mixed $value, Document $document, Database $database) { return $database ->find('indexes', [ new Query('collectionId', Query::TYPE_EQUAL, [$document->getId()]) - ], 64, 0, []); + ], 64); } ); -Database::addFilter('subQueryPlatforms', - function($value) { +Database::addFilter( + 'subQueryPlatforms', + function (mixed $value) { return null; }, - function($value, Document $document, Database $database) { + function (mixed $value, Document $document, Database $database) { return $database ->find('platforms', [ new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) - ], $database->getIndexLimit(), 0, []); + ], APP_LIMIT_SUBQUERY); } ); -Database::addFilter('subQueryDomains', - function($value) { +Database::addFilter( + 'subQueryDomains', + function (mixed $value) { return null; }, - function($value, Document $document, Database $database) { + function (mixed $value, Document $document, Database $database) { return $database ->find('domains', [ new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) - ], $database->getIndexLimit(), 0, []); + ], APP_LIMIT_SUBQUERY); } ); -Database::addFilter('subQueryKeys', - function($value) { +Database::addFilter( + 'subQueryKeys', + function (mixed $value) { return null; }, - function($value, Document $document, Database $database) { + function (mixed $value, Document $document, Database $database) { return $database ->find('keys', [ new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) - ], $database->getIndexLimit(), 0, []); + ], APP_LIMIT_SUBQUERY); } ); -Database::addFilter('subQueryWebhooks', - function($value) { +Database::addFilter( + 'subQueryWebhooks', + function (mixed $value) { return null; }, - function($value, Document $document, Database $database) { + function (mixed $value, Document $document, Database $database) { return $database ->find('webhooks', [ new Query('projectId', Query::TYPE_EQUAL, [$document->getId()]) - ], $database->getIndexLimit(), 0, []); + ], APP_LIMIT_SUBQUERY); } ); -Database::addFilter('subQuerySessions', - function($value) { +Database::addFilter( + 'subQuerySessions', + function (mixed $value) { return null; }, - function($value, Document $document, Database $database) { - $sessions = Authorization::skip(fn () => $database->find('sessions', [ + function (mixed $value, Document $document, Database $database) { + return Authorization::skip(fn () => $database->find('sessions', [ new Query('userId', Query::TYPE_EQUAL, [$document->getId()]) - ], $database->getIndexLimit(), 0, [])); - - return $sessions; + ], APP_LIMIT_SUBQUERY)); } ); -Database::addFilter('subQueryTokens', - function($value) { +Database::addFilter( + 'subQueryTokens', + function (mixed $value) { return null; }, - function($value, Document $document, Database $database) { + function (mixed $value, Document $document, Database $database) { return Authorization::skip(fn() => $database ->find('tokens', [ new Query('userId', Query::TYPE_EQUAL, [$document->getId()]) - ], $database->getIndexLimit(), 0, [])); - } -); - -Database::addFilter('subQueryMemberships', - function($value) { - return null; - }, - function($value, Document $document, Database $database) { - return Authorization::skip(fn() => $database - ->find('memberships', [ - new Query('userId', Query::TYPE_EQUAL, [$document->getId()]) - ], $database->getIndexLimit(), 0, [])); + ], APP_LIMIT_SUBQUERY)); } ); -Database::addFilter('encrypt', - function($value) { +Database::addFilter( + 'subQueryMemberships', + function (mixed $value) { + return null; + }, + function (mixed $value, Document $document, Database $database) { + return Authorization::skip(fn() => $database + ->find('memberships', [ + new Query('userId', Query::TYPE_EQUAL, [$document->getId()]) + ], APP_LIMIT_SUBQUERY)); + } +); + +Database::addFilter( + 'encrypt', + function (mixed $value) { $key = App::getEnv('_APP_OPENSSL_KEY_V1'); $iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM)); $tag = null; + return json_encode([ 'data' => OpenSSL::encrypt($value, OpenSSL::CIPHER_AES_128_GCM, $key, 0, $iv, $tag), 'method' => OpenSSL::CIPHER_AES_128_GCM, @@ -357,12 +379,12 @@ Database::addFilter('encrypt', 'version' => '1', ]); }, - function($value) { - if(is_null($value)) { + function (mixed $value) { + if (is_null($value)) { return null; } $value = json_decode($value, true); - $key = App::getEnv('_APP_OPENSSL_KEY_V'.$value['version']); + $key = App::getEnv('_APP_OPENSSL_KEY_V' . $value['version']); return OpenSSL::decrypt($value['data'], $value['method'], $key, 0, hex2bin($value['iv']), hex2bin($value['tag'])); } @@ -371,30 +393,30 @@ Database::addFilter('encrypt', /** * DB Formats */ -Structure::addFormat(APP_DATABASE_ATTRIBUTE_EMAIL, function() { +Structure::addFormat(APP_DATABASE_ATTRIBUTE_EMAIL, function () { return new Email(); }, Database::VAR_STRING); -Structure::addFormat(APP_DATABASE_ATTRIBUTE_ENUM, function($attribute) { +Structure::addFormat(APP_DATABASE_ATTRIBUTE_ENUM, function ($attribute) { $elements = $attribute['formatOptions']['elements']; return new WhiteList($elements, true); }, Database::VAR_STRING); -Structure::addFormat(APP_DATABASE_ATTRIBUTE_IP, function() { +Structure::addFormat(APP_DATABASE_ATTRIBUTE_IP, function () { return new IP(); }, Database::VAR_STRING); -Structure::addFormat(APP_DATABASE_ATTRIBUTE_URL, function() { +Structure::addFormat(APP_DATABASE_ATTRIBUTE_URL, function () { return new URL(); }, Database::VAR_STRING); -Structure::addFormat(APP_DATABASE_ATTRIBUTE_INT_RANGE, function($attribute) { +Structure::addFormat(APP_DATABASE_ATTRIBUTE_INT_RANGE, function ($attribute) { $min = $attribute['formatOptions']['min'] ?? -INF; $max = $attribute['formatOptions']['max'] ?? INF; return new Range($min, $max, Range::TYPE_INTEGER); }, Database::VAR_INTEGER); -Structure::addFormat(APP_DATABASE_ATTRIBUTE_FLOAT_RANGE, function($attribute) { +Structure::addFormat(APP_DATABASE_ATTRIBUTE_FLOAT_RANGE, function ($attribute) { $min = $attribute['formatOptions']['min'] ?? -INF; $max = $attribute['formatOptions']['max'] ?? INF; return new Range($min, $max, Range::TYPE_FLOAT); @@ -403,30 +425,33 @@ Structure::addFormat(APP_DATABASE_ATTRIBUTE_FLOAT_RANGE, function($attribute) { /* * Registry */ -$register->set('logger', function () { // Register error logger +$register->set('logger', function () { + // Register error logger $providerName = App::getEnv('_APP_LOGGING_PROVIDER', ''); $providerConfig = App::getEnv('_APP_LOGGING_CONFIG', ''); - if(empty($providerName) || empty($providerConfig)) { + if (empty($providerName) || empty($providerConfig)) { return null; } - if(!Logger::hasProvider($providerName)) { + if (!Logger::hasProvider($providerName)) { throw new Exception("Logging provider not supported. Logging disabled.", 500, Exception::GENERAL_SERVER_ERROR); } - $classname = '\\Utopia\\Logger\\Adapter\\'.\ucfirst($providerName); + $classname = '\\Utopia\\Logger\\Adapter\\' . \ucfirst($providerName); $adapter = new $classname($providerConfig); return new Logger($adapter); }); -$register->set('dbPool', function () { // Register DB connection +$register->set('dbPool', function () { + // Register DB connection $dbHost = App::getEnv('_APP_DB_HOST', ''); $dbPort = App::getEnv('_APP_DB_PORT', ''); $dbUser = App::getEnv('_APP_DB_USER', ''); $dbPass = App::getEnv('_APP_DB_PASS', ''); $dbScheme = App::getEnv('_APP_DB_SCHEMA', ''); - $pool = new PDOPool((new PDOConfig()) + $pool = new PDOPool( + (new PDOConfig()) ->withHost($dbHost) ->withPort($dbPort) ->withDbName($dbScheme) @@ -435,8 +460,9 @@ $register->set('dbPool', function () { // Register DB connection ->withPassword($dbPass) ->withOptions([ PDO::ATTR_ERRMODE => App::isDevelopment() ? PDO::ERRMODE_WARNING : PDO::ERRMODE_SILENT, // If in production mode, warnings are not displayed - ]) - , 64); + ]), + 64 + ); return $pool; }); @@ -448,19 +474,22 @@ $register->set('redisPool', function () { $redisAuth = ''; if ($redisUser && $redisPass) { - $redisAuth = $redisUser.':'.$redisPass; + $redisAuth = $redisUser . ':' . $redisPass; } - $pool = new RedisPool((new RedisConfig) + $pool = new RedisPool( + (new RedisConfig()) ->withHost($redisHost) ->withPort($redisPort) ->withAuth($redisAuth) - ->withDbIndex(0) - , 64); + ->withDbIndex(0), + 64 + ); return $pool; }); -$register->set('influxdb', function () { // Register DB connection +$register->set('influxdb', function () { + // Register DB connection $host = App::getEnv('_APP_INFLUXDB_HOST', ''); $port = App::getEnv('_APP_INFLUXDB_PORT', ''); @@ -473,7 +502,8 @@ $register->set('influxdb', function () { // Register DB connection return $client; }); -$register->set('statsd', function () { // Register DB connection +$register->set('statsd', function () { + // Register DB connection $host = App::getEnv('_APP_STATSD_HOST', 'telegraf'); $port = App::getEnv('_APP_STATSD_PORT', 8125); @@ -500,7 +530,7 @@ $register->set('smtp', function () { $mail->SMTPAutoTLS = false; $mail->CharSet = 'UTF-8'; - $from = \urldecode(App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME.' Server')); + $from = \urldecode(App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server')); $email = App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM); $mail->setFrom($email, $from); @@ -511,9 +541,10 @@ $register->set('smtp', function () { return $mail; }); $register->set('geodb', function () { - return new Reader(__DIR__.'/db/DBIP/dbip-country-lite-2022-03.mmdb'); + return new Reader(__DIR__ . '/db/DBIP/dbip-country-lite-2022-03.mmdb'); }); -$register->set('db', function () { // This is usually for our workers or CLI commands scope +$register->set('db', function () { + // This is usually for our workers or CLI commands scope $dbHost = App::getEnv('_APP_DB_HOST', ''); $dbPort = App::getEnv('_APP_DB_PORT', ''); $dbUser = App::getEnv('_APP_DB_USER', ''); @@ -530,7 +561,8 @@ $register->set('db', function () { // This is usually for our workers or CLI com return $pdo; }); -$register->set('cache', function () { // This is usually for our workers or CLI commands scope +$register->set('cache', function () { + // This is usually for our workers or CLI commands scope $redis = new Redis(); $redis->pconnect(App::getEnv('_APP_REDIS_HOST', ''), App::getEnv('_APP_REDIS_PORT', '')); $redis->setOption(Redis::OPT_READ_TIMEOUT, -1); @@ -542,59 +574,59 @@ $register->set('cache', function () { // This is usually for our workers or CLI * Localization */ Locale::$exceptions = false; -Locale::setLanguageFromJSON('af', __DIR__.'/config/locale/translations/af.json'); -Locale::setLanguageFromJSON('ar', __DIR__.'/config/locale/translations/ar.json'); -Locale::setLanguageFromJSON('as', __DIR__.'/config/locale/translations/as.json'); -Locale::setLanguageFromJSON('az', __DIR__.'/config/locale/translations/az.json'); -Locale::setLanguageFromJSON('be', __DIR__.'/config/locale/translations/be.json'); -Locale::setLanguageFromJSON('bg', __DIR__.'/config/locale/translations/bg.json'); -Locale::setLanguageFromJSON('bh', __DIR__.'/config/locale/translations/bh.json'); -Locale::setLanguageFromJSON('bn', __DIR__.'/config/locale/translations/bn.json'); -Locale::setLanguageFromJSON('bs', __DIR__.'/config/locale/translations/bs.json'); -Locale::setLanguageFromJSON('ca', __DIR__.'/config/locale/translations/ca.json'); -Locale::setLanguageFromJSON('cs', __DIR__.'/config/locale/translations/cs.json'); -Locale::setLanguageFromJSON('da', __DIR__.'/config/locale/translations/da.json'); -Locale::setLanguageFromJSON('de', __DIR__.'/config/locale/translations/de.json'); -Locale::setLanguageFromJSON('el', __DIR__.'/config/locale/translations/el.json'); -Locale::setLanguageFromJSON('en', __DIR__.'/config/locale/translations/en.json'); -Locale::setLanguageFromJSON('eo', __DIR__.'/config/locale/translations/eo.json'); -Locale::setLanguageFromJSON('es', __DIR__.'/config/locale/translations/es.json'); -Locale::setLanguageFromJSON('fa', __DIR__.'/config/locale/translations/fa.json'); -Locale::setLanguageFromJSON('fi', __DIR__.'/config/locale/translations/fi.json'); -Locale::setLanguageFromJSON('fo', __DIR__.'/config/locale/translations/fo.json'); -Locale::setLanguageFromJSON('fr', __DIR__.'/config/locale/translations/fr.json'); -Locale::setLanguageFromJSON('ga', __DIR__.'/config/locale/translations/ga.json'); -Locale::setLanguageFromJSON('gu', __DIR__.'/config/locale/translations/gu.json'); -Locale::setLanguageFromJSON('he', __DIR__.'/config/locale/translations/he.json'); -Locale::setLanguageFromJSON('hi', __DIR__.'/config/locale/translations/hi.json'); -Locale::setLanguageFromJSON('hr', __DIR__.'/config/locale/translations/hr.json'); -Locale::setLanguageFromJSON('hu', __DIR__.'/config/locale/translations/hu.json'); -Locale::setLanguageFromJSON('hy', __DIR__.'/config/locale/translations/hy.json'); -Locale::setLanguageFromJSON('id', __DIR__.'/config/locale/translations/id.json'); -Locale::setLanguageFromJSON('is', __DIR__.'/config/locale/translations/is.json'); -Locale::setLanguageFromJSON('it', __DIR__.'/config/locale/translations/it.json'); -Locale::setLanguageFromJSON('ja', __DIR__.'/config/locale/translations/ja.json'); -Locale::setLanguageFromJSON('jv', __DIR__.'/config/locale/translations/jv.json'); -Locale::setLanguageFromJSON('kn', __DIR__.'/config/locale/translations/kn.json'); -Locale::setLanguageFromJSON('km', __DIR__.'/config/locale/translations/km.json'); -Locale::setLanguageFromJSON('ko', __DIR__.'/config/locale/translations/ko.json'); -Locale::setLanguageFromJSON('la', __DIR__.'/config/locale/translations/la.json'); -Locale::setLanguageFromJSON('lb', __DIR__.'/config/locale/translations/lb.json'); -Locale::setLanguageFromJSON('lt', __DIR__.'/config/locale/translations/lt.json'); -Locale::setLanguageFromJSON('lv', __DIR__.'/config/locale/translations/lv.json'); -Locale::setLanguageFromJSON('ml', __DIR__.'/config/locale/translations/ml.json'); -Locale::setLanguageFromJSON('mr', __DIR__.'/config/locale/translations/mr.json'); -Locale::setLanguageFromJSON('ms', __DIR__.'/config/locale/translations/ms.json'); -Locale::setLanguageFromJSON('nb', __DIR__.'/config/locale/translations/nb.json'); -Locale::setLanguageFromJSON('ne', __DIR__.'/config/locale/translations/ne.json'); -Locale::setLanguageFromJSON('nl', __DIR__.'/config/locale/translations/nl.json'); -Locale::setLanguageFromJSON('nn', __DIR__.'/config/locale/translations/nn.json'); -Locale::setLanguageFromJSON('or', __DIR__.'/config/locale/translations/or.json'); -Locale::setLanguageFromJSON('pa', __DIR__.'/config/locale/translations/pa.json'); -Locale::setLanguageFromJSON('pl', __DIR__.'/config/locale/translations/pl.json'); -Locale::setLanguageFromJSON('pt-br', __DIR__.'/config/locale/translations/pt-br.json'); -Locale::setLanguageFromJSON('pt-pt', __DIR__.'/config/locale/translations/pt-pt.json'); -Locale::setLanguageFromJSON('ro', __DIR__.'/config/locale/translations/ro.json'); +Locale::setLanguageFromJSON('af', __DIR__ . '/config/locale/translations/af.json'); +Locale::setLanguageFromJSON('ar', __DIR__ . '/config/locale/translations/ar.json'); +Locale::setLanguageFromJSON('as', __DIR__ . '/config/locale/translations/as.json'); +Locale::setLanguageFromJSON('az', __DIR__ . '/config/locale/translations/az.json'); +Locale::setLanguageFromJSON('be', __DIR__ . '/config/locale/translations/be.json'); +Locale::setLanguageFromJSON('bg', __DIR__ . '/config/locale/translations/bg.json'); +Locale::setLanguageFromJSON('bh', __DIR__ . '/config/locale/translations/bh.json'); +Locale::setLanguageFromJSON('bn', __DIR__ . '/config/locale/translations/bn.json'); +Locale::setLanguageFromJSON('bs', __DIR__ . '/config/locale/translations/bs.json'); +Locale::setLanguageFromJSON('ca', __DIR__ . '/config/locale/translations/ca.json'); +Locale::setLanguageFromJSON('cs', __DIR__ . '/config/locale/translations/cs.json'); +Locale::setLanguageFromJSON('da', __DIR__ . '/config/locale/translations/da.json'); +Locale::setLanguageFromJSON('de', __DIR__ . '/config/locale/translations/de.json'); +Locale::setLanguageFromJSON('el', __DIR__ . '/config/locale/translations/el.json'); +Locale::setLanguageFromJSON('en', __DIR__ . '/config/locale/translations/en.json'); +Locale::setLanguageFromJSON('eo', __DIR__ . '/config/locale/translations/eo.json'); +Locale::setLanguageFromJSON('es', __DIR__ . '/config/locale/translations/es.json'); +Locale::setLanguageFromJSON('fa', __DIR__ . '/config/locale/translations/fa.json'); +Locale::setLanguageFromJSON('fi', __DIR__ . '/config/locale/translations/fi.json'); +Locale::setLanguageFromJSON('fo', __DIR__ . '/config/locale/translations/fo.json'); +Locale::setLanguageFromJSON('fr', __DIR__ . '/config/locale/translations/fr.json'); +Locale::setLanguageFromJSON('ga', __DIR__ . '/config/locale/translations/ga.json'); +Locale::setLanguageFromJSON('gu', __DIR__ . '/config/locale/translations/gu.json'); +Locale::setLanguageFromJSON('he', __DIR__ . '/config/locale/translations/he.json'); +Locale::setLanguageFromJSON('hi', __DIR__ . '/config/locale/translations/hi.json'); +Locale::setLanguageFromJSON('hr', __DIR__ . '/config/locale/translations/hr.json'); +Locale::setLanguageFromJSON('hu', __DIR__ . '/config/locale/translations/hu.json'); +Locale::setLanguageFromJSON('hy', __DIR__ . '/config/locale/translations/hy.json'); +Locale::setLanguageFromJSON('id', __DIR__ . '/config/locale/translations/id.json'); +Locale::setLanguageFromJSON('is', __DIR__ . '/config/locale/translations/is.json'); +Locale::setLanguageFromJSON('it', __DIR__ . '/config/locale/translations/it.json'); +Locale::setLanguageFromJSON('ja', __DIR__ . '/config/locale/translations/ja.json'); +Locale::setLanguageFromJSON('jv', __DIR__ . '/config/locale/translations/jv.json'); +Locale::setLanguageFromJSON('kn', __DIR__ . '/config/locale/translations/kn.json'); +Locale::setLanguageFromJSON('km', __DIR__ . '/config/locale/translations/km.json'); +Locale::setLanguageFromJSON('ko', __DIR__ . '/config/locale/translations/ko.json'); +Locale::setLanguageFromJSON('la', __DIR__ . '/config/locale/translations/la.json'); +Locale::setLanguageFromJSON('lb', __DIR__ . '/config/locale/translations/lb.json'); +Locale::setLanguageFromJSON('lt', __DIR__ . '/config/locale/translations/lt.json'); +Locale::setLanguageFromJSON('lv', __DIR__ . '/config/locale/translations/lv.json'); +Locale::setLanguageFromJSON('ml', __DIR__ . '/config/locale/translations/ml.json'); +Locale::setLanguageFromJSON('mr', __DIR__ . '/config/locale/translations/mr.json'); +Locale::setLanguageFromJSON('ms', __DIR__ . '/config/locale/translations/ms.json'); +Locale::setLanguageFromJSON('nb', __DIR__ . '/config/locale/translations/nb.json'); +Locale::setLanguageFromJSON('ne', __DIR__ . '/config/locale/translations/ne.json'); +Locale::setLanguageFromJSON('nl', __DIR__ . '/config/locale/translations/nl.json'); +Locale::setLanguageFromJSON('nn', __DIR__ . '/config/locale/translations/nn.json'); +Locale::setLanguageFromJSON('or', __DIR__ . '/config/locale/translations/or.json'); +Locale::setLanguageFromJSON('pa', __DIR__ . '/config/locale/translations/pa.json'); +Locale::setLanguageFromJSON('pl', __DIR__ . '/config/locale/translations/pl.json'); +Locale::setLanguageFromJSON('pt-br', __DIR__ . '/config/locale/translations/pt-br.json'); +Locale::setLanguageFromJSON('pt-pt', __DIR__ . '/config/locale/translations/pt-pt.json'); +Locale::setLanguageFromJSON('ro', __DIR__ . '/config/locale/translations/ro.json'); Locale::setLanguageFromJSON('ru', __DIR__ . '/config/locale/translations/ru.json'); Locale::setLanguageFromJSON('sa', __DIR__ . '/config/locale/translations/sa.json'); Locale::setLanguageFromJSON('sd', __DIR__ . '/config/locale/translations/sd.json'); @@ -605,39 +637,41 @@ Locale::setLanguageFromJSON('sn', __DIR__ . '/config/locale/translations/sn.json Locale::setLanguageFromJSON('sq', __DIR__ . '/config/locale/translations/sq.json'); Locale::setLanguageFromJSON('sv', __DIR__ . '/config/locale/translations/sv.json'); Locale::setLanguageFromJSON('ta', __DIR__ . '/config/locale/translations/ta.json'); -Locale::setLanguageFromJSON('te', __DIR__.'/config/locale/translations/te.json'); -Locale::setLanguageFromJSON('th', __DIR__.'/config/locale/translations/th.json'); -Locale::setLanguageFromJSON('tl', __DIR__.'/config/locale/translations/tl.json'); -Locale::setLanguageFromJSON('tr', __DIR__.'/config/locale/translations/tr.json'); -Locale::setLanguageFromJSON('uk', __DIR__.'/config/locale/translations/uk.json'); -Locale::setLanguageFromJSON('ur', __DIR__.'/config/locale/translations/ur.json'); -Locale::setLanguageFromJSON('vi', __DIR__.'/config/locale/translations/vi.json'); -Locale::setLanguageFromJSON('zh-cn', __DIR__.'/config/locale/translations/zh-cn.json'); -Locale::setLanguageFromJSON('zh-tw', __DIR__.'/config/locale/translations/zh-tw.json'); +Locale::setLanguageFromJSON('te', __DIR__ . '/config/locale/translations/te.json'); +Locale::setLanguageFromJSON('th', __DIR__ . '/config/locale/translations/th.json'); +Locale::setLanguageFromJSON('tl', __DIR__ . '/config/locale/translations/tl.json'); +Locale::setLanguageFromJSON('tr', __DIR__ . '/config/locale/translations/tr.json'); +Locale::setLanguageFromJSON('uk', __DIR__ . '/config/locale/translations/uk.json'); +Locale::setLanguageFromJSON('ur', __DIR__ . '/config/locale/translations/ur.json'); +Locale::setLanguageFromJSON('vi', __DIR__ . '/config/locale/translations/vi.json'); +Locale::setLanguageFromJSON('zh-cn', __DIR__ . '/config/locale/translations/zh-cn.json'); +Locale::setLanguageFromJSON('zh-tw', __DIR__ . '/config/locale/translations/zh-tw.json'); \stream_context_set_default([ // Set global user agent and http settings 'http' => [ 'method' => 'GET', - 'user_agent' => \sprintf(APP_USERAGENT, + 'user_agent' => \sprintf( + APP_USERAGENT, App::getEnv('_APP_VERSION', 'UNKNOWN'), - App::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS', APP_EMAIL_SECURITY)), + App::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS', APP_EMAIL_SECURITY) + ), 'timeout' => 2, ], ]); // Runtime Execution -App::setResource('logger', function($register) { +App::setResource('logger', function ($register) { return $register->get('logger'); }, ['register']); -App::setResource('loggerBreadcrumbs', function() { +App::setResource('loggerBreadcrumbs', function () { return []; }); App::setResource('register', fn() => $register); -App::setResource('layout', function($locale) { - $layout = new View(__DIR__.'/views/layouts/default.phtml'); +App::setResource('layout', function ($locale) { + $layout = new View(__DIR__ . '/views/layouts/default.phtml'); $layout->setParam('locale', $locale); return $layout; @@ -651,7 +685,7 @@ App::setResource('audits', fn() => new Audit()); App::setResource('mails', fn() => new Mail()); App::setResource('deletes', fn() => new Delete()); App::setResource('database', fn() => new EventDatabase()); -App::setResource('usage', function($register) { +App::setResource('usage', function ($register) { return new Stats($register->get('statsd')); }, ['register']); @@ -691,7 +725,7 @@ App::setResource('clients', function ($request, $console, $project) { return $clients; }, ['request', 'console', 'project']); -App::setResource('user', function($mode, $project, $console, $request, $response, $dbForProject, $dbForConsole) { +App::setResource('user', function ($mode, $project, $console, $request, $response, $dbForProject, $dbForConsole) { /** @var Appwrite\Utopia\Request $request */ /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Document $project */ @@ -701,21 +735,28 @@ App::setResource('user', function($mode, $project, $console, $request, $response Authorization::setDefaultStatus(true); - Auth::setCookieName('a_session_'.$project->getId()); + Auth::setCookieName('a_session_' . $project->getId()); if (APP_MODE_ADMIN === $mode) { - Auth::setCookieName('a_session_'.$console->getId()); + Auth::setCookieName('a_session_' . $console->getId()); } $session = Auth::decodeSession( - $request->getCookie(Auth::$cookieName, // Get sessions - $request->getCookie(Auth::$cookieName.'_legacy', '')));// Get fallback session from old clients (no SameSite support) + $request->getCookie( + Auth::$cookieName, // Get sessions + $request->getCookie(Auth::$cookieName . '_legacy', '') + ) + );// Get fallback session from old clients (no SameSite support) // Get fallback session from clients who block 3rd-party cookies - if($response) $response->addHeader('X-Debug-Fallback', 'false'); + if ($response) { + $response->addHeader('X-Debug-Fallback', 'false'); + } - if(empty($session['id']) && empty($session['secret'])) { - if($response) $response->addHeader('X-Debug-Fallback', 'true'); + if (empty($session['id']) && empty($session['secret'])) { + if ($response) { + $response->addHeader('X-Debug-Fallback', 'true'); + } $fallback = $request->getHeader('x-fallback-cookies', ''); $fallback = \json_decode($fallback, true); $session = Auth::decodeSession(((isset($fallback[Auth::$cookieName])) ? $fallback[Auth::$cookieName] : '')); @@ -727,17 +768,17 @@ App::setResource('user', function($mode, $project, $console, $request, $response if (APP_MODE_ADMIN !== $mode) { if ($project->isEmpty()) { $user = new Document(['$id' => '', '$collection' => 'users']); - } - else { + } else { $user = $dbForProject->getDocument('users', Auth::$unique); } - } - else { + } else { $user = $dbForConsole->getDocument('users', Auth::$unique); } - if ($user->isEmpty() // Check a document has been found in the DB - || !Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret)) { // Validate user has valid login token + if ( + $user->isEmpty() // Check a document has been found in the DB + || !Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret) + ) { // Validate user has valid login token $user = new Document(['$id' => '', '$collection' => 'users']); } @@ -757,13 +798,13 @@ App::setResource('user', function($mode, $project, $console, $request, $response try { $payload = $jwt->decode($authJWT); } catch (JWTException $error) { - throw new Exception('Failed to verify JWT. '.$error->getMessage(), 401, Exception::USER_JWT_INVALID); + throw new Exception('Failed to verify JWT. ' . $error->getMessage(), 401, Exception::USER_JWT_INVALID); } $jwtUserId = $payload['userId'] ?? ''; $jwtSessionId = $payload['sessionId'] ?? ''; - if($jwtUserId && $jwtSessionId) { + if ($jwtUserId && $jwtSessionId) { $user = $dbForProject->getDocument('users', $jwtUserId); } @@ -775,14 +816,14 @@ App::setResource('user', function($mode, $project, $console, $request, $response return $user; }, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForConsole']); -App::setResource('project', function($dbForConsole, $request, $console) { +App::setResource('project', function ($dbForConsole, $request, $console) { /** @var Appwrite\Utopia\Request $request */ /** @var Utopia\Database\Database $dbForConsole */ /** @var Utopia\Database\Document $console */ $projectId = $request->getParam('project', $request->getHeader('x-appwrite-project', 'console')); - if($projectId === 'console') { + if ($projectId === 'console') { return $console; } @@ -791,7 +832,7 @@ App::setResource('project', function($dbForConsole, $request, $console) { return $project; }, ['dbForConsole', 'request', 'console']); -App::setResource('console', function() { +App::setResource('console', function () { return new Document([ '$id' => 'console', 'name' => 'Appwrite', @@ -823,7 +864,7 @@ App::setResource('console', function() { ]); }, []); -App::setResource('dbForProject', function($db, $cache, $project) { +App::setResource('dbForProject', function ($db, $cache, $project) { $cache = new Cache(new RedisCache($cache)); $database = new Database(new MariaDB($db), $cache); @@ -833,7 +874,7 @@ App::setResource('dbForProject', function($db, $cache, $project) { return $database; }, ['db', 'cache', 'project']); -App::setResource('dbForConsole', function($db, $cache) { +App::setResource('dbForConsole', function ($db, $cache) { $cache = new Cache(new RedisCache($cache)); $database = new Database(new MariaDB($db), $cache); @@ -844,25 +885,27 @@ App::setResource('dbForConsole', function($db, $cache) { }, ['db', 'cache']); -App::setResource('deviceLocal', function() { +App::setResource('deviceLocal', function () { return new Local(); }); -App::setResource('deviceFiles', function($project) { +App::setResource('deviceFiles', function ($project) { return getDevice(APP_STORAGE_UPLOADS . '/app-' . $project->getId()); }, ['project']); -App::setResource('deviceFunctions', function($project) { +App::setResource('deviceFunctions', function ($project) { return getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId()); }, ['project']); -App::setResource('deviceBuilds', function($project) { +App::setResource('deviceBuilds', function ($project) { return getDevice(APP_STORAGE_BUILDS . '/app-' . $project->getId()); }, ['project']); -function getDevice($root): Device { +function getDevice($root): Device +{ switch (App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL)) { - case Storage::DEVICE_LOCAL:default: + case Storage::DEVICE_LOCAL: + default: return new Local($root); case Storage::DEVICE_S3: $s3AccessKey = App::getEnv('_APP_STORAGE_S3_ACCESS_KEY', ''); @@ -878,10 +921,31 @@ function getDevice($root): Device { $doSpacesBucket = App::getEnv('_APP_STORAGE_DO_SPACES_BUCKET', ''); $doSpacesAcl = 'private'; return new DOSpaces($root, $doSpacesAccessKey, $doSpacesSecretKey, $doSpacesBucket, $doSpacesRegion, $doSpacesAcl); + case Storage::DEVICE_BACKBLAZE: + $backblazeAccessKey = App::getEnv('_APP_STORAGE_BACKBLAZE_ACCESS_KEY', ''); + $backblazeSecretKey = App::getEnv('_APP_STORAGE_BACKBLAZE_SECRET', ''); + $backblazeRegion = App::getEnv('_APP_STORAGE_BACKBLAZE_REGION', ''); + $backblazeBucket = App::getEnv('_APP_STORAGE_BACKBLAZE_BUCKET', ''); + $backblazeAcl = 'private'; + return new Backblaze($root, $backblazeAccessKey, $backblazeSecretKey, $backblazeBucket, $backblazeRegion, $backblazeAcl); + case Storage::DEVICE_LINODE: + $linodeAccessKey = App::getEnv('_APP_STORAGE_LINODE_ACCESS_KEY', ''); + $linodeSecretKey = App::getEnv('_APP_STORAGE_LINODE_SECRET', ''); + $linodeRegion = App::getEnv('_APP_STORAGE_LINODE_REGION', ''); + $linodeBucket = App::getEnv('_APP_STORAGE_LINODE_BUCKET', ''); + $linodeAcl = 'private'; + return new Linode($root, $linodeAccessKey, $linodeSecretKey, $linodeBucket, $linodeRegion, $linodeAcl); + case Storage::DEVICE_WASABI: + $wasabiAccessKey = App::getEnv('_APP_STORAGE_WASABI_ACCESS_KEY', ''); + $wasabiSecretKey = App::getEnv('_APP_STORAGE_WASABI_SECRET', ''); + $wasabiRegion = App::getEnv('_APP_STORAGE_WASABI_REGION', ''); + $wasabiBucket = App::getEnv('_APP_STORAGE_WASABI_BUCKET', ''); + $wasabiAcl = 'private'; + return new Wasabi($root, $wasabiAccessKey, $wasabiSecretKey, $wasabiBucket, $wasabiRegion, $wasabiAcl); } } -App::setResource('mode', function($request) { +App::setResource('mode', function ($request) { /** @var Appwrite\Utopia\Request $request */ /** @@ -892,7 +956,7 @@ App::setResource('mode', function($request) { return $request->getParam('mode', $request->getHeader('x-appwrite-mode', APP_MODE_DEFAULT)); }, ['request']); -App::setResource('geodb', function($register) { +App::setResource('geodb', function ($register) { /** @var Utopia\Registry\Registry $register */ return $register->get('geodb'); }, ['register']); diff --git a/app/preload.php b/app/preload.php index a14f834ac2..bf8b0bfd1d 100644 --- a/app/preload.php +++ b/app/preload.php @@ -2,27 +2,28 @@ /** * Init - * + * * Inializes both Appwrite API entry point, queue workers, and CLI tasks. * Set configuration, framework resources, app constants - * + * */ ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); -if (file_exists(__DIR__.'/../vendor/autoload.php')) { - require __DIR__.'/../vendor/autoload.php'; +if (file_exists(__DIR__ . '/../vendor/autoload.php')) { + require __DIR__ . '/../vendor/autoload.php'; } use Utopia\Preloader\Preloader; -include __DIR__.'/controllers/general.php'; +include __DIR__ . '/controllers/general.php'; $preloader = new Preloader(); -foreach ([ +foreach ( + [ realpath(__DIR__ . '/../vendor/composer'), realpath(__DIR__ . '/../vendor/amphp'), realpath(__DIR__ . '/../vendor/felixfbecker'), @@ -34,8 +35,9 @@ foreach ([ realpath(__DIR__ . '/../vendor/symfony'), realpath(__DIR__ . '/../vendor/mongodb'), realpath(__DIR__ . '/../vendor/utopia-php/websocket'), // TODO: remove workerman autoload -] as $key => $value) { - if($value !== false) { + ] as $key => $value +) { + if ($value !== false) { $preloader->ignore($value); } } diff --git a/app/realtime.php b/app/realtime.php index 6b75c25ce1..7f3264f315 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -129,7 +129,7 @@ function getDatabase(Registry &$register, string $namespace) $register->get('redisPool')->put($redis); } ]; -}; +} $server->onStart(function () use ($stats, $register, $containerId, &$statsDocument, $logError) { sleep(5); // wait for the initial database schema to be ready @@ -187,7 +187,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume }); $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, $realtime, $logError) { - Console::success('Worker ' . $workerId . ' started succefully'); + Console::success('Worker ' . $workerId . ' started successfully'); $attempts = 0; $start = time(); @@ -197,7 +197,6 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, * Sending current connections to project channels on the console project every 5 seconds. */ if ($realtime->hasSubscriber('console', 'role:member', 'project')) { - [$database, $returnDatabase] = getDatabase($register, '_console'); $payload = []; diff --git a/app/tasks/doctor.php b/app/tasks/doctor.php index 20cafdf744..d79e8d530f 100644 --- a/app/tasks/doctor.php +++ b/app/tasks/doctor.php @@ -19,46 +19,41 @@ $cli / \ ) __/ ) __/\ /\ / ) / )( )( ) _) _ )(( O ) \_/\_/(__) (__) (_/\_)(__\_)(__) (__) (____)(_)(__)\__/ "); - Console::log("\n".'๐Ÿ‘ฉโ€โš•๏ธ Running '.APP_NAME.' Doctor for version '.App::getEnv('_APP_VERSION', 'UNKNOWN').' ...'."\n"); + Console::log("\n" . '๐Ÿ‘ฉโ€โš•๏ธ Running ' . APP_NAME . ' Doctor for version ' . App::getEnv('_APP_VERSION', 'UNKNOWN') . ' ...' . "\n"); Console::log('Checking for production best practices...'); $domain = new Domain(App::getEnv('_APP_DOMAIN')); - if(!$domain->isKnown() || $domain->isTest()) { - Console::log('๐Ÿ”ด Hostname has no public suffix ('.$domain->get().')'); - } - else { - Console::log('๐ŸŸข Hostname has a public suffix ('.$domain->get().')'); + if (!$domain->isKnown() || $domain->isTest()) { + Console::log('๐Ÿ”ด Hostname has no public suffix (' . $domain->get() . ')'); + } else { + Console::log('๐ŸŸข Hostname has a public suffix (' . $domain->get() . ')'); } $domain = new Domain(App::getEnv('_APP_DOMAIN_TARGET')); - if(!$domain->isKnown() || $domain->isTest()) { - Console::log('๐Ÿ”ด CNAME target has no public suffix ('.$domain->get().')'); - } - else { - Console::log('๐ŸŸข CNAME target has a public suffix ('.$domain->get().')'); + if (!$domain->isKnown() || $domain->isTest()) { + Console::log('๐Ÿ”ด CNAME target has no public suffix (' . $domain->get() . ')'); + } else { + Console::log('๐ŸŸข CNAME target has a public suffix (' . $domain->get() . ')'); } - if(App::getEnv('_APP_OPENSSL_KEY_V1') === 'your-secret-key' || empty(App::getEnv('_APP_OPENSSL_KEY_V1'))) { + if (App::getEnv('_APP_OPENSSL_KEY_V1') === 'your-secret-key' || empty(App::getEnv('_APP_OPENSSL_KEY_V1'))) { Console::log('๐Ÿ”ด Not using a unique secret key for encryption'); - } - else { + } else { Console::log('๐ŸŸข Using a unique secret key for encryption'); } - if(App::getEnv('_APP_ENV', 'development') !== 'production') { + if (App::getEnv('_APP_ENV', 'development') !== 'production') { Console::log('๐Ÿ”ด App environment is set for development'); - } - else { + } else { Console::log('๐ŸŸข App environment is set for production'); } - if('enabled' !== App::getEnv('_APP_OPTIONS_ABUSE', 'disabled')) { + if ('enabled' !== App::getEnv('_APP_OPTIONS_ABUSE', 'disabled')) { Console::log('๐Ÿ”ด Abuse protection is disabled'); - } - else { + } else { Console::log('๐ŸŸข Abuse protection is enabled'); } @@ -66,20 +61,19 @@ $cli $authWhitelistEmails = App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null); $authWhitelistIPs = App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null); - if(empty($authWhitelistRoot) + if ( + empty($authWhitelistRoot) && empty($authWhitelistEmails) && empty($authWhitelistIPs) ) { Console::log('๐Ÿ”ด Console access limits are disabled'); - } - else { + } else { Console::log('๐ŸŸข Console access limits are enabled'); } - if('enabled' !== App::getEnv('_APP_OPTIONS_FORCE_HTTPS', 'disabled')) { + if ('enabled' !== App::getEnv('_APP_OPTIONS_FORCE_HTTPS', 'disabled')) { Console::log('๐Ÿ”ด HTTPS force option is disabled'); - } - else { + } else { Console::log('๐ŸŸข HTTPS force option is enabled'); } @@ -87,7 +81,7 @@ $cli $providerName = App::getEnv('_APP_LOGGING_PROVIDER', ''); $providerConfig = App::getEnv('_APP_LOGGING_CONFIG', ''); - if(empty($providerName) || empty($providerConfig) || !Logger::hasProvider($providerName)) { + if (empty($providerName) || empty($providerConfig) || !Logger::hasProvider($providerName)) { Console::log('๐Ÿ”ด Logging adapter is disabled'); } else { Console::log('๐ŸŸข Logging adapter is enabled (' . $providerName . ')'); @@ -96,7 +90,7 @@ $cli \sleep(0.2); try { - Console::log("\n".'Checking connectivity...'); + Console::log("\n" . 'Checking connectivity...'); } catch (\Throwable $th) { //throw $th; } @@ -122,15 +116,16 @@ $cli Console::error('Cache............disconnected ๐Ÿ‘Ž'); } - if(App::getEnv('_APP_STORAGE_ANTIVIRUS') === 'enabled') { // Check if scans are enabled + if (App::getEnv('_APP_STORAGE_ANTIVIRUS') === 'enabled') { // Check if scans are enabled try { - $antivirus = new Network(App::getEnv('_APP_STORAGE_ANTIVIRUS_HOST', 'clamav'), - (int) App::getEnv('_APP_STORAGE_ANTIVIRUS_PORT', 3310)); + $antivirus = new Network( + App::getEnv('_APP_STORAGE_ANTIVIRUS_HOST', 'clamav'), + (int) App::getEnv('_APP_STORAGE_ANTIVIRUS_PORT', 3310) + ); - if((@$antivirus->ping())) { + if ((@$antivirus->ping())) { Console::success('Antivirus...........connected ๐Ÿ‘'); - } - else { + } else { Console::error('Antivirus........disconnected ๐Ÿ‘Ž'); } } catch (\Throwable $th) { @@ -155,7 +150,7 @@ $cli $host = App::getEnv('_APP_STATSD_HOST', 'telegraf'); $port = App::getEnv('_APP_STATSD_PORT', 8125); - if($fp = @\fsockopen('udp://'.$host, $port, $errCode, $errStr, 2)){ + if ($fp = @\fsockopen('udp://' . $host, $port, $errCode, $errStr, 2)) { Console::success('StatsD..............connected ๐Ÿ‘'); \fclose($fp); } else { @@ -165,7 +160,7 @@ $cli $host = App::getEnv('_APP_INFLUXDB_HOST', ''); $port = App::getEnv('_APP_INFLUXDB_PORT', ''); - if($fp = @\fsockopen($host, $port, $errCode, $errStr, 2)){ + if ($fp = @\fsockopen($host, $port, $errCode, $errStr, 2)) { Console::success('InfluxDB............connected ๐Ÿ‘'); \fclose($fp); } else { @@ -177,26 +172,26 @@ $cli Console::log(''); Console::log('Checking volumes...'); - foreach ([ + foreach ( + [ 'Uploads' => APP_STORAGE_UPLOADS, 'Cache' => APP_STORAGE_CACHE, 'Config' => APP_STORAGE_CONFIG, 'Certs' => APP_STORAGE_CERTIFICATES - ] as $key => $volume) { + ] as $key => $volume + ) { $device = new Local($volume); if (\is_readable($device->getRoot())) { - Console::success('๐ŸŸข '.$key.' Volume is readable'); - } - else { - Console::error('๐Ÿ”ด '.$key.' Volume is unreadable'); + Console::success('๐ŸŸข ' . $key . ' Volume is readable'); + } else { + Console::error('๐Ÿ”ด ' . $key . ' Volume is unreadable'); } if (\is_writable($device->getRoot())) { - Console::success('๐ŸŸข '.$key.' Volume is writeable'); - } - else { - Console::error('๐Ÿ”ด '.$key.' Volume is unwriteable'); + Console::success('๐ŸŸข ' . $key . ' Volume is writeable'); + } else { + Console::error('๐Ÿ”ด ' . $key . ' Volume is unwriteable'); } } @@ -205,44 +200,44 @@ $cli Console::log(''); Console::log('Checking disk space usage...'); - foreach ([ + foreach ( + [ 'Uploads' => APP_STORAGE_UPLOADS, 'Cache' => APP_STORAGE_CACHE, 'Config' => APP_STORAGE_CONFIG, 'Certs' => APP_STORAGE_CERTIFICATES - ] as $key => $volume) { + ] as $key => $volume + ) { $device = new Local($volume); $percentage = (($device->getPartitionTotalSpace() - $device->getPartitionFreeSpace()) / $device->getPartitionTotalSpace()) * 100; - $message = $key.' Volume has '.Storage::human($device->getPartitionFreeSpace()) . ' free space ('.\round($percentage, 2).'% used)'; + $message = $key . ' Volume has ' . Storage::human($device->getPartitionFreeSpace()) . ' free space (' . \round($percentage, 2) . '% used)'; if ($percentage < 80) { Console::success('๐ŸŸข ' . $message); - } - else { + } else { Console::error('๐Ÿ”ด ' . $message); } } try { - if(App::isProduction()) { + if (App::isProduction()) { Console::log(''); - $version = \json_decode(@\file_get_contents(App::getEnv('_APP_HOME', 'http://localhost').'/v1/health/version'), true); + $version = \json_decode(@\file_get_contents(App::getEnv('_APP_HOME', 'http://localhost') . '/v1/health/version'), true); if ($version && isset($version['version'])) { - if(\version_compare($version['version'], App::getEnv('_APP_VERSION', 'UNKNOWN')) === 0) { - Console::info('You are running the latest version of '.APP_NAME.'! ๐Ÿฅณ'); - } - else { - Console::info('A new version ('.$version['version'].') is available! ๐Ÿฅณ'."\n"); + if (\version_compare($version['version'], App::getEnv('_APP_VERSION', 'UNKNOWN')) === 0) { + Console::info('You are running the latest version of ' . APP_NAME . '! ๐Ÿฅณ'); + } else { + Console::info('A new version (' . $version['version'] . ') is available! ๐Ÿฅณ' . "\n"); } } else { - Console::error('Failed to check for a newer version'."\n"); + Console::error('Failed to check for a newer version' . "\n"); } } } catch (\Throwable $th) { - Console::error('Failed to check for a newer version'."\n"); + Console::error('Failed to check for a newer version' . "\n"); } }); diff --git a/app/tasks/install.php b/app/tasks/install.php index 77210a0c15..05e6ad334a 100644 --- a/app/tasks/install.php +++ b/app/tasks/install.php @@ -18,7 +18,7 @@ $cli ->param('httpsPort', '', new Text(4), 'Server HTTPS port', true) ->param('organization', 'appwrite', new Text(0), 'Docker Registry organization', true) ->param('image', 'appwrite', new Text(0), 'Main appwrite docker image', true) - ->param('interactive','Y', new Text(1), 'Run an interactive session', true) + ->param('interactive', 'Y', new Text(1), 'Run an interactive session', true) ->action(function ($httpPort, $httpsPort, $organization, $image, $interactive) { /** * 1. Start - DONE @@ -31,7 +31,7 @@ $cli * 2.4 Ask for all required vars not given as CLI args and if in interactive mode * Otherwise, just use default vars. - DONE * 3. Ask user to backup important volumes, env vars, and SQL tables - * In th future we can try and automate this for smaller/medium size setups + * In th future we can try and automate this for smaller/medium size setups * 4. Drop new docker-compose.yml setup (located inside the container, no network dependencies with appwrite.io) - DONE * 5. Run docker-compose up -d - DONE * 6. Run data migration @@ -48,8 +48,8 @@ $cli */ $analytics = new GoogleAnalytics('UA-26264668-9', uniqid('server.', true)); - foreach($config as $category) { - foreach($category['variables'] ?? [] as $var) { + foreach ($config as $category) { + foreach ($category['variables'] ?? [] as $var) { $vars[] = $var; } } @@ -59,17 +59,17 @@ $cli // Create directory with write permissions if (null !== $path && !\file_exists(\dirname($path))) { if (!@\mkdir(\dirname($path), 0755, true)) { - Console::error('Can\'t create directory '.\dirname($path)); + Console::error('Can\'t create directory ' . \dirname($path)); Console::exit(1); } } - $data = @file_get_contents($path.'/docker-compose.yml'); + $data = @file_get_contents($path . '/docker-compose.yml'); - if($data !== false) { + if ($data !== false) { $time = \time(); - Console::info('Compose file found, creating backup: docker-compose.yml.'.$time.'.backup'); - file_put_contents($path.'/docker-compose.yml.'.$time.'.backup',$data); + Console::info('Compose file found, creating backup: docker-compose.yml.' . $time . '.backup'); + file_put_contents($path . '/docker-compose.yml.' . $time . '.backup', $data); $compose = new Compose($data); $appwrite = $compose->getService('appwrite'); $oldVersion = ($appwrite) ? $appwrite->getImageVersion() : null; @@ -83,35 +83,39 @@ $cli Console::warning('Traefik not found. Falling back to default ports.'); } - if($oldVersion) { - foreach($compose->getServices() as $service) { // Fetch all env vars from previous compose file - if(!$service) { + if ($oldVersion) { + foreach ($compose->getServices() as $service) { // Fetch all env vars from previous compose file + if (!$service) { continue; } $env = $service->getEnvironment()->list(); foreach ($env as $key => $value) { - if (is_null($value)) continue; - foreach($vars as &$var) { - if($var['name'] === $key) { + if (is_null($value)) { + continue; + } + foreach ($vars as &$var) { + if ($var['name'] === $key) { $var['default'] = $value; } } } } - $data = @file_get_contents($path.'/.env'); + $data = @file_get_contents($path . '/.env'); - if($data !== false) { // Fetch all env vars from previous .env file - Console::info('Env file found, creating backup: .env.'.$time.'.backup'); - file_put_contents($path.'/.env.'.$time.'.backup',$data); + if ($data !== false) { // Fetch all env vars from previous .env file + Console::info('Env file found, creating backup: .env.' . $time . '.backup'); + file_put_contents($path . '/.env.' . $time . '.backup', $data); $env = new Env($data); foreach ($env->list() as $key => $value) { - if (is_null($value)) continue; - foreach($vars as &$var) { - if($var['name'] === $key) { + if (is_null($value)) { + continue; + } + foreach ($vars as &$var) { + if ($var['name'] === $key) { $var['default'] = $value; } } @@ -119,60 +123,60 @@ $cli } foreach ($ports as $key => $value) { - if($value === $defaultHTTPPort) { + if ($value === $defaultHTTPPort) { $defaultHTTPPort = $key; } - if($value === $defaultHTTPSPort) { + if ($value === $defaultHTTPSPort) { $defaultHTTPSPort = $key; } } } } - if(empty($httpPort)) { - $httpPort = Console::confirm('Choose your server HTTP port: (default: '.$defaultHTTPPort.')'); + if (empty($httpPort)) { + $httpPort = Console::confirm('Choose your server HTTP port: (default: ' . $defaultHTTPPort . ')'); $httpPort = ($httpPort) ? $httpPort : $defaultHTTPPort; } - if(empty($httpsPort)) { - $httpsPort = Console::confirm('Choose your server HTTPS port: (default: '.$defaultHTTPSPort.')'); + if (empty($httpsPort)) { + $httpsPort = Console::confirm('Choose your server HTTPS port: (default: ' . $defaultHTTPSPort . ')'); $httpsPort = ($httpsPort) ? $httpsPort : $defaultHTTPSPort; } $input = []; - foreach($vars as $key => $var) { - if(!empty($var['filter']) && ($interactive !== 'Y' || !Console::isInteractive())) { - if($data && $var['default'] !== null) { + foreach ($vars as $key => $var) { + if (!empty($var['filter']) && ($interactive !== 'Y' || !Console::isInteractive())) { + if ($data && $var['default'] !== null) { $input[$var['name']] = $var['default']; continue; } - if($var['filter'] === 'token') { + if ($var['filter'] === 'token') { $input[$var['name']] = Auth::tokenGenerator(); continue; } - if($var['filter'] === 'password') { + if ($var['filter'] === 'password') { $input[$var['name']] = Auth::passwordGenerator(); continue; } } - if(!$var['required'] || !Console::isInteractive() || $interactive !== 'Y') { + if (!$var['required'] || !Console::isInteractive() || $interactive !== 'Y') { $input[$var['name']] = $var['default']; continue; } - $input[$var['name']] = Console::confirm($var['question'].' (default: \''.$var['default'].'\')'); + $input[$var['name']] = Console::confirm($var['question'] . ' (default: \'' . $var['default'] . '\')'); - if(empty($input[$var['name']])) { + if (empty($input[$var['name']])) { $input[$var['name']] = $var['default']; } } - $templateForCompose = new View(__DIR__.'/../views/install/compose.phtml'); - $templateForEnv = new View(__DIR__.'/../views/install/env.phtml'); + $templateForCompose = new View(__DIR__ . '/../views/install/compose.phtml'); + $templateForEnv = new View(__DIR__ . '/../views/install/env.phtml'); $templateForCompose ->setParam('httpPort', $httpPort) @@ -186,16 +190,16 @@ $cli ->setParam('vars', $input) ; - if(!file_put_contents($path.'/docker-compose.yml', $templateForCompose->render(false))) { + if (!file_put_contents($path . '/docker-compose.yml', $templateForCompose->render(false))) { $message = 'Failed to save Docker Compose file'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE.' - '.$message); + $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); Console::error($message); Console::exit(1); } - if(!file_put_contents($path.'/.env', $templateForEnv->render(false))) { + if (!file_put_contents($path . '/.env', $templateForEnv->render(false))) { $message = 'Failed to save environment variables file'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE.' - '.$message); + $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); Console::error($message); Console::exit(1); } @@ -205,8 +209,8 @@ $cli $stderr = ''; foreach ($input as $key => $value) { - if($value) { - $env .= $key.'='.\escapeshellarg($value).' '; + if ($value) { + $env .= $key . '=' . \escapeshellarg($value) . ' '; } } @@ -216,13 +220,13 @@ $cli if ($exit !== 0) { $message = 'Failed to install Appwrite dockers'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE.' - '.$message); + $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); Console::error($message); Console::error($stderr); Console::exit($exit); } else { $message = 'Appwrite installed successfully'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE.' - '.$message); + $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); Console::success($message); } }); diff --git a/app/tasks/sdks.php b/app/tasks/sdks.php index 67bf2a6d87..b996b10e81 100644 --- a/app/tasks/sdks.php +++ b/app/tasks/sdks.php @@ -30,7 +30,7 @@ $cli $production = ($git) ? (Console::confirm('Type "Appwrite" to push code to production git repos') == 'Appwrite') : false; $message = ($git) ? Console::confirm('Please enter your commit message:') : ''; - if(!in_array($version, ['0.6.x', '0.7.x', '0.8.x', '0.9.x', '0.10.x', '0.11.x', '0.12.x', '0.13.x', '0.14.x', 'latest'])) { + if (!in_array($version, ['0.6.x', '0.7.x', '0.8.x', '0.9.x', '0.10.x', '0.11.x', '0.12.x', '0.13.x', '0.14.x', 'latest'])) { throw new Exception('Unknown version given'); } diff --git a/app/tasks/specs.php b/app/tasks/specs.php index 61e664019b..0bd94249da 100644 --- a/app/tasks/specs.php +++ b/app/tasks/specs.php @@ -25,7 +25,7 @@ $cli $response = new Response(new HttpResponse()); $mocks = ($mode === 'mocks'); - App::setResource('request', fn () => new Request); + App::setResource('request', fn () => new Request()); App::setResource('response', fn () => $response); App::setResource('db', fn () => $db); App::setResource('cache', fn () => $redis); @@ -125,7 +125,6 @@ $cli foreach (['swagger2', 'open-api3'] as $format) { foreach ($platforms as $platform) { - $routes = []; $models = []; $services = []; diff --git a/app/tasks/vars.php b/app/tasks/vars.php index 6c02348222..af972e218d 100644 --- a/app/tasks/vars.php +++ b/app/tasks/vars.php @@ -13,13 +13,13 @@ $cli $config = Config::getParam('variables', []); $vars = []; - foreach($config as $category) { - foreach($category['variables'] ?? [] as $var) { + foreach ($config as $category) { + foreach ($category['variables'] ?? [] as $var) { $vars[] = $var; } } foreach ($vars as $key => $value) { - Console::log('- '.$value['name'].'='.App::getEnv($value['name'], '')); + Console::log('- ' . $value['name'] . '=' . App::getEnv($value['name'], '')); } - }); \ No newline at end of file + }); diff --git a/app/views/console/functions/function.phtml b/app/views/console/functions/function.phtml index 68779e886c..17bb873ee5 100644 --- a/app/views/console/functions/function.phtml +++ b/app/views/console/functions/function.phtml @@ -703,7 +703,7 @@ sort($patterns); --functionId={{project-function.$id}} \ --activate=true \ --entrypoint='scriptFile' \ - --code='/myrepo/myfunction'" data-forms-code="bash" data-lang="bash" data-lang-label="Bash"> + --code='.'" data-forms-code="bash" data-lang="bash" data-lang-label="Bash">

PowerShell

@@ -713,7 +713,7 @@ sort($patterns); --functionId={{project-function.$id}} ` --activate=true ` --entrypoint='scriptFile' ` - --code='/myrepo/myfunction'" data-forms-code="powershell" data-lang="powershell" data-lang-label="PowerShell"> + --code='.'" data-forms-code="powershell" data-lang="powershell" data-lang-label="PowerShell">

Learn more about creating deployments, installing and using the Appwrite CLI.

diff --git a/app/views/console/users/team.phtml b/app/views/console/users/team.phtml index c7c3f84b88..1fbe5d622d 100644 --- a/app/views/console/users/team.phtml +++ b/app/views/console/users/team.phtml @@ -137,12 +137,12 @@ data-analytics-label="Create Team Membership" data-service="teams.createMembership" data-event="submit" - data-loading="Sending invitation, please wait..." + data-loading="Adding user, please wait..." data-success="alert,trigger,reset" - data-success-param-alert-text="Invitation sent successfully" + data-success-param-alert-text="User added successfully" data-success-param-trigger-events="teams.createMembership" data-failure="alert" - data-failure-param-alert-text="Failed to send invite" + data-failure-param-alert-text="Failed to add user" data-failure-param-alert-classname="error"> diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index 2a1738a9c3..6fa8335bfa 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -4,7 +4,6 @@ x-logging: &x-logging options: max-file: '5' max-size: '10m' - getParam('httpPort', ''); @@ -120,6 +119,18 @@ services: - _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 @@ -267,6 +278,18 @@ services: - _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 @@ -432,6 +455,18 @@ services: - _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 diff --git a/app/workers/builds.php b/app/workers/builds.php index c1affa5907..14986c5354 100644 --- a/app/workers/builds.php +++ b/app/workers/builds.php @@ -174,7 +174,7 @@ class BuildsV1 extends Worker $build->setAttribute('status', $response['status']); $build->setAttribute('outputPath', $response['outputPath']); $build->setAttribute('stderr', $response['stderr']); - $build->setAttribute('stdout', $response['stdout']); + $build->setAttribute('stdout', $response['response']); Console::success("Build id: $buildId created"); @@ -200,7 +200,7 @@ class BuildsV1 extends Worker } finally { $build = $dbForProject->updateDocument('builds', $buildId, $build); - /** + /** * Send realtime Event */ $target = Realtime::fromPayload( diff --git a/app/workers/certificates.php b/app/workers/certificates.php index 39a02d6fdb..c32b44f49f 100644 --- a/app/workers/certificates.php +++ b/app/workers/certificates.php @@ -18,10 +18,9 @@ Console::success(APP_NAME . ' certificates worker v1 has started'); class CertificatesV1 extends Worker { - /** * Database connection shared across all methods of this file - * + * * @var Database */ private Database $dbForConsole; @@ -52,20 +51,20 @@ class CertificatesV1 extends Worker * 10. Create/Update our Storage with new Traefik config with new certificate paths * 11. Read certificate file and update 'renewDate' on certificate document * 12. Update 'issueDate' and 'attempts' on certificate - * + * * If at any point unexpected error occurs, program stops without applying changes to document, and error is thrown into worker - * + * * If code stops with expected error: * 1. 'log' attribute on document is updated with error message * 2. 'attempts' amount is increased * 3. Console log is shown * 4. Email is sent to security email - * + * * Unless unexpected error occurs, at the end, we: * 1. Update 'updated' attribute on document * 2. Save document to database * 3. Update all domains documents with current certificate ID - * + * * Note: Renewals are checked and scheduled from maintenence worker */ @@ -148,7 +147,7 @@ class CertificatesV1 extends Worker * * @param string $domain Domain name that certificate is for * @param Document $certificate Certificate document that we need to save - * + * * @return void */ private function saveCertificateDocument(string $domain, Document $certificate): void diff --git a/app/workers/database.php b/app/workers/database.php index a3451461cc..7b3d08a5f2 100644 --- a/app/workers/database.php +++ b/app/workers/database.php @@ -7,10 +7,10 @@ use Utopia\CLI\Console; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; -require_once __DIR__.'/../init.php'; +require_once __DIR__ . '/../init.php'; Console::title('Database V1 Worker'); -Console::success(APP_NAME.' database worker v1 has started'."\n"); +Console::success(APP_NAME . ' database worker v1 has started' . "\n"); class DatabaseV1 extends Worker { @@ -27,11 +27,11 @@ class DatabaseV1 extends Worker $collection = new Document($this->args['collection'] ?? []); $document = new Document($this->args['document'] ?? []); - if($collection->isEmpty()) { + if ($collection->isEmpty()) { throw new Exception('Missing collection'); } - if($document->isEmpty()) { + if ($document->isEmpty()) { throw new Exception('Missing document'); } @@ -50,9 +50,9 @@ class DatabaseV1 extends Worker break; default: - Console::error('No database operation for type: '.$type); + Console::error('No database operation for type: ' . $type); break; - } + } Authorization::reset(); } @@ -94,7 +94,7 @@ class DatabaseV1 extends Worker $project = $dbForConsole->getDocument('projects', $projectId); try { - if(!$dbForProject->createAttribute('collection_' . $collection->getInternalId(), $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) { + if (!$dbForProject->createAttribute('collection_' . $collection->getInternalId(), $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) { throw new Exception('Failed to create Attribute'); } $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'available')); @@ -151,7 +151,7 @@ class DatabaseV1 extends Worker // - failed: attribute was never created // - stuck: attribute was available but cannot be removed try { - if($status !== 'failed' && !$dbForProject->deleteAttribute('collection_' . $collection->getInternalId(), $key)) { + if ($status !== 'failed' && !$dbForProject->deleteAttribute('collection_' . $collection->getInternalId(), $key)) { throw new Exception('Failed to delete Attribute'); } $dbForProject->deleteDocument('attributes', $attribute->getId()); @@ -194,7 +194,7 @@ class DatabaseV1 extends Worker if ($found !== false) { // If found, remove entry from attributes, lengths, and orders - // array_values wraps array_diff to reindex array keys + // array_values wraps array_diff to reindex array keys // when found attribute is removed from array $attributes = \array_values(\array_diff($attributes, [$attributes[$found]])); $lengths = \array_values(\array_diff($lengths, [$lengths[$found]])); @@ -212,7 +212,8 @@ class DatabaseV1 extends Worker // Check if an index exists with the same attributes and orders $exists = false; foreach ($indexes as $existing) { - if ($existing->getAttribute('key') !== $index->getAttribute('key') // Ignore itself + if ( + $existing->getAttribute('key') !== $index->getAttribute('key') // Ignore itself && $existing->getAttribute('attributes') === $index->getAttribute('attributes') && $existing->getAttribute('orders') === $index->getAttribute('orders') ) { @@ -221,7 +222,7 @@ class DatabaseV1 extends Worker } } - if ($exists) { // Delete the duplicate if created, else update in db + if ($exists) { // Delete the duplicate if created, else update in db $this->deleteIndex($collection, $index, $projectId); } else { $dbForProject->updateDocument('indexes', $index->getId(), $index); @@ -257,7 +258,7 @@ class DatabaseV1 extends Worker $project = $dbForConsole->getDocument('projects', $projectId); try { - if(!$dbForProject->createIndex('collection_' . $collection->getInternalId(), $key, $type, $attributes, $lengths, $orders)) { + if (!$dbForProject->createIndex('collection_' . $collection->getInternalId(), $key, $type, $attributes, $lengths, $orders)) { throw new Exception('Failed to create Index'); } $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'available')); @@ -307,7 +308,7 @@ class DatabaseV1 extends Worker $project = $dbForConsole->getDocument('projects', $projectId); try { - if($status !== 'failed' && !$dbForProject->deleteIndex('collection_' . $collection->getInternalId(), $key)) { + if ($status !== 'failed' && !$dbForProject->deleteIndex('collection_' . $collection->getInternalId(), $key)) { throw new Exception('Failed to delete index'); } $dbForProject->deleteDocument('indexes', $index->getId()); diff --git a/app/workers/deletes.php b/app/workers/deletes.php index 0f9d76f81e..17b1bf963c 100644 --- a/app/workers/deletes.php +++ b/app/workers/deletes.php @@ -8,9 +8,6 @@ use Utopia\Database\Validator\Authorization; use Appwrite\Resque\Worker; use Executor\Executor; use Utopia\Storage\Device\Local; -use Utopia\Storage\Device\S3; -use Utopia\Storage\Device\DOSpaces; -use Utopia\Storage\Storage; use Utopia\Abuse\Abuse; use Utopia\Abuse\Adapters\TimeLimit; use Utopia\CLI\Console; @@ -361,7 +358,7 @@ class DeletesV1 extends Worker }); } - /** + /** * Delete Executions */ Console::info("Deleting executions for function " . $functionId); @@ -526,7 +523,7 @@ class DeletesV1 extends Worker } /** - * @param Document $document certificates document + * @param Document $document certificates document */ protected function deleteCertificates(Document $document): void { @@ -577,26 +574,7 @@ class DeletesV1 extends Worker $dbForProject = $this->getProjectDB($projectId); $dbForProject->deleteCollection('bucket_' . $document->getInternalId()); - $device = new Local(APP_STORAGE_UPLOADS . '/app-' . $projectId); - - switch (App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL)) { - case Storage::DEVICE_S3: - $s3AccessKey = App::getEnv('_APP_STORAGE_S3_ACCESS_KEY', ''); - $s3SecretKey = App::getEnv('_APP_STORAGE_S3_SECRET', ''); - $s3Region = App::getEnv('_APP_STORAGE_S3_REGION', ''); - $s3Bucket = App::getEnv('_APP_STORAGE_S3_BUCKET', ''); - $s3Acl = 'private'; - $device = new S3(APP_STORAGE_UPLOADS . '/app-' . $projectId, $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl); - break; - case Storage::DEVICE_DO_SPACES: - $doSpacesAccessKey = App::getEnv('_APP_STORAGE_DO_SPACES_ACCESS_KEY', ''); - $doSpacesSecretKey = App::getEnv('_APP_STORAGE_DO_SPACES_SECRET', ''); - $doSpacesRegion = App::getEnv('_APP_STORAGE_DO_SPACES_REGION', ''); - $doSpacesBucket = App::getEnv('_APP_STORAGE_DO_SPACES_BUCKET', ''); - $doSpacesAcl = 'private'; - $device = new DOSpaces(APP_STORAGE_UPLOADS . '/app-' . $projectId, $doSpacesAccessKey, $doSpacesSecretKey, $doSpacesBucket, $doSpacesRegion, $doSpacesAcl); - break; - } + $device = $this->getDevice(APP_STORAGE_UPLOADS . '/app-' . $projectId); $device->deletePath($document->getId()); } diff --git a/app/workers/mails.php b/app/workers/mails.php index 8c78ff9006..9b81353f05 100644 --- a/app/workers/mails.php +++ b/app/workers/mails.php @@ -14,7 +14,8 @@ Console::success(APP_NAME . ' mails worker v1 has started' . "\n"); class MailsV1 extends Worker { - public function getName(): string { + public function getName(): string + { return "mails"; } @@ -131,9 +132,9 @@ class MailsV1 extends Worker /** * Returns a prefix from a mail type - * + * * @param $type - * + * * @return string */ protected function getPrefix(string $type): string @@ -156,10 +157,10 @@ class MailsV1 extends Worker /** * Returns true if all the required terms in a locale exist. False otherwise - * + * * @param $locale * @param $prefix - * + * * @return bool */ protected function doesLocaleExist(Locale $locale, string $prefix): bool diff --git a/app/workers/webhooks.php b/app/workers/webhooks.php index e44881c1b4..4048581c0c 100644 --- a/app/workers/webhooks.php +++ b/app/workers/webhooks.php @@ -43,9 +43,11 @@ class WebhooksV1 extends Worker protected function execute(array $events, string $payload, Document $webhook, Document $user, Document $project): void { + $url = \rawurldecode($webhook->getAttribute('url')); + $signatureKey = $webhook->getAttribute('signatureKey'); + $signature = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $httpUser = $webhook->getAttribute('httpUser'); $httpPass = $webhook->getAttribute('httpPass'); - $ch = \curl_init($webhook->getAttribute('url')); \curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); @@ -68,7 +70,7 @@ class WebhooksV1 extends Worker 'X-' . APP_NAME . '-Webhook-Name: ' . $webhook->getAttribute('name', ''), 'X-' . APP_NAME . '-Webhook-User-Id: ' . $user->getId(), 'X-' . APP_NAME . '-Webhook-Project-Id: ' . $project->getId(), - 'X-' . APP_NAME . '-Webhook-Signature: ' . $webhook->getAttribute('signature', 'not-yet-implemented'), + 'X-' . APP_NAME . '-Webhook-Signature: ' . $signature, ] ); diff --git a/composer.json b/composer.json index 1cd1236d0f..6ce1bd218f 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,7 @@ "utopia-php/preloader": "0.2.*", "utopia-php/domains": "1.1.*", "utopia-php/swoole": "0.3.*", - "utopia-php/storage": "0.7.*", + "utopia-php/storage": "0.9.*", "utopia-php/websocket": "0.1.0", "utopia-php/image": "0.5.*", "utopia-php/orchestration": "0.4.*", @@ -62,7 +62,8 @@ "phpmailer/phpmailer": "6.6.0", "chillerlan/php-qrcode": "4.3.3", "adhocore/jwt": "1.1.2", - "slickdeals/statsd": "3.1.0" + "slickdeals/statsd": "3.1.0", + "squizlabs/php_codesniffer": "^3.6" }, "repositories": [ { @@ -71,11 +72,10 @@ } ], "require-dev": { - "appwrite/sdk-generator": "0.18.6", + "appwrite/sdk-generator": "0.18.8", "phpunit/phpunit": "9.5.20", "swoole/ide-helper": "4.8.9", - "textalk/websocket": "1.5.7", - "vimeo/psalm": "4.13.1" + "textalk/websocket": "1.5.7" }, "provide": { "ext-phpiredis": "*" diff --git a/composer.lock b/composer.lock index 69aadee3ae..77a95ecc29 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "69e0c12a4c4b22cf17727f5b8833b1ac", + "content-hash": "9450d0e08c0f21141af8d99232d37df9", "packages": [ { "name": "adhocore/jwt", @@ -115,11 +115,11 @@ }, { "name": "appwrite/php-runtimes", - "version": "0.9.0", + "version": "0.9.1", "source": { "type": "git", "url": "https://github.com/appwrite/runtimes.git", - "reference": "e8aa94aa42f45711e11cb1da401b442ecc2c32a4" + "reference": "01acf8741f539f64248d54a9f0f6c4d39195d16c" }, "require": { "php": ">=8.0", @@ -154,7 +154,7 @@ "php", "runtimes" ], - "time": "2022-05-16T10:54:14+00:00" + "time": "2022-05-19T11:48:16+00:00" }, { "name": "chillerlan/php-qrcode", @@ -481,16 +481,16 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.4.2", + "version": "7.4.4", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "ac1ec1cd9b5624694c3a40be801d94137afb12b4" + "reference": "e3ff079b22820c2029d4c2a87796b6a0b8716ad8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ac1ec1cd9b5624694c3a40be801d94137afb12b4", - "reference": "ac1ec1cd9b5624694c3a40be801d94137afb12b4", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/e3ff079b22820c2029d4c2a87796b6a0b8716ad8", + "reference": "e3ff079b22820c2029d4c2a87796b6a0b8716ad8", "shasum": "" }, "require": { @@ -585,7 +585,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.4.2" + "source": "https://github.com/guzzle/guzzle/tree/7.4.4" }, "funding": [ { @@ -601,7 +601,7 @@ "type": "tidelift" } ], - "time": "2022-03-20T14:16:28+00:00" + "time": "2022-06-09T21:39:15+00:00" }, { "name": "guzzlehttp/promises", @@ -689,16 +689,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "2.2.1", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "c94a94f120803a18554c1805ef2e539f8285f9a2" + "reference": "83260bb50b8fc753c72d14dc1621a2dac31877ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/c94a94f120803a18554c1805ef2e539f8285f9a2", - "reference": "c94a94f120803a18554c1805ef2e539f8285f9a2", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/83260bb50b8fc753c72d14dc1621a2dac31877ee", + "reference": "83260bb50b8fc753c72d14dc1621a2dac31877ee", "shasum": "" }, "require": { @@ -722,7 +722,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev" + "dev-master": "2.3-dev" } }, "autoload": { @@ -784,7 +784,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.2.1" + "source": "https://github.com/guzzle/psr7/tree/2.3.0" }, "funding": [ { @@ -800,7 +800,7 @@ "type": "tidelift" } ], - "time": "2022-03-20T21:55:58+00:00" + "time": "2022-06-09T08:26:02+00:00" }, { "name": "influxdb/influxdb-php", @@ -1582,26 +1582,82 @@ "time": "2021-06-04T20:33:46+00:00" }, { - "name": "symfony/deprecation-contracts", - "version": "v3.0.1", + "name": "squizlabs/php_codesniffer", + "version": "3.6.2", "source": { "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c" + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", - "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a", + "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a", "shasum": "" }, "require": { - "php": ">=8.0.2" + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards" + ], + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "source": "https://github.com/squizlabs/PHP_CodeSniffer", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + }, + "time": "2021-12-12T21:44:58+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "shasum": "" + }, + "require": { + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "2.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -1630,7 +1686,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.1" }, "funding": [ { @@ -1646,20 +1702,20 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:55:41+00:00" + "time": "2022-01-02T09:53:40+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.25.0", + "version": "v1.26.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "30885182c981ab175d4d034db0f6f469898070ab" + "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab", - "reference": "30885182c981ab175d4d034db0f6f469898070ab", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", + "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", "shasum": "" }, "require": { @@ -1674,7 +1730,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.26-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1712,7 +1768,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0" }, "funding": [ { @@ -1728,20 +1784,20 @@ "type": "tidelift" } ], - "time": "2021-10-20T20:35:02+00:00" + "time": "2022-05-24T11:49:31+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.25.0", + "version": "v1.26.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c" + "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c", - "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace", + "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace", "shasum": "" }, "require": { @@ -1750,7 +1806,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.26-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1795,7 +1851,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0" }, "funding": [ { @@ -1811,7 +1867,7 @@ "type": "tidelift" } ], - "time": "2022-03-04T08:16:47+00:00" + "time": "2022-05-10T07:21:04+00:00" }, { "name": "utopia-php/abuse", @@ -2628,16 +2684,16 @@ }, { "name": "utopia-php/storage", - "version": "0.7.1", + "version": "0.9.0", "source": { "type": "git", "url": "https://github.com/utopia-php/storage.git", - "reference": "1921d5da3d155c1e03b26f8f6184dba3a69cd5e4" + "reference": "c7912481a56e17cc86358fa8de57309de5e88ef7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/storage/zipball/1921d5da3d155c1e03b26f8f6184dba3a69cd5e4", - "reference": "1921d5da3d155c1e03b26f8f6184dba3a69cd5e4", + "url": "https://api.github.com/repos/utopia-php/storage/zipball/c7912481a56e17cc86358fa8de57309de5e88ef7", + "reference": "c7912481a56e17cc86358fa8de57309de5e88ef7", "shasum": "" }, "require": { @@ -2674,9 +2730,9 @@ ], "support": { "issues": "https://github.com/utopia-php/storage/issues", - "source": "https://github.com/utopia-php/storage/tree/0.7.1" + "source": "https://github.com/utopia-php/storage/tree/0.9.0" }, - "time": "2022-02-20T13:27:43+00:00" + "time": "2022-05-19T11:05:45+00:00" }, { "name": "utopia-php/swoole", @@ -2907,184 +2963,18 @@ } ], "packages-dev": [ - { - "name": "amphp/amp", - "version": "v2.6.2", - "source": { - "type": "git", - "url": "https://github.com/amphp/amp.git", - "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", - "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1", - "ext-json": "*", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^7 | ^8 | ^9", - "psalm/phar": "^3.11@dev", - "react/promise": "^2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "files": [ - "lib/functions.php", - "lib/Internal/functions.php" - ], - "psr-4": { - "Amp\\": "lib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A non-blocking concurrency framework for PHP applications.", - "homepage": "https://amphp.org/amp", - "keywords": [ - "async", - "asynchronous", - "awaitable", - "concurrency", - "event", - "event-loop", - "future", - "non-blocking", - "promise" - ], - "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/amp/issues", - "source": "https://github.com/amphp/amp/tree/v2.6.2" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2022-02-20T17:52:18+00:00" - }, - { - "name": "amphp/byte-stream", - "version": "v1.8.1", - "source": { - "type": "git", - "url": "https://github.com/amphp/byte-stream.git", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd", - "shasum": "" - }, - "require": { - "amphp/amp": "^2", - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1.4", - "friendsofphp/php-cs-fixer": "^2.3", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^6 || ^7 || ^8", - "psalm/phar": "^3.11.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "files": [ - "lib/functions.php" - ], - "psr-4": { - "Amp\\ByteStream\\": "lib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A stream abstraction to make working with non-blocking I/O simple.", - "homepage": "http://amphp.org/byte-stream", - "keywords": [ - "amp", - "amphp", - "async", - "io", - "non-blocking", - "stream" - ], - "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/byte-stream/issues", - "source": "https://github.com/amphp/byte-stream/tree/v1.8.1" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2021-03-30T17:13:30+00:00" - }, { "name": "appwrite/sdk-generator", - "version": "0.18.6", + "version": "0.18.8", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "c0914d9f4047fd7b86112c289d98e9161cf9d0b0" + "reference": "8ba45dfb74ff6062f96c0e4d10d7c4fae94768b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/c0914d9f4047fd7b86112c289d98e9161cf9d0b0", - "reference": "c0914d9f4047fd7b86112c289d98e9161cf9d0b0", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/8ba45dfb74ff6062f96c0e4d10d7c4fae94768b1", + "reference": "8ba45dfb74ff6062f96c0e4d10d7c4fae94768b1", "shasum": "" }, "require": { @@ -3119,264 +3009,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.18.6" + "source": "https://github.com/appwrite/sdk-generator/tree/0.18.8" }, - "time": "2022-05-17T15:09:23+00:00" - }, - { - "name": "composer/pcre", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/67a32d7d6f9f560b726ab25a061b38ff3a80c560", - "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.3", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Pcre\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", - "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" - ], - "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/1.0.1" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-01-21T20:24:37+00:00" - }, - { - "name": "composer/semver", - "version": "3.3.2", - "source": { - "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.4", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Semver\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" - } - ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", - "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.3.2" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-04-01T19:23:25+00:00" - }, - { - "name": "composer/xdebug-handler", - "version": "2.0.5", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/9e36aeed4616366d2b690bdce11f71e9178c579a", - "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a", - "shasum": "" - }, - "require": { - "composer/pcre": "^1", - "php": "^5.3.2 || ^7.0 || ^8.0", - "psr/log": "^1 || ^2 || ^3" - }, - "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/2.0.5" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-02-24T20:20:32+00:00" - }, - { - "name": "dnoegel/php-xdg-base-dir", - "version": "v0.1.1", - "source": { - "type": "git", - "url": "https://github.com/dnoegel/php-xdg-base-dir.git", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" - }, - "type": "library", - "autoload": { - "psr-4": { - "XdgBaseDir\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "implementation of xdg base directory specification for php", - "support": { - "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", - "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" - }, - "time": "2019-12-04T15:06:13+00:00" + "time": "2022-05-19T10:34:06+00:00" }, { "name": "doctrine/instantiator", @@ -3448,107 +3083,6 @@ ], "time": "2022-03-03T08:28:38+00:00" }, - { - "name": "felixfbecker/advanced-json-rpc", - "version": "v3.2.1", - "source": { - "type": "git", - "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "shasum": "" - }, - "require": { - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "php": "^7.1 || ^8.0", - "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" - }, - "require-dev": { - "phpunit/phpunit": "^7.0 || ^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "AdvancedJsonRpc\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } - ], - "description": "A more advanced JSONRPC implementation", - "support": { - "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", - "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1" - }, - "time": "2021-06-11T22:34:44+00:00" - }, - { - "name": "felixfbecker/language-server-protocol", - "version": "v1.5.2", - "source": { - "type": "git", - "url": "https://github.com/felixfbecker/php-language-server-protocol.git", - "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/6e82196ffd7c62f7794d778ca52b69feec9f2842", - "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "phpstan/phpstan": "*", - "squizlabs/php_codesniffer": "^3.1", - "vimeo/psalm": "^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "LanguageServerProtocol\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } - ], - "description": "PHP classes for the Language Server Protocol", - "keywords": [ - "language", - "microsoft", - "php", - "server" - ], - "support": { - "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", - "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.2" - }, - "time": "2022-03-02T22:36:06+00:00" - }, { "name": "matthiasmullie/minify", "version": "1.3.68", @@ -3731,69 +3265,18 @@ ], "time": "2022-03-03T13:19:32+00:00" }, - { - "name": "netresearch/jsonmapper", - "version": "v4.0.0", - "source": { - "type": "git", - "url": "https://github.com/cweiske/jsonmapper.git", - "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d", - "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0", - "squizlabs/php_codesniffer": "~3.5" - }, - "type": "library", - "autoload": { - "psr-0": { - "JsonMapper": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "OSL-3.0" - ], - "authors": [ - { - "name": "Christian Weiske", - "email": "cweiske@cweiske.de", - "homepage": "http://github.com/cweiske/jsonmapper/", - "role": "Developer" - } - ], - "description": "Map nested JSON structures onto PHP classes", - "support": { - "email": "cweiske@cweiske.de", - "issues": "https://github.com/cweiske/jsonmapper/issues", - "source": "https://github.com/cweiske/jsonmapper/tree/v4.0.0" - }, - "time": "2020-12-01T19:48:11+00:00" - }, { "name": "nikic/php-parser", - "version": "v4.13.2", + "version": "v4.14.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "210577fe3cf7badcc5814d99455df46564f3c077" + "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077", - "reference": "210577fe3cf7badcc5814d99455df46564f3c077", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/34bea19b6e03d8153165d8f30bba4c3be86184c1", + "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1", "shasum": "" }, "require": { @@ -3834,62 +3317,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.2" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.14.0" }, - "time": "2021-11-30T19:35:32+00:00" - }, - { - "name": "openlss/lib-array2xml", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/nullivex/lib-array2xml.git", - "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nullivex/lib-array2xml/zipball/a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", - "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "type": "library", - "autoload": { - "psr-0": { - "LSS": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Bryan Tong", - "email": "bryan@nullivex.com", - "homepage": "https://www.nullivex.com" - }, - { - "name": "Tony Butler", - "email": "spudz76@gmail.com", - "homepage": "https://www.nullivex.com" - } - ], - "description": "Array2XML conversion library credit to lalit.org", - "homepage": "https://www.nullivex.com", - "keywords": [ - "array", - "array conversion", - "xml", - "xml conversion" - ], - "support": { - "issues": "https://github.com/nullivex/lib-array2xml/issues", - "source": "https://github.com/nullivex/lib-array2xml/tree/master" - }, - "time": "2019-03-29T20:06:56+00:00" + "time": "2022-05-31T20:59:12+00:00" }, { "name": "phar-io/manifest", @@ -4650,59 +4080,6 @@ ], "time": "2022-04-01T12:37:26+00:00" }, - { - "name": "psr/container", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" - }, - "time": "2021-11-05T16:47:00+00:00" - }, { "name": "sebastian/cli-parser", "version": "1.0.1", @@ -5709,278 +5086,18 @@ ], "time": "2022-04-18T20:38:04+00:00" }, - { - "name": "symfony/console", - "version": "v6.0.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "0d00aa289215353aa8746a31d101f8e60826285c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0d00aa289215353aa8746a31d101f8e60826285c", - "reference": "0d00aa289215353aa8746a31d101f8e60826285c", - "shasum": "" - }, - "require": { - "php": ">=8.0.2", - "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.4|^6.0" - }, - "conflict": { - "symfony/dependency-injection": "<5.4", - "symfony/dotenv": "<5.4", - "symfony/event-dispatcher": "<5.4", - "symfony/lock": "<5.4", - "symfony/process": "<5.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0|3.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/lock": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command line", - "console", - "terminal" - ], - "support": { - "source": "https://github.com/symfony/console/tree/v6.0.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-04-20T15:01:42+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.25.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "81b86b50cf841a64252b439e738e97f4a34e2783" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783", - "reference": "81b86b50cf841a64252b439e738e97f4a34e2783", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.25.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-11-23T21:10:46+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.25.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8", - "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-02-19T12:13:01+00:00" - }, { "name": "symfony/polyfill-mbstring", - "version": "v1.25.0", + "version": "v1.26.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825" + "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825", - "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", + "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", "shasum": "" }, "require": { @@ -5995,7 +5112,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.26-dev" }, "thanks": { "name": "symfony/polyfill", @@ -6034,7 +5151,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0" }, "funding": [ { @@ -6050,174 +5167,7 @@ "type": "tidelift" } ], - "time": "2021-11-30T18:21:41+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v3.0.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "e517458f278c2131ca9f262f8fbaf01410f2c65c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e517458f278c2131ca9f262f8fbaf01410f2c65c", - "reference": "e517458f278c2131ca9f262f8fbaf01410f2c65c", - "shasum": "" - }, - "require": { - "php": ">=8.0.2", - "psr/container": "^2.0" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "suggest": { - "symfony/service-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.0.1" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-03-13T20:10:05+00:00" - }, - { - "name": "symfony/string", - "version": "v6.0.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "ac0aa5c2282e0de624c175b68d13f2c8f2e2649d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/ac0aa5c2282e0de624c175b68d13f2c8f2e2649d", - "reference": "ac0aa5c2282e0de624c175b68d13f2c8f2e2649d", - "shasum": "" - }, - "require": { - "php": ">=8.0.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/translation-contracts": "<2.0" - }, - "require-dev": { - "symfony/error-handler": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/translation-contracts": "^2.0|^3.0", - "symfony/var-exporter": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], - "support": { - "source": "https://github.com/symfony/string/tree/v6.0.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-04-22T08:18:02+00:00" + "time": "2022-05-24T11:49:31+00:00" }, { "name": "textalk/websocket", @@ -6393,163 +5343,6 @@ } ], "time": "2022-05-17T05:48:52+00:00" - }, - { - "name": "vimeo/psalm", - "version": "4.13.1", - "source": { - "type": "git", - "url": "https://github.com/vimeo/psalm.git", - "reference": "5cf660f63b548ccd4a56f62d916ee4d6028e01a3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/5cf660f63b548ccd4a56f62d916ee4d6028e01a3", - "reference": "5cf660f63b548ccd4a56f62d916ee4d6028e01a3", - "shasum": "" - }, - "require": { - "amphp/amp": "^2.4.2", - "amphp/byte-stream": "^1.5", - "composer/package-versions-deprecated": "^1.8.0", - "composer/semver": "^1.4 || ^2.0 || ^3.0", - "composer/xdebug-handler": "^1.1 || ^2.0", - "dnoegel/php-xdg-base-dir": "^0.1.1", - "ext-ctype": "*", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-simplexml": "*", - "ext-tokenizer": "*", - "felixfbecker/advanced-json-rpc": "^3.0.3", - "felixfbecker/language-server-protocol": "^1.5", - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "nikic/php-parser": "^4.13", - "openlss/lib-array2xml": "^1.0", - "php": "^7.1|^8", - "sebastian/diff": "^3.0 || ^4.0", - "symfony/console": "^3.4.17 || ^4.1.6 || ^5.0 || ^6.0", - "webmozart/path-util": "^2.3" - }, - "provide": { - "psalm/psalm": "self.version" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.2", - "brianium/paratest": "^4.0||^6.0", - "ext-curl": "*", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpdocumentor/reflection-docblock": "^5", - "phpmyadmin/sql-parser": "5.1.0||dev-master", - "phpspec/prophecy": ">=1.9.0", - "phpunit/phpunit": "^9.0", - "psalm/plugin-phpunit": "^0.16", - "slevomat/coding-standard": "^7.0", - "squizlabs/php_codesniffer": "^3.5", - "symfony/process": "^4.3 || ^5.0 || ^6.0", - "weirdan/prophecy-shim": "^1.0 || ^2.0" - }, - "suggest": { - "ext-curl": "In order to send data to shepherd", - "ext-igbinary": "^2.0.5 is required, used to serialize caching data" - }, - "bin": [ - "psalm", - "psalm-language-server", - "psalm-plugin", - "psalm-refactor", - "psalter" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.x-dev", - "dev-3.x": "3.x-dev", - "dev-2.x": "2.x-dev", - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "files": [ - "src/functions.php", - "src/spl_object_id.php" - ], - "psr-4": { - "Psalm\\": "src/Psalm/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matthew Brown" - } - ], - "description": "A static analysis tool for finding errors in PHP applications", - "keywords": [ - "code", - "inspection", - "php" - ], - "support": { - "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/4.13.1" - }, - "time": "2021-11-23T23:52:49+00:00" - }, - { - "name": "webmozart/path-util", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/webmozart/path-util.git", - "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725", - "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "webmozart/assert": "~1.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\PathUtil\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.", - "support": { - "issues": "https://github.com/webmozart/path-util/issues", - "source": "https://github.com/webmozart/path-util/tree/2.3.0" - }, - "abandoned": "symfony/filesystem", - "time": "2015-12-17T08:42:14+00:00" } ], "aliases": [], diff --git a/docker-compose.yml b/docker-compose.yml index 159b811566..b6e1ed68b2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,6 +10,30 @@ 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: @@ -77,7 +101,6 @@ services: - appwrite-certificates:/storage/certificates:rw - appwrite-functions:/storage/functions:rw - ./phpunit.xml:/usr/src/code/phpunit.xml - - ./psalm.xml:/usr/src/code/psalm.xml - ./tests:/usr/src/code/tests - ./app:/usr/src/code/app # - ./vendor:/usr/src/code/vendor @@ -133,15 +156,7 @@ services: - _APP_STORAGE_ANTIVIRUS - _APP_STORAGE_ANTIVIRUS_HOST - _APP_STORAGE_ANTIVIRUS_PORT - - _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 + - *x-env-storage - _APP_FUNCTIONS_SIZE_LIMIT - _APP_FUNCTIONS_TIMEOUT - _APP_FUNCTIONS_BUILD_TIMEOUT @@ -296,15 +311,7 @@ services: - _APP_DB_SCHEMA - _APP_DB_USER - _APP_DB_PASS - - _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 + - *x-env-storage - _APP_LOGGING_PROVIDER - _APP_LOGGING_CONFIG - _APP_EXECUTOR_SECRET @@ -481,15 +488,7 @@ services: - OPEN_RUNTIMES_NETWORK - _APP_LOGGING_PROVIDER - _APP_LOGGING_CONFIG - - _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 + - *x-env-storage - DOCKERHUB_PULL_USERNAME - DOCKERHUB_PULL_PASSWORD diff --git a/docs/sdks/dart/CHANGELOG.md b/docs/sdks/dart/CHANGELOG.md index 7103bfa733..319398a285 100644 --- a/docs/sdks/dart/CHANGELOG.md +++ b/docs/sdks/dart/CHANGELOG.md @@ -1,3 +1,6 @@ +## 5.0.1 +* Code formatting fix + ## 5.0.0 * Support for Appwrite 0.14 * **BREAKING** `account.delete()` -> `account.updateStatus()` diff --git a/docs/sdks/dart/GETTING_STARTED.md b/docs/sdks/dart/GETTING_STARTED.md index dd1dd3918c..e6c4ecf677 100644 --- a/docs/sdks/dart/GETTING_STARTED.md +++ b/docs/sdks/dart/GETTING_STARTED.md @@ -7,11 +7,11 @@ Once you add the dependencies, its extremely easy to get started with the SDK; A import 'package:dart_appwrite/dart_appwrite.dart'; void main() async { - Client client = Client(); + Client client = Client() .setEndpoint('http://[HOSTNAME_OR_IP]/v1') // Make sure your endpoint is accessible .setProject('5ff3379a01d25') // Your project ID .setKey('cd868c7af8bdc893b4...93b7535db89') - .setSelfSigned() // Use only on dev mode with a self-signed SSL cert + .setSelfSigned(); // Use only on dev mode with a self-signed SSL cert Users users = Users(client); diff --git a/docs/sdks/flutter/GETTING_STARTED.md b/docs/sdks/flutter/GETTING_STARTED.md index 78fa4f93b7..0a83ae67bd 100644 --- a/docs/sdks/flutter/GETTING_STARTED.md +++ b/docs/sdks/flutter/GETTING_STARTED.md @@ -10,11 +10,14 @@ If you are building your Flutter application for multiple devices, you have to f ### Android For **Android** first add your app name and package name, Your package name is generally the **applicationId** in your app-level build.gradle file. By registering your new app platform, you are allowing your app to communicate with the Appwrite API. -In order to capture the Appwrite OAuth callback url, the following activity needs to be added to your [AndroidManifest.xml](https://github.com/appwrite/playground-for-flutter/blob/master/android/app/src/main/AndroidManifest.xml). Be sure to replace the **[PROJECT_ID]** string with your actual Appwrite project ID. You can find your Appwrite project ID in your project settings screen in the console. +In order to capture the Appwrite OAuth callback url, the following activity needs to be added inside the `` tag, along side the existing `` tags in your [AndroidManifest.xml](https://github.com/appwrite/playground-for-flutter/blob/master/android/app/src/main/AndroidManifest.xml). Be sure to replace the **[PROJECT_ID]** string with your actual Appwrite project ID. You can find your Appwrite project ID in your project settings screen in the console. ```xml - - + + .... + + .... + diff --git a/docs/services/storage.md b/docs/services/storage.md index 97f8b10da3..02f1ff430c 100644 --- a/docs/services/storage.md +++ b/docs/services/storage.md @@ -4,4 +4,6 @@ Files are managed using buckets. Storage buckets are similar to Collections we h Using Appwrite permissions architecture, you can assign read or write access to each bucket or file in your project for either a specific user, team, user role, or even grant it with public access (`role:all`). You can learn more about [how Appwrite handles permissions and access control](/docs/permissions). -The preview endpoint allows you to generate preview images for your files. Using the preview endpoint, you can also manipulate the resulting image so that it will fit perfectly inside your app in terms of dimensions, file size, and style. The preview endpoint also allows you to change the resulting image file format for better compression or image quality for better delivery over the network. \ No newline at end of file +The preview endpoint allows you to generate preview images for your files. Using the preview endpoint, you can also manipulate the resulting image so that it will fit perfectly inside your app in terms of dimensions, file size, and style. The preview endpoint also allows you to change the resulting image file format for better compression or image quality for better delivery over the network. + +The maximum file size allowed for file upload is controlled by the `_APP_STORAGE_LIMIT` environment variable, which defaults to 30 MB. See [Environment Variables](/docs/environment-variables#storage) for more information. diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 0000000000..cb31d549e0 --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,22 @@ + + + + ./app + ./src + ./tests + + + ./app/sdks + + + * + + + + * + + + + ./app + + \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml index 11436083ce..e3d583022f 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -6,7 +6,7 @@ convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" - stopOnFailure="true" + stopOnFailure="false" > @@ -35,4 +35,4 @@ ./tests/e2e/Services/Functions/FunctionsCustomClientTest.php - \ No newline at end of file + diff --git a/psalm.xml b/psalm.xml deleted file mode 100644 index 30258a7095..0000000000 --- a/psalm.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - diff --git a/public/images/runtimes/dotnet.png b/public/images/runtimes/dotnet.png index 824721f200..aa003d5c3c 100644 Binary files a/public/images/runtimes/dotnet.png and b/public/images/runtimes/dotnet.png differ diff --git a/src/Appwrite/Auth/Auth.php b/src/Appwrite/Auth/Auth.php index 8ac5839ee0..40560371f4 100644 --- a/src/Appwrite/Auth/Auth.php +++ b/src/Appwrite/Auth/Auth.php @@ -10,38 +10,38 @@ class Auth /** * User Roles. */ - const USER_ROLE_ALL = 'all'; - const USER_ROLE_GUEST = 'guest'; - const USER_ROLE_MEMBER = 'member'; - const USER_ROLE_ADMIN = 'admin'; - const USER_ROLE_DEVELOPER = 'developer'; - const USER_ROLE_OWNER = 'owner'; - const USER_ROLE_APP = 'app'; - const USER_ROLE_SYSTEM = 'system'; + public const USER_ROLE_ALL = 'all'; + public const USER_ROLE_GUEST = 'guest'; + public const USER_ROLE_MEMBER = 'member'; + public const USER_ROLE_ADMIN = 'admin'; + public const USER_ROLE_DEVELOPER = 'developer'; + public const USER_ROLE_OWNER = 'owner'; + public const USER_ROLE_APP = 'app'; + public const USER_ROLE_SYSTEM = 'system'; /** * Token Types. */ - const TOKEN_TYPE_LOGIN = 1; // Deprecated - const TOKEN_TYPE_VERIFICATION = 2; - const TOKEN_TYPE_RECOVERY = 3; - const TOKEN_TYPE_INVITE = 4; - const TOKEN_TYPE_MAGIC_URL = 5; + public const TOKEN_TYPE_LOGIN = 1; // Deprecated + public const TOKEN_TYPE_VERIFICATION = 2; + public const TOKEN_TYPE_RECOVERY = 3; + public const TOKEN_TYPE_INVITE = 4; + public const TOKEN_TYPE_MAGIC_URL = 5; /** * Session Providers. */ - const SESSION_PROVIDER_EMAIL = 'email'; - const SESSION_PROVIDER_ANONYMOUS = 'anonymous'; - const SESSION_PROVIDER_MAGIC_URL = 'magic-url'; + public const SESSION_PROVIDER_EMAIL = 'email'; + public const SESSION_PROVIDER_ANONYMOUS = 'anonymous'; + public const SESSION_PROVIDER_MAGIC_URL = 'magic-url'; /** * Token Expiration times. */ - const TOKEN_EXPIRATION_LOGIN_LONG = 31536000; /* 1 year */ - const TOKEN_EXPIRATION_LOGIN_SHORT = 3600; /* 1 hour */ - const TOKEN_EXPIRATION_RECOVERY = 3600; /* 1 hour */ - const TOKEN_EXPIRATION_CONFIRM = 3600 * 24 * 7; /* 7 days */ + public const TOKEN_EXPIRATION_LOGIN_LONG = 31536000; /* 1 year */ + public const TOKEN_EXPIRATION_LOGIN_SHORT = 3600; /* 1 hour */ + public const TOKEN_EXPIRATION_RECOVERY = 3600; /* 1 hour */ + public const TOKEN_EXPIRATION_CONFIRM = 3600 * 24 * 7; /* 7 days */ /** * @var string @@ -163,7 +163,7 @@ class Auth * * @throws \Exception */ - public static function passwordGenerator(int $length = 20):string + public static function passwordGenerator(int $length = 20): string { return \bin2hex(\random_bytes($length)); } @@ -179,7 +179,7 @@ class Auth * * @throws \Exception */ - public static function tokenGenerator(int $length = 128):string + public static function tokenGenerator(int $length = 128): string { return \bin2hex(\random_bytes($length)); } @@ -196,12 +196,14 @@ class Auth public static function tokenVerify(array $tokens, int $type, string $secret) { foreach ($tokens as $token) { /** @var Document $token */ - if ($token->isSet('type') && + if ( + $token->isSet('type') && $token->isSet('secret') && $token->isSet('expire') && $token->getAttribute('type') == $type && $token->getAttribute('secret') === self::hash($secret) && - $token->getAttribute('expire') >= \time()) { + $token->getAttribute('expire') >= \time() + ) { return (string)$token->getId(); } } @@ -220,11 +222,13 @@ class Auth public static function sessionVerify(array $sessions, string $secret) { foreach ($sessions as $session) { /** @var Document $session */ - if ($session->isSet('secret') && + if ( + $session->isSet('secret') && $session->isSet('expire') && $session->isSet('provider') && $session->getAttribute('secret') === self::hash($secret) && - $session->getAttribute('expire') >= \time()) { + $session->getAttribute('expire') >= \time() + ) { return (string)$session->getId(); } } @@ -242,9 +246,9 @@ class Auth public static function isPrivilegedUser(array $roles): bool { if ( - in_array('role:'.self::USER_ROLE_OWNER, $roles) || - in_array('role:'.self::USER_ROLE_DEVELOPER, $roles) || - in_array('role:'.self::USER_ROLE_ADMIN, $roles) + in_array('role:' . self::USER_ROLE_OWNER, $roles) || + in_array('role:' . self::USER_ROLE_DEVELOPER, $roles) || + in_array('role:' . self::USER_ROLE_ADMIN, $roles) ) { return true; } @@ -261,7 +265,7 @@ class Auth */ public static function isAppUser(array $roles): bool { - if (in_array('role:'.self::USER_ROLE_APP, $roles)) { + if (in_array('role:' . self::USER_ROLE_APP, $roles)) { return true; } @@ -280,10 +284,10 @@ class Auth if (!self::isPrivilegedUser(Authorization::getRoles()) && !self::isAppUser(Authorization::getRoles())) { if ($user->getId()) { - $roles[] = 'user:'.$user->getId(); - $roles[] = 'role:'.Auth::USER_ROLE_MEMBER; + $roles[] = 'user:' . $user->getId(); + $roles[] = 'role:' . Auth::USER_ROLE_MEMBER; } else { - return ['role:'.Auth::USER_ROLE_GUEST]; + return ['role:' . Auth::USER_ROLE_GUEST]; } } diff --git a/src/Appwrite/Auth/OAuth2.php b/src/Appwrite/Auth/OAuth2.php index 99b40019ac..d7c1c99546 100644 --- a/src/Appwrite/Auth/OAuth2.php +++ b/src/Appwrite/Auth/OAuth2.php @@ -82,9 +82,9 @@ abstract class OAuth2 /** * Check if the OAuth email is verified - * + * * @param string $accessToken - * + * * @return bool */ abstract public function isEmailVerified(string $accessToken): bool; @@ -189,7 +189,7 @@ abstract class OAuth2 \curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); } - $headers[] = 'Content-length: '.\strlen($payload); + $headers[] = 'Content-length: ' . \strlen($payload); \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // Send the request & save response to $response diff --git a/src/Appwrite/Auth/OAuth2/Amazon.php b/src/Appwrite/Auth/OAuth2/Amazon.php index 2e72975fd1..d1d2cb5a38 100644 --- a/src/Appwrite/Auth/OAuth2/Amazon.php +++ b/src/Appwrite/Auth/OAuth2/Amazon.php @@ -140,11 +140,11 @@ class Amazon extends OAuth2 /** * Check if the OAuth email is verified - * + * * If present, the email is verified. This was verfied through a manual Amazon sign up process - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Apple.php b/src/Appwrite/Auth/OAuth2/Apple.php index 1ea352e685..2abf61c947 100644 --- a/src/Appwrite/Auth/OAuth2/Apple.php +++ b/src/Appwrite/Auth/OAuth2/Apple.php @@ -137,11 +137,11 @@ class Apple extends OAuth2 /** * Check if the OAuth email is verified - * + * * @link https://developer.apple.com/forums/thread/121411 - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Auth0.php b/src/Appwrite/Auth/OAuth2/Auth0.php index 4775139a0b..eba7d18b5f 100644 --- a/src/Appwrite/Auth/OAuth2/Auth0.php +++ b/src/Appwrite/Auth/OAuth2/Auth0.php @@ -132,11 +132,11 @@ class Auth0 extends OAuth2 /** * Check if the OAuth email is verified - * + * * @link https://auth0.com/docs/api/authentication?javascript#user-profile - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -180,7 +180,7 @@ class Auth0 extends OAuth2 /** * Extracts the Client Secret from the JSON stored in appSecret - * + * * @return string */ protected function getClientSecret(): string @@ -192,7 +192,7 @@ class Auth0 extends OAuth2 /** * Extracts the Auth0 Domain from the JSON stored in appSecret - * + * * @return string */ protected function getAuth0Domain(): string @@ -204,7 +204,7 @@ class Auth0 extends OAuth2 /** * Decode the JSON stored in appSecret - * + * * @return array */ protected function getAppSecret(): array diff --git a/src/Appwrite/Auth/OAuth2/Bitbucket.php b/src/Appwrite/Auth/OAuth2/Bitbucket.php index bbefe144c1..361bc22b65 100644 --- a/src/Appwrite/Auth/OAuth2/Bitbucket.php +++ b/src/Appwrite/Auth/OAuth2/Bitbucket.php @@ -124,9 +124,9 @@ class Bitbucket extends OAuth2 /** * Check if the OAuth email is verified - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Bitly.php b/src/Appwrite/Auth/OAuth2/Bitly.php index 08350bea6f..290876a8cb 100644 --- a/src/Appwrite/Auth/OAuth2/Bitly.php +++ b/src/Appwrite/Auth/OAuth2/Bitly.php @@ -9,7 +9,6 @@ use Appwrite\Auth\OAuth2; class Bitly extends OAuth2 { - /** * @var string */ @@ -149,11 +148,11 @@ class Bitly extends OAuth2 /** * Check if the OAuth email is verified - * + * * @link https://dev.bitly.com/api-reference#getUser - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Box.php b/src/Appwrite/Auth/OAuth2/Box.php index da925eed1a..e88c165833 100644 --- a/src/Appwrite/Auth/OAuth2/Box.php +++ b/src/Appwrite/Auth/OAuth2/Box.php @@ -141,11 +141,11 @@ class Box extends OAuth2 /** * Check if the OAuth email is verified - * + * * If present, the email is verified. This was verfied through a manual Box sign up process - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Discord.php b/src/Appwrite/Auth/OAuth2/Discord.php index 7cf2ef1b7b..b77ce6a236 100644 --- a/src/Appwrite/Auth/OAuth2/Discord.php +++ b/src/Appwrite/Auth/OAuth2/Discord.php @@ -18,7 +18,7 @@ class Discord extends OAuth2 * @var array */ protected array $user = []; - + /** * @var array */ @@ -45,7 +45,7 @@ class Discord extends OAuth2 */ public function getLoginURL(): string { - $url = $this->endpoint . '/oauth2/authorize?'. + $url = $this->endpoint . '/oauth2/authorize?' . \http_build_query([ 'response_type' => 'code', 'client_id' => $this->appID, @@ -64,7 +64,7 @@ class Discord extends OAuth2 */ protected function getTokens(string $code): array { - if(empty($this->tokens)) { + if (empty($this->tokens)) { $this->tokens = \json_decode($this->request( 'POST', $this->endpoint . '/oauth2/token', @@ -88,7 +88,7 @@ class Discord extends OAuth2 * * @return array */ - public function refreshTokens(string $refreshToken):array + public function refreshTokens(string $refreshToken): array { $this->tokens = \json_decode($this->request( 'POST', @@ -102,7 +102,7 @@ class Discord extends OAuth2 ]) ), true); - if(empty($this->tokens['refresh_token'])) { + if (empty($this->tokens['refresh_token'])) { $this->tokens['refresh_token'] = $refreshToken; } @@ -135,11 +135,11 @@ class Discord extends OAuth2 /** * Check if the OAuth email is verified - * + * * @link https://discord.com/developers/docs/resources/user - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -176,7 +176,7 @@ class Discord extends OAuth2 $user = $this->request( 'GET', $this->endpoint . '/users/@me', - ['Authorization: Bearer '.\urlencode($accessToken)] + ['Authorization: Bearer ' . \urlencode($accessToken)] ); $this->user = \json_decode($user, true); } diff --git a/src/Appwrite/Auth/OAuth2/Dropbox.php b/src/Appwrite/Auth/OAuth2/Dropbox.php index 5025cb3dc8..ff30b87d8a 100644 --- a/src/Appwrite/Auth/OAuth2/Dropbox.php +++ b/src/Appwrite/Auth/OAuth2/Dropbox.php @@ -125,11 +125,11 @@ class Dropbox extends OAuth2 /** * Check if the OAuth email is verified - * + * * @link https://www.dropbox.com/developers/documentation/http/documentation#users-get_current_account - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Facebook.php b/src/Appwrite/Auth/OAuth2/Facebook.php index 555daedc58..90fe8e7388 100644 --- a/src/Appwrite/Auth/OAuth2/Facebook.php +++ b/src/Appwrite/Auth/OAuth2/Facebook.php @@ -122,11 +122,11 @@ class Facebook extends OAuth2 /** * Check if the OAuth email is verified - * + * * If present, the email is verified. This was verfied through a manual Facebook sign up process - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Github.php b/src/Appwrite/Auth/OAuth2/Github.php index 1130134f68..c582617d67 100644 --- a/src/Appwrite/Auth/OAuth2/Github.php +++ b/src/Appwrite/Auth/OAuth2/Github.php @@ -128,11 +128,11 @@ class Github extends OAuth2 /** * Check if the OAuth email is verified - * + * * @link https://docs.github.com/en/rest/users/emails#list-email-addresses-for-the-authenticated-user - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Gitlab.php b/src/Appwrite/Auth/OAuth2/Gitlab.php index fa0a93df92..ab230c7760 100644 --- a/src/Appwrite/Auth/OAuth2/Gitlab.php +++ b/src/Appwrite/Auth/OAuth2/Gitlab.php @@ -125,11 +125,11 @@ class Gitlab extends OAuth2 /** * Check if the OAuth email is verified - * + * * @link https://docs.gitlab.com/ee/api/users.html#list-current-user-for-normal-users - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Google.php b/src/Appwrite/Auth/OAuth2/Google.php index fe29855339..c6f621b814 100644 --- a/src/Appwrite/Auth/OAuth2/Google.php +++ b/src/Appwrite/Auth/OAuth2/Google.php @@ -131,11 +131,11 @@ class Google extends OAuth2 /** * Check if the OAuth email is verified - * + * * @link https://www.oauth.com/oauth2-servers/signing-in-with-google/verifying-the-user-info/ - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Linkedin.php b/src/Appwrite/Auth/OAuth2/Linkedin.php index 3ada765319..8cf9b8aff7 100644 --- a/src/Appwrite/Auth/OAuth2/Linkedin.php +++ b/src/Appwrite/Auth/OAuth2/Linkedin.php @@ -137,11 +137,11 @@ class Linkedin extends OAuth2 /** * Check if the OAuth email is verified - * + * * If present, the email is verified. This was verfied through a manual Linkedin sign up process - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Microsoft.php b/src/Appwrite/Auth/OAuth2/Microsoft.php index 84f128a08e..bc05843b37 100644 --- a/src/Appwrite/Auth/OAuth2/Microsoft.php +++ b/src/Appwrite/Auth/OAuth2/Microsoft.php @@ -131,11 +131,11 @@ class Microsoft extends OAuth2 /** * Check if the OAuth email is verified - * + * * If present, the email is verified. This was verfied through a manual Microsoft sign up process - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -175,7 +175,7 @@ class Microsoft extends OAuth2 /** * Decode the JSON stored in appSecret - * + * * @return array */ protected function getAppSecret(): array @@ -190,7 +190,7 @@ class Microsoft extends OAuth2 /** * Extracts the Client Secret from the JSON stored in appSecret - * + * * @return string */ protected function getClientSecret(): string @@ -202,7 +202,7 @@ class Microsoft extends OAuth2 /** * Extracts the Tenant Id from the JSON stored in appSecret. Defaults to 'common' as a fallback - * + * * @return string */ protected function getTenantID(): string diff --git a/src/Appwrite/Auth/OAuth2/Mock.php b/src/Appwrite/Auth/OAuth2/Mock.php index f80287947e..d2cb8c1c2a 100644 --- a/src/Appwrite/Auth/OAuth2/Mock.php +++ b/src/Appwrite/Auth/OAuth2/Mock.php @@ -124,9 +124,9 @@ class Mock extends OAuth2 /** * Check if the OAuth email is verified - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Notion.php b/src/Appwrite/Auth/OAuth2/Notion.php index 5d9d75bffd..c2f1ee98e4 100644 --- a/src/Appwrite/Auth/OAuth2/Notion.php +++ b/src/Appwrite/Auth/OAuth2/Notion.php @@ -128,11 +128,11 @@ class Notion extends OAuth2 /** * Check if the OAuth email is verified - * + * * If present, the email is verified. This was verfied through a manual Notion sign up process - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Okta.php b/src/Appwrite/Auth/OAuth2/Okta.php index 3de3df96d5..610d9847f2 100644 --- a/src/Appwrite/Auth/OAuth2/Okta.php +++ b/src/Appwrite/Auth/OAuth2/Okta.php @@ -132,11 +132,11 @@ class Okta extends OAuth2 /** * Check if the OAuth email is verified - * + * * @link https://developer.okta.com/docs/reference/api/oidc/#userinfo - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -180,7 +180,7 @@ class Okta extends OAuth2 /** * Extracts the Client Secret from the JSON stored in appSecret - * + * * @return string */ protected function getClientSecret(): string @@ -192,7 +192,7 @@ class Okta extends OAuth2 /** * Extracts the Okta Domain from the JSON stored in appSecret - * + * * @return string */ protected function getOktaDomain(): string @@ -204,7 +204,7 @@ class Okta extends OAuth2 /** * Extracts the Okta Authorization Server ID from the JSON stored in appSecret - * + * * @return string */ protected function getAuthorizationServerId(): string @@ -216,7 +216,7 @@ class Okta extends OAuth2 /** * Decode the JSON stored in appSecret - * + * * @return array */ protected function getAppSecret(): array diff --git a/src/Appwrite/Auth/OAuth2/Paypal.php b/src/Appwrite/Auth/OAuth2/Paypal.php index 74f4291594..5d5bd0a06f 100644 --- a/src/Appwrite/Auth/OAuth2/Paypal.php +++ b/src/Appwrite/Auth/OAuth2/Paypal.php @@ -158,11 +158,11 @@ class Paypal extends OAuth2 /** * Check if the OAuth email is verified - * + * * @link https://developer.paypal.com/docs/api/identity/v1/#userinfo_get - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Salesforce.php b/src/Appwrite/Auth/OAuth2/Salesforce.php index 636c3f4c3c..564fc51139 100644 --- a/src/Appwrite/Auth/OAuth2/Salesforce.php +++ b/src/Appwrite/Auth/OAuth2/Salesforce.php @@ -142,11 +142,11 @@ class Salesforce extends OAuth2 /** * Check if the OAuth email is verified - * + * * @link https://help.salesforce.com/s/articleView?id=sf.remoteaccess_using_userinfo_endpoint.htm&type=5 - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Slack.php b/src/Appwrite/Auth/OAuth2/Slack.php index c8adfdd697..8898f4d1f7 100644 --- a/src/Appwrite/Auth/OAuth2/Slack.php +++ b/src/Appwrite/Auth/OAuth2/Slack.php @@ -121,13 +121,13 @@ class Slack extends OAuth2 /** * Check if the OAuth email is verified - * + * * If present, the email is verified. This was verfied through a manual Slack sign up process - * + * * @link https://slack.com/help/articles/207262907-Change-your-email-address - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool @@ -151,7 +151,7 @@ class Slack extends OAuth2 /** * @link https://api.slack.com/methods/users.identity - * + * * @param string $accessToken * * @return array diff --git a/src/Appwrite/Auth/OAuth2/Spotify.php b/src/Appwrite/Auth/OAuth2/Spotify.php index 98f4226d84..d8e23cf0f0 100644 --- a/src/Appwrite/Auth/OAuth2/Spotify.php +++ b/src/Appwrite/Auth/OAuth2/Spotify.php @@ -9,7 +9,6 @@ use Appwrite\Auth\OAuth2; class Spotify extends OAuth2 { - /** * @var string */ @@ -135,13 +134,13 @@ class Spotify extends OAuth2 /** * Check if the OAuth email is verified - * - * Spotify does not assure that the email is verified - * + * + * Spotify does not assure that the email is verified + * * @link https://developer.spotify.com/documentation/web-api/reference/#/operations/get-current-users-profile - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Stripe.php b/src/Appwrite/Auth/OAuth2/Stripe.php index e2ca3a92ba..5a959dbfcb 100644 --- a/src/Appwrite/Auth/OAuth2/Stripe.php +++ b/src/Appwrite/Auth/OAuth2/Stripe.php @@ -138,11 +138,11 @@ class Stripe extends OAuth2 /** * Check if the OAuth email is verified - * + * * If present, the email is verified. This was verfied through a manual Stripe sign up process - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Tradeshift.php b/src/Appwrite/Auth/OAuth2/Tradeshift.php index 8fdcde5f29..8d0bfa8784 100644 --- a/src/Appwrite/Auth/OAuth2/Tradeshift.php +++ b/src/Appwrite/Auth/OAuth2/Tradeshift.php @@ -9,8 +9,8 @@ use Appwrite\Auth\OAuth2; class Tradeshift extends OAuth2 { - const TRADESHIFT_SANDBOX_API_DOMAIN = 'api-sandbox.tradeshift.com'; - const TRADESHIFT_API_DOMAIN = 'api.tradeshift.com'; + public const TRADESHIFT_SANDBOX_API_DOMAIN = 'api-sandbox.tradeshift.com'; + public const TRADESHIFT_API_DOMAIN = 'api.tradeshift.com'; private array $apiDomain = [ 'sandbox' => self::TRADESHIFT_SANDBOX_API_DOMAIN, @@ -42,7 +42,7 @@ class Tradeshift extends OAuth2 /** * @var array */ - protected array$scopes = [ + protected array $scopes = [ 'openid', 'offline', ]; @@ -145,11 +145,11 @@ class Tradeshift extends OAuth2 /** * Check if the OAuth email is verified - * + * * If present, the email is verified. This was verfied through a manual Tradeshift sign up process - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Twitch.php b/src/Appwrite/Auth/OAuth2/Twitch.php index 04e542ffb9..ed73054c31 100644 --- a/src/Appwrite/Auth/OAuth2/Twitch.php +++ b/src/Appwrite/Auth/OAuth2/Twitch.php @@ -9,7 +9,6 @@ use Appwrite\Auth\OAuth2; class Twitch extends OAuth2 { - /** * @var string */ @@ -134,13 +133,13 @@ class Twitch extends OAuth2 /** * Check if the OAuth email is verified - * + * * If present, the email is verified - * + * * @link https://dev.twitch.tv/docs/api/reference#get-users - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Twitter.php b/src/Appwrite/Auth/OAuth2/Twitter.php deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/Appwrite/Auth/OAuth2/WordPress.php b/src/Appwrite/Auth/OAuth2/WordPress.php index 6c1aade1de..1bd55916fc 100644 --- a/src/Appwrite/Auth/OAuth2/WordPress.php +++ b/src/Appwrite/Auth/OAuth2/WordPress.php @@ -129,11 +129,11 @@ class WordPress extends OAuth2 /** * Check if the OAuth email is verified - * + * * @link https://developer.wordpress.com/docs/api/1.1/get/me/ - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Yahoo.php b/src/Appwrite/Auth/OAuth2/Yahoo.php index d8abbbfd69..c70a2fb6c9 100644 --- a/src/Appwrite/Auth/OAuth2/Yahoo.php +++ b/src/Appwrite/Auth/OAuth2/Yahoo.php @@ -9,7 +9,6 @@ use Appwrite\Auth\OAuth2; class Yahoo extends OAuth2 { - /** * @var string */ @@ -155,11 +154,11 @@ class Yahoo extends OAuth2 /** * Check if the OAuth email is verified - * + * * If present, the email is verified. This was verfied through a manual Yahoo sign up process - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Yammer.php b/src/Appwrite/Auth/OAuth2/Yammer.php index 80bd44b244..9e1827bc58 100644 --- a/src/Appwrite/Auth/OAuth2/Yammer.php +++ b/src/Appwrite/Auth/OAuth2/Yammer.php @@ -124,11 +124,11 @@ class Yammer extends OAuth2 /** * Check if the OAuth email is verified - * + * * If present, the email is verified. This was verfied through a manual Yammer sign up process - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Yandex.php b/src/Appwrite/Auth/OAuth2/Yandex.php index efab408275..a6a2e2e550 100644 --- a/src/Appwrite/Auth/OAuth2/Yandex.php +++ b/src/Appwrite/Auth/OAuth2/Yandex.php @@ -138,9 +138,9 @@ class Yandex extends OAuth2 /** * Check if the OAuth email is verified - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/OAuth2/Zoom.php b/src/Appwrite/Auth/OAuth2/Zoom.php index ee4185934c..9dad22212a 100644 --- a/src/Appwrite/Auth/OAuth2/Zoom.php +++ b/src/Appwrite/Auth/OAuth2/Zoom.php @@ -30,7 +30,7 @@ class Zoom extends OAuth2 * @var array */ protected array $scopes = [ - 'user_profile' + 'user_info:read' ]; /** @@ -130,11 +130,11 @@ class Zoom extends OAuth2 /** * Check if the OAuth email is verified - * + * * @link https://marketplace.zoom.us/docs/api-reference/zoom-api/methods/#operation/user - * + * * @param string $accessToken - * + * * @return bool */ public function isEmailVerified(string $accessToken): bool diff --git a/src/Appwrite/Auth/Validator/Password.php b/src/Appwrite/Auth/Validator/Password.php index 3e9bb6fbfc..93a9f74114 100644 --- a/src/Appwrite/Auth/Validator/Password.php +++ b/src/Appwrite/Auth/Validator/Password.php @@ -34,7 +34,7 @@ class Password extends Validator { if (!\is_string($value)) { return false; - } + } if (\strlen($value) < 8) { return false; diff --git a/src/Appwrite/Docker/Compose.php b/src/Appwrite/Docker/Compose.php index e5c6a81712..64441805de 100644 --- a/src/Appwrite/Docker/Compose.php +++ b/src/Appwrite/Docker/Compose.php @@ -21,7 +21,7 @@ class Compose $this->compose['services'] = (isset($this->compose['services']) && is_array($this->compose['services'])) ? $this->compose['services'] : []; - + foreach ($this->compose['services'] as $key => &$service) { $service = new Service($service); } diff --git a/src/Appwrite/Docker/Compose/Service.php b/src/Appwrite/Docker/Compose/Service.php index 66aae8b740..a3f9c91253 100644 --- a/src/Appwrite/Docker/Compose/Service.php +++ b/src/Appwrite/Docker/Compose/Service.php @@ -17,7 +17,7 @@ class Service public function __construct(array $service) { $this->service = $service; - + $ports = (isset($this->service['ports']) && is_array($this->service['ports'])) ? $this->service['ports'] : []; $this->service['ports'] = []; @@ -54,7 +54,7 @@ class Service public function getImageVersion(): string { $image = $this->getImage(); - return substr($image, ((int)strpos($image, ':'))+1); + return substr($image, ((int)strpos($image, ':')) + 1); } /** diff --git a/src/Appwrite/Docker/Env.php b/src/Appwrite/Docker/Env.php index 07966edb34..19979eb0ce 100644 --- a/src/Appwrite/Docker/Env.php +++ b/src/Appwrite/Docker/Env.php @@ -70,7 +70,7 @@ class Env $output = ''; foreach ($this->vars as $key => $value) { - $output .= $key.'='.$value."\n"; + $output .= $key . '=' . $value . "\n"; } return $output; diff --git a/src/Appwrite/Event/Audit.php b/src/Appwrite/Event/Audit.php index b2d34424ea..4df3eeec62 100644 --- a/src/Appwrite/Event/Audit.php +++ b/src/Appwrite/Event/Audit.php @@ -127,4 +127,4 @@ class Audit extends Event 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) ]); } -} \ No newline at end of file +} diff --git a/src/Appwrite/Event/Build.php b/src/Appwrite/Event/Build.php index 970de82653..4d4b338118 100644 --- a/src/Appwrite/Event/Build.php +++ b/src/Appwrite/Event/Build.php @@ -32,7 +32,7 @@ class Build extends Event /** * Returns set resource document for the build event. * - * @return null|Document + * @return null|Document */ public function getResource(): ?Document { diff --git a/src/Appwrite/Event/Database.php b/src/Appwrite/Event/Database.php index 5e5e687857..2f182897b0 100644 --- a/src/Appwrite/Event/Database.php +++ b/src/Appwrite/Event/Database.php @@ -31,7 +31,7 @@ class Database extends Event /** * Returns the set type for the database event. - * @return string + * @return string */ public function getType(): string { @@ -100,4 +100,4 @@ class Database extends Event 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) ]); } -} \ No newline at end of file +} diff --git a/src/Appwrite/Event/Delete.php b/src/Appwrite/Event/Delete.php index 1c2be4b013..057abe17f7 100644 --- a/src/Appwrite/Event/Delete.php +++ b/src/Appwrite/Event/Delete.php @@ -34,7 +34,7 @@ class Delete extends Event /** * Returns the set type for the delete event. * - * @return string + * @return string */ public function getType(): string { diff --git a/src/Appwrite/Event/Event.php b/src/Appwrite/Event/Event.php index 3b6c754e61..629a058fed 100644 --- a/src/Appwrite/Event/Event.php +++ b/src/Appwrite/Event/Event.php @@ -8,29 +8,29 @@ use Utopia\Database\Document; class Event { - const DATABASE_QUEUE_NAME = 'v1-database'; - const DATABASE_CLASS_NAME = 'DatabaseV1'; + public const DATABASE_QUEUE_NAME = 'v1-database'; + public const DATABASE_CLASS_NAME = 'DatabaseV1'; - const DELETE_QUEUE_NAME = 'v1-deletes'; - const DELETE_CLASS_NAME = 'DeletesV1'; + public const DELETE_QUEUE_NAME = 'v1-deletes'; + public const DELETE_CLASS_NAME = 'DeletesV1'; - const AUDITS_QUEUE_NAME = 'v1-audits'; - const AUDITS_CLASS_NAME = 'AuditsV1'; + public const AUDITS_QUEUE_NAME = 'v1-audits'; + public const AUDITS_CLASS_NAME = 'AuditsV1'; - const MAILS_QUEUE_NAME = 'v1-mails'; - const MAILS_CLASS_NAME = 'MailsV1'; + public const MAILS_QUEUE_NAME = 'v1-mails'; + public const MAILS_CLASS_NAME = 'MailsV1'; - const FUNCTIONS_QUEUE_NAME = 'v1-functions'; - const FUNCTIONS_CLASS_NAME = 'FunctionsV1'; + public const FUNCTIONS_QUEUE_NAME = 'v1-functions'; + public const FUNCTIONS_CLASS_NAME = 'FunctionsV1'; - const WEBHOOK_QUEUE_NAME = 'v1-webhooks'; - const WEBHOOK_CLASS_NAME = 'WebhooksV1'; + public const WEBHOOK_QUEUE_NAME = 'v1-webhooks'; + public const WEBHOOK_CLASS_NAME = 'WebhooksV1'; - const CERTIFICATES_QUEUE_NAME = 'v1-certificates'; - const CERTIFICATES_CLASS_NAME = 'CertificatesV1'; + public const CERTIFICATES_QUEUE_NAME = 'v1-certificates'; + public const CERTIFICATES_CLASS_NAME = 'CertificatesV1'; - const BUILDS_QUEUE_NAME = 'v1-builds'; - const BUILDS_CLASS_NAME = 'BuildsV1'; + public const BUILDS_QUEUE_NAME = 'v1-builds'; + public const BUILDS_CLASS_NAME = 'BuildsV1'; protected string $queue = ''; protected string $class = ''; @@ -332,7 +332,7 @@ class Event * @return array * @throws \InvalidArgumentException */ - static function generateEvents(string $pattern, array $params = []): array + public static function generateEvents(string $pattern, array $params = []): array { // $params = \array_filter($params, fn($param) => !\is_array($param)); $paramKeys = \array_keys($params); @@ -392,7 +392,9 @@ class Event $events[] = \str_replace($paramKeys, '*', $eventPattern); foreach ($paramKeys as $key) { foreach ($paramKeys as $current) { - if ($current === $key) continue; + if ($current === $key) { + continue; + } $filtered = \array_filter($paramKeys, fn(string $k) => $k === $current); $events[] = \str_replace($paramKeys, $paramValues, \str_replace($filtered, '*', $eventPattern)); diff --git a/src/Appwrite/Event/Func.php b/src/Appwrite/Event/Func.php index 98652431f0..b7531cf475 100644 --- a/src/Appwrite/Event/Func.php +++ b/src/Appwrite/Event/Func.php @@ -36,7 +36,7 @@ class Func extends Event /** * Returns set function document for the function event. * - * @return null|Document + * @return null|Document */ public function getFunction(): ?Document { diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 95c51ed991..62695742f0 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -6,10 +6,10 @@ class Exception extends \Exception { /** * Error Codes - * - * Naming the error types based on the following convention + * + * Naming the error types based on the following convention * _ - * + * * Appwrite has the follwing entities: * - General * - Users @@ -32,135 +32,135 @@ class Exception extends \Exception */ /** General */ - const GENERAL_UNKNOWN = 'general_unknown'; - const GENERAL_MOCK = 'general_mock'; - const GENERAL_ACCESS_FORBIDDEN = 'general_access_forbidden'; - const GENERAL_UNKNOWN_ORIGIN = 'general_unknown_origin'; - const GENERAL_SERVICE_DISABLED = 'general_service_disabled'; - const GENERAL_UNAUTHORIZED_SCOPE = 'general_unauthorized_scope'; - const GENERAL_RATE_LIMIT_EXCEEDED = 'general_rate_limit_exceeded'; - const GENERAL_SMTP_DISABLED = 'general_smtp_disabled'; - const GENERAL_ARGUMENT_INVALID = 'general_argument_invalid'; - const GENERAL_QUERY_LIMIT_EXCEEDED = 'general_query_limit_exceeded'; - const GENERAL_QUERY_INVALID = 'general_query_invalid'; - const GENERAL_ROUTE_NOT_FOUND = 'general_route_not_found'; - const GENERAL_CURSOR_NOT_FOUND = 'general_cursor_not_found'; - const GENERAL_SERVER_ERROR = 'general_server_error'; - const GENERAL_PROTOCOL_UNSUPPORTED = 'general_protocol_unsupported'; + public const GENERAL_UNKNOWN = 'general_unknown'; + public const GENERAL_MOCK = 'general_mock'; + public const GENERAL_ACCESS_FORBIDDEN = 'general_access_forbidden'; + public const GENERAL_UNKNOWN_ORIGIN = 'general_unknown_origin'; + public const GENERAL_SERVICE_DISABLED = 'general_service_disabled'; + public const GENERAL_UNAUTHORIZED_SCOPE = 'general_unauthorized_scope'; + public const GENERAL_RATE_LIMIT_EXCEEDED = 'general_rate_limit_exceeded'; + public const GENERAL_SMTP_DISABLED = 'general_smtp_disabled'; + public const GENERAL_ARGUMENT_INVALID = 'general_argument_invalid'; + public const GENERAL_QUERY_LIMIT_EXCEEDED = 'general_query_limit_exceeded'; + public const GENERAL_QUERY_INVALID = 'general_query_invalid'; + public const GENERAL_ROUTE_NOT_FOUND = 'general_route_not_found'; + public const GENERAL_CURSOR_NOT_FOUND = 'general_cursor_not_found'; + public const GENERAL_SERVER_ERROR = 'general_server_error'; + public const GENERAL_PROTOCOL_UNSUPPORTED = 'general_protocol_unsupported'; /** Users */ - const USER_COUNT_EXCEEDED = 'user_count_exceeded'; - const USER_JWT_INVALID = 'user_jwt_invalid'; - const USER_ALREADY_EXISTS = 'user_already_exists'; - const USER_BLOCKED = 'user_blocked'; - const USER_INVALID_TOKEN = 'user_invalid_token'; - const USER_PASSWORD_RESET_REQUIRED = 'user_password_reset_required'; - const USER_EMAIL_NOT_WHITELISTED = 'user_email_not_whitelisted'; - const USER_IP_NOT_WHITELISTED = 'user_ip_not_whitelisted'; - const USER_INVALID_CREDENTIALS = 'user_invalid_credentials'; - const USER_ANONYMOUS_CONSOLE_PROHIBITED = 'user_anonymous_console_prohibited'; - const USER_SESSION_ALREADY_EXISTS = 'user_session_already_exists'; - const USER_NOT_FOUND = 'user_not_found'; - const USER_EMAIL_ALREADY_EXISTS = 'user_email_already_exists'; - const USER_PASSWORD_MISMATCH = 'user_password_mismatch'; - const USER_SESSION_NOT_FOUND = 'user_session_not_found'; - const USER_UNAUTHORIZED = 'user_unauthorized'; - const USER_AUTH_METHOD_UNSUPPORTED = 'user_auth_method_unsupported'; + public const USER_COUNT_EXCEEDED = 'user_count_exceeded'; + public const USER_JWT_INVALID = 'user_jwt_invalid'; + public const USER_ALREADY_EXISTS = 'user_already_exists'; + public const USER_BLOCKED = 'user_blocked'; + public const USER_INVALID_TOKEN = 'user_invalid_token'; + public const USER_PASSWORD_RESET_REQUIRED = 'user_password_reset_required'; + public const USER_EMAIL_NOT_WHITELISTED = 'user_email_not_whitelisted'; + public const USER_IP_NOT_WHITELISTED = 'user_ip_not_whitelisted'; + public const USER_INVALID_CREDENTIALS = 'user_invalid_credentials'; + public const USER_ANONYMOUS_CONSOLE_PROHIBITED = 'user_anonymous_console_prohibited'; + public const USER_SESSION_ALREADY_EXISTS = 'user_session_already_exists'; + public const USER_NOT_FOUND = 'user_not_found'; + public const USER_EMAIL_ALREADY_EXISTS = 'user_email_already_exists'; + public const USER_PASSWORD_MISMATCH = 'user_password_mismatch'; + public const USER_SESSION_NOT_FOUND = 'user_session_not_found'; + public const USER_UNAUTHORIZED = 'user_unauthorized'; + public const USER_AUTH_METHOD_UNSUPPORTED = 'user_auth_method_unsupported'; /** Teams */ - const TEAM_NOT_FOUND = 'team_not_found'; - const TEAM_INVITE_ALREADY_EXISTS = 'team_invite_already_exists'; - const TEAM_INVITE_NOT_FOUND = 'team_invite_not_found'; - const TEAM_INVALID_SECRET = 'team_invalid_secret'; - const TEAM_MEMBERSHIP_MISMATCH = 'team_membership_mismatch'; - const TEAM_INVITE_MISMATCH = 'team_invite_mismatch'; + public const TEAM_NOT_FOUND = 'team_not_found'; + public const TEAM_INVITE_ALREADY_EXISTS = 'team_invite_already_exists'; + public const TEAM_INVITE_NOT_FOUND = 'team_invite_not_found'; + public const TEAM_INVALID_SECRET = 'team_invalid_secret'; + public const TEAM_MEMBERSHIP_MISMATCH = 'team_membership_mismatch'; + public const TEAM_INVITE_MISMATCH = 'team_invite_mismatch'; /** Membership */ - const MEMBERSHIP_NOT_FOUND = 'membership_not_found'; + public const MEMBERSHIP_NOT_FOUND = 'membership_not_found'; /** Avatars */ - const AVATAR_SET_NOT_FOUND = 'avatar_set_not_found'; - const AVATAR_NOT_FOUND = 'avatar_not_found'; - const AVATAR_IMAGE_NOT_FOUND = 'avatar_image_not_found'; - const AVATAR_REMOTE_URL_FAILED = 'avatar_remote_url_failed'; - const AVATAR_ICON_NOT_FOUND = 'avatar_icon_not_found'; + public const AVATAR_SET_NOT_FOUND = 'avatar_set_not_found'; + public const AVATAR_NOT_FOUND = 'avatar_not_found'; + public const AVATAR_IMAGE_NOT_FOUND = 'avatar_image_not_found'; + public const AVATAR_REMOTE_URL_FAILED = 'avatar_remote_url_failed'; + public const AVATAR_ICON_NOT_FOUND = 'avatar_icon_not_found'; /** Storage */ - const STORAGE_FILE_NOT_FOUND = 'storage_file_not_found'; - const STORAGE_DEVICE_NOT_FOUND = 'storage_device_not_found'; - const STORAGE_FILE_EMPTY = 'storage_file_empty'; - const STORAGE_FILE_TYPE_UNSUPPORTED = 'storage_file_type_unsupported'; - const STORAGE_INVALID_FILE_SIZE = 'storage_invalid_file_size'; - const STORAGE_INVALID_FILE = 'storage_invalid_file'; - const STORAGE_BUCKET_ALREADY_EXISTS = 'storage_bucket_already_exists'; - const STORAGE_BUCKET_NOT_FOUND = 'storage_bucket_not_found'; - const STORAGE_INVALID_CONTENT_RANGE = 'storage_invalid_content_range'; - const STORAGE_INVALID_RANGE = 'storage_invalid_range'; + public const STORAGE_FILE_NOT_FOUND = 'storage_file_not_found'; + public const STORAGE_DEVICE_NOT_FOUND = 'storage_device_not_found'; + public const STORAGE_FILE_EMPTY = 'storage_file_empty'; + public const STORAGE_FILE_TYPE_UNSUPPORTED = 'storage_file_type_unsupported'; + public const STORAGE_INVALID_FILE_SIZE = 'storage_invalid_file_size'; + public const STORAGE_INVALID_FILE = 'storage_invalid_file'; + public const STORAGE_BUCKET_ALREADY_EXISTS = 'storage_bucket_already_exists'; + public const STORAGE_BUCKET_NOT_FOUND = 'storage_bucket_not_found'; + public const STORAGE_INVALID_CONTENT_RANGE = 'storage_invalid_content_range'; + public const STORAGE_INVALID_RANGE = 'storage_invalid_range'; /** Functions */ - const FUNCTION_NOT_FOUND = 'function_not_found'; - const FUNCTION_RUNTIME_UNSUPPORTED = 'function_runtime_unsupported'; + public const FUNCTION_NOT_FOUND = 'function_not_found'; + public const FUNCTION_RUNTIME_UNSUPPORTED = 'function_runtime_unsupported'; /** Deployments */ - const DEPLOYMENT_NOT_FOUND = 'deployment_not_found'; + public const DEPLOYMENT_NOT_FOUND = 'deployment_not_found'; /** Builds */ - const BUILD_NOT_FOUND = 'build_not_found'; - const BUILD_NOT_READY = 'build_not_ready'; - const BUILD_IN_PROGRESS = 'build_in_progress'; + public const BUILD_NOT_FOUND = 'build_not_found'; + public const BUILD_NOT_READY = 'build_not_ready'; + public const BUILD_IN_PROGRESS = 'build_in_progress'; /** Execution */ - const EXECUTION_NOT_FOUND = 'execution_not_found'; + public const EXECUTION_NOT_FOUND = 'execution_not_found'; /** Collections */ - const COLLECTION_NOT_FOUND = 'collection_not_found'; - const COLLECTION_ALREADY_EXISTS = 'collection_already_exists'; - const COLLECTION_LIMIT_EXCEEDED = 'collection_limit_exceeded'; - + public const COLLECTION_NOT_FOUND = 'collection_not_found'; + public const COLLECTION_ALREADY_EXISTS = 'collection_already_exists'; + public const COLLECTION_LIMIT_EXCEEDED = 'collection_limit_exceeded'; + /** Documents */ - const DOCUMENT_NOT_FOUND = 'document_not_found'; - const DOCUMENT_INVALID_STRUCTURE = 'document_invalid_structure'; - const DOCUMENT_MISSING_PAYLOAD = 'document_missing_payload'; - const DOCUMENT_ALREADY_EXISTS = 'document_already_exists'; + public const DOCUMENT_NOT_FOUND = 'document_not_found'; + public const DOCUMENT_INVALID_STRUCTURE = 'document_invalid_structure'; + public const DOCUMENT_MISSING_PAYLOAD = 'document_missing_payload'; + public const DOCUMENT_ALREADY_EXISTS = 'document_already_exists'; /** Attribute */ - const ATTRIBUTE_NOT_FOUND = 'attribute_not_found'; - const ATTRIBUTE_UNKNOWN = 'attribute_unknown'; - const ATTRIBUTE_NOT_AVAILABLE = 'attribute_not_available'; - const ATTRIBUTE_FORMAT_UNSUPPORTED = 'attribute_format_unsupported'; - const ATTRIBUTE_DEFAULT_UNSUPPORTED = 'attribute_default_unsupported'; - const ATTRIBUTE_ALREADY_EXISTS = 'attribute_already_exists'; - const ATTRIBUTE_LIMIT_EXCEEDED = 'attribute_limit_exceeded'; - const ATTRIBUTE_VALUE_INVALID = 'attribute_value_invalid'; + public const ATTRIBUTE_NOT_FOUND = 'attribute_not_found'; + public const ATTRIBUTE_UNKNOWN = 'attribute_unknown'; + public const ATTRIBUTE_NOT_AVAILABLE = 'attribute_not_available'; + public const ATTRIBUTE_FORMAT_UNSUPPORTED = 'attribute_format_unsupported'; + public const ATTRIBUTE_DEFAULT_UNSUPPORTED = 'attribute_default_unsupported'; + public const ATTRIBUTE_ALREADY_EXISTS = 'attribute_already_exists'; + public const ATTRIBUTE_LIMIT_EXCEEDED = 'attribute_limit_exceeded'; + public const ATTRIBUTE_VALUE_INVALID = 'attribute_value_invalid'; /** Indexes */ - const INDEX_NOT_FOUND = 'index_not_found'; - const INDEX_LIMIT_EXCEEDED = 'index_limit_exceeded'; - const INDEX_ALREADY_EXISTS = 'index_already_exists'; + public const INDEX_NOT_FOUND = 'index_not_found'; + public const INDEX_LIMIT_EXCEEDED = 'index_limit_exceeded'; + public const INDEX_ALREADY_EXISTS = 'index_already_exists'; /** Projects */ - const PROJECT_NOT_FOUND = 'project_not_found'; - const PROJECT_UNKNOWN = 'project_unknown'; - const PROJECT_PROVIDER_DISABLED = 'project_provider_disabled'; - const PROJECT_PROVIDER_UNSUPPORTED = 'project_provider_unsupported'; - const PROJECT_INVALID_SUCCESS_URL = 'project_invalid_success_url'; - const PROJECT_INVALID_FAILURE_URL = 'project_invalid_failure_url'; - const PROJECT_MISSING_USER_ID = 'project_missing_user_id'; - const PROJECT_RESERVED_PROJECT = 'project_reserved_project'; + public const PROJECT_NOT_FOUND = 'project_not_found'; + public const PROJECT_UNKNOWN = 'project_unknown'; + public const PROJECT_PROVIDER_DISABLED = 'project_provider_disabled'; + public const PROJECT_PROVIDER_UNSUPPORTED = 'project_provider_unsupported'; + public const PROJECT_INVALID_SUCCESS_URL = 'project_invalid_success_url'; + public const PROJECT_INVALID_FAILURE_URL = 'project_invalid_failure_url'; + public const PROJECT_MISSING_USER_ID = 'project_missing_user_id'; + public const PROJECT_RESERVED_PROJECT = 'project_reserved_project'; /** Webhooks */ - const WEBHOOK_NOT_FOUND = 'webhook_not_found'; + public const WEBHOOK_NOT_FOUND = 'webhook_not_found'; /** Keys */ - const KEY_NOT_FOUND = 'key_not_found'; + public const KEY_NOT_FOUND = 'key_not_found'; /** Platform */ - const PLATFORM_NOT_FOUND = 'platform_not_found'; + public const PLATFORM_NOT_FOUND = 'platform_not_found'; /** Domain */ - const DOMAIN_NOT_FOUND = 'domain_not_found'; - const DOMAIN_ALREADY_EXISTS = 'domain_already_exists'; - const DOMAIN_VERIFICATION_FAILED = 'domain_verification_failed'; + public const DOMAIN_NOT_FOUND = 'domain_not_found'; + public const DOMAIN_ALREADY_EXISTS = 'domain_already_exists'; + public const DOMAIN_VERIFICATION_FAILED = 'domain_verification_failed'; private $type = ''; @@ -174,9 +174,9 @@ class Exception extends \Exception /** * Get the type of the exception. - * + * * @return string - */ + */ public function getType(): string { return $this->type; @@ -184,14 +184,13 @@ class Exception extends \Exception /** * Set the type of the exception. - * + * * @param string $type - * + * * @return void */ public function setType(string $type): void { $this->type = $type; } - -} \ No newline at end of file +} diff --git a/src/Appwrite/Extend/PDO.php b/src/Appwrite/Extend/PDO.php index bdaac3f435..bc3f42afb9 100644 --- a/src/Appwrite/Extend/PDO.php +++ b/src/Appwrite/Extend/PDO.php @@ -99,8 +99,8 @@ class PDO extends PDONative { $this->pdo = new PDONative($this->dsn, $this->username, $this->passwd, $this->options); - echo '[PDO] MySQL connection restarted'.PHP_EOL; - + echo '[PDO] MySQL connection restarted' . PHP_EOL; + // Connection settings $this->pdo->setAttribute(PDONative::ATTR_DEFAULT_FETCH_MODE, PDONative::FETCH_ASSOC); // Return arrays $this->pdo->setAttribute(PDONative::ATTR_ERRMODE, PDONative::ERRMODE_EXCEPTION); // Handle all errors with exceptions diff --git a/src/Appwrite/Extend/PDOStatement.php b/src/Appwrite/Extend/PDOStatement.php index 3dc7a4aa1d..9c5a83ec34 100644 --- a/src/Appwrite/Extend/PDOStatement.php +++ b/src/Appwrite/Extend/PDOStatement.php @@ -76,7 +76,7 @@ class PDOStatement extends PDOStatementNative foreach ($this->values as $key => $set) { $this->PDOStatement->bindValue($key, $set['value'], $set['data_type']); } - + foreach ($this->params as $key => $set) { $this->PDOStatement->bindParam($key, $set['variable'], $set['data_type'], $set['length'], $set['driver_options']); } @@ -109,7 +109,7 @@ class PDOStatement extends PDOStatementNative public function fetchAll(int $fetch_style = PDO::FETCH_BOTH, mixed ...$fetch_args) { $result = $this->PDOStatement->fetchAll(); - + return $result; } } diff --git a/src/Appwrite/Messaging/Adapter.php b/src/Appwrite/Messaging/Adapter.php index 1910847245..27dd7f68eb 100644 --- a/src/Appwrite/Messaging/Adapter.php +++ b/src/Appwrite/Messaging/Adapter.php @@ -4,7 +4,7 @@ namespace Appwrite\Messaging; abstract class Adapter { - public abstract function subscribe(string $projectId, mixed $identifier, array $roles, array $channels): void; - public abstract function unsubscribe(mixed $identifier): void; - public static abstract function send(string $projectId, array $payload, array $events, array $channels, array $roles, array $options): void; + abstract public function subscribe(string $projectId, mixed $identifier, array $roles, array $channels): void; + abstract public function unsubscribe(mixed $identifier): void; + abstract public static function send(string $projectId, array $payload, array $events, array $channels, array $roles, array $options): void; } diff --git a/src/Appwrite/Messaging/Adapter/Realtime.php b/src/Appwrite/Messaging/Adapter/Realtime.php index ad38444cbe..853e804d9a 100644 --- a/src/Appwrite/Messaging/Adapter/Realtime.php +++ b/src/Appwrite/Messaging/Adapter/Realtime.php @@ -10,7 +10,7 @@ class Realtime extends Adapter { /** * Connection Tree - * + * * [CONNECTION_ID] -> * 'projectId' -> [PROJECT_ID] * 'roles' -> [ROLE_x, ROLE_Y] @@ -67,7 +67,7 @@ class Realtime extends Adapter /** * Removes Subscription. - * + * * @param mixed $connection * @return void */ @@ -129,7 +129,9 @@ class Realtime extends Adapter */ public static function send(string $projectId, array $payload, array $events, array $channels, array $roles, array $options = []): void { - if (empty($channels) || empty($roles) || empty($projectId)) return; + if (empty($channels) || empty($roles) || empty($projectId)) { + return; + } $permissionsChanged = array_key_exists('permissionsChanged', $options) && $options['permissionsChanged']; $userId = array_key_exists('userId', $options) ? $options['userId'] : null; @@ -154,12 +156,12 @@ class Realtime extends Adapter * Identifies the receivers of all subscriptions, based on the permissions and event. * * Example of performance with an event with user:XXX permissions and with X users spread across 10 different channels: - * - 0.014 ms (ยฑ6.88%) | 10 Connections / 100 Subscriptions - * - 0.070 ms (ยฑ3.71%) | 100 Connections / 1,000 Subscriptions + * - 0.014 ms (ยฑ6.88%) | 10 Connections / 100 Subscriptions + * - 0.070 ms (ยฑ3.71%) | 100 Connections / 1,000 Subscriptions * - 0.846 ms (ยฑ2.74%) | 1,000 Connections / 10,000 Subscriptions * - 10.866 ms (ยฑ1.01%) | 10,000 Connections / 100,000 Subscriptions * - 110.201 ms (ยฑ2.32%) | 100,000 Connections / 1,000,000 Subscriptions - * - 1,121.328 ms (ยฑ0.84%) | 1,000,000 Connections / 10,000,000 Subscriptions + * - 1,121.328 ms (ยฑ0.84%) | 1,000,000 Connections / 10,000,000 Subscriptions * * @param array $event */ @@ -209,7 +211,7 @@ class Realtime extends Adapter * Also renames the account channel to account.USER_ID and removes all illegal account channel variations. * @param array $channels * @param string $userId - * @return array + * @return array */ public static function convertChannels(array $channels, string $userId): array { @@ -238,7 +240,7 @@ class Realtime extends Adapter * @param string $event * @param Document $payload * @param Document|null $project - * @return array + * @return array */ public static function fromPayload(string $event, Document $payload, Document $project = null, Document $collection = null, Document $bucket = null): array { diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index b479a42262..51df96b63b 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -44,6 +44,7 @@ abstract class Migration '0.13.4' => 'V12', '0.14.0' => 'V13', '0.14.1' => 'V13', + '0.14.2' => 'V13', ]; /** @@ -101,7 +102,9 @@ abstract class Migration Runtime::enableCoroutine(SWOOLE_HOOK_ALL); foreach ($this->collections as $collection) { - if ($collection['$collection'] !== Database::METADATA) return; + if ($collection['$collection'] !== Database::METADATA) { + return; + } $sum = 0; $nextDocument = null; $collectionCount = $this->projectDB->count($collection['$id']); @@ -124,21 +127,7 @@ abstract class Migration $old = $document->getArrayCopy(); $new = call_user_func($callback, $document); - foreach ($document as &$attr) { - if ($attr instanceof Document) { - $attr = call_user_func($callback, $attr); - } - - if (\is_array($attr)) { - foreach ($attr as &$child) { - if ($child instanceof Document) { - $child = call_user_func($callback, $child); - } - } - } - } - - if (!$this->check_diff_multi($new->getArrayCopy(), $old)) { + if (!self::hasDifference($new->getArrayCopy(), $old)) { return; } @@ -167,35 +156,28 @@ abstract class Migration /** * Checks 2 arrays for differences. - * - * @param array $array1 - * @param array $array2 - * @return array + * + * @param array $array1 + * @param array $array2 + * @return bool */ - public function check_diff_multi(array $array1, array $array2): array + public static function hasDifference(array $array1, array $array2): bool { - $result = array(); - - foreach ($array1 as $key => $val) { - if (is_array($val) && isset($array2[$key])) { - $tmp = $this->check_diff_multi($val, $array2[$key]); - if ($tmp) { - $result[$key] = $tmp; + foreach ($array1 as $key => $value) { + if (is_array($value)) { + if (!isset($array2[$key]) || !is_array($array2[$key])) { + return true; + } else { + if (self::hasDifference($value, $array2[$key])) { + return true; + } } - } elseif (!isset($array2[$key])) { - $result[$key] = null; - } elseif ($val !== $array2[$key]) { - $result[$key] = $array2[$key]; - } - - if (isset($array2[$key])) { - unset($array2[$key]); + } elseif (!array_key_exists($key, $array2) || $array2[$key] !== $value) { + return true; } } - $result = array_merge($result, $array2); - - return $result; + return false; } /** diff --git a/src/Appwrite/Migration/Version/V12.php b/src/Appwrite/Migration/Version/V12.php index 6b8e88c7d6..78d6407519 100644 --- a/src/Appwrite/Migration/Version/V12.php +++ b/src/Appwrite/Migration/Version/V12.php @@ -300,11 +300,11 @@ class V12 extends Migration /** * Migrates permissions to dedicated table. * - * @param \Utopia\Database\Document $document - * @param string $internalId - * @return void - * @throws \Exception - * @throws \PDOException + * @param \Utopia\Database\Document $document + * @param string $internalId + * @return void + * @throws \Exception + * @throws \PDOException */ protected function migratePermissionsToDedicatedTable(string $collection, Document $document): void { @@ -499,8 +499,8 @@ class V12 extends Migration /** * Fix run on each document * - * @param \Utopia\Database\Document $document - * @return \Utopia\Database\Document + * @param \Utopia\Database\Document $document + * @return \Utopia\Database\Document */ protected function fixDocument(Document $document) { diff --git a/src/Appwrite/Migration/Version/V13.php b/src/Appwrite/Migration/Version/V13.php index 5c5ad08e8e..d204be84f3 100644 --- a/src/Appwrite/Migration/Version/V13.php +++ b/src/Appwrite/Migration/Version/V13.php @@ -223,8 +223,8 @@ class V13 extends Migration /** * Fix run on each document * - * @param \Utopia\Database\Document $document - * @return \Utopia\Database\Document + * @param \Utopia\Database\Document $document + * @return \Utopia\Database\Document */ protected function fixDocument(Document $document) { @@ -273,7 +273,9 @@ class V13 extends Migration public function migrateEvents(array $events): array { return array_filter(array_unique(array_map(function ($event) { - if (!in_array($event, $this->events)) return $event; + if (!in_array($event, $this->events)) { + return $event; + } $parts = \explode('.', $event); $first = array_shift($parts); switch ($first) { @@ -317,7 +319,7 @@ class V13 extends Migration return 'buckets.*.' . implode('.', $parts); case 'files': return 'buckets.*.' . $second . '.*.' . implode('.', $parts); - } + } // intentional fallthrough case 'database': $second = array_shift($parts); switch ($second) { diff --git a/src/Appwrite/Network/Validator/IP.php b/src/Appwrite/Network/Validator/IP.php index c9b50fe3ca..0245d59d3e 100644 --- a/src/Appwrite/Network/Validator/IP.php +++ b/src/Appwrite/Network/Validator/IP.php @@ -66,7 +66,7 @@ class IP extends Validator if (\filter_var($value, FILTER_VALIDATE_IP)) { return true; } - break; + break; case self::V4: if (\filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { diff --git a/src/Appwrite/Network/Validator/Origin.php b/src/Appwrite/Network/Validator/Origin.php index 30efe50c4c..9ee30a26ad 100644 --- a/src/Appwrite/Network/Validator/Origin.php +++ b/src/Appwrite/Network/Validator/Origin.php @@ -95,8 +95,8 @@ class Origin extends Validator return 'Unsupported platform'; } - return 'Invalid Origin. Register your new client ('.$this->host.') as a new ' - .$this->platforms[$this->client].' platform on your project console dashboard'; + return 'Invalid Origin. Register your new client (' . $this->host . ') as a new ' + . $this->platforms[$this->client] . ' platform on your project console dashboard'; } /** @@ -124,7 +124,7 @@ class Origin extends Validator } $validator = new Hostname($this->clients); - + return $validator->isValid($host); } diff --git a/src/Appwrite/Resque/Worker.php b/src/Appwrite/Resque/Worker.php index 88489b5412..84feb0f961 100644 --- a/src/Appwrite/Resque/Worker.php +++ b/src/Appwrite/Resque/Worker.php @@ -12,8 +12,10 @@ use Utopia\Storage\Device; use Utopia\Storage\Storage; use Utopia\Storage\Device\Local; use Utopia\Storage\Device\DOSpaces; +use Utopia\Storage\Device\Linode; +use Utopia\Storage\Device\Wasabi; +use Utopia\Storage\Device\Backblaze; use Utopia\Storage\Device\S3; - use Exception; abstract class Worker @@ -23,7 +25,7 @@ abstract class Worker * * @var array */ - static protected array $errorCallbacks = []; + protected static array $errorCallbacks = []; /** * Associative array holding all information passed into the worker @@ -50,7 +52,8 @@ abstract class Worker * @return void * @throws \Exception|\Throwable */ - public function init() { + public function init() + { throw new Exception("Please implement init method in worker"); } @@ -61,7 +64,8 @@ abstract class Worker * @return void * @throws \Exception|\Throwable */ - public function run() { + public function run() + { throw new Exception("Please implement run method in worker"); } @@ -72,12 +76,13 @@ abstract class Worker * @return void * @throws \Exception|\Throwable */ - public function shutdown() { + public function shutdown() + { throw new Exception("Please implement shutdown method in worker"); } - const DATABASE_PROJECT = 'project'; - const DATABASE_CONSOLE = 'console'; + public const DATABASE_PROJECT = 'project'; + public const DATABASE_CONSOLE = 'console'; /** * A wrapper around 'init' function with non-worker-specific code @@ -89,7 +94,7 @@ abstract class Worker { try { $this->init(); - } catch(\Throwable $error) { + } catch (\Throwable $error) { foreach (self::$errorCallbacks as $errorCallback) { $errorCallback($error, "init", $this->getName()); } @@ -108,7 +113,7 @@ abstract class Worker { try { $this->run(); - } catch(\Throwable $error) { + } catch (\Throwable $error) { foreach (self::$errorCallbacks as $errorCallback) { $errorCallback($error, "run", $this->getName(), $this->args); } @@ -127,7 +132,7 @@ abstract class Worker { try { $this->shutdown(); - } catch(\Throwable $error) { + } catch (\Throwable $error) { foreach (self::$errorCallbacks as $errorCallback) { $errorCallback($error, "shutdown", $this->getName()); } @@ -214,10 +219,10 @@ abstract class Worker } break; // leave loop if successful - } catch(\Exception $e) { + } catch (\Exception $e) { Console::warning("Database not ready. Retrying connection ({$attempts})..."); if ($attempts >= DATABASE_RECONNECT_MAX_ATTEMPTS) { - throw new \Exception('Failed to connect to database: '. $e->getMessage()); + throw new \Exception('Failed to connect to database: ' . $e->getMessage()); } sleep($sleep); } @@ -231,7 +236,8 @@ abstract class Worker * @param string $projectId of the project * @return Device */ - protected function getFunctionsDevice($projectId): Device { + protected function getFunctionsDevice($projectId): Device + { return $this->getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $projectId); } @@ -240,7 +246,8 @@ abstract class Worker * @param string $projectId of the project * @return Device */ - protected function getFilesDevice($projectId): Device { + protected function getFilesDevice($projectId): Device + { return $this->getDevice(APP_STORAGE_UPLOADS . '/app-' . $projectId); } @@ -250,7 +257,8 @@ abstract class Worker * @param string $projectId of the project * @return Device */ - protected function getBuildsDevice($projectId): Device { + protected function getBuildsDevice($projectId): Device + { return $this->getDevice(APP_STORAGE_BUILDS . '/app-' . $projectId); } @@ -259,25 +267,47 @@ abstract class Worker * @param string $root path of the device * @return Device */ - private function getDevice($root): Device + public function getDevice($root): Device { switch (App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL)) { - case Storage::DEVICE_LOCAL:default: - return new Local($root); - case Storage::DEVICE_S3: - $s3AccessKey = App::getEnv('_APP_STORAGE_S3_ACCESS_KEY', ''); - $s3SecretKey = App::getEnv('_APP_STORAGE_S3_SECRET', ''); - $s3Region = App::getEnv('_APP_STORAGE_S3_REGION', ''); - $s3Bucket = App::getEnv('_APP_STORAGE_S3_BUCKET', ''); - $s3Acl = 'private'; - return new S3($root, $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl); - case Storage::DEVICE_DO_SPACES: - $doSpacesAccessKey = App::getEnv('_APP_STORAGE_DO_SPACES_ACCESS_KEY', ''); - $doSpacesSecretKey = App::getEnv('_APP_STORAGE_DO_SPACES_SECRET', ''); - $doSpacesRegion = App::getEnv('_APP_STORAGE_DO_SPACES_REGION', ''); - $doSpacesBucket = App::getEnv('_APP_STORAGE_DO_SPACES_BUCKET', ''); - $doSpacesAcl = 'private'; - return new DOSpaces($root, $doSpacesAccessKey, $doSpacesSecretKey, $doSpacesBucket, $doSpacesRegion, $doSpacesAcl); + case Storage::DEVICE_LOCAL: + default: + return new Local($root); + case Storage::DEVICE_S3: + $s3AccessKey = App::getEnv('_APP_STORAGE_S3_ACCESS_KEY', ''); + $s3SecretKey = App::getEnv('_APP_STORAGE_S3_SECRET', ''); + $s3Region = App::getEnv('_APP_STORAGE_S3_REGION', ''); + $s3Bucket = App::getEnv('_APP_STORAGE_S3_BUCKET', ''); + $s3Acl = 'private'; + return new S3($root, $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl); + case Storage::DEVICE_DO_SPACES: + $doSpacesAccessKey = App::getEnv('_APP_STORAGE_DO_SPACES_ACCESS_KEY', ''); + $doSpacesSecretKey = App::getEnv('_APP_STORAGE_DO_SPACES_SECRET', ''); + $doSpacesRegion = App::getEnv('_APP_STORAGE_DO_SPACES_REGION', ''); + $doSpacesBucket = App::getEnv('_APP_STORAGE_DO_SPACES_BUCKET', ''); + $doSpacesAcl = 'private'; + return new DOSpaces($root, $doSpacesAccessKey, $doSpacesSecretKey, $doSpacesBucket, $doSpacesRegion, $doSpacesAcl); + case Storage::DEVICE_BACKBLAZE: + $backblazeAccessKey = App::getEnv('_APP_STORAGE_BACKBLAZE_ACCESS_KEY', ''); + $backblazeSecretKey = App::getEnv('_APP_STORAGE_BACKBLAZE_SECRET', ''); + $backblazeRegion = App::getEnv('_APP_STORAGE_BACKBLAZE_REGION', ''); + $backblazeBucket = App::getEnv('_APP_STORAGE_BACKBLAZE_BUCKET', ''); + $backblazeAcl = 'private'; + return new Backblaze($root, $backblazeAccessKey, $backblazeSecretKey, $backblazeBucket, $backblazeRegion, $backblazeAcl); + case Storage::DEVICE_LINODE: + $linodeAccessKey = App::getEnv('_APP_STORAGE_LINODE_ACCESS_KEY', ''); + $linodeSecretKey = App::getEnv('_APP_STORAGE_LINODE_SECRET', ''); + $linodeRegion = App::getEnv('_APP_STORAGE_LINODE_REGION', ''); + $linodeBucket = App::getEnv('_APP_STORAGE_LINODE_BUCKET', ''); + $linodeAcl = 'private'; + return new Linode($root, $linodeAccessKey, $linodeSecretKey, $linodeBucket, $linodeRegion, $linodeAcl); + case Storage::DEVICE_WASABI: + $wasabiAccessKey = App::getEnv('_APP_STORAGE_WASABI_ACCESS_KEY', ''); + $wasabiSecretKey = App::getEnv('_APP_STORAGE_WASABI_SECRET', ''); + $wasabiRegion = App::getEnv('_APP_STORAGE_WASABI_REGION', ''); + $wasabiBucket = App::getEnv('_APP_STORAGE_WASABI_BUCKET', ''); + $wasabiAcl = 'private'; + return new Wasabi($root, $wasabiAccessKey, $wasabiSecretKey, $wasabiBucket, $wasabiRegion, $wasabiAcl); } } } diff --git a/src/Appwrite/Specification/Format.php b/src/Appwrite/Specification/Format.php index f76a4c1a56..44696700f0 100644 --- a/src/Appwrite/Specification/Format.php +++ b/src/Appwrite/Specification/Format.php @@ -12,32 +12,32 @@ abstract class Format * @var App */ protected $app; - + /** * @var array */ protected $services; - + /** * @var Route[] */ protected $routes; - + /** * @var Model[] */ protected $models; - + /** * @var array */ protected $keys; - + /** * @var int */ protected $authCount; - + /** * @var array */ @@ -99,7 +99,7 @@ abstract class Format * * @param string $key * @param string $value - * + * * @return self */ public function setParam(string $key, string $value): self @@ -116,16 +116,15 @@ abstract class Format * * @param string $key * @param string $default - * + * * @return string */ public function getParam(string $key, string $default = ''): string { - if(!isset($this->params[$key])) { + if (!isset($this->params[$key])) { return $default; } return $this->params[$key]; } - } diff --git a/src/Appwrite/Specification/Format/OpenAPI3.php b/src/Appwrite/Specification/Format/OpenAPI3.php index 1e4d323fc1..3297be9625 100644 --- a/src/Appwrite/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/Specification/Format/OpenAPI3.php @@ -15,7 +15,7 @@ class OpenAPI3 extends Format * * @return string */ - public function getName():string + public function getName(): string { return 'Open API 3'; } @@ -100,7 +100,7 @@ class OpenAPI3 extends Format } $id = $route->getLabel('sdk.method', \uniqid()); - $desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__.'/../../../../'.$route->getLabel('sdk.description', '')) : null; + $desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__ . '/../../../../' . $route->getLabel('sdk.description', '')) : null; $produces = $route->getLabel('sdk.response.type', null); $model = $route->getLabel('sdk.response.model', 'none'); $routeSecurity = $route->getLabel('sdk.auth', []); @@ -123,13 +123,13 @@ class OpenAPI3 extends Format } } - if(empty($routeSecurity)) { + if (empty($routeSecurity)) { $sdkPlatofrms[] = APP_PLATFORM_CLIENT; } $temp = [ 'summary' => $route->getDesc(), - 'operationId' => $route->getLabel('sdk.namespace', 'default').ucfirst($id), + 'operationId' => $route->getLabel('sdk.namespace', 'default') . ucfirst($id), // 'consumes' => [], // 'produces' => [$produces], 'tags' => [$route->getLabel('sdk.namespace', 'default')], @@ -140,7 +140,7 @@ class OpenAPI3 extends Format 'weight' => $route->getOrder(), 'cookies' => $route->getLabel('sdk.cookies', false), 'type' => $route->getLabel('sdk.methodType', ''), - 'demo' => Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')).'/'.Template::fromCamelCaseToDash($id).'.md', + 'demo' => Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')) . '/' . Template::fromCamelCaseToDash($id) . '.md', 'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $route->getLabel('sdk.description', ''), 'rate-limit' => $route->getLabel('abuse-limit', 0), 'rate-time' => $route->getLabel('abuse-time', 3600), @@ -152,24 +152,23 @@ class OpenAPI3 extends Format ]; foreach ($this->models as $key => $value) { - if(\is_array($model)) { - $model = \array_map(function($m) use($value) { - if($m === $value->getType()) { + if (\is_array($model)) { + $model = \array_map(function ($m) use ($value) { + if ($m === $value->getType()) { return $value; } return $m; }, $model); } else { - if($value->getType() === $model) { + if ($value->getType() === $model) { $model = $value; break; } } - } - if(!(\is_array($model)) && $model->isNone()) { + if (!(\is_array($model)) && $model->isNone()) { $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ 'description' => (in_array($produces, [ 'image/*', @@ -186,7 +185,7 @@ class OpenAPI3 extends Format // ], ]; } else { - if(\is_array($model)) { + if (\is_array($model)) { $modelDescription = \join(', or ', \array_map(function ($m) { return $m->getName(); }, $model)); @@ -201,8 +200,8 @@ class OpenAPI3 extends Format 'content' => [ $produces => [ 'schema' => [ - 'oneOf' => \array_map(function($m) { - return ['$ref' => '#/components/schemas/'.$m->getType()]; + 'oneOf' => \array_map(function ($m) { + return ['$ref' => '#/components/schemas/' . $m->getType()]; }, $model) ], ], @@ -216,16 +215,15 @@ class OpenAPI3 extends Format 'content' => [ $produces => [ 'schema' => [ - '$ref' => '#/components/schemas/'.$model->getType(), + '$ref' => '#/components/schemas/' . $model->getType(), ], ], ], ]; } - } - if($route->getLabel('sdk.response.code', 500) === 204) { + if ($route->getLabel('sdk.response.code', 500) === 204) { $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['description'] = 'No content'; unset($temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['schema']); } @@ -233,8 +231,8 @@ class OpenAPI3 extends Format if ((!empty($scope))) { // && 'public' != $scope $securities = ['Project' => []]; - foreach($route->getLabel('sdk.auth', []) as $security) { - if(array_key_exists($security, $this->keys)) { + foreach ($route->getLabel('sdk.auth', []) as $security) { + if (array_key_exists($security, $this->keys)) { $securities[$security] = []; } } @@ -268,7 +266,7 @@ class OpenAPI3 extends Format switch ((!empty($validator)) ? \get_class($validator) : '') { case 'Utopia\Validator\Text': $node['schema']['type'] = $validator->getType(); - $node['schema']['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']'; + $node['schema']['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; break; case 'Utopia\Validator\Boolean': $node['schema']['type'] = $validator->getType(); @@ -276,14 +274,14 @@ class OpenAPI3 extends Format break; case 'Utopia\Database\Validator\UID': $node['schema']['type'] = $validator->getType(); - $node['schema']['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']'; + $node['schema']['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; break; case 'Appwrite\Utopia\Database\Validator\CustomId': - if($route->getLabel('sdk.methodType', '') === 'upload') { + if ($route->getLabel('sdk.methodType', '') === 'upload') { $node['schema']['x-upload-id'] = true; } $node['schema']['type'] = $validator->getType(); - $node['schema']['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']'; + $node['schema']['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; break; case 'Appwrite\Network\Validator\Email': $node['schema']['type'] = $validator->getType(); @@ -326,7 +324,7 @@ class OpenAPI3 extends Format $node['schema']['x-example'] = 'password'; break; case 'Utopia\Validator\Range': /** @var \Utopia\Validator\Range $validator */ - $node['schema']['type'] = $validator->getType() === Validator::TYPE_FLOAT ? 'number': $validator->getType(); + $node['schema']['type'] = $validator->getType() === Validator::TYPE_FLOAT ? 'number' : $validator->getType(); $node['schema']['format'] = $validator->getType() == Validator::TYPE_INTEGER ? 'int32' : 'float'; $node['schema']['x-example'] = $validator->getMin(); break; @@ -364,14 +362,14 @@ class OpenAPI3 extends Format $node['schema']['default'] = $param['default']; } - if (false !== \strpos($url, ':'.$name)) { // Param is in URL path + if (false !== \strpos($url, ':' . $name)) { // Param is in URL path $node['in'] = 'path'; $temp['parameters'][] = $node; } elseif ($route->getMethod() == 'GET') { // Param is in query $node['in'] = 'query'; $temp['parameters'][] = $node; } else { // Param is in payload - if(!$param['optional']) { + if (!$param['optional']) { $bodyRequired[] = $name; } @@ -381,27 +379,27 @@ class OpenAPI3 extends Format 'x-example' => $node['schema']['x-example'] ?? null ]; - if($node['schema']['x-upload-id'] ?? false) { + if ($node['schema']['x-upload-id'] ?? false) { $body['content'][$consumes[0]]['schema']['properties'][$name]['x-upload-id'] = $node['schema']['x-upload-id']; } - if(isset($node['default'])) { + if (isset($node['default'])) { $body['content'][$consumes[0]]['schema']['properties'][$name]['default'] = $node['default']; } - if(\array_key_exists('items', $node['schema'])) { + if (\array_key_exists('items', $node['schema'])) { $body['content'][$consumes[0]]['schema']['properties'][$name]['items'] = $node['schema']['items']; } } - $url = \str_replace(':'.$name, '{'.$name.'}', $url); + $url = \str_replace(':' . $name, '{' . $name . '}', $url); } - if(!empty($bodyRequired)) { + if (!empty($bodyRequired)) { $body['content'][$consumes[0]]['schema']['required'] = $bodyRequired; } - if(!empty($body['content'][$consumes[0]]['schema']['properties'])) { + if (!empty($body['content'][$consumes[0]]['schema']['properties'])) { $temp['requestBody'] = $body; } @@ -434,19 +432,19 @@ class OpenAPI3 extends Format 'type' => 'object', ]; - if(!empty($rules)) { + if (!empty($rules)) { $output['components']['schemas'][$model->getType()]['properties'] = []; } - if($model->isAny()) { + if ($model->isAny()) { $output['components']['schemas'][$model->getType()]['additionalProperties'] = true; } - if(!empty($required)) { + if (!empty($required)) { $output['components']['schemas'][$model->getType()]['required'] = $required; } - foreach($model->getRules() as $name => $rule) { + foreach ($model->getRules() as $name => $rule) { $type = ''; $format = null; $items = null; @@ -484,29 +482,29 @@ class OpenAPI3 extends Format $type = 'object'; $rule['type'] = ($rule['type']) ? $rule['type'] : 'none'; - if(\is_array($rule['type'])) { - if($rule['array']) { + if (\is_array($rule['type'])) { + if ($rule['array']) { $items = [ - 'anyOf' => \array_map(function($type) { - return ['$ref' => '#/components/schemas/'.$type]; + 'anyOf' => \array_map(function ($type) { + return ['$ref' => '#/components/schemas/' . $type]; }, $rule['type']) ]; } else { $items = [ - 'oneOf' => \array_map(function($type) { - return ['$ref' => '#/components/schemas/'.$type]; + 'oneOf' => \array_map(function ($type) { + return ['$ref' => '#/components/schemas/' . $type]; }, $rule['type']) ]; } } else { $items = [ - '$ref' => '#/components/schemas/'.$rule['type'], + '$ref' => '#/components/schemas/' . $rule['type'], ]; } break; } - if($rule['array']) { + if ($rule['array']) { $output['components']['schemas'][$model->getType()]['properties'][$name] = [ 'type' => 'array', 'description' => $rule['description'] ?? '', @@ -516,10 +514,9 @@ class OpenAPI3 extends Format 'x-example' => $rule['example'] ?? null, ]; - if($format) { + if ($format) { $output['components']['schemas'][$model->getType()]['properties'][$name]['items']['format'] = $format; } - } else { $output['components']['schemas'][$model->getType()]['properties'][$name] = [ 'type' => $type, @@ -527,12 +524,11 @@ class OpenAPI3 extends Format 'x-example' => $rule['example'] ?? null, ]; - if($format) { + if ($format) { $output['components']['schemas'][$model->getType()]['properties'][$name]['format'] = $format; } - } - if($items) { + if ($items) { $output['components']['schemas'][$model->getType()]['properties'][$name]['items'] = $items; } if (!in_array($name, $required)) { diff --git a/src/Appwrite/Specification/Format/Swagger2.php b/src/Appwrite/Specification/Format/Swagger2.php index 4a32dc5f75..af5a8ccb19 100644 --- a/src/Appwrite/Specification/Format/Swagger2.php +++ b/src/Appwrite/Specification/Format/Swagger2.php @@ -15,7 +15,7 @@ class Swagger2 extends Format * * @return string */ - public function getName():string + public function getName(): string { return 'Swagger 2'; } @@ -98,7 +98,7 @@ class Swagger2 extends Format } $id = $route->getLabel('sdk.method', \uniqid()); - $desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__.'/../../../../'.$route->getLabel('sdk.description', '')) : null; + $desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__ . '/../../../../' . $route->getLabel('sdk.description', '')) : null; $produces = $route->getLabel('sdk.response.type', null); $model = $route->getLabel('sdk.response.model', 'none'); $routeSecurity = $route->getLabel('sdk.auth', []); @@ -121,13 +121,13 @@ class Swagger2 extends Format } } - if(empty($routeSecurity)) { + if (empty($routeSecurity)) { $sdkPlatofrms[] = APP_PLATFORM_CLIENT; } $temp = [ 'summary' => $route->getDesc(), - 'operationId' => $route->getLabel('sdk.namespace', 'default').ucfirst($id), + 'operationId' => $route->getLabel('sdk.namespace', 'default') . ucfirst($id), 'consumes' => [], 'produces' => [], 'tags' => [$route->getLabel('sdk.namespace', 'default')], @@ -138,7 +138,7 @@ class Swagger2 extends Format 'weight' => $route->getOrder(), 'cookies' => $route->getLabel('sdk.cookies', false), 'type' => $route->getLabel('sdk.methodType', ''), - 'demo' => Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')).'/'.Template::fromCamelCaseToDash($id).'.md', + 'demo' => Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')) . '/' . Template::fromCamelCaseToDash($id) . '.md', 'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $route->getLabel('sdk.description', ''), 'rate-limit' => $route->getLabel('abuse-limit', 0), 'rate-time' => $route->getLabel('abuse-time', 3600), @@ -149,27 +149,27 @@ class Swagger2 extends Format ], ]; - if($produces) { + if ($produces) { $temp['produces'][] = $produces; } foreach ($this->models as $key => $value) { - if(\is_array($model)) { - $model = \array_map(function($m) use($value) { - if($m === $value->getType()) { + if (\is_array($model)) { + $model = \array_map(function ($m) use ($value) { + if ($m === $value->getType()) { return $value; } return $m; }, $model); } else { - if($value->getType() === $model) { + if ($value->getType() === $model) { $model = $value; break; } } } - if(!(\is_array($model)) && $model->isNone()) { + if (!(\is_array($model)) && $model->isNone()) { $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ 'description' => (in_array($produces, [ 'image/*', @@ -186,8 +186,7 @@ class Swagger2 extends Format ], ]; } else { - - if(\is_array($model)) { + if (\is_array($model)) { $modelDescription = \join(', or ', \array_map(function ($m) { return $m->getName(); }, $model)); @@ -198,8 +197,8 @@ class Swagger2 extends Format $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ 'description' => $modelDescription, 'schema' => [ - 'x-oneOf' => \array_map(function($m) { - return ['$ref' => '#/definitions/'.$m->getType()]; + 'x-oneOf' => \array_map(function ($m) { + return ['$ref' => '#/definitions/' . $m->getType()]; }, $model) ], ]; @@ -209,13 +208,13 @@ class Swagger2 extends Format $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ 'description' => $model->getName(), 'schema' => [ - '$ref' => '#/definitions/'.$model->getType(), + '$ref' => '#/definitions/' . $model->getType(), ], ]; } } - if(in_array($route->getLabel('sdk.response.code', 500), [204, 301, 302, 308], true)) { + if (in_array($route->getLabel('sdk.response.code', 500), [204, 301, 302, 308], true)) { $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['description'] = 'No content'; unset($temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['schema']); } @@ -223,8 +222,8 @@ class Swagger2 extends Format if ((!empty($scope))) { // && 'public' != $scope $securities = ['Project' => []]; - foreach($route->getLabel('sdk.auth', []) as $security) { - if(array_key_exists($security, $this->keys)) { + foreach ($route->getLabel('sdk.auth', []) as $security) { + if (array_key_exists($security, $this->keys)) { $securities[$security] = []; } } @@ -256,22 +255,22 @@ class Swagger2 extends Format switch ((!empty($validator)) ? \get_class($validator) : '') { case 'Utopia\Validator\Text': $node['type'] = $validator->getType(); - $node['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']'; + $node['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; break; case 'Utopia\Validator\Boolean': $node['type'] = $validator->getType(); $node['x-example'] = false; break; case 'Appwrite\Utopia\Database\Validator\CustomId': - if($route->getLabel('sdk.methodType', '') === 'upload') { + if ($route->getLabel('sdk.methodType', '') === 'upload') { $node['x-upload-id'] = true; } $node['type'] = $validator->getType(); - $node['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']'; + $node['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; break; case 'Utopia\Database\Validator\UID': $node['type'] = $validator->getType(); - $node['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']'; + $node['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']'; break; case 'Appwrite\Network\Validator\Email': $node['type'] = $validator->getType(); @@ -316,7 +315,7 @@ class Swagger2 extends Format $node['x-example'] = 'password'; break; case 'Utopia\Validator\Range': /** @var \Utopia\Validator\Range $validator */ - $node['type'] = $validator->getType() === Validator::TYPE_FLOAT ? 'number': $validator->getType(); + $node['type'] = $validator->getType() === Validator::TYPE_FLOAT ? 'number' : $validator->getType(); $node['format'] = $validator->getType() == Validator::TYPE_INTEGER ? 'int32' : 'float'; $node['x-example'] = $validator->getMin(); break; @@ -354,14 +353,13 @@ class Swagger2 extends Format $node['default'] = $param['default']; } - if (false !== \strpos($url, ':'.$name)) { // Param is in URL path + if (false !== \strpos($url, ':' . $name)) { // Param is in URL path $node['in'] = 'path'; $temp['parameters'][] = $node; } elseif ($route->getMethod() == 'GET') { // Param is in query $node['in'] = 'query'; $temp['parameters'][] = $node; } else { // Param is in payload - if (\in_array('multipart/form-data', $consumes)) { $node['in'] = 'formData'; $temp['parameters'][] = $node; @@ -380,19 +378,19 @@ class Swagger2 extends Format 'x-example' => $node['x-example'] ?? null, ]; - if(\array_key_exists('items', $node)) { + if (\array_key_exists('items', $node)) { $body['schema']['properties'][$name]['items'] = $node['items']; } } - $url = \str_replace(':'.$name, '{'.$name.'}', $url); + $url = \str_replace(':' . $name, '{' . $name . '}', $url); } - if(!empty($bodyRequired)) { + if (!empty($bodyRequired)) { $body['schema']['required'] = $bodyRequired; } - if(!empty($body['schema']['properties'])) { + if (!empty($body['schema']['properties'])) { $temp['parameters'][] = $body; } @@ -425,19 +423,19 @@ class Swagger2 extends Format 'type' => 'object', ]; - if(!empty($rules)) { + if (!empty($rules)) { $output['definitions'][$model->getType()]['properties'] = []; } - if($model->isAny()) { + if ($model->isAny()) { $output['definitions'][$model->getType()]['additionalProperties'] = true; } - if(!empty($required)) { + if (!empty($required)) { $output['definitions'][$model->getType()]['required'] = $required; } - foreach($model->getRules() as $name => $rule) { + foreach ($model->getRules() as $name => $rule) { $type = ''; $format = null; $items = null; @@ -474,24 +472,24 @@ class Swagger2 extends Format $type = 'object'; $rule['type'] = ($rule['type']) ?: 'none'; - if(\is_array($rule['type'])) { - if($rule['array']) { + if (\is_array($rule['type'])) { + if ($rule['array']) { $items = [ - 'x-anyOf' => \array_map(function($type) { - return ['$ref' => '#/definitions/'.$type]; + 'x-anyOf' => \array_map(function ($type) { + return ['$ref' => '#/definitions/' . $type]; }, $rule['type']) ]; } else { $items = [ - 'x-oneOf' => \array_map(function($type) { - return ['$ref' => '#/definitions/'.$type]; + 'x-oneOf' => \array_map(function ($type) { + return ['$ref' => '#/definitions/' . $type]; }, $rule['type']) ]; } } else { $items = [ 'type' => $type, - '$ref' => '#/definitions/'.$rule['type'], + '$ref' => '#/definitions/' . $rule['type'], ]; } break; @@ -507,7 +505,7 @@ class Swagger2 extends Format continue; } - if($rule['array']) { + if ($rule['array']) { $output['definitions'][$model->getType()]['properties'][$name] = [ 'type' => 'array', 'description' => $rule['description'] ?? '', @@ -517,10 +515,9 @@ class Swagger2 extends Format 'x-example' => $rule['example'] ?? null, ]; - if($format) { + if ($format) { $output['definitions'][$model->getType()]['properties'][$name]['items']['format'] = $format; } - } else { $output['definitions'][$model->getType()]['properties'][$name] = [ 'type' => $type, @@ -528,12 +525,11 @@ class Swagger2 extends Format 'x-example' => $rule['example'] ?? null, ]; - if($format) { + if ($format) { $output['definitions'][$model->getType()]['properties'][$name]['format'] = $format; } - } - if($items) { + if ($items) { $output['definitions'][$model->getType()]['properties'][$name]['items'] = $items; } if (!in_array($name, $required)) { diff --git a/src/Appwrite/Specification/Specification.php b/src/Appwrite/Specification/Specification.php index d28ddd8be6..635cb069bf 100644 --- a/src/Appwrite/Specification/Specification.php +++ b/src/Appwrite/Specification/Specification.php @@ -24,7 +24,7 @@ class Specification * * @return string */ - public function getName():string + public function getName(): string { return $this->format->getName(); } @@ -40,4 +40,4 @@ class Specification { return $this->format->parse(); } -} \ No newline at end of file +} diff --git a/src/Appwrite/Stats/Stats.php b/src/Appwrite/Stats/Stats.php index 938c7b0fa0..a737c4fd28 100644 --- a/src/Appwrite/Stats/Stats.php +++ b/src/Appwrite/Stats/Stats.php @@ -173,7 +173,7 @@ class Stats foreach ($sessionsMetrics as $metric) { $value = $this->params[$metric] ?? 0; if ($value >= 1) { - $tags = ",projectId={$projectId},provider=". ($this->params['provider'] ?? ''); + $tags = ",projectId={$projectId},provider=" . ($this->params['provider'] ?? ''); $this->statsd->count($metric . $tags, $value); } } diff --git a/src/Appwrite/Template/Template.php b/src/Appwrite/Template/Template.php index 6f586a6256..c01d54389b 100644 --- a/src/Appwrite/Template/Template.php +++ b/src/Appwrite/Template/Template.php @@ -74,7 +74,7 @@ class Template extends View } elseif (!empty($this->content)) { $template = $this->print($this->content, self::FILTER_NL2P); } else { - throw new Exception('"'.$this->path.'" template is not readable or not found'); + throw new Exception('"' . $this->path . '" template is not readable or not found'); } // First replace the variables inside the params. Then replace the variables in the template @@ -109,20 +109,20 @@ class Template extends View */ public static function unParseURL(array $url) { - $scheme = isset($url['scheme']) ? $url['scheme'].'://' : ''; + $scheme = isset($url['scheme']) ? $url['scheme'] . '://' : ''; $host = isset($url['host']) ? $url['host'] : ''; - $port = isset($url['port']) ? ':'.$url['port'] : ''; + $port = isset($url['port']) ? ':' . $url['port'] : ''; $user = isset($url['user']) ? $url['user'] : ''; - $pass = isset($url['pass']) ? ':'.$url['pass'] : ''; + $pass = isset($url['pass']) ? ':' . $url['pass'] : ''; $pass = ($user || $pass) ? "$pass@" : ''; $path = isset($url['path']) ? $url['path'] : ''; - $query = isset($url['query']) && !empty($url['query']) ? '?'.$url['query'] : ''; + $query = isset($url['query']) && !empty($url['query']) ? '?' . $url['query'] : ''; - $fragment = isset($url['fragment']) ? '#'.$url['fragment'] : ''; + $fragment = isset($url['fragment']) ? '#' . $url['fragment'] : ''; - return $scheme.$user.$pass.$host.$port.$path.$query.$fragment; + return $scheme . $user . $pass . $host . $port . $path . $query . $fragment; } /** diff --git a/src/Appwrite/URL/URL.php b/src/Appwrite/URL/URL.php index 99edf9cf8b..98250ab429 100644 --- a/src/Appwrite/URL/URL.php +++ b/src/Appwrite/URL/URL.php @@ -42,28 +42,28 @@ class URL public static function unparse(array $url, array $ommit = []): string { if (isset($url['path']) && \mb_substr($url['path'], 0, 1) !== '/') { - $url['path'] = '/'.$url['path']; + $url['path'] = '/' . $url['path']; } $parts = []; - $parts['scheme'] = isset($url['scheme']) ? $url['scheme'].'://' : ''; + $parts['scheme'] = isset($url['scheme']) ? $url['scheme'] . '://' : ''; $parts['host'] = isset($url['host']) ? $url['host'] : ''; - $parts['port'] = isset($url['port']) ? ':'.$url['port'] : ''; + $parts['port'] = isset($url['port']) ? ':' . $url['port'] : ''; $parts['user'] = isset($url['user']) ? $url['user'] : ''; - $parts['pass'] = isset($url['pass']) ? ':'.$url['pass'] : ''; + $parts['pass'] = isset($url['pass']) ? ':' . $url['pass'] : ''; - $parts['pass'] = ($parts['user'] || $parts['pass']) ? $parts['pass'].'@' : ''; + $parts['pass'] = ($parts['user'] || $parts['pass']) ? $parts['pass'] . '@' : ''; $parts['path'] = isset($url['path']) ? $url['path'] : ''; - $parts['query'] = isset($url['query']) && !empty($url['query']) ? '?'.$url['query'] : ''; + $parts['query'] = isset($url['query']) && !empty($url['query']) ? '?' . $url['query'] : ''; - $parts['fragment'] = isset($url['fragment']) ? '#'.$url['fragment'] : ''; + $parts['fragment'] = isset($url['fragment']) ? '#' . $url['fragment'] : ''; if ($ommit) { foreach ($ommit as $key) { @@ -73,7 +73,7 @@ class URL } } - return $parts['scheme'].$parts['user'].$parts['pass'].$parts['host'].$parts['port'].$parts['path'].$parts['query'].$parts['fragment']; + return $parts['scheme'] . $parts['user'] . $parts['pass'] . $parts['host'] . $parts['port'] . $parts['path'] . $parts['query'] . $parts['fragment']; } /** diff --git a/src/Appwrite/Utopia/Database/Validator/CustomId.php b/src/Appwrite/Utopia/Database/Validator/CustomId.php index 96891bf68a..90d550371b 100644 --- a/src/Appwrite/Utopia/Database/Validator/CustomId.php +++ b/src/Appwrite/Utopia/Database/Validator/CustomId.php @@ -1,9 +1,11 @@ getAttribute('status') === 'available'; }); parent::__construct($attributes, $indexes, $strict); } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Database/Validator/Queries.php b/src/Appwrite/Utopia/Database/Validator/Queries.php index 73bf04be40..02ffab1838 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries.php @@ -1,4 +1,5 @@ getAttribute('status') === 'available'; }); parent::__construct($attributes, $indexes, $strict); } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Request.php b/src/Appwrite/Utopia/Request.php index d6ad3d8a85..17148d6920 100644 --- a/src/Appwrite/Utopia/Request.php +++ b/src/Appwrite/Utopia/Request.php @@ -1,6 +1,5 @@ getMethod()) { + switch ($this->getMethod()) { case self::METHOD_GET: $requestParameters = (!empty($this->swoole->get)) ? $this->swoole->get : []; break; @@ -125,4 +124,4 @@ class Request extends UtopiaRequest { return self::$route != null; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Request/Filter.php b/src/Appwrite/Utopia/Request/Filter.php index 9f3e94bb3f..59346c7e17 100644 --- a/src/Appwrite/Utopia/Request/Filter.php +++ b/src/Appwrite/Utopia/Request/Filter.php @@ -4,7 +4,6 @@ namespace Appwrite\Utopia\Request; abstract class Filter { - /** * Parse params to another format. * diff --git a/src/Appwrite/Utopia/Request/Filters/V12.php b/src/Appwrite/Utopia/Request/Filters/V12.php index 6c2fe0b9b9..f2a65307ae 100644 --- a/src/Appwrite/Utopia/Request/Filters/V12.php +++ b/src/Appwrite/Utopia/Request/Filters/V12.php @@ -93,9 +93,15 @@ class V12 extends Filter protected function removeParentProperties(array $content): array { - if (isset($content['parentDocument'])) unset($content['parentDocument']); - if (isset($content['parentProperty'])) unset($content['parentProperty']); - if (isset($content['parentPropertyType'])) unset($content['parentPropertyType']); + if (isset($content['parentDocument'])) { + unset($content['parentDocument']); + } + if (isset($content['parentProperty'])) { + unset($content['parentProperty']); + } + if (isset($content['parentPropertyType'])) { + unset($content['parentPropertyType']); + } return $content; } @@ -128,7 +134,7 @@ class V12 extends Filter { $queries = []; - if(!empty($content['filters'])) { + if (!empty($content['filters'])) { foreach ($content['filters'] as $filter) { $operators = ['=' => 'equal', '!=' => 'notEqual', '>' => 'greater', '<' => 'lesser', '<=' => 'lesserEqual', '>=' => 'greaterEqual']; foreach ($operators as $operator => $operatorVerbose) { @@ -138,10 +144,10 @@ class V12 extends Filter } } - if(isset($usedOperator)) { + if (isset($usedOperator)) { [ $attributeKey, $filterValue ] = \explode($usedOperator, $filter); - if($filterValue === 'true' || $filterValue === 'false') { + if ($filterValue === 'true' || $filterValue === 'false') { // Let's keep it at true and false string, but without "" around // No action needed } else { diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 778724d36e..8a876ecb4d 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -76,116 +76,116 @@ use Appwrite\Utopia\Response\Model\UsageUsers; class Response extends SwooleResponse { // General - const MODEL_NONE = 'none'; - const MODEL_ANY = 'any'; - const MODEL_LOG = 'log'; - const MODEL_LOG_LIST = 'logList'; - const MODEL_ERROR = 'error'; - const MODEL_METRIC = 'metric'; - const MODEL_METRIC_LIST = 'metricList'; - const MODEL_ERROR_DEV = 'errorDev'; - const MODEL_BASE_LIST = 'baseList'; - const MODEL_USAGE_DATABASE = 'usageDatabase'; - const MODEL_USAGE_COLLECTION = 'usageCollection'; - const MODEL_USAGE_USERS = 'usageUsers'; - const MODEL_USAGE_BUCKETS = 'usageBuckets'; - const MODEL_USAGE_STORAGE = 'usageStorage'; - const MODEL_USAGE_FUNCTIONS = 'usageFunctions'; - const MODEL_USAGE_PROJECT = 'usageProject'; - + public const MODEL_NONE = 'none'; + public const MODEL_ANY = 'any'; + public const MODEL_LOG = 'log'; + public const MODEL_LOG_LIST = 'logList'; + public const MODEL_ERROR = 'error'; + public const MODEL_METRIC = 'metric'; + public const MODEL_METRIC_LIST = 'metricList'; + public const MODEL_ERROR_DEV = 'errorDev'; + public const MODEL_BASE_LIST = 'baseList'; + public const MODEL_USAGE_DATABASE = 'usageDatabase'; + public const MODEL_USAGE_COLLECTION = 'usageCollection'; + public const MODEL_USAGE_USERS = 'usageUsers'; + public const MODEL_USAGE_BUCKETS = 'usageBuckets'; + public const MODEL_USAGE_STORAGE = 'usageStorage'; + public const MODEL_USAGE_FUNCTIONS = 'usageFunctions'; + public const MODEL_USAGE_PROJECT = 'usageProject'; + // Database - const MODEL_COLLECTION = 'collection'; - const MODEL_COLLECTION_LIST = 'collectionList'; - const MODEL_INDEX = 'index'; - const MODEL_INDEX_LIST = 'indexList'; - const MODEL_DOCUMENT = 'document'; - const MODEL_DOCUMENT_LIST = 'documentList'; + public const MODEL_COLLECTION = 'collection'; + public const MODEL_COLLECTION_LIST = 'collectionList'; + public const MODEL_INDEX = 'index'; + public const MODEL_INDEX_LIST = 'indexList'; + public const MODEL_DOCUMENT = 'document'; + public const MODEL_DOCUMENT_LIST = 'documentList'; // Database Attributes - const MODEL_ATTRIBUTE = 'attribute'; - const MODEL_ATTRIBUTE_LIST = 'attributeList'; - const MODEL_ATTRIBUTE_STRING = 'attributeString'; - const MODEL_ATTRIBUTE_INTEGER = 'attributeInteger'; - const MODEL_ATTRIBUTE_FLOAT = 'attributeFloat'; - const MODEL_ATTRIBUTE_BOOLEAN = 'attributeBoolean'; - const MODEL_ATTRIBUTE_EMAIL = 'attributeEmail'; - const MODEL_ATTRIBUTE_ENUM = 'attributeEnum'; - const MODEL_ATTRIBUTE_IP = 'attributeIp'; - const MODEL_ATTRIBUTE_URL= 'attributeUrl'; + public const MODEL_ATTRIBUTE = 'attribute'; + public const MODEL_ATTRIBUTE_LIST = 'attributeList'; + public const MODEL_ATTRIBUTE_STRING = 'attributeString'; + public const MODEL_ATTRIBUTE_INTEGER = 'attributeInteger'; + public const MODEL_ATTRIBUTE_FLOAT = 'attributeFloat'; + public const MODEL_ATTRIBUTE_BOOLEAN = 'attributeBoolean'; + public const MODEL_ATTRIBUTE_EMAIL = 'attributeEmail'; + public const MODEL_ATTRIBUTE_ENUM = 'attributeEnum'; + public const MODEL_ATTRIBUTE_IP = 'attributeIp'; + public const MODEL_ATTRIBUTE_URL = 'attributeUrl'; // Users - const MODEL_USER = 'user'; - const MODEL_USER_LIST = 'userList'; - const MODEL_SESSION = 'session'; - const MODEL_SESSION_LIST = 'sessionList'; - const MODEL_TOKEN = 'token'; - const MODEL_JWT = 'jwt'; - const MODEL_PREFERENCES = 'preferences'; - + public const MODEL_USER = 'user'; + public const MODEL_USER_LIST = 'userList'; + public const MODEL_SESSION = 'session'; + public const MODEL_SESSION_LIST = 'sessionList'; + public const MODEL_TOKEN = 'token'; + public const MODEL_JWT = 'jwt'; + public const MODEL_PREFERENCES = 'preferences'; + // Storage - const MODEL_FILE = 'file'; - const MODEL_FILE_LIST = 'fileList'; - const MODEL_BUCKET = 'bucket'; - const MODEL_BUCKET_LIST = 'bucketList'; + public const MODEL_FILE = 'file'; + public const MODEL_FILE_LIST = 'fileList'; + public const MODEL_BUCKET = 'bucket'; + public const MODEL_BUCKET_LIST = 'bucketList'; // Locale - const MODEL_LOCALE = 'locale'; - const MODEL_COUNTRY = 'country'; - const MODEL_COUNTRY_LIST = 'countryList'; - const MODEL_CONTINENT = 'continent'; - const MODEL_CONTINENT_LIST = 'continentList'; - const MODEL_CURRENCY = 'currency'; - const MODEL_CURRENCY_LIST = 'currencyList'; - const MODEL_LANGUAGE = 'language'; - const MODEL_LANGUAGE_LIST = 'languageList'; - const MODEL_PHONE = 'phone'; - const MODEL_PHONE_LIST = 'phoneList'; + public const MODEL_LOCALE = 'locale'; + public const MODEL_COUNTRY = 'country'; + public const MODEL_COUNTRY_LIST = 'countryList'; + public const MODEL_CONTINENT = 'continent'; + public const MODEL_CONTINENT_LIST = 'continentList'; + public const MODEL_CURRENCY = 'currency'; + public const MODEL_CURRENCY_LIST = 'currencyList'; + public const MODEL_LANGUAGE = 'language'; + public const MODEL_LANGUAGE_LIST = 'languageList'; + public const MODEL_PHONE = 'phone'; + public const MODEL_PHONE_LIST = 'phoneList'; // Teams - const MODEL_TEAM = 'team'; - const MODEL_TEAM_LIST = 'teamList'; - const MODEL_MEMBERSHIP = 'membership'; - const MODEL_MEMBERSHIP_LIST = 'membershipList'; + public const MODEL_TEAM = 'team'; + public const MODEL_TEAM_LIST = 'teamList'; + public const MODEL_MEMBERSHIP = 'membership'; + public const MODEL_MEMBERSHIP_LIST = 'membershipList'; // Functions - const MODEL_FUNCTION = 'function'; - const MODEL_FUNCTION_LIST = 'functionList'; - const MODEL_RUNTIME = 'runtime'; - const MODEL_RUNTIME_LIST = 'runtimeList'; - const MODEL_DEPLOYMENT = 'deployment'; - const MODEL_DEPLOYMENT_LIST = 'deploymentList'; - const MODEL_EXECUTION = 'execution'; - const MODEL_EXECUTION_LIST = 'executionList'; - const MODEL_BUILD = 'build'; - const MODEL_BUILD_LIST = 'buildList'; // Not used anywhere yet - const MODEL_FUNC_PERMISSIONS = 'funcPermissions'; - + public const MODEL_FUNCTION = 'function'; + public const MODEL_FUNCTION_LIST = 'functionList'; + public const MODEL_RUNTIME = 'runtime'; + public const MODEL_RUNTIME_LIST = 'runtimeList'; + public const MODEL_DEPLOYMENT = 'deployment'; + public const MODEL_DEPLOYMENT_LIST = 'deploymentList'; + public const MODEL_EXECUTION = 'execution'; + public const MODEL_EXECUTION_LIST = 'executionList'; + public const MODEL_BUILD = 'build'; + public const MODEL_BUILD_LIST = 'buildList'; // Not used anywhere yet + public const MODEL_FUNC_PERMISSIONS = 'funcPermissions'; + // Project - const MODEL_PROJECT = 'project'; - const MODEL_PROJECT_LIST = 'projectList'; - const MODEL_WEBHOOK = 'webhook'; - const MODEL_WEBHOOK_LIST = 'webhookList'; - const MODEL_KEY = 'key'; - const MODEL_KEY_LIST = 'keyList'; - const MODEL_PLATFORM = 'platform'; - const MODEL_PLATFORM_LIST = 'platformList'; - const MODEL_DOMAIN = 'domain'; - const MODEL_DOMAIN_LIST = 'domainList'; + public const MODEL_PROJECT = 'project'; + public const MODEL_PROJECT_LIST = 'projectList'; + public const MODEL_WEBHOOK = 'webhook'; + public const MODEL_WEBHOOK_LIST = 'webhookList'; + public const MODEL_KEY = 'key'; + public const MODEL_KEY_LIST = 'keyList'; + public const MODEL_PLATFORM = 'platform'; + public const MODEL_PLATFORM_LIST = 'platformList'; + public const MODEL_DOMAIN = 'domain'; + public const MODEL_DOMAIN_LIST = 'domainList'; // Health - const MODEL_HEALTH_STATUS = 'healthStatus'; - const MODEL_HEALTH_VERSION = 'healthVersion'; - const MODEL_HEALTH_QUEUE = 'healthQueue'; - const MODEL_HEALTH_TIME = 'healthTime'; - const MODEL_HEALTH_ANTIVIRUS = 'healthAntivirus'; - + public const MODEL_HEALTH_STATUS = 'healthStatus'; + public const MODEL_HEALTH_VERSION = 'healthVersion'; + public const MODEL_HEALTH_QUEUE = 'healthQueue'; + public const MODEL_HEALTH_TIME = 'healthTime'; + public const MODEL_HEALTH_ANTIVIRUS = 'healthAntivirus'; + // Deprecated - const MODEL_PERMISSIONS = 'permissions'; - const MODEL_RULE = 'rule'; - const MODEL_TASK = 'task'; + public const MODEL_PERMISSIONS = 'permissions'; + public const MODEL_RULE = 'rule'; + public const MODEL_TASK = 'task'; // Tests (keep last) - const MODEL_MOCK = 'mock'; + public const MODEL_MOCK = 'mock'; /** * @var Filter @@ -302,7 +302,7 @@ class Response extends SwooleResponse /** * HTTP content types */ - const CONTENT_TYPE_YAML = 'application/x-yaml'; + public const CONTENT_TYPE_YAML = 'application/x-yaml'; /** * List of defined output objects @@ -329,7 +329,7 @@ class Response extends SwooleResponse public function getModel(string $key): Model { if (!isset($this->models[$key])) { - throw new Exception('Undefined model: '.$key); + throw new Exception('Undefined model: ' . $key); } return $this->models[$key]; @@ -392,13 +392,13 @@ class Response extends SwooleResponse if (!is_null($rule['default'])) { $document->setAttribute($key, $rule['default']); } else { - throw new Exception('Model '.$model->getName().' is missing response key: '.$key); + throw new Exception('Model ' . $model->getName() . ' is missing response key: ' . $key); } } if ($rule['array']) { if (!is_array($data[$key])) { - throw new Exception($key.' must be an array of type '.$rule['type']); + throw new Exception($key . ' must be an array of type ' . $rule['type']); } foreach ($data[$key] as &$item) { @@ -408,7 +408,7 @@ class Response extends SwooleResponse $condition = false; foreach ($this->getModel($type)->conditions as $attribute => $val) { $condition = $item->getAttribute($attribute) === $val; - if(!$condition) { + if (!$condition) { break; } } @@ -422,7 +422,7 @@ class Response extends SwooleResponse } if (!array_key_exists($ruleType, $this->models)) { - throw new Exception('Missing model for rule: '. $ruleType); + throw new Exception('Missing model for rule: ' . $ruleType); } $item = $this->output($item, $ruleType); @@ -465,7 +465,7 @@ class Response extends SwooleResponse /** * @return array */ - public function getPayload():array + public function getPayload(): array { return $this->payload; } diff --git a/src/Appwrite/Utopia/Response/Filter.php b/src/Appwrite/Utopia/Response/Filter.php index 5446dff924..9110abd07a 100644 --- a/src/Appwrite/Utopia/Response/Filter.php +++ b/src/Appwrite/Utopia/Response/Filter.php @@ -4,7 +4,6 @@ namespace Appwrite\Utopia\Response; abstract class Filter { - /** * Parse the content to another format. * diff --git a/src/Appwrite/Utopia/Response/Filters/V11.php b/src/Appwrite/Utopia/Response/Filters/V11.php index 746269c8e7..31b0949e28 100644 --- a/src/Appwrite/Utopia/Response/Filters/V11.php +++ b/src/Appwrite/Utopia/Response/Filters/V11.php @@ -27,21 +27,21 @@ class V11 extends Filter case Response::MODEL_FILE_LIST: $parsedResponse = $this->parseFileList($content); break; - + case Response::MODEL_EXECUTION: $parsedResponse = $this->parseExecutionPermissions($content); break; case Response::MODEL_EXECUTION_LIST: $parsedResponse = $this->parseExecutionsList($content); break; - + case Response::MODEL_FUNCTION: $parsedResponse = $this->parseFunctionPermissions($content); break; case Response::MODEL_FUNCTION_LIST: $parsedResponse = $this->parseFunctionsList($content); break; - + // Convert status from boolean to int case Response::MODEL_USER: $parsedResponse = $this->parseStatus($content); @@ -49,7 +49,7 @@ class V11 extends Filter case Response::MODEL_USER_LIST: $parsedResponse = $this->parseUserList($content); break; - + // Convert all Health responses back to original case Response::MODEL_HEALTH_STATUS: $parsedResponse = $this->parseHealthStatus($content); @@ -93,7 +93,7 @@ class V11 extends Filter return $parsedResponse; } - protected function parseDocumentList(array $content) + protected function parseDocumentList(array $content) { $documents = $content['documents']; $parsedResponse = []; @@ -104,7 +104,7 @@ class V11 extends Filter return $content; } - protected function parseFileList(array $content) + protected function parseFileList(array $content) { $files = $content['files']; $parsedResponse = []; @@ -115,7 +115,7 @@ class V11 extends Filter return $content; } - protected function parseExecutionsList(array $content) + protected function parseExecutionsList(array $content) { $executions = $content['executions']; $parsedResponse = []; @@ -126,7 +126,7 @@ class V11 extends Filter return $content; } - protected function parseFunctionsList(array $content) + protected function parseFunctionsList(array $content) { $functions = $content['functions']; $parsedResponse = []; @@ -137,7 +137,7 @@ class V11 extends Filter return $content; } - protected function parseUserList(array $content) + protected function parseUserList(array $content) { $users = $content['users']; $parsedResponse = []; @@ -148,7 +148,7 @@ class V11 extends Filter return $content; } - protected function parseCollection(array $content) + protected function parseCollection(array $content) { $parsedResponse = []; $parsedResponse = $this->parsePermissions($content); @@ -162,7 +162,7 @@ class V11 extends Filter return $parsedResponse; } - protected function parseCollectionList(array $content) + protected function parseCollectionList(array $content) { $collections = $content['collections']; $parsedResponse = []; @@ -173,7 +173,7 @@ class V11 extends Filter return $content; } - protected function parseLog(array $content) + protected function parseLog(array $content) { $parsedResponse = []; $parsedResponse = $this->removeRule($content, 'userId'); @@ -184,7 +184,7 @@ class V11 extends Filter return $parsedResponse; } - protected function parseLogList(array $content) + protected function parseLogList(array $content) { $logs = $content['logs']; $parsedResponse = []; @@ -206,7 +206,7 @@ class V11 extends Filter return $parsedResponse; } - protected function parseProjectList(array $content) + protected function parseProjectList(array $content) { $projects = $content['projects']; $parsedResponse = []; @@ -219,11 +219,11 @@ class V11 extends Filter protected function parseHealthAntivirus(array $content) { - if($content['status'] === 'pass') { + if ($content['status'] === 'pass') { $content['status'] = 'online'; } - if($content['status'] === 'fail') { + if ($content['status'] === 'fail') { $content['status'] = 'offline'; } @@ -275,7 +275,7 @@ class V11 extends Filter protected function parseAttributes(array $content) { - $content['rules'] = \array_map(function($attribute) use($content) { + $content['rules'] = \array_map(function ($attribute) use ($content) { return [ '$id' => $attribute['key'], '$collection' => $content['$id'], @@ -307,7 +307,7 @@ class V11 extends Filter foreach ($content as $key => $value) { \preg_match_all($regexPattern, $key, $regexGroups); - if(\count($regexGroups[1]) > 0 && \count($regexGroups[2]) > 0) { + if (\count($regexGroups[1]) > 0 && \count($regexGroups[2]) > 0) { $providerName = $regexGroups[1][0]; $valueKey = $regexGroups[2][0]; $content['usersOauth2' . $providerName . $valueKey] = $value; @@ -324,7 +324,7 @@ class V11 extends Filter foreach ($content as $key => $value) { \preg_match_all($regexPattern, $key, $regexGroups); - if(\count($regexGroups[1]) > 0) { + if (\count($regexGroups[1]) > 0) { $providerName = $regexGroups[1][0]; $content[$providerName] = $value; @@ -340,7 +340,7 @@ class V11 extends Filter // Such a key is part of new response, but is not part of old one. We simply remove it, older version never // expected it anyway. foreach ($content as $key => $value) { - if(\str_starts_with($key, 'serviceStatusFor')) { + if (\str_starts_with($key, 'serviceStatusFor')) { unset($content[$key]); } } diff --git a/src/Appwrite/Utopia/Response/Filters/V12.php b/src/Appwrite/Utopia/Response/Filters/V12.php index 6b19b2ce0f..79d22ad044 100644 --- a/src/Appwrite/Utopia/Response/Filters/V12.php +++ b/src/Appwrite/Utopia/Response/Filters/V12.php @@ -219,14 +219,16 @@ class V12 extends Filter return $content; } - protected function parseExecution($content) { + protected function parseExecution($content) + { $content['exitCode'] = $content['statusCode']; unset($content['statusCode']); return $content; } - protected function parseExecutionList($content) { + protected function parseExecutionList($content) + { $executions = $content['executions']; $parsedResponse = []; foreach ($executions as $document) { @@ -238,13 +240,15 @@ class V12 extends Filter return $content; } - protected function parseTeam($content) { + protected function parseTeam($content) + { $content['sum'] = $content['total']; unset($content['total']); return $content; } - protected function parseTeamList($content) { + protected function parseTeamList($content) + { $teams = $content['teams']; $parsedResponse = []; foreach ($teams as $document) { @@ -256,9 +260,10 @@ class V12 extends Filter return $content; } - protected function parseList($content) { + protected function parseList($content) + { $content['sum'] = $content['total']; unset($content['total']); return $content; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Response/Filters/V13.php b/src/Appwrite/Utopia/Response/Filters/V13.php index c3795d2180..d48473593e 100644 --- a/src/Appwrite/Utopia/Response/Filters/V13.php +++ b/src/Appwrite/Utopia/Response/Filters/V13.php @@ -39,14 +39,16 @@ class V13 extends Filter return $parsedResponse; } - protected function parseExecution($content) { + protected function parseExecution($content) + { $content['stdout'] = $content['response']; unset($content['response']); return $content; } - protected function parseExecutionList($content) { + protected function parseExecutionList($content) + { $executions = $content['executions']; $parsedResponse = []; foreach ($executions as $document) { @@ -56,14 +58,16 @@ class V13 extends Filter return $content; } - protected function parseProject($content) { + protected function parseProject($content) + { $content['providers'] = $content['authProviders']; unset($content['authProviders']); return $content; } - protected function parseProjectList($content) { + protected function parseProjectList($content) + { $projects = $content['projects']; $parsedResponse = []; foreach ($projects as $document) { @@ -73,7 +77,8 @@ class V13 extends Filter return $content; } - protected function parseMembership($content) { + protected function parseMembership($content) + { $content['name'] = $content['userName']; unset($content['userName']); @@ -85,7 +90,8 @@ class V13 extends Filter return $content; } - protected function parseMembershipList($content) { + protected function parseMembershipList($content) + { $memberships = $content['memberships']; $parsedResponse = []; foreach ($memberships as $document) { @@ -94,4 +100,4 @@ class V13 extends Filter $content['memberships'] = $parsedResponse; return $content; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Response/Model.php b/src/Appwrite/Utopia/Response/Model.php index 9a98e55eae..6407c85118 100644 --- a/src/Appwrite/Utopia/Response/Model.php +++ b/src/Appwrite/Utopia/Response/Model.php @@ -6,11 +6,11 @@ use Utopia\Database\Document; abstract class Model { - const TYPE_STRING = 'string'; - const TYPE_INTEGER = 'integer'; - const TYPE_FLOAT = 'double'; - const TYPE_BOOLEAN = 'boolean'; - const TYPE_JSON = 'json'; + public const TYPE_STRING = 'string'; + public const TYPE_INTEGER = 'integer'; + public const TYPE_FLOAT = 'double'; + public const TYPE_BOOLEAN = 'boolean'; + public const TYPE_JSON = 'json'; /** * @var bool @@ -34,7 +34,7 @@ abstract class Model /** * Filter Document Structure - * + * * @return Document */ public function filter(Document $document): Document diff --git a/src/Appwrite/Utopia/Response/Model/Any.php b/src/Appwrite/Utopia/Response/Model/Any.php index 44f588250b..589dfd1eb4 100644 --- a/src/Appwrite/Utopia/Response/Model/Any.php +++ b/src/Appwrite/Utopia/Response/Model/Any.php @@ -17,7 +17,7 @@ class Any extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Any'; } @@ -27,7 +27,7 @@ class Any extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_ANY; } diff --git a/src/Appwrite/Utopia/Response/Model/Attribute.php b/src/Appwrite/Utopia/Response/Model/Attribute.php index 7d064ecb1b..274b0caa92 100644 --- a/src/Appwrite/Utopia/Response/Model/Attribute.php +++ b/src/Appwrite/Utopia/Response/Model/Attribute.php @@ -48,20 +48,20 @@ class Attribute extends Model /** * Get Name - * + * * @return string */ - public function getName():string + public function getName(): string { return 'Attribute'; } /** * Get Collection - * + * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_ATTRIBUTE; } diff --git a/src/Appwrite/Utopia/Response/Model/AttributeBoolean.php b/src/Appwrite/Utopia/Response/Model/AttributeBoolean.php index 97bab3d8a1..0623406636 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeBoolean.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeBoolean.php @@ -41,21 +41,21 @@ class AttributeBoolean extends Attribute /** * Get Name - * + * * @return string */ - public function getName():string + public function getName(): string { return 'AttributeBoolean'; } /** * Get Type - * + * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_ATTRIBUTE_BOOLEAN; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Response/Model/AttributeEmail.php b/src/Appwrite/Utopia/Response/Model/AttributeEmail.php index 77cffe9113..dd9a514996 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeEmail.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeEmail.php @@ -50,21 +50,21 @@ class AttributeEmail extends Attribute /** * Get Name - * + * * @return string */ - public function getName():string + public function getName(): string { return 'AttributeEmail'; } /** * Get Type - * + * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_ATTRIBUTE_EMAIL; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Response/Model/AttributeEnum.php b/src/Appwrite/Utopia/Response/Model/AttributeEnum.php index e38c92a9bd..2a10cf7fca 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeEnum.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeEnum.php @@ -61,7 +61,7 @@ class AttributeEnum extends Attribute * * @return string */ - public function getName():string + public function getName(): string { return 'AttributeEnum'; } @@ -71,8 +71,8 @@ class AttributeEnum extends Attribute * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_ATTRIBUTE_ENUM; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Response/Model/AttributeFloat.php b/src/Appwrite/Utopia/Response/Model/AttributeFloat.php index e8a8a07aea..5cc6f90649 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeFloat.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeFloat.php @@ -57,21 +57,21 @@ class AttributeFloat extends Attribute /** * Get Name - * + * * @return string */ - public function getName():string + public function getName(): string { return 'AttributeFloat'; } /** * Get Type - * + * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_ATTRIBUTE_FLOAT; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Response/Model/AttributeIP.php b/src/Appwrite/Utopia/Response/Model/AttributeIP.php index 0e8701e67c..00d9ddcab2 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeIP.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeIP.php @@ -50,21 +50,21 @@ class AttributeIP extends Attribute /** * Get Name - * + * * @return string */ - public function getName():string + public function getName(): string { return 'AttributeIP'; } /** * Get Type - * + * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_ATTRIBUTE_IP; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Response/Model/AttributeInteger.php b/src/Appwrite/Utopia/Response/Model/AttributeInteger.php index a8bb6fb095..eefa5e39d7 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeInteger.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeInteger.php @@ -56,21 +56,21 @@ class AttributeInteger extends Attribute ]; /** - * Get Name * + * Get Name * * @return string */ - public function getName():string + public function getName(): string { return 'AttributeInteger'; } /** * Get Type - * + * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_ATTRIBUTE_INTEGER; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Response/Model/AttributeList.php b/src/Appwrite/Utopia/Response/Model/AttributeList.php index 6f3d0ab99d..eb398e455a 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeList.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeList.php @@ -40,7 +40,7 @@ class AttributeList extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Attributes List'; } @@ -50,8 +50,8 @@ class AttributeList extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_ATTRIBUTE_LIST; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Response/Model/AttributeString.php b/src/Appwrite/Utopia/Response/Model/AttributeString.php index bb44c6af6d..c09ce0eea8 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeString.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeString.php @@ -35,20 +35,20 @@ class AttributeString extends Attribute /** * Get Name - * + * * @return string */ - public function getName():string + public function getName(): string { return 'AttributeString'; } /** * Get Type - * + * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_ATTRIBUTE_STRING; } diff --git a/src/Appwrite/Utopia/Response/Model/AttributeURL.php b/src/Appwrite/Utopia/Response/Model/AttributeURL.php index d0d0931935..4a468b6ee1 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeURL.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeURL.php @@ -50,21 +50,21 @@ class AttributeURL extends Attribute /** * Get Name - * + * * @return string */ - public function getName():string + public function getName(): string { return 'AttributeURL'; } /** * Get Type - * + * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_ATTRIBUTE_URL; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Response/Model/BaseList.php b/src/Appwrite/Utopia/Response/Model/BaseList.php index 404f2ad652..ee8788e6a6 100644 --- a/src/Appwrite/Utopia/Response/Model/BaseList.php +++ b/src/Appwrite/Utopia/Response/Model/BaseList.php @@ -11,7 +11,7 @@ class BaseList extends Model * @var string */ protected $name = ''; - + /** * @var string */ @@ -53,7 +53,7 @@ class BaseList extends Model } $this->addRule($key, [ 'type' => $model, - 'description' => 'List of '.$key.'.', + 'description' => 'List of ' . $key . '.', 'default' => [], 'array' => true, ]); @@ -64,7 +64,7 @@ class BaseList extends Model * * @return string */ - public function getName():string + public function getName(): string { return $this->name; } @@ -74,7 +74,7 @@ class BaseList extends Model * * @return string */ - public function getType():string + public function getType(): string { return $this->type; } diff --git a/src/Appwrite/Utopia/Response/Model/Bucket.php b/src/Appwrite/Utopia/Response/Model/Bucket.php index a2f39499cc..0d9c6e98e5 100644 --- a/src/Appwrite/Utopia/Response/Model/Bucket.php +++ b/src/Appwrite/Utopia/Response/Model/Bucket.php @@ -7,7 +7,6 @@ use Appwrite\Utopia\Response\Model; class Bucket extends Model { - public function __construct() { $this diff --git a/src/Appwrite/Utopia/Response/Model/Collection.php b/src/Appwrite/Utopia/Response/Model/Collection.php index 69a1c7184e..2f6a7af0f3 100644 --- a/src/Appwrite/Utopia/Response/Model/Collection.php +++ b/src/Appwrite/Utopia/Response/Model/Collection.php @@ -61,14 +61,14 @@ class Collection extends Model ], 'description' => 'Collection attributes.', 'default' => [], - 'example' => new \stdClass, + 'example' => new \stdClass(), 'array' => true, ]) ->addRule('indexes', [ 'type' => Response::MODEL_INDEX, 'description' => 'Collection indexes.', 'default' => [], - 'example' => new \stdClass, + 'example' => new \stdClass(), 'array' => true ]) ; @@ -79,7 +79,7 @@ class Collection extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Collection'; } @@ -89,7 +89,7 @@ class Collection extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_COLLECTION; } diff --git a/src/Appwrite/Utopia/Response/Model/Continent.php b/src/Appwrite/Utopia/Response/Model/Continent.php index 2d12f9d6a6..5291424a4a 100644 --- a/src/Appwrite/Utopia/Response/Model/Continent.php +++ b/src/Appwrite/Utopia/Response/Model/Continent.php @@ -30,7 +30,7 @@ class Continent extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Continent'; } @@ -40,7 +40,7 @@ class Continent extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_CONTINENT; } diff --git a/src/Appwrite/Utopia/Response/Model/Country.php b/src/Appwrite/Utopia/Response/Model/Country.php index 1595aea75f..64590a54d4 100644 --- a/src/Appwrite/Utopia/Response/Model/Country.php +++ b/src/Appwrite/Utopia/Response/Model/Country.php @@ -30,7 +30,7 @@ class Country extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Country'; } @@ -40,7 +40,7 @@ class Country extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_COUNTRY; } diff --git a/src/Appwrite/Utopia/Response/Model/Currency.php b/src/Appwrite/Utopia/Response/Model/Currency.php index d6f9a6b166..883ef486d8 100644 --- a/src/Appwrite/Utopia/Response/Model/Currency.php +++ b/src/Appwrite/Utopia/Response/Model/Currency.php @@ -60,7 +60,7 @@ class Currency extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Currency'; } @@ -70,7 +70,7 @@ class Currency extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_CURRENCY; } diff --git a/src/Appwrite/Utopia/Response/Model/Deployment.php b/src/Appwrite/Utopia/Response/Model/Deployment.php index b2d38f144a..3aefe4dd77 100644 --- a/src/Appwrite/Utopia/Response/Model/Deployment.php +++ b/src/Appwrite/Utopia/Response/Model/Deployment.php @@ -84,7 +84,7 @@ class Deployment extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Deployment'; } @@ -94,7 +94,7 @@ class Deployment extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_DEPLOYMENT; } diff --git a/src/Appwrite/Utopia/Response/Model/Domain.php b/src/Appwrite/Utopia/Response/Model/Domain.php index 9bd665fa2c..54031acbdb 100644 --- a/src/Appwrite/Utopia/Response/Model/Domain.php +++ b/src/Appwrite/Utopia/Response/Model/Domain.php @@ -11,7 +11,7 @@ class Domain extends Model * @var bool */ protected $public = false; - + public function __construct() { $this @@ -59,7 +59,7 @@ class Domain extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Domain'; } @@ -69,7 +69,7 @@ class Domain extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_DOMAIN; } diff --git a/src/Appwrite/Utopia/Response/Model/Error.php b/src/Appwrite/Utopia/Response/Model/Error.php index 20c91fa7c0..99cf3cbce2 100644 --- a/src/Appwrite/Utopia/Response/Model/Error.php +++ b/src/Appwrite/Utopia/Response/Model/Error.php @@ -42,7 +42,7 @@ class Error extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Error'; } @@ -52,7 +52,7 @@ class Error extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_ERROR; } diff --git a/src/Appwrite/Utopia/Response/Model/ErrorDev.php b/src/Appwrite/Utopia/Response/Model/ErrorDev.php index abe2229ea0..b5450c67ad 100644 --- a/src/Appwrite/Utopia/Response/Model/ErrorDev.php +++ b/src/Appwrite/Utopia/Response/Model/ErrorDev.php @@ -14,7 +14,7 @@ class ErrorDev extends Error public function __construct() { parent::__construct(); - + $this ->addRule('file', [ 'type' => self::TYPE_STRING, @@ -43,7 +43,7 @@ class ErrorDev extends Error * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_ERROR_DEV; } diff --git a/src/Appwrite/Utopia/Response/Model/Execution.php b/src/Appwrite/Utopia/Response/Model/Execution.php index a8031bb0cd..0be784b37c 100644 --- a/src/Appwrite/Utopia/Response/Model/Execution.php +++ b/src/Appwrite/Utopia/Response/Model/Execution.php @@ -79,7 +79,7 @@ class Execution extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Execution'; } @@ -89,7 +89,7 @@ class Execution extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_EXECUTION; } diff --git a/src/Appwrite/Utopia/Response/Model/File.php b/src/Appwrite/Utopia/Response/Model/File.php index f41557b23b..c475b145bb 100644 --- a/src/Appwrite/Utopia/Response/Model/File.php +++ b/src/Appwrite/Utopia/Response/Model/File.php @@ -86,7 +86,7 @@ class File extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'File'; } @@ -96,7 +96,7 @@ class File extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_FILE; } diff --git a/src/Appwrite/Utopia/Response/Model/Func.php b/src/Appwrite/Utopia/Response/Model/Func.php index c409768b9b..c2bf5f6589 100644 --- a/src/Appwrite/Utopia/Response/Model/Func.php +++ b/src/Appwrite/Utopia/Response/Model/Func.php @@ -106,7 +106,7 @@ class Func extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Function'; } @@ -116,27 +116,27 @@ class Func extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_FUNCTION; } /** * Filter Function - * + * * Automatically converts a [] default to a stdClass, this is called while grabbing the document. - * + * * @param Document $document * @return Document */ public function filter(Document $document): Document { $vars = $document->getAttribute('vars'); - if($vars instanceof Document) { + if ($vars instanceof Document) { $vars = $vars->getArrayCopy(); } - if(is_array($vars) && empty($vars)) { + if (is_array($vars) && empty($vars)) { $document->setAttribute('vars', new stdClass()); } return $document; diff --git a/src/Appwrite/Utopia/Response/Model/HealthAntivirus.php b/src/Appwrite/Utopia/Response/Model/HealthAntivirus.php index 26bc8f8279..7a74195371 100644 --- a/src/Appwrite/Utopia/Response/Model/HealthAntivirus.php +++ b/src/Appwrite/Utopia/Response/Model/HealthAntivirus.php @@ -30,7 +30,7 @@ class HealthAntivirus extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Health Antivirus'; } @@ -40,7 +40,7 @@ class HealthAntivirus extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_HEALTH_ANTIVIRUS; } diff --git a/src/Appwrite/Utopia/Response/Model/HealthQueue.php b/src/Appwrite/Utopia/Response/Model/HealthQueue.php index 04120a1ade..da7c49a43f 100644 --- a/src/Appwrite/Utopia/Response/Model/HealthQueue.php +++ b/src/Appwrite/Utopia/Response/Model/HealthQueue.php @@ -24,7 +24,7 @@ class HealthQueue extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Health Queue'; } @@ -34,7 +34,7 @@ class HealthQueue extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_HEALTH_QUEUE; } diff --git a/src/Appwrite/Utopia/Response/Model/HealthStatus.php b/src/Appwrite/Utopia/Response/Model/HealthStatus.php index 2887c3c4d7..23756de131 100644 --- a/src/Appwrite/Utopia/Response/Model/HealthStatus.php +++ b/src/Appwrite/Utopia/Response/Model/HealthStatus.php @@ -30,7 +30,7 @@ class HealthStatus extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Health Status'; } @@ -40,7 +40,7 @@ class HealthStatus extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_HEALTH_STATUS; } diff --git a/src/Appwrite/Utopia/Response/Model/HealthTime.php b/src/Appwrite/Utopia/Response/Model/HealthTime.php index 2bd666ed26..042d073ce5 100644 --- a/src/Appwrite/Utopia/Response/Model/HealthTime.php +++ b/src/Appwrite/Utopia/Response/Model/HealthTime.php @@ -36,7 +36,7 @@ class HealthTime extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Health Time'; } @@ -46,7 +46,7 @@ class HealthTime extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_HEALTH_TIME; } diff --git a/src/Appwrite/Utopia/Response/Model/HealthVersion.php b/src/Appwrite/Utopia/Response/Model/HealthVersion.php index fed63714c5..15a73c0e75 100644 --- a/src/Appwrite/Utopia/Response/Model/HealthVersion.php +++ b/src/Appwrite/Utopia/Response/Model/HealthVersion.php @@ -24,7 +24,7 @@ class HealthVersion extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Health Version'; } @@ -34,7 +34,7 @@ class HealthVersion extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_HEALTH_VERSION; } diff --git a/src/Appwrite/Utopia/Response/Model/Index.php b/src/Appwrite/Utopia/Response/Model/Index.php index 9328198ee2..b7ac626be9 100644 --- a/src/Appwrite/Utopia/Response/Model/Index.php +++ b/src/Appwrite/Utopia/Response/Model/Index.php @@ -48,20 +48,20 @@ class Index extends Model /** * Get Name - * + * * @return string */ - public function getName():string + public function getName(): string { return 'Index'; } /** * Get Collection - * + * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_INDEX; } diff --git a/src/Appwrite/Utopia/Response/Model/JWT.php b/src/Appwrite/Utopia/Response/Model/JWT.php index 5777479910..a2563a2ad8 100644 --- a/src/Appwrite/Utopia/Response/Model/JWT.php +++ b/src/Appwrite/Utopia/Response/Model/JWT.php @@ -23,7 +23,7 @@ class JWT extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'JWT'; } @@ -33,7 +33,7 @@ class JWT extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_JWT; } diff --git a/src/Appwrite/Utopia/Response/Model/Key.php b/src/Appwrite/Utopia/Response/Model/Key.php index c01136d24f..d5a19012cd 100644 --- a/src/Appwrite/Utopia/Response/Model/Key.php +++ b/src/Appwrite/Utopia/Response/Model/Key.php @@ -11,7 +11,7 @@ class Key extends Model * @var bool */ protected $public = false; - + public function __construct() { $this @@ -48,7 +48,7 @@ class Key extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Key'; } @@ -58,7 +58,7 @@ class Key extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_KEY; } diff --git a/src/Appwrite/Utopia/Response/Model/Language.php b/src/Appwrite/Utopia/Response/Model/Language.php index e56dd7a744..64f99a006f 100644 --- a/src/Appwrite/Utopia/Response/Model/Language.php +++ b/src/Appwrite/Utopia/Response/Model/Language.php @@ -36,7 +36,7 @@ class Language extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Language'; } @@ -46,7 +46,7 @@ class Language extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_LANGUAGE; } diff --git a/src/Appwrite/Utopia/Response/Model/Locale.php b/src/Appwrite/Utopia/Response/Model/Locale.php index 292ea1d82d..e883a76fd4 100644 --- a/src/Appwrite/Utopia/Response/Model/Locale.php +++ b/src/Appwrite/Utopia/Response/Model/Locale.php @@ -60,7 +60,7 @@ class Locale extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Locale'; } @@ -70,7 +70,7 @@ class Locale extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_LOCALE; } diff --git a/src/Appwrite/Utopia/Response/Model/Log.php b/src/Appwrite/Utopia/Response/Model/Log.php index ba2e52dbcb..67b2efcc89 100644 --- a/src/Appwrite/Utopia/Response/Model/Log.php +++ b/src/Appwrite/Utopia/Response/Model/Log.php @@ -144,7 +144,7 @@ class Log extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Log'; } @@ -154,7 +154,7 @@ class Log extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_LOG; } diff --git a/src/Appwrite/Utopia/Response/Model/Membership.php b/src/Appwrite/Utopia/Response/Model/Membership.php index 2e093b7650..c1f5d402b4 100644 --- a/src/Appwrite/Utopia/Response/Model/Membership.php +++ b/src/Appwrite/Utopia/Response/Model/Membership.php @@ -79,7 +79,7 @@ class Membership extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Membership'; } @@ -89,7 +89,7 @@ class Membership extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_MEMBERSHIP; } diff --git a/src/Appwrite/Utopia/Response/Model/Metric.php b/src/Appwrite/Utopia/Response/Model/Metric.php index 26038af081..70706d6143 100644 --- a/src/Appwrite/Utopia/Response/Model/Metric.php +++ b/src/Appwrite/Utopia/Response/Model/Metric.php @@ -27,21 +27,21 @@ class Metric extends Model /** * Get Name - * + * * @return string */ - public function getName():string + public function getName(): string { return 'Metric'; } /** * Get Collection - * + * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_METRIC; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Response/Model/Mock.php b/src/Appwrite/Utopia/Response/Model/Mock.php index ae3030828c..afdae66084 100644 --- a/src/Appwrite/Utopia/Response/Model/Mock.php +++ b/src/Appwrite/Utopia/Response/Model/Mock.php @@ -24,7 +24,7 @@ class Mock extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Mock'; } @@ -34,7 +34,7 @@ class Mock extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_MOCK; } diff --git a/src/Appwrite/Utopia/Response/Model/None.php b/src/Appwrite/Utopia/Response/Model/None.php index 78d990ea1b..ecc387498e 100644 --- a/src/Appwrite/Utopia/Response/Model/None.php +++ b/src/Appwrite/Utopia/Response/Model/None.php @@ -17,7 +17,7 @@ class None extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'None'; } @@ -27,7 +27,7 @@ class None extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_NONE; } diff --git a/src/Appwrite/Utopia/Response/Model/Phone.php b/src/Appwrite/Utopia/Response/Model/Phone.php index 744f90372f..226955919b 100644 --- a/src/Appwrite/Utopia/Response/Model/Phone.php +++ b/src/Appwrite/Utopia/Response/Model/Phone.php @@ -36,7 +36,7 @@ class Phone extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Phone'; } @@ -46,7 +46,7 @@ class Phone extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_PHONE; } diff --git a/src/Appwrite/Utopia/Response/Model/Platform.php b/src/Appwrite/Utopia/Response/Model/Platform.php index 0377b0cafc..e36a63e61d 100644 --- a/src/Appwrite/Utopia/Response/Model/Platform.php +++ b/src/Appwrite/Utopia/Response/Model/Platform.php @@ -70,7 +70,7 @@ class Platform extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Platform'; } @@ -80,7 +80,7 @@ class Platform extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_PLATFORM; } diff --git a/src/Appwrite/Utopia/Response/Model/Preferences.php b/src/Appwrite/Utopia/Response/Model/Preferences.php index 68e1781633..ad4bf66132 100644 --- a/src/Appwrite/Utopia/Response/Model/Preferences.php +++ b/src/Appwrite/Utopia/Response/Model/Preferences.php @@ -16,7 +16,7 @@ class Preferences extends Any * * @return string */ - public function getName():string + public function getName(): string { return 'Preferences'; } @@ -26,7 +26,7 @@ class Preferences extends Any * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_PREFERENCES; } diff --git a/src/Appwrite/Utopia/Response/Model/Project.php b/src/Appwrite/Utopia/Response/Model/Project.php index 9071966e3b..06906f8712 100644 --- a/src/Appwrite/Utopia/Response/Model/Project.php +++ b/src/Appwrite/Utopia/Response/Model/Project.php @@ -13,7 +13,7 @@ class Project extends Model * @var bool */ protected $public = false; - + public function __construct() { $this @@ -99,28 +99,28 @@ class Project extends Model 'type' => Response::MODEL_PLATFORM, 'description' => 'List of Platforms.', 'default' => [], - 'example' => new \stdClass, + 'example' => new \stdClass(), 'array' => true, ]) ->addRule('webhooks', [ 'type' => Response::MODEL_WEBHOOK, 'description' => 'List of Webhooks.', 'default' => [], - 'example' => new \stdClass, + 'example' => new \stdClass(), 'array' => true, ]) ->addRule('keys', [ 'type' => Response::MODEL_KEY, 'description' => 'List of API Keys.', 'default' => [], - 'example' => new \stdClass, + 'example' => new \stdClass(), 'array' => true, ]) ->addRule('domains', [ 'type' => Response::MODEL_DOMAIN, 'description' => 'List of Domains.', 'default' => [], - 'example' => new \stdClass, + 'example' => new \stdClass(), 'array' => true, ]) ; @@ -137,15 +137,15 @@ class Project extends Model $name = (isset($provider['name'])) ? $provider['name'] : 'Unknown'; $this - ->addRule('provider'.\ucfirst($index).'Appid', [ + ->addRule('provider' . \ucfirst($index) . 'Appid', [ 'type' => self::TYPE_STRING, - 'description' => $name.' OAuth app ID.', + 'description' => $name . ' OAuth app ID.', 'example' => '123247283472834787438', 'default' => '', ]) - ->addRule('provider'.\ucfirst($index).'Secret', [ + ->addRule('provider' . \ucfirst($index) . 'Secret', [ 'type' => self::TYPE_STRING, - 'description' => $name.' OAuth secret ID.', + 'description' => $name . ' OAuth secret ID.', 'example' => 'djsgudsdsewe43434343dd34...', 'default' => '', ]) @@ -159,7 +159,7 @@ class Project extends Model $this ->addRule('auth' . ucfirst($key), [ 'type' => self::TYPE_BOOLEAN, - 'description' => $name.' auth method status', + 'description' => $name . ' auth method status', 'example' => true, 'default' => true, ]) @@ -167,7 +167,7 @@ class Project extends Model } foreach ($services as $service) { - if(!$service['optional']) { + if (!$service['optional']) { continue; } @@ -175,9 +175,9 @@ class Project extends Model $key = $service['key'] ?? ''; $this - ->addRule('serviceStatusFor'.ucfirst($key), [ + ->addRule('serviceStatusFor' . ucfirst($key), [ 'type' => self::TYPE_BOOLEAN, - 'description' => $name.' service status', + 'description' => $name . ' service status', 'example' => true, 'default' => true, ]) @@ -190,7 +190,7 @@ class Project extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Project'; } @@ -200,14 +200,14 @@ class Project extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_PROJECT; } /** * Get Collection - * + * * @return string */ public function filter(Document $document): Document @@ -215,16 +215,16 @@ class Project extends Model $values = $document->getAttribute('services', []); $services = Config::getParam('services', []); - foreach($services as $service) { - if(!$service['optional']) { + foreach ($services as $service) { + if (!$service['optional']) { continue; } $key = $service['key'] ?? ''; $value = $values[$key] ?? true; - $document->setAttribute('serviceStatusFor'.ucfirst($key), $value); + $document->setAttribute('serviceStatusFor' . ucfirst($key), $value); } - $authValues = $document->getAttribute('auths',[]); + $authValues = $document->getAttribute('auths', []); $auth = Config::getParam('auth', []); $document->setAttribute('authLimit', $authValues['limit'] ?? 0); diff --git a/src/Appwrite/Utopia/Response/Model/Runtime.php b/src/Appwrite/Utopia/Response/Model/Runtime.php index 2aae2f95ef..8bc42cb418 100644 --- a/src/Appwrite/Utopia/Response/Model/Runtime.php +++ b/src/Appwrite/Utopia/Response/Model/Runtime.php @@ -61,7 +61,7 @@ class Runtime extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Runtime'; } @@ -71,7 +71,7 @@ class Runtime extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_RUNTIME; } diff --git a/src/Appwrite/Utopia/Response/Model/Session.php b/src/Appwrite/Utopia/Response/Model/Session.php index f98e797845..145ff4a27e 100644 --- a/src/Appwrite/Utopia/Response/Model/Session.php +++ b/src/Appwrite/Utopia/Response/Model/Session.php @@ -162,7 +162,7 @@ class Session extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Session'; } @@ -172,7 +172,7 @@ class Session extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_SESSION; } diff --git a/src/Appwrite/Utopia/Response/Model/Team.php b/src/Appwrite/Utopia/Response/Model/Team.php index afecd050d1..39b5feb07e 100644 --- a/src/Appwrite/Utopia/Response/Model/Team.php +++ b/src/Appwrite/Utopia/Response/Model/Team.php @@ -42,7 +42,7 @@ class Team extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Team'; } @@ -52,7 +52,7 @@ class Team extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_TEAM; } diff --git a/src/Appwrite/Utopia/Response/Model/Token.php b/src/Appwrite/Utopia/Response/Model/Token.php index 84dc467734..0ba6a804bf 100644 --- a/src/Appwrite/Utopia/Response/Model/Token.php +++ b/src/Appwrite/Utopia/Response/Model/Token.php @@ -42,7 +42,7 @@ class Token extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Token'; } @@ -52,7 +52,7 @@ class Token extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_TOKEN; } diff --git a/src/Appwrite/Utopia/Response/Model/UsageBuckets.php b/src/Appwrite/Utopia/Response/Model/UsageBuckets.php index 99849bb98c..72a2cc9f52 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageBuckets.php +++ b/src/Appwrite/Utopia/Response/Model/UsageBuckets.php @@ -20,64 +20,64 @@ class UsageBuckets extends Model 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for total number of files in this bucket.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('filesStorage', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for total storage of files in this bucket.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('filesCreate', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for files created.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('filesRead', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for files read.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('filesUpdate', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for files updated.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('filesDelete', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for files deleted.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ; } /** * Get Name - * + * * @return string */ - public function getName():string + public function getName(): string { return 'UsageBuckets'; } /** * Get Type - * + * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_USAGE_BUCKETS; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Response/Model/UsageCollection.php b/src/Appwrite/Utopia/Response/Model/UsageCollection.php index 3a6acbaab3..1fb8b0beb5 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageCollection.php +++ b/src/Appwrite/Utopia/Response/Model/UsageCollection.php @@ -20,57 +20,57 @@ class UsageCollection extends Model 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for total number of documents.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('documentsCreate', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for documents created.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('documentsRead', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for documents read.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('documentsUpdate', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for documents updated.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('documentsDelete', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for documents deleted.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ; } /** * Get Name - * + * * @return string */ - public function getName():string + public function getName(): string { return 'UsageCollection'; } /** * Get Type - * + * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_USAGE_COLLECTION; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Response/Model/UsageDatabase.php b/src/Appwrite/Utopia/Response/Model/UsageDatabase.php index 4d78381565..f69b4ef884 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageDatabase.php +++ b/src/Appwrite/Utopia/Response/Model/UsageDatabase.php @@ -20,92 +20,92 @@ class UsageDatabase extends Model 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for total number of documents.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('collectionsCount', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for total number of collections.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('documentsCreate', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for documents created.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('documentsRead', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for documents read.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('documentsUpdate', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for documents updated.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('documentsDelete', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for documents deleted.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('collectionsCreate', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for collections created.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('collectionsRead', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for collections read.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('collectionsUpdate', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for collections updated.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('collectionsDelete', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for collections delete.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ; } /** * Get Name - * + * * @return string */ - public function getName():string + public function getName(): string { return 'UsageDatabase'; } /** * Get Type - * + * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_USAGE_DATABASE; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Response/Model/UsageFunctions.php b/src/Appwrite/Utopia/Response/Model/UsageFunctions.php index 15a7e4de7d..48ba65fa21 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageFunctions.php +++ b/src/Appwrite/Utopia/Response/Model/UsageFunctions.php @@ -20,43 +20,43 @@ class UsageFunctions extends Model 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for function executions.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('functionsFailures', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for function execution failures.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('functionsCompute', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for function execution duration.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ; } /** * Get Name - * + * * @return string */ - public function getName():string + public function getName(): string { return 'UsageFunctions'; } /** * Get Type - * + * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_USAGE_FUNCTIONS; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Response/Model/UsageProject.php b/src/Appwrite/Utopia/Response/Model/UsageProject.php index 5593def1d8..2b431181ce 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageProject.php +++ b/src/Appwrite/Utopia/Response/Model/UsageProject.php @@ -20,71 +20,71 @@ class UsageProject extends Model 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for number of requests.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('network', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for consumed bandwidth.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('functions', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for function executions.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('documents', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for number of documents.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('collections', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for number of collections.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('users', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for number of users.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('storage', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for the occupied storage size (in bytes).', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ; } /** * Get Name - * + * * @return string */ - public function getName():string + public function getName(): string { return 'UsageProject'; } /** * Get Type - * + * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_USAGE_PROJECT; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Response/Model/UsageStorage.php b/src/Appwrite/Utopia/Response/Model/UsageStorage.php index 84c9af03ad..7d0d5ed0fa 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageStorage.php +++ b/src/Appwrite/Utopia/Response/Model/UsageStorage.php @@ -20,106 +20,106 @@ class UsageStorage extends Model 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for the occupied storage size by files (in bytes).', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('tagsStorage', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for the occupied storage size by tags (in bytes).', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('filesCount', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for total number of files.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('bucketsCount', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for total number of buckets.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('bucketsCreate', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for buckets created.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('bucketsRead', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for buckets read.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('bucketsUpdate', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for buckets updated.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('bucketsDelete', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for buckets deleted.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('filesCreate', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for files created.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('filesRead', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for files read.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('filesUpdate', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for files updated.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('filesDelete', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for files deleted.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ; } /** * Get Name - * + * * @return string */ - public function getName():string + public function getName(): string { return 'StorageUsage'; } /** * Get Type - * + * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_USAGE_STORAGE; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Response/Model/UsageUsers.php b/src/Appwrite/Utopia/Response/Model/UsageUsers.php index 153a2d32d4..70c21f83dc 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageUsers.php +++ b/src/Appwrite/Utopia/Response/Model/UsageUsers.php @@ -20,78 +20,78 @@ class UsageUsers extends Model 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for total number of users.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('usersCreate', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for users created.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('usersRead', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for users read.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('usersUpdate', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for users updated.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('usersDelete', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for users deleted.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('sessionsCreate', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for sessions created.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('sessionsProviderCreate', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for sessions created for a provider ( email, anonymous or oauth2 ).', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ->addRule('sessionsDelete', [ 'type' => Response::MODEL_METRIC_LIST, 'description' => 'Aggregated stats for sessions deleted.', 'default' => [], - 'example' => new \stdClass, - 'array' => true + 'example' => new \stdClass(), + 'array' => true ]) ; } /** * Get Name - * + * * @return string */ - public function getName():string + public function getName(): string { return 'UsageUsers'; } /** * Get Type - * + * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_USAGE_USERS; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Response/Model/User.php b/src/Appwrite/Utopia/Response/Model/User.php index 6c87778043..fe5bd3aa9c 100644 --- a/src/Appwrite/Utopia/Response/Model/User.php +++ b/src/Appwrite/Utopia/Response/Model/User.php @@ -56,7 +56,7 @@ class User extends Model ->addRule('prefs', [ 'type' => Response::MODEL_PREFERENCES, 'description' => 'User preferences as a key-value object', - 'default' => new \stdClass, + 'default' => new \stdClass(), 'example' => ['theme' => 'pink', 'timezone' => 'UTC'], ]) ; @@ -64,18 +64,18 @@ class User extends Model /** * Get Collection - * + * * @return string */ public function filter(Document $document): Document { $prefs = $document->getAttribute('prefs'); - if($prefs instanceof Document) { + if ($prefs instanceof Document) { $prefs = $prefs->getArrayCopy(); } - if(is_array($prefs) && empty($prefs)) { - $document->setAttribute('prefs', new \stdClass); + if (is_array($prefs) && empty($prefs)) { + $document->setAttribute('prefs', new \stdClass()); } return $document; } @@ -85,7 +85,7 @@ class User extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'User'; } @@ -95,7 +95,7 @@ class User extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_USER; } diff --git a/src/Appwrite/Utopia/Response/Model/Webhook.php b/src/Appwrite/Utopia/Response/Model/Webhook.php index 14f45164a6..0fabdc2a60 100644 --- a/src/Appwrite/Utopia/Response/Model/Webhook.php +++ b/src/Appwrite/Utopia/Response/Model/Webhook.php @@ -58,6 +58,12 @@ class Webhook extends Model 'default' => '', 'example' => 'password', ]) + ->addRule('signatureKey', [ + 'type' => self::TYPE_STRING, + 'description' => 'Signature key which can be used to validated incoming', + 'default' => '', + 'example' => 'ad3d581ca230e2b7059c545e5a', + ]) ; } @@ -66,7 +72,7 @@ class Webhook extends Model * * @return string */ - public function getName():string + public function getName(): string { return 'Webhook'; } @@ -76,7 +82,7 @@ class Webhook extends Model * * @return string */ - public function getType():string + public function getType(): string { return Response::MODEL_WEBHOOK; } diff --git a/src/Appwrite/Utopia/View.php b/src/Appwrite/Utopia/View.php index 4dee180877..e4ed8164c9 100644 --- a/src/Appwrite/Utopia/View.php +++ b/src/Appwrite/Utopia/View.php @@ -19,4 +19,4 @@ class View extends OldView { return \htmlentities($str, ENT_QUOTES, 'UTF-8'); } -} \ No newline at end of file +} diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index 300e1a7a9b..416d47ab82 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -8,15 +8,15 @@ use Utopia\CLI\Console; class Executor { - const METHOD_GET = 'GET'; - const METHOD_POST = 'POST'; - const METHOD_PUT = 'PUT'; - const METHOD_PATCH = 'PATCH'; - const METHOD_DELETE = 'DELETE'; - const METHOD_HEAD = 'HEAD'; - const METHOD_OPTIONS = 'OPTIONS'; - const METHOD_CONNECT = 'CONNECT'; - const METHOD_TRACE = 'TRACE'; + public const METHOD_GET = 'GET'; + public const METHOD_POST = 'POST'; + public const METHOD_PUT = 'PUT'; + public const METHOD_PATCH = 'PATCH'; + public const METHOD_DELETE = 'DELETE'; + public const METHOD_HEAD = 'HEAD'; + public const METHOD_OPTIONS = 'OPTIONS'; + public const METHOD_CONNECT = 'CONNECT'; + public const METHOD_TRACE = 'TRACE'; private $endpoint; @@ -36,9 +36,9 @@ class Executor /** * Create runtime - * + * * Launches a runtime container for a deployment ready for execution - * + * * @param string $deploymentId * @param string $projectId * @param string $source @@ -53,10 +53,10 @@ class Executor * @param array $commands */ public function createRuntime( - string $deploymentId, - string $projectId, + string $deploymentId, + string $projectId, string $source, - string $runtime, + string $runtime, string $baseImage, bool $remove = false, string $entrypoint = '', @@ -90,16 +90,16 @@ class Executor $status = $response['headers']['status-code']; if ($status >= 400) { throw new \Exception($response['body']['message'], $status); - } + } return $response['body']; } /** * Delete Runtime - * + * * Deletes a runtime and cleans up any containers remaining. - * + * * @param string $projectId * @param string $deploymentId */ @@ -115,7 +115,7 @@ class Executor $params = []; $response = $this->call(self::METHOD_DELETE, $route, $headers, $params, true, 30); - + $status = $response['headers']['status-code']; if ($status >= 400) { throw new \Exception($response['body']['message'], $status); @@ -126,7 +126,7 @@ class Executor /** * Create an execution - * + * * @param string $projectId * @param string $deploymentId * @param string $path @@ -136,7 +136,7 @@ class Executor * @param string runtime * @param string $baseImage * @param int $timeout - * + * * @return array */ public function createExecution( @@ -157,7 +157,7 @@ class Executor ]; $params = [ 'runtimeId' => "$projectId-$deploymentId", - 'vars' => $vars, + 'vars' => $vars, 'data' => $data, 'timeout' => $timeout, ]; @@ -186,10 +186,18 @@ class Executor ); $response = $this->call(self::METHOD_POST, $route, $headers, $params, true, $requestTimeout); $status = $response['headers']['status-code']; + + if ($status < 400) { + return $response['body']; + } break; case $status === 406: $response = $this->call(self::METHOD_POST, $route, $headers, $params, true, $requestTimeout); $status = $response['headers']['status-code']; + + if ($status < 400) { + return $response['body']; + } break; default: throw new \Exception($response['body']['message'], $status); @@ -248,7 +256,7 @@ class Executor curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($curl, $header) use (&$responseHeaders) { $len = strlen($header); @@ -277,18 +285,18 @@ class Executor $responseType = $responseHeaders['content-type'] ?? ''; $responseStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE); - if($decode) { + if ($decode) { switch (substr($responseType, 0, strpos($responseType, ';'))) { case 'application/json': $json = json_decode($responseBody, true); - + if ($json === null) { - throw new Exception('Failed to parse response: '.$responseBody); + throw new Exception('Failed to parse response: ' . $responseBody); } - + $responseBody = $json; $json = null; - break; + break; } } diff --git a/tests/benchmarks/http.js b/tests/benchmarks/http.js index c84fc18251..799c8fb23c 100644 --- a/tests/benchmarks/http.js +++ b/tests/benchmarks/http.js @@ -9,22 +9,22 @@ export const requests = new Counter('http_reqs'); // target is the number of VUs you are aiming for export const options = { - stages: [ + stages: [ { target: 50, duration: '1m' }, // { target: 15, duration: '1m' }, // { target: 0, duration: '1m' }, - ], - thresholds: { - requests: ['count < 100'], - }, + ], + thresholds: { + requests: ['count < 100'], + }, }; export default function () { const config = { - headers: { - 'X-Appwrite-Key': '24356eb021863f81eb7dd77c7750304d0464e141cad6e9a8befa1f7d2b066fde190df3dab1e8d2639dbb82ee848da30501424923f4cd80d887ee40ad77ded62763ee489448523f6e39667f290f9a54b2ab8fad131a0bc985e6c0f760015f7f3411e40626c75646bb19d2bb2f7bf2f63130918220a206758cbc48845fd725a695', - 'X-Appwrite-Project': '60479fe35d95d' - }} + headers: { + 'X-Appwrite-Key': '24356eb021863f81eb7dd77c7750304d0464e141cad6e9a8befa1f7d2b066fde190df3dab1e8d2639dbb82ee848da30501424923f4cd80d887ee40ad77ded62763ee489448523f6e39667f290f9a54b2ab8fad131a0bc985e6c0f760015f7f3411e40626c75646bb19d2bb2f7bf2f63130918220a206758cbc48845fd725a695', + 'X-Appwrite-Project': '60479fe35d95d' + }} const resDb = http.get('http://localhost:9501/', config); diff --git a/tests/benchmarks/ws.js b/tests/benchmarks/ws.js index 768930d5c4..916458856f 100644 --- a/tests/benchmarks/ws.js +++ b/tests/benchmarks/ws.js @@ -9,11 +9,11 @@ export let options = { { duration: '10s', target: 500 - }, + }, { duration: '1m', target: 500 - }, + }, ], } diff --git a/tests/e2e/Client.php b/tests/e2e/Client.php index c86ebc5951..226556b789 100644 --- a/tests/e2e/Client.php +++ b/tests/e2e/Client.php @@ -6,15 +6,15 @@ use Exception; class Client { - const METHOD_GET = 'GET'; - const METHOD_POST = 'POST'; - const METHOD_PUT = 'PUT'; - const METHOD_PATCH = 'PATCH'; - const METHOD_DELETE = 'DELETE'; - const METHOD_HEAD = 'HEAD'; - const METHOD_OPTIONS = 'OPTIONS'; - const METHOD_CONNECT = 'CONNECT'; - const METHOD_TRACE = 'TRACE'; + public const METHOD_GET = 'GET'; + public const METHOD_POST = 'POST'; + public const METHOD_PUT = 'PUT'; + public const METHOD_PATCH = 'PATCH'; + public const METHOD_DELETE = 'DELETE'; + public const METHOD_HEAD = 'HEAD'; + public const METHOD_OPTIONS = 'OPTIONS'; + public const METHOD_CONNECT = 'CONNECT'; + public const METHOD_TRACE = 'TRACE'; /** * Is Self Signed Certificates Allowed? @@ -226,18 +226,18 @@ class Client $responseType = $responseHeaders['content-type'] ?? ''; $responseStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE); - if($decode) { + if ($decode) { switch (substr($responseType, 0, strpos($responseType, ';'))) { case 'application/json': $json = json_decode($responseBody, true); - + if ($json === null) { - throw new Exception('Failed to parse response: '.$responseBody); + throw new Exception('Failed to parse response: ' . $responseBody); } - + $responseBody = $json; $json = null; - break; + break; } } @@ -250,7 +250,7 @@ class Client $responseHeaders['status-code'] = $responseStatus; if ($responseStatus === 500) { - echo 'Server error('.$method.': '.$path.'. Params: '.json_encode($params).'): '.json_encode($responseBody)."\n"; + echo 'Server error(' . $method . ': ' . $path . '. Params: ' . json_encode($params) . '): ' . json_encode($responseBody) . "\n"; } return [ diff --git a/tests/e2e/General/HTTPTest.php b/tests/e2e/General/HTTPTest.php index 3d4ec32b46..268ef330f3 100644 --- a/tests/e2e/General/HTTPTest.php +++ b/tests/e2e/General/HTTPTest.php @@ -164,16 +164,16 @@ class HTTPTest extends Scope $client = new Client(); $client->setEndpoint('https://validator.swagger.io'); - foreach($files as $file) { - if(in_array($file, ['.', '..'])) { + foreach ($files as $file) { + if (in_array($file, ['.', '..'])) { continue; } - if( + if ( (strpos($file, 'latest') === false) && (strpos($file, '0.12.x') === false) && (strpos($file, '0.13.x') === false) - ) { + ) { continue; } @@ -182,7 +182,7 @@ class HTTPTest extends Scope */ $response = $client->call(Client::METHOD_POST, '/validator/debug', [ 'content-type' => 'application/json', - ], json_decode(file_get_contents($directory.$file), true)); + ], json_decode(file_get_contents($directory . $file), true)); $response['body'] = json_decode($response['body'], true); $this->assertEquals(200, $response['headers']['status-code']); @@ -190,7 +190,8 @@ class HTTPTest extends Scope } } - public function testVersions() { + public function testVersions() + { /** * Test without header */ diff --git a/tests/e2e/Scopes/ProjectCustom.php b/tests/e2e/Scopes/ProjectCustom.php index 049583743c..62f4f95dfd 100644 --- a/tests/e2e/Scopes/ProjectCustom.php +++ b/tests/e2e/Scopes/ProjectCustom.php @@ -90,7 +90,7 @@ trait ProjectCustom $this->assertNotEmpty($key['body']); $this->assertNotEmpty($key['body']['secret']); - $webhook = $this->client->call(Client::METHOD_POST, '/projects/'.$project['body']['$id'].'/webhooks', [ + $webhook = $this->client->call(Client::METHOD_POST, '/projects/' . $project['body']['$id'] . '/webhooks', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'cookie' => 'a_session_console=' . $this->getRoot()['session'], @@ -118,12 +118,14 @@ trait ProjectCustom 'name' => $project['body']['name'], 'apiKey' => $key['body']['secret'], 'webhookId' => $webhook['body']['$id'], + 'signatureKey' => $webhook['body']['signatureKey'], ]; return self::$project; } - public function getNewKey(array $scopes) { + public function getNewKey(array $scopes) + { $projectId = self::$project['$id']; diff --git a/tests/e2e/Scopes/Scope.php b/tests/e2e/Scopes/Scope.php index 079777be4c..3d17576ffd 100644 --- a/tests/e2e/Scopes/Scope.php +++ b/tests/e2e/Scopes/Scope.php @@ -31,7 +31,7 @@ abstract class Scope extends TestCase $this->client = null; } - protected function getLastEmail():array + protected function getLastEmail(): array { sleep(3); @@ -44,25 +44,25 @@ abstract class Scope extends TestCase return []; } - protected function getLastRequest():array + protected function getLastRequest(): array { sleep(2); - + $resquest = json_decode(file_get_contents('http://request-catcher:5000/__last_request__'), true); $resquest['data'] = json_decode($resquest['data'], true); - + return $resquest; } /** * @return array */ - abstract public function getHeaders():array; + abstract public function getHeaders(): array; /** * @return array */ - abstract public function getProject():array; + abstract public function getProject(): array; /** * @var array @@ -78,7 +78,7 @@ abstract class Scope extends TestCase return self::$root; } - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -130,7 +130,7 @@ abstract class Scope extends TestCase return self::$user[$this->getProject()['$id']]; } - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -156,7 +156,7 @@ abstract class Scope extends TestCase 'password' => $password, ]); - $session = $this->client->parseCookie((string)$session['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$session['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; self::$user[$this->getProject()['$id']] = [ '$id' => $user['body']['$id'], diff --git a/tests/e2e/Scopes/SideClient.php b/tests/e2e/Scopes/SideClient.php index acf79a3721..54f77a9747 100644 --- a/tests/e2e/Scopes/SideClient.php +++ b/tests/e2e/Scopes/SideClient.php @@ -4,11 +4,11 @@ namespace Tests\E2E\Scopes; trait SideClient { - public function getHeaders():array + public function getHeaders(): array { return [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $this->getUser()['session'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $this->getUser()['session'], ]; } diff --git a/tests/e2e/Scopes/SideConsole.php b/tests/e2e/Scopes/SideConsole.php index ada99a6e6a..74a0dd0c60 100644 --- a/tests/e2e/Scopes/SideConsole.php +++ b/tests/e2e/Scopes/SideConsole.php @@ -4,11 +4,11 @@ namespace Tests\E2E\Scopes; trait SideConsole { - public function getHeaders():array + public function getHeaders(): array { return [ 'origin' => 'http://localhost', - 'cookie' => 'a_session_console='. $this->getRoot()['session'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], 'x-appwrite-mode' => 'admin' ]; } diff --git a/tests/e2e/Scopes/SideNone.php b/tests/e2e/Scopes/SideNone.php index 41522d0353..79c52afe00 100644 --- a/tests/e2e/Scopes/SideNone.php +++ b/tests/e2e/Scopes/SideNone.php @@ -4,7 +4,7 @@ namespace Tests\E2E\Scopes; trait SideNone { - public function getHeaders():array + public function getHeaders(): array { return []; } diff --git a/tests/e2e/Scopes/SideServer.php b/tests/e2e/Scopes/SideServer.php index a979b25b07..b5e15150e9 100644 --- a/tests/e2e/Scopes/SideServer.php +++ b/tests/e2e/Scopes/SideServer.php @@ -9,7 +9,7 @@ trait SideServer */ protected $key = []; - public function getHeaders():array + public function getHeaders(): array { return [ 'x-appwrite-key' => $this->getProject()['apiKey'] diff --git a/tests/e2e/Services/Account/AccountBase.php b/tests/e2e/Services/Account/AccountBase.php index 301ffff8ac..7ffa9eb7c9 100644 --- a/tests/e2e/Services/Account/AccountBase.php +++ b/tests/e2e/Services/Account/AccountBase.php @@ -6,9 +6,9 @@ use Tests\E2E\Client; trait AccountBase { - public function testCreateAccount():array + public function testCreateAccount(): array { - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -98,7 +98,7 @@ trait AccountBase /** * @depends testCreateAccount */ - public function testCreateAccountSession($data):array + public function testCreateAccountSession($data): array { $email = $data['email'] ?? ''; $password = $data['password'] ?? ''; @@ -118,7 +118,7 @@ trait AccountBase $this->assertEquals($response['headers']['status-code'], 201); $sessionId = $response['body']['$id']; - $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; /** * Test for FAILURE @@ -128,7 +128,7 @@ trait AccountBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]), [ - 'email' => $email.'x', + 'email' => $email . 'x', 'password' => $password, ]); @@ -140,7 +140,7 @@ trait AccountBase 'x-appwrite-project' => $this->getProject()['$id'], ]), [ 'email' => $email, - 'password' => $password.'x', + 'password' => $password . 'x', ]); $this->assertEquals($response['headers']['status-code'], 401); @@ -165,7 +165,7 @@ trait AccountBase /** * @depends testCreateAccountSession */ - public function testGetAccount($data):array + public function testGetAccount($data): array { $email = $data['email'] ?? ''; $name = $data['name'] ?? ''; @@ -178,7 +178,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -200,7 +200,7 @@ trait AccountBase $response = $this->client->call(Client::METHOD_GET, '/account', [ 'content-type' => 'application/json', - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session.'xx', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session . 'xx', 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -212,7 +212,7 @@ trait AccountBase /** * @depends testCreateAccountSession */ - public function testGetAccountPrefs($data):array + public function testGetAccountPrefs($data): array { $session = $data['session'] ?? ''; @@ -223,7 +223,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -248,7 +248,7 @@ trait AccountBase /** * @depends testCreateAccountSession */ - public function testGetAccountSessions($data):array + public function testGetAccountSessions($data): array { $session = $data['session'] ?? ''; $sessionId = $data['sessionId'] ?? ''; @@ -260,7 +260,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -269,7 +269,7 @@ trait AccountBase $this->assertCount(2, $response['body']); $this->assertEquals(1, $response['body']['total']); $this->assertEquals($sessionId, $response['body']['sessions'][0]['$id']); - + $this->assertEquals('Windows', $response['body']['sessions'][0]['osName']); $this->assertEquals('WIN', $response['body']['sessions'][0]['osCode']); $this->assertEquals('10', $response['body']['sessions'][0]['osVersion']); @@ -306,7 +306,7 @@ trait AccountBase /** * @depends testCreateAccountSession */ - public function testGetAccountLogs($data):array + public function testGetAccountLogs($data): array { sleep(10); $session = $data['session'] ?? ''; @@ -319,7 +319,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -375,7 +375,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'limit' => 1 ]); @@ -392,7 +392,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'offset' => 1 ]); @@ -409,7 +409,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'limit' => 1, 'offset' => 1 @@ -441,7 +441,7 @@ trait AccountBase /** * @depends testCreateAccountSession */ - public function testUpdateAccountName($data):array + public function testUpdateAccountName($data): array { $email = $data['email'] ?? ''; $session = $data['session'] ?? ''; @@ -454,7 +454,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'name' => $newName ]); @@ -482,7 +482,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ ]); @@ -492,7 +492,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'name' => 'ocSRq1d3QphHivJyUmYY7WMnrxyjdk5YvVwcDqx2zS0coxESN8RmsQwLWw5Whnf0WbVohuFWTRAaoKgCOO0Y0M7LwgFnZmi8881Y72222222222222222222222222222' ]); @@ -507,7 +507,7 @@ trait AccountBase /** * @depends testUpdateAccountName */ - public function testUpdateAccountPassword($data):array + public function testUpdateAccountPassword($data): array { $email = $data['email'] ?? ''; $password = $data['password'] ?? ''; @@ -520,7 +520,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'password' => 'new-password', 'oldPassword' => $password, @@ -554,15 +554,14 @@ trait AccountBase ])); $this->assertEquals($response['headers']['status-code'], 401); - $response = $this->client->call(Client::METHOD_PATCH, '/account/password', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ ]); - + $this->assertEquals($response['headers']['status-code'], 400); /** @@ -572,7 +571,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'password' => 'new-password', 'oldPassword' => $password, @@ -580,13 +579,13 @@ trait AccountBase $this->assertEquals($response['headers']['status-code'], 401); /** - * Existing user tries to update password without passing old password -> SHOULD FAIL + * Existing user tries to update password without passing old password -> SHOULD FAIL */ $response = $this->client->call(Client::METHOD_PATCH, '/account/password', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'password' => 'new-password' ]); @@ -600,9 +599,9 @@ trait AccountBase /** * @depends testUpdateAccountPassword */ - public function testUpdateAccountEmail($data):array + public function testUpdateAccountEmail($data): array { - $newEmail = uniqid().'new@localhost.test'; + $newEmail = uniqid() . 'new@localhost.test'; $session = $data['session'] ?? ''; /** @@ -612,7 +611,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'email' => $newEmail, 'password' => 'new-password', @@ -640,7 +639,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ ]); @@ -667,8 +666,8 @@ trait AccountBase $this->assertNotEmpty($response['body']['$id']); $this->assertIsNumeric($response['body']['registration']); $this->assertEquals($response['body']['email'], $data['email']); - $this->assertEquals($response['body']['name'], $data['name'],); - + $this->assertEquals($response['body']['name'], $data['name']); + $data['email'] = $newEmail; @@ -678,9 +677,9 @@ trait AccountBase /** * @depends testUpdateAccountEmail */ - public function testUpdateAccountPrefs($data):array + public function testUpdateAccountPrefs($data): array { - $newEmail = uniqid().'new@localhost.test'; + $newEmail = uniqid() . 'new@localhost.test'; $session = $data['session'] ?? ''; /** @@ -690,7 +689,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'prefs' => [ 'prefKey1' => 'prefValue1', @@ -714,35 +713,35 @@ trait AccountBase ])); $this->assertEquals($response['headers']['status-code'], 401); - + $response = $this->client->call(Client::METHOD_PATCH, '/account/prefs', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'prefs' => '{}' ]); $this->assertEquals($response['headers']['status-code'], 400); - - + + $response = $this->client->call(Client::METHOD_PATCH, '/account/prefs', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'prefs' => '[]' ]); $this->assertEquals($response['headers']['status-code'], 400); - + $response = $this->client->call(Client::METHOD_PATCH, '/account/prefs', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'prefs' => '{"test": "value"}' ]); @@ -758,7 +757,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'prefs' => $prefsObject ]); @@ -772,7 +771,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'prefs' => $prefsObject ]); @@ -785,7 +784,7 @@ trait AccountBase /** * @depends testUpdateAccountPrefs */ - public function testCreateAccountVerification($data):array + public function testCreateAccountVerification($data): array { $email = $data['email'] ?? ''; $name = $data['name'] ?? ''; @@ -798,8 +797,8 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, - + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ]), [ 'url' => 'http://localhost/verification', ]); @@ -817,15 +816,15 @@ trait AccountBase $verification = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); - $expireTime = strpos($lastEmail['text'], 'expire='.$response['body']['expire'], 0); + $expireTime = strpos($lastEmail['text'], 'expire=' . $response['body']['expire'], 0); $this->assertNotFalse($expireTime); - - $secretTest = strpos($lastEmail['text'], 'secret='.$response['body']['secret'], 0); + + $secretTest = strpos($lastEmail['text'], 'secret=' . $response['body']['secret'], 0); $this->assertNotFalse($secretTest); - $userIDTest = strpos($lastEmail['text'], 'userId='.$response['body']['userId'], 0); + $userIDTest = strpos($lastEmail['text'], 'userId=' . $response['body']['userId'], 0); $this->assertNotFalse($userIDTest); @@ -836,7 +835,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'url' => 'localhost/verification', ]); @@ -847,7 +846,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'url' => 'http://remotehost/verification', ]); @@ -862,12 +861,12 @@ trait AccountBase /** * @depends testCreateAccountVerification */ - public function testUpdateAccountVerification($data):array + public function testUpdateAccountVerification($data): array { $id = $data['id'] ?? ''; $session = $data['session'] ?? ''; $verification = $data['verification'] ?? ''; - + /** * Test for SUCCESS */ @@ -875,14 +874,14 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'userId' => $id, 'secret' => $verification, ]); $this->assertEquals(200, $response['headers']['status-code']); - + /** * Test for FAILURE */ @@ -890,7 +889,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'userId' => 'ewewe', 'secret' => $verification, @@ -902,7 +901,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'userId' => $id, 'secret' => 'sdasdasdasd', @@ -916,7 +915,7 @@ trait AccountBase /** * @depends testUpdateAccountVerification */ - public function testDeleteAccountSession($data):array + public function testDeleteAccountSession($data): array { $email = $data['email'] ?? ''; $password = $data['password'] ?? ''; @@ -935,7 +934,7 @@ trait AccountBase ]); $sessionNewId = $response['body']['$id']; - $sessionNew = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $sessionNew = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $this->assertEquals($response['headers']['status-code'], 201); @@ -943,16 +942,16 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $sessionNew, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionNew, ]); $this->assertEquals($response['headers']['status-code'], 200); - $response = $this->client->call(Client::METHOD_DELETE, '/account/sessions/'.$sessionNewId, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/account/sessions/' . $sessionNewId, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $sessionNew, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionNew, ])); $this->assertEquals($response['headers']['status-code'], 204); @@ -961,7 +960,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -973,7 +972,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $sessionNew, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionNew, ]); $this->assertEquals($response['headers']['status-code'], 401); @@ -984,7 +983,7 @@ trait AccountBase /** * @depends testUpdateAccountVerification */ - public function testDeleteAccountSessionCurrent($data):array + public function testDeleteAccountSessionCurrent($data): array { $email = $data['email'] ?? ''; $password = $data['password'] ?? ''; @@ -1001,14 +1000,14 @@ trait AccountBase 'password' => $password, ]); - $sessionNew = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $sessionNew = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $this->assertEquals($response['headers']['status-code'], 201); $response = $this->client->call(Client::METHOD_GET, '/account', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $sessionNew, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionNew, 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -1017,7 +1016,7 @@ trait AccountBase $response = $this->client->call(Client::METHOD_DELETE, '/account/sessions/current', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $sessionNew, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionNew, 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -1029,7 +1028,7 @@ trait AccountBase $response = $this->client->call(Client::METHOD_GET, '/account', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $sessionNew, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionNew, 'x-appwrite-project' => $this->getProject()['$id'], ]); @@ -1041,7 +1040,7 @@ trait AccountBase /** * @depends testUpdateAccountVerification */ - public function testDeleteAccountSessions($data):array + public function testDeleteAccountSessions($data): array { $session = $data['session'] ?? ''; @@ -1052,7 +1051,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 204); @@ -1083,7 +1082,7 @@ trait AccountBase 'password' => $password, ]); - $data['session'] = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $data['session'] = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; return $data; } @@ -1091,7 +1090,7 @@ trait AccountBase /** * @depends testDeleteAccountSession */ - public function testCreateAccountRecovery($data):array + public function testCreateAccountRecovery($data): array { $email = $data['email'] ?? ''; $name = $data['name'] ?? ''; @@ -1121,15 +1120,15 @@ trait AccountBase $recovery = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); - $expireTime = strpos($lastEmail['text'], 'expire='.$response['body']['expire'], 0); + $expireTime = strpos($lastEmail['text'], 'expire=' . $response['body']['expire'], 0); $this->assertNotFalse($expireTime); - - $secretTest = strpos($lastEmail['text'], 'secret='.$response['body']['secret'], 0); + + $secretTest = strpos($lastEmail['text'], 'secret=' . $response['body']['secret'], 0); $this->assertNotFalse($secretTest); - $userIDTest = strpos($lastEmail['text'], 'userId='.$response['body']['userId'], 0); + $userIDTest = strpos($lastEmail['text'], 'userId=' . $response['body']['userId'], 0); $this->assertNotFalse($userIDTest); @@ -1177,12 +1176,12 @@ trait AccountBase /** * @depends testCreateAccountRecovery */ - public function testUpdateAccountRecovery($data):array + public function testUpdateAccountRecovery($data): array { $id = $data['id'] ?? ''; $recovery = $data['recovery'] ?? ''; $newPassowrd = 'test-recovery'; - + /** * Test for SUCCESS */ @@ -1198,7 +1197,7 @@ trait AccountBase ]); $this->assertEquals(200, $response['headers']['status-code']); - + /** * Test for FAILURE */ @@ -1235,18 +1234,18 @@ trait AccountBase ]), [ 'userId' => $id, 'secret' => $recovery, - 'password' => $newPassowrd.'x', + 'password' => $newPassowrd . 'x', 'passwordAgain' => $newPassowrd, ]); $this->assertEquals(400, $response['headers']['status-code']); - + return $data; } - public function testCreateMagicUrl():array + public function testCreateMagicUrl(): array { - $email = \time().'user@appwrite.io'; + $email = \time() . 'user@appwrite.io'; /** * Test for SUCCESS @@ -1274,15 +1273,15 @@ trait AccountBase $token = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); - $expireTime = strpos($lastEmail['text'], 'expire='.$response['body']['expire'], 0); + $expireTime = strpos($lastEmail['text'], 'expire=' . $response['body']['expire'], 0); $this->assertNotFalse($expireTime); - $secretTest = strpos($lastEmail['text'], 'secret='.$response['body']['secret'], 0); + $secretTest = strpos($lastEmail['text'], 'secret=' . $response['body']['secret'], 0); $this->assertNotFalse($secretTest); - $userIDTest = strpos($lastEmail['text'], 'userId='.$response['body']['userId'], 0); + $userIDTest = strpos($lastEmail['text'], 'userId=' . $response['body']['userId'], 0); $this->assertNotFalse($userIDTest); @@ -1333,7 +1332,7 @@ trait AccountBase /** * @depends testCreateMagicUrl */ - public function testCreateSessionWithMagicUrl($data):array + public function testCreateSessionWithMagicUrl($data): array { $id = $data['id'] ?? ''; $token = $data['token'] ?? ''; @@ -1358,13 +1357,13 @@ trait AccountBase $this->assertNotEmpty($response['body']['userId']); $sessionId = $response['body']['$id']; - $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ])); $this->assertEquals($response['headers']['status-code'], 200); @@ -1409,7 +1408,7 @@ trait AccountBase /** * @depends testCreateSessionWithMagicUrl */ - public function testUpdateAccountPasswordWithMagicUrl($data):array + public function testUpdateAccountPasswordWithMagicUrl($data): array { $email = $data['email'] ?? ''; $session = $data['session'] ?? ''; @@ -1421,7 +1420,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'password' => 'new-password' ]); @@ -1454,15 +1453,15 @@ trait AccountBase ])); $this->assertEquals($response['headers']['status-code'], 401); - + $response = $this->client->call(Client::METHOD_PATCH, '/account/password', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ ]); - + $this->assertEquals($response['headers']['status-code'], 400); /** @@ -1472,7 +1471,7 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'password' => 'new-password', 'oldPassword' => 'wrong-password', @@ -1480,13 +1479,13 @@ trait AccountBase $this->assertEquals($response['headers']['status-code'], 401); /** - * Existing user tries to update password without passing old password -> SHOULD FAIL + * Existing user tries to update password without passing old password -> SHOULD FAIL */ $response = $this->client->call(Client::METHOD_PATCH, '/account/password', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'password' => 'new-password' ]); @@ -1496,5 +1495,4 @@ trait AccountBase return $data; } - -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Account/AccountConsoleClientTest.php b/tests/e2e/Services/Account/AccountConsoleClientTest.php index 513ec54e08..4aa2462f89 100644 --- a/tests/e2e/Services/Account/AccountConsoleClientTest.php +++ b/tests/e2e/Services/Account/AccountConsoleClientTest.php @@ -11,4 +11,4 @@ class AccountConsoleClientTest extends Scope use AccountBase; use ProjectConsole; use SideClient; -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index e041946fe5..b54711305a 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -6,6 +6,7 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; + use function sleep; class AccountCustomClientTest extends Scope diff --git a/tests/e2e/Services/Account/AccountCustomServerTest.php b/tests/e2e/Services/Account/AccountCustomServerTest.php index 832dd34389..3c5955f47b 100644 --- a/tests/e2e/Services/Account/AccountCustomServerTest.php +++ b/tests/e2e/Services/Account/AccountCustomServerTest.php @@ -12,9 +12,9 @@ class AccountCustomServerTest extends Scope use ProjectCustom; use SideServer; - public function testCreateAccount():array + public function testCreateAccount(): array { - $email = uniqid().'user@localhost.test'; + $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name'; @@ -36,4 +36,4 @@ class AccountCustomServerTest extends Scope return []; } -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Avatars/AvatarsBase.php b/tests/e2e/Services/Avatars/AvatarsBase.php index 82c6ab99b1..e631fd4391 100644 --- a/tests/e2e/Services/Avatars/AvatarsBase.php +++ b/tests/e2e/Services/Avatars/AvatarsBase.php @@ -6,7 +6,7 @@ use Tests\E2E\Client; trait AvatarsBase { - public function testGetCreditCard():array + public function testGetCreditCard(): array { /** * Test for SUCCESS @@ -55,7 +55,7 @@ trait AvatarsBase ]); $this->assertEquals(400, $response['headers']['status-code']); - + $response = $this->client->call(Client::METHOD_GET, '/avatars/credit-cards/visa', [ 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -65,11 +65,11 @@ trait AvatarsBase ]); $this->assertEquals(400, $response['headers']['status-code']); - + return []; } - public function testGetBrowser():array + public function testGetBrowser(): array { /** * Test for SUCCESS @@ -104,7 +104,7 @@ trait AvatarsBase $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals('image/png', $response['headers']['content-type']); $this->assertNotEmpty($response['body']); - + /** * Test for FAILURE */ @@ -118,7 +118,7 @@ trait AvatarsBase ]); $this->assertEquals(400, $response['headers']['status-code']); - + $response = $this->client->call(Client::METHOD_GET, '/avatars/browsers/ch', [ 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -126,13 +126,13 @@ trait AvatarsBase 'height' => 300, 'quality' => 30, ]); - + $this->assertEquals(400, $response['headers']['status-code']); return []; } - public function testGetFlag():array + public function testGetFlag(): array { /** * Test for SUCCESS @@ -167,7 +167,7 @@ trait AvatarsBase $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals('image/png', $response['headers']['content-type']); $this->assertNotEmpty($response['body']); - + /** * Test for FAILURE */ @@ -180,7 +180,7 @@ trait AvatarsBase ]); $this->assertEquals(400, $response['headers']['status-code']); - + $response = $this->client->call(Client::METHOD_GET, '/avatars/flags/us', [ 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -188,13 +188,13 @@ trait AvatarsBase 'height' => 300, 'quality' => 30, ]); - + $this->assertEquals(400, $response['headers']['status-code']); return []; } - public function testGetImage():array + public function testGetImage(): array { /** * Test for SUCCESS @@ -233,7 +233,7 @@ trait AvatarsBase $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals('image/png', $response['headers']['content-type']); $this->assertNotEmpty($response['body']); - + /** * Test for FAILURE */ @@ -272,7 +272,7 @@ trait AvatarsBase return []; } - public function testGetFavicon():array + public function testGetFavicon(): array { /** * Test for SUCCESS @@ -329,7 +329,7 @@ trait AvatarsBase return []; } - public function testGetQR():array + public function testGetQR(): array { /** * Test for SUCCESS @@ -408,7 +408,7 @@ trait AvatarsBase $this->assertEquals('attachment; filename="qr.png"', $response['headers']['content-disposition']); $this->assertEquals('image/png', $response['headers']['content-type']); $this->assertNotEmpty($response['body']); - + /** * Test for FAILURE */ @@ -538,4 +538,4 @@ trait AvatarsBase $this->assertEquals(400, $response['headers']['status-code']); } -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Avatars/AvatarsConsoleClientTest.php b/tests/e2e/Services/Avatars/AvatarsConsoleClientTest.php index 5a86e33f9e..a59d694114 100644 --- a/tests/e2e/Services/Avatars/AvatarsConsoleClientTest.php +++ b/tests/e2e/Services/Avatars/AvatarsConsoleClientTest.php @@ -11,4 +11,4 @@ class AvatarsConsoleClientTest extends Scope use AvatarsBase; use ProjectConsole; use SideClient; -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Avatars/AvatarsCustomClientTest.php b/tests/e2e/Services/Avatars/AvatarsCustomClientTest.php index 5056415575..dc399971a0 100644 --- a/tests/e2e/Services/Avatars/AvatarsCustomClientTest.php +++ b/tests/e2e/Services/Avatars/AvatarsCustomClientTest.php @@ -11,4 +11,4 @@ class AvatarsCustomClientTest extends Scope use AvatarsBase; use ProjectCustom; use SideClient; -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Avatars/AvatarsCustomServerTest.php b/tests/e2e/Services/Avatars/AvatarsCustomServerTest.php index be8b4d1a77..02f68a623b 100644 --- a/tests/e2e/Services/Avatars/AvatarsCustomServerTest.php +++ b/tests/e2e/Services/Avatars/AvatarsCustomServerTest.php @@ -11,4 +11,4 @@ class AvatarsCustomServerTest extends Scope use AvatarsBase; use ProjectCustom; use SideServer; -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Database/DatabaseBase.php b/tests/e2e/Services/Database/DatabaseBase.php index 640ab99361..47aa3ce351 100644 --- a/tests/e2e/Services/Database/DatabaseBase.php +++ b/tests/e2e/Services/Database/DatabaseBase.php @@ -7,7 +7,7 @@ use Utopia\Database\Database; trait DatabaseBase { - public function testCreateCollection():array + public function testCreateCollection(): array { /** * Test for SUCCESS @@ -60,8 +60,8 @@ trait DatabaseBase 'data' => [ 'title' => 'Captain America', ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $responseListDocument = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ @@ -118,6 +118,15 @@ trait DatabaseBase 'required' => true, ]); + $duration = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['moviesId'] . '/attributes/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'duration', + 'required' => false, + ]); + $actors = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['moviesId'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -140,6 +149,11 @@ trait DatabaseBase $this->assertEquals($releaseYear['body']['type'], 'integer'); $this->assertEquals($releaseYear['body']['required'], true); + $this->assertEquals($duration['headers']['status-code'], 201); + $this->assertEquals($duration['body']['key'], 'duration'); + $this->assertEquals($duration['body']['type'], 'integer'); + $this->assertEquals($duration['body']['required'], false); + $this->assertEquals($actors['headers']['status-code'], 201); $this->assertEquals($actors['body']['key'], 'actors'); $this->assertEquals($actors['body']['type'], 'string'); @@ -154,13 +168,14 @@ trait DatabaseBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] - ]), []); + ]), []); $this->assertIsArray($movies['body']['attributes']); - $this->assertCount(3, $movies['body']['attributes']); + $this->assertCount(4, $movies['body']['attributes']); $this->assertEquals($movies['body']['attributes'][0]['key'], $title['body']['key']); $this->assertEquals($movies['body']['attributes'][1]['key'], $releaseYear['body']['key']); - $this->assertEquals($movies['body']['attributes'][2]['key'], $actors['body']['key']); + $this->assertEquals($movies['body']['attributes'][2]['key'], $duration['body']['key']); + $this->assertEquals($movies['body']['attributes'][3]['key'], $actors['body']['key']); return $data; } @@ -170,7 +185,7 @@ trait DatabaseBase */ public function testAttributeResponseModels(array $data): array { - $collection= $this->client->call(Client::METHOD_POST, '/database/collections', array_merge([ + $collection = $this->client->call(Client::METHOD_POST, '/database/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -343,49 +358,49 @@ trait DatabaseBase // wait for database worker to create attributes sleep(30); - $stringResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$string['body']['key']}",array_merge([ + $stringResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$string['body']['key']}", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $emailResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$email['body']['key']}",array_merge([ + $emailResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$email['body']['key']}", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $enumResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$enum['body']['key']}",array_merge([ + $enumResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$enum['body']['key']}", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $ipResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$ip['body']['key']}",array_merge([ + $ipResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$ip['body']['key']}", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $urlResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$url['body']['key']}",array_merge([ + $urlResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$url['body']['key']}", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $integerResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$integer['body']['key']}",array_merge([ + $integerResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$integer['body']['key']}", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $floatResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$float['body']['key']}",array_merge([ + $floatResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$float['body']['key']}", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ])); - $booleanResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$boolean['body']['key']}",array_merge([ + $booleanResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$boolean['body']['key']}", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -469,7 +484,7 @@ trait DatabaseBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] - ])); + ])); $this->assertEquals(200, $attributes['headers']['status-code']); $this->assertEquals(8, $attributes['body']['total']); @@ -688,7 +703,7 @@ trait DatabaseBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] - ]), []); + ]), []); $this->assertIsArray($movies['body']['indexes']); $this->assertCount(2, $movies['body']['indexes']); @@ -703,7 +718,7 @@ trait DatabaseBase /** * @depends testCreateIndexes */ - public function testCreateDocument(array $data):array + public function testCreateDocument(array $data): array { $document1 = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -718,8 +733,8 @@ trait DatabaseBase 'Samuel Jackson', ] ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $document2 = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ @@ -736,8 +751,8 @@ trait DatabaseBase 'Samuel Jackson', ] ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $document3 = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ @@ -748,15 +763,17 @@ trait DatabaseBase 'data' => [ 'title' => 'Spider-Man: Homecoming', 'releaseYear' => 2017, + 'duration' => 0, 'actors' => [ 'Tom Holland', 'Zendaya Maree Stoermer', ], ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); + $document4 = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -765,8 +782,8 @@ trait DatabaseBase 'data' => [ 'releaseYear' => 2020, // Missing title, expect an 400 error ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $this->assertEquals($document1['headers']['status-code'], 201); @@ -783,6 +800,7 @@ trait DatabaseBase $this->assertEquals($document2['headers']['status-code'], 201); $this->assertEquals($document2['body']['title'], 'Spider-Man: Far From Home'); $this->assertEquals($document2['body']['releaseYear'], 2019); + $this->assertEquals($document2['body']['duration'], null); $this->assertIsArray($document2['body']['$read']); $this->assertIsArray($document2['body']['$write']); $this->assertCount(1, $document2['body']['$read']); @@ -795,6 +813,7 @@ trait DatabaseBase $this->assertEquals($document3['headers']['status-code'], 201); $this->assertEquals($document3['body']['title'], 'Spider-Man: Homecoming'); $this->assertEquals($document3['body']['releaseYear'], 2017); + $this->assertEquals($document3['body']['duration'], 0); $this->assertIsArray($document3['body']['$read']); $this->assertIsArray($document3['body']['$write']); $this->assertCount(1, $document3['body']['$read']); @@ -811,7 +830,7 @@ trait DatabaseBase /** * @depends testCreateDocument */ - public function testListDocuments(array $data):array + public function testListDocuments(array $data): array { $documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -876,7 +895,7 @@ trait DatabaseBase /** * @depends testCreateDocument */ - public function testListDocumentsAfterPagination(array $data):array + public function testListDocumentsAfterPagination(array $data): array { /** * Test after without order. @@ -992,7 +1011,7 @@ trait DatabaseBase /** * @depends testCreateDocument */ - public function testListDocumentsBeforePagination(array $data):array + public function testListDocumentsBeforePagination(array $data): array { /** * Test before without order. @@ -1100,7 +1119,7 @@ trait DatabaseBase /** * @depends testCreateDocument */ - public function testListDocumentsLimitAndOffset(array $data):array + public function testListDocumentsLimitAndOffset(array $data): array { $documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -1136,7 +1155,7 @@ trait DatabaseBase /** * @depends testCreateDocument */ - public function testDocumentsListQueries(array $data):array + public function testDocumentsListQueries(array $data): array { $documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -1218,7 +1237,7 @@ trait DatabaseBase $conditions = []; - for ($i=0; $i < 101; $i++) { + for ($i = 0; $i < 101; $i++) { $conditions[] = $i; } @@ -1237,7 +1256,7 @@ trait DatabaseBase /** * @depends testCreateDocument */ - public function testUpdateDocument(array $data):array + public function testUpdateDocument(array $data): array { $document = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -1249,8 +1268,8 @@ trait DatabaseBase 'releaseYear' => 2017, 'actors' => [], ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $id = $document['body']['$id']; @@ -1258,8 +1277,8 @@ trait DatabaseBase $this->assertEquals($document['headers']['status-code'], 201); $this->assertEquals($document['body']['title'], 'Thor: Ragnaroc'); $this->assertEquals($document['body']['releaseYear'], 2017); - $this->assertEquals('user:'.$this->getUser()['$id'], $document['body']['$read'][0]); - $this->assertEquals('user:'.$this->getUser()['$id'], $document['body']['$write'][0]); + $this->assertEquals('user:' . $this->getUser()['$id'], $document['body']['$read'][0]); + $this->assertEquals('user:' . $this->getUser()['$id'], $document['body']['$write'][0]); $document = $this->client->call(Client::METHOD_PATCH, '/database/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ 'content-type' => 'application/json', @@ -1297,7 +1316,7 @@ trait DatabaseBase /** * @depends testCreateDocument */ - public function testDeleteDocument(array $data):array + public function testDeleteDocument(array $data): array { $document = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -1309,8 +1328,8 @@ trait DatabaseBase 'releaseYear' => 2017, 'actors' => [], ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $id = $document['body']['$id']; @@ -1531,7 +1550,7 @@ trait DatabaseBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], - ]), []); + ]), []); $this->assertCount(9, $collection['body']['attributes']); @@ -1547,8 +1566,8 @@ trait DatabaseBase 'data' => [ 'email' => 'user@example.com', ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $goodEnum = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([ @@ -1559,8 +1578,8 @@ trait DatabaseBase 'data' => [ 'enum' => 'yes', ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $goodIp = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([ @@ -1571,8 +1590,8 @@ trait DatabaseBase 'data' => [ 'ip' => '1.1.1.1', ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $goodUrl = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([ @@ -1583,8 +1602,8 @@ trait DatabaseBase 'data' => [ 'url' => 'http://www.example.com', ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $goodRange = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([ @@ -1595,8 +1614,8 @@ trait DatabaseBase 'data' => [ 'range' => 3, ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $goodFloatRange = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([ @@ -1605,10 +1624,10 @@ trait DatabaseBase ], $this->getHeaders()), [ 'documentId' => 'unique()', 'data' => [ - 'floatRange' => 1.4, + 'floatRange' => 1.4, ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $goodProbability = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([ @@ -1619,8 +1638,8 @@ trait DatabaseBase 'data' => [ 'probability' => 0.99999, ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $notTooHigh = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([ @@ -1629,10 +1648,10 @@ trait DatabaseBase ], $this->getHeaders()), [ 'documentId' => 'unique()', 'data' => [ - 'upperBound' => 8, + 'upperBound' => 8, ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $notTooLow = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([ @@ -1641,10 +1660,10 @@ trait DatabaseBase ], $this->getHeaders()), [ 'documentId' => 'unique()', 'data' => [ - 'lowerBound' => 8, + 'lowerBound' => 8, ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $this->assertEquals(201, $goodEmail['headers']['status-code']); @@ -1669,8 +1688,8 @@ trait DatabaseBase 'data' => [ 'email' => 'user@@example.com', ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $badEnum = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([ @@ -1681,8 +1700,8 @@ trait DatabaseBase 'data' => [ 'enum' => 'badEnum', ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $badIp = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([ @@ -1693,8 +1712,8 @@ trait DatabaseBase 'data' => [ 'ip' => '1.1.1.1.1', ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $badUrl = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([ @@ -1705,8 +1724,8 @@ trait DatabaseBase 'data' => [ 'url' => 'example...com', ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $badRange = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([ @@ -1717,8 +1736,8 @@ trait DatabaseBase 'data' => [ 'range' => 11, ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $badFloatRange = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([ @@ -1729,8 +1748,8 @@ trait DatabaseBase 'data' => [ 'floatRange' => 2.5, ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $badProbability = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([ @@ -1741,8 +1760,8 @@ trait DatabaseBase 'data' => [ 'probability' => 1.1, ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $tooHigh = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([ @@ -1753,8 +1772,8 @@ trait DatabaseBase 'data' => [ 'upperBound' => 11, ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $tooLow = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([ @@ -1765,8 +1784,8 @@ trait DatabaseBase 'data' => [ 'lowerBound' => 3, ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $this->assertEquals(400, $badEmail['headers']['status-code']); @@ -1792,7 +1811,7 @@ trait DatabaseBase /** * @depends testDeleteDocument */ - public function testDefaultPermissions(array $data):array + public function testDefaultPermissions(array $data): array { $document = $this->client->call(Client::METHOD_POST, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ 'content-type' => 'application/json', @@ -1814,18 +1833,18 @@ trait DatabaseBase $this->assertIsArray($document['body']['$read']); $this->assertIsArray($document['body']['$write']); - if($this->getSide() == 'client') { + if ($this->getSide() == 'client') { $this->assertCount(1, $document['body']['$read']); $this->assertCount(1, $document['body']['$write']); - $this->assertEquals(['user:'.$this->getUser()['$id']], $document['body']['$read']); - $this->assertEquals(['user:'.$this->getUser()['$id']], $document['body']['$write']); + $this->assertEquals(['user:' . $this->getUser()['$id']], $document['body']['$read']); + $this->assertEquals(['user:' . $this->getUser()['$id']], $document['body']['$write']); } - if($this->getSide() == 'server') { + if ($this->getSide() == 'server') { $this->assertCount(0, $document['body']['$read']); $this->assertCount(0, $document['body']['$write']); $this->assertEquals([], $document['body']['$read']); - $this->assertEquals([], $document['body']['$write']); + $this->assertEquals([], $document['body']['$write']); } // Updated and Inherit Permissions @@ -1846,18 +1865,18 @@ trait DatabaseBase $this->assertEquals($document['body']['title'], 'Captain America 2'); $this->assertEquals($document['body']['releaseYear'], 1945); - if($this->getSide() == 'client') { + if ($this->getSide() == 'client') { $this->assertCount(1, $document['body']['$read']); $this->assertCount(1, $document['body']['$write']); $this->assertEquals(['role:all'], $document['body']['$read']); - $this->assertEquals(['user:'.$this->getUser()['$id']], $document['body']['$write']); + $this->assertEquals(['user:' . $this->getUser()['$id']], $document['body']['$write']); } - if($this->getSide() == 'server') { + if ($this->getSide() == 'server') { $this->assertCount(1, $document['body']['$read']); $this->assertCount(0, $document['body']['$write']); $this->assertEquals(['role:all'], $document['body']['$read']); - $this->assertEquals([], $document['body']['$write']); + $this->assertEquals([], $document['body']['$write']); } $document = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents/' . $id, array_merge([ @@ -1869,18 +1888,18 @@ trait DatabaseBase $this->assertEquals($document['body']['title'], 'Captain America 2'); $this->assertEquals($document['body']['releaseYear'], 1945); - if($this->getSide() == 'client') { + if ($this->getSide() == 'client') { $this->assertCount(1, $document['body']['$read']); $this->assertCount(1, $document['body']['$write']); $this->assertEquals(['role:all'], $document['body']['$read']); - $this->assertEquals(['user:'.$this->getUser()['$id']], $document['body']['$write']); + $this->assertEquals(['user:' . $this->getUser()['$id']], $document['body']['$write']); } - if($this->getSide() == 'server') { + if ($this->getSide() == 'server') { $this->assertCount(1, $document['body']['$read']); $this->assertCount(0, $document['body']['$write']); $this->assertEquals(['role:all'], $document['body']['$read']); - $this->assertEquals([], $document['body']['$write']); + $this->assertEquals([], $document['body']['$write']); } // Reset Permissions @@ -1898,18 +1917,18 @@ trait DatabaseBase 'write' => [], ]); - if($this->getSide() == 'client') { + if ($this->getSide() == 'client') { $this->assertEquals($document['headers']['status-code'], 401); } - if($this->getSide() == 'server') { + if ($this->getSide() == 'server') { $this->assertEquals($document['headers']['status-code'], 200); $this->assertEquals($document['body']['title'], 'Captain America 3'); $this->assertEquals($document['body']['releaseYear'], 1946); $this->assertCount(0, $document['body']['$read']); $this->assertCount(0, $document['body']['$write']); $this->assertEquals([], $document['body']['$read']); - $this->assertEquals([], $document['body']['$write']); + $this->assertEquals([], $document['body']['$write']); } return $data; @@ -2051,11 +2070,11 @@ trait DatabaseBase 'write' => [$user], ]); - if($this->getSide() == 'client') { + if ($this->getSide() == 'client') { $this->assertEquals(401, $badDocument['headers']['status-code']); } - if($this->getSide() == 'server') { + if ($this->getSide() == 'server') { $this->assertEquals(201, $badDocument['headers']['status-code']); } @@ -2114,8 +2133,8 @@ trait DatabaseBase 'Samuel Jackson', ] ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $this->assertEquals(409, $duplicate['headers']['status-code']); @@ -2134,8 +2153,8 @@ trait DatabaseBase 'Samuel Jackson', ] ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $this->assertEquals(201, $document['headers']['status-code']); @@ -2154,12 +2173,12 @@ trait DatabaseBase 'Samuel Jackson', ] ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $this->assertEquals(409, $duplicate['headers']['status-code']); return $data; } -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Database/DatabaseCustomClientTest.php b/tests/e2e/Services/Database/DatabaseCustomClientTest.php index f0f373323b..5f4b2f30ea 100644 --- a/tests/e2e/Services/Database/DatabaseCustomClientTest.php +++ b/tests/e2e/Services/Database/DatabaseCustomClientTest.php @@ -114,4 +114,4 @@ class DatabaseCustomClientTest extends Scope return []; } -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Database/DatabaseCustomServerTest.php b/tests/e2e/Services/Database/DatabaseCustomServerTest.php index e824d2f75c..96fd657545 100644 --- a/tests/e2e/Services/Database/DatabaseCustomServerTest.php +++ b/tests/e2e/Services/Database/DatabaseCustomServerTest.php @@ -144,7 +144,7 @@ class DatabaseCustomServerTest extends Scope ], $this->getHeaders()), [ 'search' => 'Test' ]); - + $this->assertEquals(2, $collections['body']['total']); $this->assertEquals('Test 1', $collections['body']['collections'][0]['name']); $this->assertEquals('Test 2', $collections['body']['collections'][1]['name']); @@ -155,7 +155,7 @@ class DatabaseCustomServerTest extends Scope ], $this->getHeaders()), [ 'search' => 'Nonexistent' ]); - + $this->assertEquals(0, $collections['body']['total']); /** @@ -276,7 +276,7 @@ class DatabaseCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] - ]), []); + ]), []); $unneededId = $unneeded['body']['key']; @@ -313,7 +313,7 @@ class DatabaseCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] - ]), []); + ]), []); $this->assertEquals($collection['headers']['status-code'], 200); $this->assertIsArray($collection['body']['attributes']); @@ -332,7 +332,7 @@ class DatabaseCustomServerTest extends Scope */ public function testDeleteIndex($data): array { - $index = $this->client->call(Client::METHOD_DELETE, '/database/collections/' . $data['collectionId'] . '/indexes/'. $data['key'], array_merge([ + $index = $this->client->call(Client::METHOD_DELETE, '/database/collections/' . $data['collectionId'] . '/indexes/' . $data['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -415,7 +415,7 @@ class DatabaseCustomServerTest extends Scope sleep(2); // Expected behavior: deleting attribute2 will cause index2 to be dropped, and index1 rebuilt with a single key - $deleted = $this->client->call(Client::METHOD_DELETE, '/database/collections/' . $data['collectionId'] . '/attributes/'. $attribute2['body']['key'], array_merge([ + $deleted = $this->client->call(Client::METHOD_DELETE, '/database/collections/' . $data['collectionId'] . '/attributes/' . $attribute2['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -527,7 +527,7 @@ class DatabaseCustomServerTest extends Scope sleep(2); // Expected behavior: deleting attribute1 would cause index1 to be a duplicate of index2 and automatically removed - $deleted = $this->client->call(Client::METHOD_DELETE, '/database/collections/' . $collectionId . '/attributes/'. $attribute1['body']['key'], array_merge([ + $deleted = $this->client->call(Client::METHOD_DELETE, '/database/collections/' . $collectionId . '/attributes/' . $attribute1['body']['key'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] @@ -579,8 +579,8 @@ class DatabaseCustomServerTest extends Scope 'firstName' => 'Tom', 'lastName' => 'Holland', ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $document2 = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([ @@ -592,8 +592,8 @@ class DatabaseCustomServerTest extends Scope 'firstName' => 'Samuel', 'lastName' => 'Jackson', ], - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $this->assertEquals($document1['headers']['status-code'], 201); @@ -613,17 +613,17 @@ class DatabaseCustomServerTest extends Scope $this->assertEquals($document2['body']['lastName'], 'Jackson'); // Delete the actors collection - $response = $this->client->call(Client::METHOD_DELETE, '/database/collections/' . $collectionId , array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/database/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ], $this->getHeaders())); $this->assertEquals($response['headers']['status-code'], 204); - $this->assertEquals($response['body'],""); + $this->assertEquals($response['body'], ""); // Try to get the collection and check if it has been deleted - $response = $this->client->call(Client::METHOD_GET, '/database/collections/' . $collectionId , array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/database/collections/' . $collectionId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders())); @@ -705,7 +705,7 @@ class DatabaseCustomServerTest extends Scope $collectionId = $collection['body']['$id']; // Add wide string attributes to approach row width limit - for ($i=0; $i < 15; $i++) { + for ($i = 0; $i < 15; $i++) { $attribute = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/attributes/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -755,7 +755,7 @@ class DatabaseCustomServerTest extends Scope $collectionId = $collection['body']['$id']; // add unique attributes for indexing - for ($i=0; $i < 64; $i++) { + for ($i = 0; $i < 64; $i++) { // $this->assertEquals(true, static::getDatabase()->createAttribute('indexLimit', "test{$i}", Database::VAR_STRING, 16, true)); $attribute = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/attributes/string', array_merge([ 'content-type' => 'application/json', @@ -792,7 +792,7 @@ class DatabaseCustomServerTest extends Scope // testing for indexLimit = 64 // MariaDB, MySQL, and MongoDB create 3 indexes per new collection // Add up to the limit, then check if the next index throws IndexLimitException - for ($i=0; $i < 61; $i++) { + for ($i = 0; $i < 61; $i++) { // $this->assertEquals(true, static::getDatabase()->createIndex('indexLimit', "index{$i}", Database::INDEX_KEY, ["test{$i}"], [16])); $index = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/indexes', array_merge([ 'content-type' => 'application/json', @@ -844,4 +844,4 @@ class DatabaseCustomServerTest extends Scope $this->assertEquals(204, $collection['headers']['status-code']); } -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Database/DatabasePermissionsMemberTest.php b/tests/e2e/Services/Database/DatabasePermissionsMemberTest.php index 84c5ee6d6b..c3d581cf3d 100644 --- a/tests/e2e/Services/Database/DatabasePermissionsMemberTest.php +++ b/tests/e2e/Services/Database/DatabasePermissionsMemberTest.php @@ -160,6 +160,5 @@ class DatabasePermissionsMemberTest extends Scope }, false); $this->assertTrue($hasPermissions); } - } } diff --git a/tests/e2e/Services/Functions/FunctionsBase.php b/tests/e2e/Services/Functions/FunctionsBase.php index 3d0a541fbe..c45ebbe068 100644 --- a/tests/e2e/Services/Functions/FunctionsBase.php +++ b/tests/e2e/Services/Functions/FunctionsBase.php @@ -10,8 +10,9 @@ trait FunctionsBase 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); + 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); } // /** @@ -72,7 +73,7 @@ trait FunctionsBase // $this->assertGreaterThan(0, $response['body']['total']); // $this->assertIsInt($response['body']['total']); // $this->assertCount(2, $response['body']['teams']); - + // $response = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ // 'content-type' => 'application/json', // 'x-appwrite-project' => $this->getProject()['$id'], @@ -84,7 +85,7 @@ trait FunctionsBase // $this->assertGreaterThan(0, $response['body']['total']); // $this->assertIsInt($response['body']['total']); // $this->assertCount(2, $response['body']['teams']); - + // $response = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ // 'content-type' => 'application/json', // 'x-appwrite-project' => $this->getProject()['$id'], @@ -97,7 +98,7 @@ trait FunctionsBase // $this->assertIsInt($response['body']['total']); // $this->assertCount(1, $response['body']['teams']); // $this->assertEquals('Manchester United', $response['body']['teams'][0]['name']); - + // $response = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ // 'content-type' => 'application/json', // 'x-appwrite-project' => $this->getProject()['$id'], @@ -206,4 +207,4 @@ trait FunctionsBase // return []; // } -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index 8927302819..b2fb7d7d37 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -16,7 +16,7 @@ class FunctionsCustomClientTest extends Scope use ProjectCustom; use SideClient; - public function testCreate():array + public function testCreate(): array { /** * Test for SUCCESS @@ -45,7 +45,7 @@ class FunctionsCustomClientTest extends Scope return []; } - public function testCreateExecution():array + public function testCreateExecution(): array { /** * Test for SUCCESS @@ -57,7 +57,7 @@ class FunctionsCustomClientTest extends Scope ], [ 'functionId' => 'unique()', 'name' => 'Test', - 'execute' => ['user:'.$this->getUser()['$id']], + 'execute' => ['user:' . $this->getUser()['$id']], 'runtime' => 'php-8.0', 'vars' => [ 'funcKey1' => 'funcValue1', @@ -75,10 +75,10 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); $folder = 'php'; - $code = realpath(__DIR__ . '/../../../resources/functions'). "/$folder/code.tar.gz"; + $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; $this->packageCode($folder); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/deployments', [ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/deployments', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -94,7 +94,7 @@ class FunctionsCustomClientTest extends Scope // Wait for deployment to be built. sleep(10); - $function = $this->client->call(Client::METHOD_PATCH, '/functions/'.$function['body']['$id'].'/deployments/'.$deploymentId, [ + $function = $this->client->call(Client::METHOD_PATCH, '/functions/' . $function['body']['$id'] . '/deployments/' . $deploymentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -102,7 +102,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(200, $function['headers']['status-code']); - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/executions', [ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -111,7 +111,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(401, $execution['headers']['status-code']); - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -121,7 +121,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $execution['headers']['status-code']); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$function['body']['$id'], [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $function['body']['$id'], [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], @@ -132,7 +132,7 @@ class FunctionsCustomClientTest extends Scope return []; } - public function testCreateCustomExecution():array + public function testCreateCustomExecution(): array { /** * Test for SUCCESS @@ -162,10 +162,10 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); $folder = 'php-fn'; - $code = realpath(__DIR__ . '/../../../resources/functions'). "/$folder/code.tar.gz"; + $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; $this->packageCode($folder); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', [ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -181,7 +181,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $deployment['headers']['status-code']); - $function = $this->client->call(Client::METHOD_PATCH, '/functions/'.$functionId.'/deployments/'.$deploymentId, [ + $function = $this->client->call(Client::METHOD_PATCH, '/functions/' . $functionId . '/deployments/' . $deploymentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -189,7 +189,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(200, $function['headers']['status-code']); - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], $this->getHeaders()), [ @@ -202,7 +202,7 @@ class FunctionsCustomClientTest extends Scope sleep(10); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions/'.$executionId, [ + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions/' . $executionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -229,7 +229,7 @@ class FunctionsCustomClientTest extends Scope ]; } - public function testCreateExecutionUnauthorized():array + public function testCreateExecutionUnauthorized(): array { $function = $this->client->call(Client::METHOD_POST, '/functions', [ 'content-type' => 'application/json', @@ -243,7 +243,7 @@ class FunctionsCustomClientTest extends Scope 'timeout' => 10, ]); - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/executions', [ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -264,7 +264,7 @@ class FunctionsCustomClientTest extends Scope $projectId = $this->getProject()['$id']; $apikey = $this->getProject()['apiKey']; - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], $this->getHeaders()), [ @@ -275,7 +275,7 @@ class FunctionsCustomClientTest extends Scope sleep(10); - $base = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ + $base = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -286,7 +286,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals('completed', $base['body']['executions'][0]['status']); $this->assertEquals('completed', $base['body']['executions'][1]['status']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -297,7 +297,7 @@ class FunctionsCustomClientTest extends Scope $this->assertCount(1, $executions['body']['executions']); $this->assertEquals($base['body']['executions'][1]['$id'], $executions['body']['executions'][0]['$id']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -307,17 +307,16 @@ class FunctionsCustomClientTest extends Scope ]); // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/'. $functionId, [ + $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], []); $this->assertEquals(204, $response['headers']['status-code']); - } - public function testSynchronousExecution():array + public function testSynchronousExecution(): array { /** * Test for SUCCESS @@ -348,10 +347,10 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); $folder = 'php-fn'; - $code = realpath(__DIR__ . '/../../../resources/functions'). "/$folder/code.tar.gz"; + $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; $this->packageCode($folder); - $deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', [ + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -367,7 +366,7 @@ class FunctionsCustomClientTest extends Scope // Wait for deployment to be built. sleep(10); - $function = $this->client->call(Client::METHOD_PATCH, '/functions/'.$functionId.'/deployments/'.$deploymentId, [ + $function = $this->client->call(Client::METHOD_PATCH, '/functions/' . $functionId . '/deployments/' . $deploymentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, @@ -375,7 +374,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(200, $function['headers']['status-code']); - $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, ], $this->getHeaders()), [ @@ -399,8 +398,8 @@ class FunctionsCustomClientTest extends Scope $this->assertNotEmpty($output['APPWRITE_FUNCTION_JWT']); $this->assertEquals($projectId, $output['APPWRITE_FUNCTION_PROJECT_ID']); - // Cleanup : Delete function - $response = $this->client->call(Client::METHOD_DELETE, '/functions/'. $functionId, [ + // Cleanup : Delete function + $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index 307a634393..7967fbc5f9 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -764,8 +764,8 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals($executions['body']['executions'][0]['status'], 'failed'); $this->assertEquals($executions['body']['executions'][0]['statusCode'], 500); $this->assertGreaterThan(2, $executions['body']['executions'][0]['time']); - $this->assertLessThan(7, $executions['body']['executions'][0]['time']); - $this->assertGreaterThan(5, $executions['body']['executions'][0]['time']); + $this->assertLessThan(6, $executions['body']['executions'][0]['time']); + $this->assertGreaterThan(4, $executions['body']['executions'][0]['time']); $this->assertEquals($executions['body']['executions'][0]['response'], ''); $this->assertEquals($executions['body']['executions'][0]['stderr'], 'An internal curl error has occurred within the executor! Error Msg: Operation timed out'); @@ -879,7 +879,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals($executions['body']['executions'][0]['trigger'], 'http'); $this->assertStringContainsString('foobar', $executions['body']['executions'][0]['response']); - // Cleanup : Delete function + // Cleanup : Delete function $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -985,7 +985,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals($executions['body']['executions'][0]['trigger'], 'http'); $this->assertStringContainsString('foobar', $executions['body']['executions'][0]['response']); - // Cleanup : Delete function + // Cleanup : Delete function $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -1090,7 +1090,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals($executions['body']['executions'][0]['trigger'], 'http'); $this->assertStringContainsString('foobar', $executions['body']['executions'][0]['response']); - // Cleanup : Delete function + // Cleanup : Delete function $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -1195,7 +1195,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals($executions['body']['executions'][0]['trigger'], 'http'); $this->assertStringContainsString('foobar', $executions['body']['executions'][0]['response']); - // Cleanup : Delete function + // Cleanup : Delete function $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -1300,7 +1300,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals($executions['body']['executions'][0]['trigger'], 'http'); $this->assertStringContainsString('foobar', $executions['body']['executions'][0]['response']); - // Cleanup : Delete function + // Cleanup : Delete function $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -1405,7 +1405,7 @@ class FunctionsCustomServerTest extends Scope // $this->assertEquals($executions['body']['executions'][0]['trigger'], 'http'); // $this->assertStringContainsString('foobar', $executions['body']['executions'][0]['response']); - // // Cleanup : Delete function + // // Cleanup : Delete function // $response = $this->client->call(Client::METHOD_DELETE, '/functions/'. $functionId, [ // 'content-type' => 'application/json', // 'x-appwrite-project' => $this->getProject()['$id'], diff --git a/tests/e2e/Services/Health/HealthBase.php b/tests/e2e/Services/Health/HealthBase.php index b7d4ce4772..cbd0f97668 100644 --- a/tests/e2e/Services/Health/HealthBase.php +++ b/tests/e2e/Services/Health/HealthBase.php @@ -6,4 +6,4 @@ use Tests\E2E\Client; trait HealthBase { -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Locale/LocaleBase.php b/tests/e2e/Services/Locale/LocaleBase.php index dec0d2131c..64b5e5f43e 100644 --- a/tests/e2e/Services/Locale/LocaleBase.php +++ b/tests/e2e/Services/Locale/LocaleBase.php @@ -7,7 +7,7 @@ use Tests\E2E\Client; trait LocaleBase { - public function testGetLocale():array + public function testGetLocale(): array { /** * Test for SUCCESS @@ -29,11 +29,11 @@ trait LocaleBase /** * Test for FAILURE */ - + return []; } - public function testGetCountries():array + public function testGetCountries(): array { /** * Test for SUCCESS @@ -62,7 +62,7 @@ trait LocaleBase $this->assertEquals(194, $response['body']['total']); $this->assertEquals($response['body']['countries'][0]['name'], 'Afganistรกn'); $this->assertEquals($response['body']['countries'][0]['code'], 'AF'); - + /** * Test for FAILURE */ @@ -70,7 +70,7 @@ trait LocaleBase return []; } - public function testGetCountriesEU():array + public function testGetCountriesEU(): array { /** * Test for SUCCESS @@ -100,7 +100,7 @@ trait LocaleBase $this->assertEquals($response['body']['countries'][0]['name'], 'Alemania'); $this->assertEquals($response['body']['countries'][0]['code'], 'DE'); - + /** * Test for FAILURE */ @@ -108,7 +108,7 @@ trait LocaleBase return []; } - public function testGetCountriesPhones():array + public function testGetCountriesPhones(): array { /** * Test for SUCCESS @@ -117,7 +117,7 @@ trait LocaleBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - + $this->assertEquals($response['headers']['status-code'], 200); $this->assertIsArray($response['body']); $this->assertEquals(194, $response['body']['total']); @@ -125,7 +125,7 @@ trait LocaleBase $this->assertEquals($response['body']['phones'][0]['code'], '+1'); $this->assertEquals($response['body']['phones'][0]['countryName'], 'Canada'); $this->assertEquals($response['body']['phones'][0]['countryCode'], 'CA'); - + /** * Test for FAILURE */ @@ -133,7 +133,7 @@ trait LocaleBase return []; } - public function testGetContinents():array + public function testGetContinents(): array { /** * Test for SUCCESS @@ -162,7 +162,7 @@ trait LocaleBase $this->assertEquals($response['body']['continents'][0]['code'], 'NA'); $this->assertEquals($response['body']['continents'][0]['name'], 'Amรฉrica del Norte'); - + /** * Test for FAILURE */ @@ -170,7 +170,7 @@ trait LocaleBase return []; } - public function testGetCurrencies():array + public function testGetCurrencies(): array { /** * Test for SUCCESS @@ -185,7 +185,7 @@ trait LocaleBase $this->assertEquals(117, $response['body']['total']); $this->assertEquals($response['body']['currencies'][0]['symbol'], '$'); $this->assertEquals($response['body']['currencies'][0]['name'], 'US Dollar'); - + /** * Test for FAILURE */ @@ -193,7 +193,7 @@ trait LocaleBase return []; } - public function testGetLanguages():array + public function testGetLanguages(): array { /** * Test for SUCCESS @@ -214,7 +214,7 @@ trait LocaleBase $this->assertEquals($response['body']['languages'][183]['code'], 'zu'); $this->assertEquals($response['body']['languages'][183]['name'], 'Zulu'); $this->assertEquals($response['body']['languages'][183]['nativeName'], 'isiZulu'); - + /** * Test for FAILURE */ @@ -238,8 +238,8 @@ trait LocaleBase 'x-appwrite-locale' => $lang, ]); - if(!\is_array($response['body']['countries'])) { - throw new Exception('Failed to iterate locale: '.$lang); + if (!\is_array($response['body']['countries'])) { + throw new Exception('Failed to iterate locale: ' . $lang); } foreach ($response['body']['countries'] as $i => $code) { @@ -258,7 +258,7 @@ trait LocaleBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-locale' => $lang, ]); - + foreach ($response['body']['continents'] as $i => $code) { $this->assertContains($code['code'], $defaultContinents, $code['code'] . ' continent should be removed from ' . $lang); } @@ -270,11 +270,11 @@ trait LocaleBase $this->assertEquals($response['headers']['status-code'], 200); $this->assertEquals(7, $response['body']['total']); } - + /** * Test for FAILURE */ return []; } -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Locale/LocaleConsoleClientTest.php b/tests/e2e/Services/Locale/LocaleConsoleClientTest.php index e43f0f50ab..29b3150fed 100644 --- a/tests/e2e/Services/Locale/LocaleConsoleClientTest.php +++ b/tests/e2e/Services/Locale/LocaleConsoleClientTest.php @@ -11,4 +11,4 @@ class LocaleConsoleClientTest extends Scope use LocaleBase; use ProjectConsole; use SideClient; -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Locale/LocaleCustomClientTest.php b/tests/e2e/Services/Locale/LocaleCustomClientTest.php index be1e5d0e85..b28584280e 100644 --- a/tests/e2e/Services/Locale/LocaleCustomClientTest.php +++ b/tests/e2e/Services/Locale/LocaleCustomClientTest.php @@ -11,4 +11,4 @@ class LocaleCustomClientTest extends Scope use LocaleBase; use ProjectCustom; use SideClient; -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Locale/LocaleCustomServerTest.php b/tests/e2e/Services/Locale/LocaleCustomServerTest.php index b8a3ebb19c..62d4e76802 100644 --- a/tests/e2e/Services/Locale/LocaleCustomServerTest.php +++ b/tests/e2e/Services/Locale/LocaleCustomServerTest.php @@ -12,4 +12,4 @@ class LocaleCustomServerTest extends Scope use LocaleBase; use ProjectCustom; use SideServer; -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Projects/ProjectsBase.php b/tests/e2e/Services/Projects/ProjectsBase.php index ef67968b99..a9ccd73900 100644 --- a/tests/e2e/Services/Projects/ProjectsBase.php +++ b/tests/e2e/Services/Projects/ProjectsBase.php @@ -6,4 +6,4 @@ use Tests\E2E\Client; trait ProjectsBase { -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 1154515648..1a4318c310 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -786,6 +786,104 @@ class ProjectsConsoleClientTest extends Scope } } + /** @depends testUpdateProjectServiceStatusAdmin */ + public function testUpdateProjectServiceStatusServer($data): void + { + $id = $data['projectId']; + + $services = require('app/config/services.php'); + + /** + * Test for Disabled + */ + foreach ($services as $service) { + if (!$service['optional']) { + continue; + } + + $key = $service['key'] ?? ''; + + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/service', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + ]), [ + 'service' => $key, + 'status' => false, + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']['$id']); + + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + ])); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']['$id']); + $this->assertEquals(false, $response['body']['serviceStatusFor' . ucfirst($key)]); + } + + // Create API Key + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + ]), [ + 'name' => 'Key Test', + 'scopes' => ['functions.read', 'teams.write'], + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + $keyId = $response['body']['$id']; + $keySecret = $response['body']['secret']; + + /** + * Request with API Key must succeed + */ + $response = $this->client->call(Client::METHOD_GET, '/functions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $id, + 'x-appwrite-key' => $keySecret, + ])); + + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_POST, '/teams', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $id, + 'x-appwrite-key' => $keySecret, + ]), [ + 'teamId' => 'unique()', + 'name' => 'Arsenal' + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Cleanup + + $response = $this->client->call(Client::METHOD_DELETE, '/projects/' . $id . '/keys/' . $keyId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + ]), []); + + $this->assertEquals(204, $response['headers']['status-code']); + + foreach ($services as $service) { + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $id . '/service/', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'service' => $service, + 'status' => true, + ]); + } + } + /** * @depends testCreateProject */ @@ -924,6 +1022,7 @@ class ProjectsConsoleClientTest extends Scope 'security' => false, 'httpUser' => '', 'httpPass' => '', + 'signatureKey' => 'My own uniq key', ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -939,6 +1038,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(false, $response['body']['security']); $this->assertEquals('', $response['body']['httpUser']); $this->assertEquals('', $response['body']['httpPass']); + $this->assertEquals('My own uniq key', $response['body']['signatureKey']); $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/webhooks/' . $webhookId, array_merge([ 'content-type' => 'application/json', diff --git a/tests/e2e/Services/Projects/ProjectsCustomClientTest.php b/tests/e2e/Services/Projects/ProjectsCustomClientTest.php index e9e3049937..9dfd48ce50 100644 --- a/tests/e2e/Services/Projects/ProjectsCustomClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsCustomClientTest.php @@ -16,4 +16,4 @@ class ProjectsCustomClientTest extends Scope { $this->assertEquals(true, true); } -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Projects/ProjectsCustomServerTest.php b/tests/e2e/Services/Projects/ProjectsCustomServerTest.php index e232848460..1c5b48f146 100644 --- a/tests/e2e/Services/Projects/ProjectsCustomServerTest.php +++ b/tests/e2e/Services/Projects/ProjectsCustomServerTest.php @@ -16,4 +16,4 @@ class ProjectsCustomServerTest extends Scope { $this->assertEquals(true, true); } -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php index 017792a61f..88c4e56839 100644 --- a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php @@ -10,7 +10,6 @@ use Tests\E2E\Scopes\SideClient; use Utopia\CLI\Console; use WebSocket\ConnectionException; - class RealtimeCustomClientTest extends Scope { use RealtimeBase; @@ -1257,7 +1256,7 @@ class RealtimeCustomClientTest extends Scope $client->close(); - // Cleanup : Delete function + // Cleanup : Delete function $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index 525c4144db..a63bab7652 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -72,7 +72,7 @@ trait StorageBase $source = __DIR__ . "/../../../resources/disk-a/large-file.mp4"; $totalSize = \filesize($source); - $chunkSize = 5*1024*1024; + $chunkSize = 5 * 1024 * 1024; $handle = @fopen($source, "rb"); $fileId = 'unique()'; $mimeType = mime_content_type($source); @@ -86,7 +86,7 @@ trait StorageBase while (!feof($handle)) { $curlFile = new \CURLFile('data://' . $mimeType . ';base64,' . base64_encode(@fread($handle, $chunkSize)), $mimeType, 'large-file.mp4'); $headers['content-range'] = 'bytes ' . ($counter * $chunkSize) . '-' . min(((($counter * $chunkSize) + $chunkSize) - 1), $size) . '/' . $size; - if(!empty($id)) { + if (!empty($id)) { $headers['x-appwrite-id'] = $id; } $largeFile = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucket2['body']['$id'] . '/files', array_merge($headers, $this->getHeaders()), [ @@ -114,7 +114,7 @@ trait StorageBase */ $source = __DIR__ . "/../../../resources/disk-a/large-file.mp4"; $totalSize = \filesize($source); - $chunkSize = 6*1024*1024; + $chunkSize = 6 * 1024 * 1024; $handle = @fopen($source, "rb"); $fileId = 'unique()'; $mimeType = mime_content_type($source); @@ -127,7 +127,7 @@ trait StorageBase $id = ''; $curlFile = new \CURLFile('data://' . $mimeType . ';base64,' . base64_encode(@fread($handle, $chunkSize)), $mimeType, 'large-file.mp4'); $headers['content-range'] = 'bytes ' . ($counter * $chunkSize) . '-' . min(((($counter * $chunkSize) + $chunkSize) - 1), $size) . '/' . $size; - $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucket2['body']['$id'] . '/files', $this->getHeaders(), [ + $res = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucket2['body']['$id'] . '/files', $this->getHeaders(), [ 'fileId' => $fileId, 'file' => $curlFile, 'read' => ['role:all'], @@ -350,7 +350,7 @@ trait StorageBase $this->assertEquals('image/png', $file51['headers']['content-type']); $this->assertNotEmpty($file51['body']); $this->assertEquals($originalChunk, $file51['body']); - + // Test ranged download - with invalid range $file52 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/download', array_merge([ 'content-type' => 'application/json', @@ -359,25 +359,25 @@ trait StorageBase ], $this->getHeaders())); $this->assertEquals(206, $file52['headers']['status-code']); - + // Test ranged download - with invalid range $file53 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'Range' => 'bytes=988', ], $this->getHeaders())); - + $this->assertEquals(416, $file53['headers']['status-code']); - + // Test ranged download - with invalid range $file54 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/download', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'Range' => 'bytes=-988', ], $this->getHeaders())); - + $this->assertEquals(416, $file54['headers']['status-code']); - + $file6 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $data['fileId'] . '/view', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -399,7 +399,7 @@ trait StorageBase 'output' => 'png', 'rotation' => '-315', ]); - + $this->assertEquals(200, $file7['headers']['status-code']); $this->assertEquals('image/png', $file7['headers']['content-type']); $this->assertNotEmpty($file7['body']); @@ -460,7 +460,7 @@ trait StorageBase ]); $this->assertEquals(201, $file['headers']['status-code']); $this->assertNotEmpty($file['body']['$id']); - + $fileId = $file['body']['$id']; //get image preview @@ -503,7 +503,7 @@ trait StorageBase ]); $this->assertEquals(201, $file['headers']['status-code']); $this->assertNotEmpty($file['body']['$id']); - + //get image preview after $file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([ 'content-type' => 'application/json', @@ -541,8 +541,8 @@ trait StorageBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $this->assertEquals(200, $file['headers']['status-code']); @@ -570,8 +570,8 @@ trait StorageBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'read' => ['user:'.$this->getUser()['$id']], - 'write' => ['user:'.$this->getUser()['$id']], + 'read' => ['user:' . $this->getUser()['$id']], + 'write' => ['user:' . $this->getUser()['$id']], ]); $this->assertEquals(404, $file['headers']['status-code']); @@ -604,5 +604,4 @@ trait StorageBase return $data; } - } diff --git a/tests/e2e/Services/Storage/StorageCustomClientTest.php b/tests/e2e/Services/Storage/StorageCustomClientTest.php index ddc320fb24..dc8fc6165e 100644 --- a/tests/e2e/Services/Storage/StorageCustomClientTest.php +++ b/tests/e2e/Services/Storage/StorageCustomClientTest.php @@ -38,7 +38,7 @@ class StorageCustomClientTest extends Scope $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucketId); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'. $bucketId . '/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -85,7 +85,7 @@ class StorageCustomClientTest extends Scope /** * Test for FAILURE */ - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'. $bucketId . '/files', [ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', [ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], [ @@ -126,7 +126,7 @@ class StorageCustomClientTest extends Scope $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucket['body']['$id']); - $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/'. $bucket['body']['$id'] . '/files', array_merge([ + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucket['body']['$id'] . '/files', array_merge([ 'content-type' => 'multipart/form-data', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -136,8 +136,8 @@ class StorageCustomClientTest extends Scope $this->assertEquals($file['headers']['status-code'], 201); $this->assertNotEmpty($file['body']['$id']); - $this->assertContains('user:'.$this->getUser()['$id'], $file['body']['$read']); - $this->assertContains('user:'.$this->getUser()['$id'], $file['body']['$write']); + $this->assertContains('user:' . $this->getUser()['$id'], $file['body']['$read']); + $this->assertContains('user:' . $this->getUser()['$id'], $file['body']['$write']); $this->assertIsInt($file['body']['dateCreated']); $this->assertEquals('permissions.png', $file['body']['name']); $this->assertEquals('image/png', $file['body']['mimeType']); @@ -168,7 +168,7 @@ class StorageCustomClientTest extends Scope $this->assertStringStartsWith('Read permissions must be one of:', $file['body']['message']); $this->assertStringContainsString('role:all', $file['body']['message']); $this->assertStringContainsString('role:member', $file['body']['message']); - $this->assertStringContainsString('user:'.$this->getUser()['$id'], $file['body']['message']); + $this->assertStringContainsString('user:' . $this->getUser()['$id'], $file['body']['message']); $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ 'content-type' => 'multipart/form-data', @@ -184,7 +184,7 @@ class StorageCustomClientTest extends Scope $this->assertStringStartsWith('Write permissions must be one of:', $file['body']['message']); $this->assertStringContainsString('role:all', $file['body']['message']); $this->assertStringContainsString('role:member', $file['body']['message']); - $this->assertStringContainsString('user:'.$this->getUser()['$id'], $file['body']['message']); + $this->assertStringContainsString('user:' . $this->getUser()['$id'], $file['body']['message']); $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ 'content-type' => 'multipart/form-data', @@ -201,7 +201,7 @@ class StorageCustomClientTest extends Scope $this->assertStringStartsWith('Read permissions must be one of:', $file['body']['message']); $this->assertStringContainsString('role:all', $file['body']['message']); $this->assertStringContainsString('role:member', $file['body']['message']); - $this->assertStringContainsString('user:'.$this->getUser()['$id'], $file['body']['message']); + $this->assertStringContainsString('user:' . $this->getUser()['$id'], $file['body']['message']); } /** @@ -223,7 +223,7 @@ class StorageCustomClientTest extends Scope $this->assertStringStartsWith('Read permissions must be one of:', $file['body']['message']); $this->assertStringContainsString('role:all', $file['body']['message']); $this->assertStringContainsString('role:member', $file['body']['message']); - $this->assertStringContainsString('user:'.$this->getUser()['$id'], $file['body']['message']); + $this->assertStringContainsString('user:' . $this->getUser()['$id'], $file['body']['message']); $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $data['bucketId'] . '/files/' . $data['fileId'], array_merge([ 'content-type' => 'application/json', @@ -236,7 +236,7 @@ class StorageCustomClientTest extends Scope $this->assertStringStartsWith('Write permissions must be one of:', $file['body']['message']); $this->assertStringContainsString('role:all', $file['body']['message']); $this->assertStringContainsString('role:member', $file['body']['message']); - $this->assertStringContainsString('user:'.$this->getUser()['$id'], $file['body']['message']); + $this->assertStringContainsString('user:' . $this->getUser()['$id'], $file['body']['message']); $file = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $data['bucketId'] . '/files/' . $data['fileId'], array_merge([ 'content-type' => 'application/json', @@ -250,6 +250,6 @@ class StorageCustomClientTest extends Scope $this->assertStringStartsWith('Read permissions must be one of:', $file['body']['message']); $this->assertStringContainsString('role:all', $file['body']['message']); $this->assertStringContainsString('role:member', $file['body']['message']); - $this->assertStringContainsString('user:'.$this->getUser()['$id'], $file['body']['message']); + $this->assertStringContainsString('user:' . $this->getUser()['$id'], $file['body']['message']); } -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Storage/StorageCustomServerTest.php b/tests/e2e/Services/Storage/StorageCustomServerTest.php index 66ab2cc105..09777ec20e 100644 --- a/tests/e2e/Services/Storage/StorageCustomServerTest.php +++ b/tests/e2e/Services/Storage/StorageCustomServerTest.php @@ -77,11 +77,17 @@ class StorageCustomServerTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/storage/buckets', - array_merge([ + $response = $this->client->call( + Client::METHOD_GET, + '/storage/buckets', + array_merge( + [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); + ], + $this->getHeaders() + ) + ); $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']); $this->assertEquals($id, $response['body']['buckets'][0]['$id']); @@ -112,11 +118,17 @@ class StorageCustomServerTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $id, - array_merge([ + $response = $this->client->call( + Client::METHOD_GET, + '/storage/buckets/' . $id, + array_merge( + [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); + ], + $this->getHeaders() + ) + ); $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']); $this->assertEquals($id, $response['body']['$id']); @@ -126,18 +138,30 @@ class StorageCustomServerTest extends Scope * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/storage/buckets/empty', - array_merge([ + $response = $this->client->call( + Client::METHOD_GET, + '/storage/buckets/empty', + array_merge( + [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); + ], + $this->getHeaders() + ) + ); $this->assertEquals(404, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_GET, '/storage/buckets/id-is-really-long-id-is-really-long-id-is-really-long-id-is-really-long', - array_merge([ + $response = $this->client->call( + Client::METHOD_GET, + '/storage/buckets/id-is-really-long-id-is-really-long-id-is-really-long-id-is-really-long', + array_merge( + [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); + ], + $this->getHeaders() + ) + ); $this->assertEquals(400, $response['headers']['status-code']); return $data; @@ -196,22 +220,33 @@ class StorageCustomServerTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $id, - array_merge([ + $response = $this->client->call( + Client::METHOD_DELETE, + '/storage/buckets/' . $id, + array_merge( + [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); + ], + $this->getHeaders() + ) + ); $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $id, - array_merge([ + $response = $this->client->call( + Client::METHOD_GET, + '/storage/buckets/' . $id, + array_merge( + [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); + ], + $this->getHeaders() + ) + ); $this->assertEquals(404, $response['headers']['status-code']); return $data; } - } diff --git a/tests/e2e/Services/Teams/TeamsBase.php b/tests/e2e/Services/Teams/TeamsBase.php index 7c85988977..54a423b89b 100644 --- a/tests/e2e/Services/Teams/TeamsBase.php +++ b/tests/e2e/Services/Teams/TeamsBase.php @@ -7,7 +7,7 @@ use Utopia\Database\Database; trait TeamsBase { - public function testCreateTeam():array + public function testCreateTeam(): array { /** * Test for SUCCESS @@ -79,14 +79,14 @@ trait TeamsBase /** * @depends testCreateTeam */ - public function testGetTeam($data):array + public function testGetTeam($data): array { $id = $data['teamUid'] ?? ''; /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$id, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -108,7 +108,7 @@ trait TeamsBase /** * @depends testCreateTeam */ - public function testListTeams($data):array + public function testListTeams($data): array { /** * Test for SUCCESS @@ -242,7 +242,7 @@ trait TeamsBase return []; } - public function testUpdateTeam():array + public function testUpdateTeam(): array { /** * Test for SUCCESS @@ -262,7 +262,7 @@ trait TeamsBase $this->assertIsInt($response['body']['total']); $this->assertIsInt($response['body']['dateCreated']); - $response = $this->client->call(Client::METHOD_PUT, '/teams/'.$response['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/teams/' . $response['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -280,7 +280,7 @@ trait TeamsBase /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_PUT, '/teams/'.$response['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_PUT, '/teams/' . $response['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -291,7 +291,7 @@ trait TeamsBase return []; } - public function testDeleteTeam():array + public function testDeleteTeam(): array { /** * Test for SUCCESS @@ -313,7 +313,7 @@ trait TeamsBase $this->assertIsInt($response['body']['total']); $this->assertIsInt($response['body']['dateCreated']); - $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamUid, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -324,7 +324,7 @@ trait TeamsBase /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -333,4 +333,4 @@ trait TeamsBase return []; } -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Teams/TeamsBaseClient.php b/tests/e2e/Services/Teams/TeamsBaseClient.php index f298532947..bd9b9c1ae0 100644 --- a/tests/e2e/Services/Teams/TeamsBaseClient.php +++ b/tests/e2e/Services/Teams/TeamsBaseClient.php @@ -9,7 +9,7 @@ trait TeamsBaseClient /** * @depends testCreateTeam */ - public function testGetTeamMemberships($data):array + public function testGetTeamMemberships($data): array { $teamUid = $data['teamUid'] ?? ''; $teamName = $data['teamName'] ?? ''; @@ -17,7 +17,7 @@ trait TeamsBaseClient /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -32,7 +32,7 @@ trait TeamsBaseClient $membershipId = $response['body']['memberships'][0]['$id']; - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -47,7 +47,7 @@ trait TeamsBaseClient $this->assertEquals($teamName, $response['body']['memberships'][0]['teamName']); $this->assertEquals('owner', $response['body']['memberships'][0]['roles'][0]); - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -62,7 +62,7 @@ trait TeamsBaseClient $this->assertEquals($teamName, $response['body']['memberships'][0]['teamName']); $this->assertEquals('owner', $response['body']['memberships'][0]['roles'][0]); - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -84,17 +84,17 @@ trait TeamsBaseClient /** * @depends testCreateTeam */ - public function testCreateTeamMembership($data):array + public function testCreateTeamMembership($data): array { $teamUid = $data['teamUid'] ?? ''; $teamName = $data['teamName'] ?? ''; - $email = uniqid().'friend@localhost.test'; + $email = uniqid() . 'friend@localhost.test'; $name = 'Friend User'; /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -117,7 +117,7 @@ trait TeamsBaseClient $this->assertEquals($email, $lastEmail['to'][0]['address']); $this->assertEquals($name, $lastEmail['to'][0]['name']); - $this->assertEquals('Invitation to '.$teamName.' Team at '.$this->getProject()['name'], $lastEmail['subject']); + $this->assertEquals('Invitation to ' . $teamName . ' Team at ' . $this->getProject()['name'], $lastEmail['subject']); $secret = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); $membershipUid = substr($lastEmail['text'], strpos($lastEmail['text'], '?membershipId=', 0) + 14, 20); @@ -127,7 +127,7 @@ trait TeamsBaseClient * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -139,7 +139,7 @@ trait TeamsBaseClient $this->assertEquals(409, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -151,7 +151,7 @@ trait TeamsBaseClient $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -163,7 +163,7 @@ trait TeamsBaseClient $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -191,7 +191,7 @@ trait TeamsBaseClient */ public function testListTeamMemberships($data): void { - $memberships = $this->client->call(Client::METHOD_GET, '/teams/'.$data['teamUid'].'/memberships', array_merge([ + $memberships = $this->client->call(Client::METHOD_GET, '/teams/' . $data['teamUid'] . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -201,7 +201,7 @@ trait TeamsBaseClient $this->assertNotEmpty($memberships['body']['memberships']); $this->assertCount(2, $memberships['body']['memberships']); - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$data['teamUid'].'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $data['teamUid'] . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -218,7 +218,7 @@ trait TeamsBaseClient /** * @depends testCreateTeamMembership */ - public function testUpdateTeamMembership($data):array + public function testUpdateTeamMembership($data): array { $teamUid = $data['teamUid'] ?? ''; $secret = $data['secret'] ?? ''; @@ -230,7 +230,7 @@ trait TeamsBaseClient /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -246,7 +246,7 @@ trait TeamsBaseClient $this->assertCount(2, $response['body']['roles']); $this->assertIsInt($response['body']['joined']); $this->assertEquals(true, $response['body']['confirm']); - $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; + $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $data['session'] = $session; @@ -258,7 +258,7 @@ trait TeamsBaseClient 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'password' => 'new-password' ]); @@ -278,7 +278,7 @@ trait TeamsBaseClient 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'password' => 'new-password', ]); @@ -291,7 +291,7 @@ trait TeamsBaseClient 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ 'password' => 'newer-password', 'oldPassword' => 'new-password' @@ -310,7 +310,7 @@ trait TeamsBaseClient /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -321,7 +321,7 @@ trait TeamsBaseClient $this->assertEquals(401, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -332,7 +332,7 @@ trait TeamsBaseClient $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -343,7 +343,7 @@ trait TeamsBaseClient $this->assertEquals(401, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -354,7 +354,7 @@ trait TeamsBaseClient $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid.'/status', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -371,7 +371,7 @@ trait TeamsBaseClient /** * @depends testUpdateTeamMembership */ - public function testUpdateTeamMembershipRoles($data):array + public function testUpdateTeamMembershipRoles($data): array { $teamUid = $data['teamUid'] ?? ''; $membershipUid = $data['membershipUid'] ?? ''; @@ -381,7 +381,7 @@ trait TeamsBaseClient * Test for SUCCESS */ $roles = ['admin', 'editor', 'uncle']; - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -401,7 +401,7 @@ trait TeamsBaseClient /** * Test for unknown team */ - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.'abc'.'/memberships/'.$membershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . 'abc' . '/memberships/' . $membershipUid, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -414,7 +414,7 @@ trait TeamsBaseClient /** * Test for unknown membership ID */ - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.'abc', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . 'abc', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -424,42 +424,42 @@ trait TeamsBaseClient $this->assertEquals(404, $response['headers']['status-code']); - + /** * Test for when a user other than the owner tries to update membership */ - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid, [ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid, [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ], [ 'roles' => $roles ]); $this->assertEquals(401, $response['headers']['status-code']); $this->assertEquals('User is not allowed to modify roles', $response['body']['message']); - + return $data; } /** * @depends testUpdateTeamMembershipRoles */ - public function testDeleteTeamMembership($data):array + public function testDeleteTeamMembership($data): array { $teamUid = $data['teamUid'] ?? ''; $membershipUid = $data['membershipUid'] ?? ''; $session = $data['session'] ?? ''; - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(2, $response['body']['total']); - + $ownerMembershipUid = $response['body']['memberships'][0]['$id']; /** @@ -469,25 +469,25 @@ trait TeamsBaseClient /** * Test deleting a membership that does not exists */ - $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamUid.'/memberships/dne', [ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/dne', [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]); - + $this->assertEquals(404, $response['headers']['status-code']); /** * Test deleting another user's membership */ - $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamUid.'/memberships/'.$ownerMembershipUid, [ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/' . $ownerMembershipUid, [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]); - + $this->assertEquals(401, $response['headers']['status-code']); /** @@ -497,17 +497,17 @@ trait TeamsBaseClient /** * Test for when a user other than the owner tries to delete their membership */ - $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamUid.'/memberships/'.$membershipUid, [ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/' . $membershipUid, [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_'.$this->getProject()['$id'].'='.$session, + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]); - + $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -518,7 +518,7 @@ trait TeamsBaseClient /** * Test for when the owner tries to delete their membership */ - $response = $this->client->call(Client::METHOD_DELETE, '/teams/'.$teamUid.'/memberships/'.$ownerMembershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/' . $ownerMembershipUid, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -527,7 +527,7 @@ trait TeamsBaseClient $this->assertEquals(204, $response['headers']['status-code']); $this->assertEmpty($response['body']); - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid.'/memberships/'.$ownerMembershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $ownerMembershipUid, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -537,5 +537,4 @@ trait TeamsBaseClient return []; } - -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Teams/TeamsBaseServer.php b/tests/e2e/Services/Teams/TeamsBaseServer.php index 5db4b628f6..86705d5e6a 100644 --- a/tests/e2e/Services/Teams/TeamsBaseServer.php +++ b/tests/e2e/Services/Teams/TeamsBaseServer.php @@ -9,18 +9,18 @@ trait TeamsBaseServer /** * @depends testCreateTeam */ - public function testGetTeamMemberships($data):array + public function testGetTeamMemberships($data): array { $id = $data['teamUid'] ?? ''; /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$id.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $id . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - + $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(0, $response['body']['total']); @@ -35,16 +35,16 @@ trait TeamsBaseServer /** * @depends testCreateTeam */ - public function testCreateTeamMembership($data):array + public function testCreateTeamMembership($data): array { $teamUid = $data['teamUid'] ?? ''; $teamName = $data['teamName'] ?? ''; - $email = uniqid().'friend@localhost.test'; + $email = uniqid() . 'friend@localhost.test'; /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -80,7 +80,7 @@ trait TeamsBaseServer * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -92,7 +92,7 @@ trait TeamsBaseServer $this->assertEquals(409, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -104,7 +104,7 @@ trait TeamsBaseServer $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -116,7 +116,7 @@ trait TeamsBaseServer $this->assertEquals(400, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/teams/'.$teamUid.'/memberships', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -147,7 +147,7 @@ trait TeamsBaseServer * Test for SUCCESS */ $roles = ['admin', 'editor', 'uncle']; - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid, array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid, array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -170,7 +170,7 @@ trait TeamsBaseServer */ $apiKey = $this->getNewKey(['teams.read']); $roles = ['admin', 'editor', 'uncle']; - $response = $this->client->call(Client::METHOD_PATCH, '/teams/'.$teamUid.'/memberships/'.$membershipUid, [ + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid, [ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -187,12 +187,13 @@ trait TeamsBaseServer /** * @depends testUpdateMembershipRoles */ - public function testDeleteUserUpdatesTeamMembershipCount($data) { + public function testDeleteUserUpdatesTeamMembershipCount($data) + { $teamUid = $data['teamUid'] ?? ''; $userUid = $data['userUid'] ?? ''; /** Get Team Count */ - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -204,8 +205,8 @@ trait TeamsBaseServer $this->assertEquals(1, $response['body']['total']); $this->assertIsInt($response['body']['total']); $this->assertIsInt($response['body']['dateCreated']); - - + + /** Delete User */ $user = $this->client->call(Client::METHOD_DELETE, '/users/' . $userUid, array_merge([ 'content-type' => 'application/json', @@ -218,7 +219,7 @@ trait TeamsBaseServer sleep(5); /** Get Team Count */ - $response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid, array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -229,7 +230,6 @@ trait TeamsBaseServer $this->assertEquals('Arsenal', $response['body']['name']); $this->assertEquals(0, $response['body']['total']); $this->assertIsInt($response['body']['total']); - $this->assertIsInt($response['body']['dateCreated']); - + $this->assertIsInt($response['body']['dateCreated']); } -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Teams/TeamsConsoleClientTest.php b/tests/e2e/Services/Teams/TeamsConsoleClientTest.php index 7b7e24aee6..970a9e88a0 100644 --- a/tests/e2e/Services/Teams/TeamsConsoleClientTest.php +++ b/tests/e2e/Services/Teams/TeamsConsoleClientTest.php @@ -14,7 +14,8 @@ class TeamsConsoleClientTest extends Scope use ProjectConsole; use SideClient; - public function testRequestHeader() { + public function testRequestHeader() + { /** * Test without header */ @@ -61,4 +62,4 @@ class TeamsConsoleClientTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); } -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Teams/TeamsCustomClientTest.php b/tests/e2e/Services/Teams/TeamsCustomClientTest.php index a1dc3f23b4..3b46cbcb7f 100644 --- a/tests/e2e/Services/Teams/TeamsCustomClientTest.php +++ b/tests/e2e/Services/Teams/TeamsCustomClientTest.php @@ -12,4 +12,4 @@ class TeamsCustomClientTest extends Scope use TeamsBaseClient; use ProjectCustom; use SideClient; -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Teams/TeamsCustomServerTest.php b/tests/e2e/Services/Teams/TeamsCustomServerTest.php index 905203a404..ccbb598934 100644 --- a/tests/e2e/Services/Teams/TeamsCustomServerTest.php +++ b/tests/e2e/Services/Teams/TeamsCustomServerTest.php @@ -13,4 +13,4 @@ class TeamsCustomServerTest extends Scope use TeamsBaseServer; use ProjectCustom; use SideServer; -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index c2a96a87da..5e1e3206ff 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -7,7 +7,7 @@ use Utopia\Database\Database; trait UsersBase { - public function testCreateUser():array + public function testCreateUser(): array { /** * Test for SUCCESS @@ -24,7 +24,7 @@ trait UsersBase // Test empty prefs is object not array $bodyString = $user['body']; - $prefs = substr($bodyString, strpos($bodyString, '"prefs":')+8,2); + $prefs = substr($bodyString, strpos($bodyString, '"prefs":') + 8, 2); $this->assertEquals('{}', $prefs); $body = json_decode($bodyString, true); @@ -214,7 +214,7 @@ trait UsersBase /** * @depends testCreateUser */ - public function testGetUser(array $data):array + public function testGetUser(array $data): array { /** * Test for SUCCESS @@ -255,7 +255,7 @@ trait UsersBase /** * @depends testGetUser */ - public function testUpdateUserName(array $data):array + public function testUpdateUserName(array $data): array { /** * Test for SUCCESS @@ -322,7 +322,7 @@ trait UsersBase /** * @depends testGetUser */ - public function testUpdateUserEmail(array $data):array + public function testUpdateUserEmail(array $data): array { /** * Test for SUCCESS @@ -389,7 +389,7 @@ trait UsersBase /** * @depends testUpdateUserEmail */ - public function testUpdateUserPassword(array $data):array + public function testUpdateUserPassword(array $data): array { /** * Test for SUCCESS @@ -420,7 +420,7 @@ trait UsersBase /** * @depends testGetUser */ - public function testUpdateUserStatus(array $data):array + public function testUpdateUserStatus(array $data): array { /** * Test for SUCCESS @@ -449,7 +449,7 @@ trait UsersBase /** * @depends testGetUser */ - public function testUpdateEmailVerification(array $data):array + public function testUpdateEmailVerification(array $data): array { /** * Test for SUCCESS @@ -478,12 +478,12 @@ trait UsersBase /** * @depends testGetUser */ - public function testUpdateAndGetUserPrefs(array $data):array + public function testUpdateAndGetUserPrefs(array $data): array { /** * Test for SUCCESS */ - $user = $this->client->call(Client::METHOD_PATCH, '/users/'.$data['userId'].'/prefs', array_merge([ + $user = $this->client->call(Client::METHOD_PATCH, '/users/' . $data['userId'] . '/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -497,7 +497,7 @@ trait UsersBase $this->assertEquals($user['body']['funcKey1'], 'funcValue1'); $this->assertEquals($user['body']['funcKey2'], 'funcValue2'); - $user = $this->client->call(Client::METHOD_GET, '/users/'.$data['userId'].'/prefs', array_merge([ + $user = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/prefs', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -588,7 +588,7 @@ trait UsersBase /** * @depends testGetUser */ - public function testDeleteUser(array $data):array + public function testDeleteUser(array $data): array { /** * Test for SUCCESS @@ -615,4 +615,4 @@ trait UsersBase // TODO add test for session delete // TODO add test for all sessions delete -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Users/UsersCustomServerTest.php b/tests/e2e/Services/Users/UsersCustomServerTest.php index aae114f97d..6b9a990d4c 100644 --- a/tests/e2e/Services/Users/UsersCustomServerTest.php +++ b/tests/e2e/Services/Users/UsersCustomServerTest.php @@ -12,4 +12,4 @@ class UsersCustomServerTest extends Scope use UsersBase; use ProjectCustom; use SideServer; -} \ No newline at end of file +} diff --git a/tests/e2e/Services/Webhooks/WebhooksBase.php b/tests/e2e/Services/Webhooks/WebhooksBase.php index fd65b9484c..fc52d7a174 100644 --- a/tests/e2e/Services/Webhooks/WebhooksBase.php +++ b/tests/e2e/Services/Webhooks/WebhooksBase.php @@ -7,6 +7,14 @@ use Tests\E2E\Client; trait WebhooksBase { + public static function getWebhookSignature(array $webhook, string $signatureKey): string + { + $payload = json_encode($webhook['data']); + $url = $webhook['url']; + return base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); + } + + public function testCreateCollection(): array { /** @@ -30,6 +38,7 @@ trait WebhooksBase $this->assertNotEmpty($actors['body']['$id']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -38,7 +47,7 @@ trait WebhooksBase $this->assertStringContainsString('collections.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("collections.{$actorsId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("collections.{$actorsId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), true); @@ -102,6 +111,7 @@ trait WebhooksBase sleep(10); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -116,7 +126,7 @@ trait WebhooksBase $this->assertStringContainsString("collections.{$actorsId}.attributes.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("collections.{$actorsId}.attributes.{$actorsId}_{$attributeId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("collections.{$actorsId}.attributes.{$actorsId}_{$attributeId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertNotEmpty($webhook['data']['key']); @@ -131,6 +141,7 @@ trait WebhooksBase $this->assertEquals(204, $removed['headers']['status-code']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); // $this->assertEquals($webhook['method'], 'DELETE'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -145,7 +156,7 @@ trait WebhooksBase $this->assertStringContainsString("collections.{$actorsId}.attributes.*.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("collections.{$actorsId}.attributes.{$actorsId}_{$attributeId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("collections.{$actorsId}.attributes.{$actorsId}_{$attributeId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertNotEmpty($webhook['data']['key']); @@ -183,6 +194,7 @@ trait WebhooksBase $this->assertNotEmpty($document['body']['$id']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -197,7 +209,7 @@ trait WebhooksBase $this->assertStringContainsString("collections.{$actorsId}.documents.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("collections.{$actorsId}.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("collections.{$actorsId}.documents.{$documentId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -242,6 +254,7 @@ trait WebhooksBase $this->assertNotEmpty($document['body']['$id']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -256,7 +269,7 @@ trait WebhooksBase $this->assertStringContainsString("collections.{$actorsId}.documents.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("collections.{$actorsId}.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("collections.{$actorsId}.documents.{$documentId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -308,6 +321,7 @@ trait WebhooksBase $this->assertEquals($document['headers']['status-code'], 204); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -322,7 +336,7 @@ trait WebhooksBase $this->assertStringContainsString("collections.{$actorsId}.documents.*.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("collections.{$actorsId}.documents.{$documentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("collections.{$actorsId}.documents.{$documentId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -361,6 +375,7 @@ trait WebhooksBase $this->assertNotEmpty($bucket['body']['$id']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -369,7 +384,7 @@ trait WebhooksBase $this->assertStringContainsString('buckets.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("buckets.{$bucketId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("buckets.{$bucketId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), true); @@ -406,6 +421,7 @@ trait WebhooksBase $this->assertNotEmpty($bucket['body']['$id']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -414,7 +430,7 @@ trait WebhooksBase $this->assertStringContainsString('buckets.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("buckets.{$bucketId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("buckets.{$bucketId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), true); @@ -466,6 +482,7 @@ trait WebhooksBase $this->assertNotEmpty($file['body']['$id']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -480,7 +497,7 @@ trait WebhooksBase $this->assertStringContainsString("buckets.{$bucketId}.files.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("buckets.{$bucketId}.files.{$fileId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("buckets.{$bucketId}.files.{$fileId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -521,6 +538,7 @@ trait WebhooksBase $this->assertNotEmpty($file['body']['$id']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -535,7 +553,7 @@ trait WebhooksBase $this->assertStringContainsString("buckets.{$bucketId}.files.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("buckets.{$bucketId}.files.{$fileId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("buckets.{$bucketId}.files.{$fileId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -571,6 +589,7 @@ trait WebhooksBase $this->assertEmpty($file['body']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -585,7 +604,7 @@ trait WebhooksBase $this->assertStringContainsString("buckets.{$bucketId}.files.*.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("buckets.{$bucketId}.files.{$fileId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("buckets.{$bucketId}.files.{$fileId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -620,6 +639,7 @@ trait WebhooksBase $this->assertEmpty($bucket['body']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -628,7 +648,7 @@ trait WebhooksBase $this->assertStringContainsString('buckets.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("buckets.{$bucketId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("buckets.{$bucketId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), true); @@ -658,6 +678,7 @@ trait WebhooksBase $this->assertNotEmpty($team['body']['$id']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -666,7 +687,7 @@ trait WebhooksBase $this->assertStringContainsString('teams.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("teams.{$teamId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("teams.{$teamId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -702,6 +723,7 @@ trait WebhooksBase $this->assertNotEmpty($team['body']['$id']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -710,7 +732,7 @@ trait WebhooksBase $this->assertStringContainsString('teams.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("teams.{$teamId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("teams.{$teamId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -750,6 +772,7 @@ trait WebhooksBase ], $this->getHeaders())); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -758,7 +781,7 @@ trait WebhooksBase $this->assertStringContainsString('teams.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("teams.{$teamId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("teams.{$teamId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -804,6 +827,7 @@ trait WebhooksBase $membershipId = $team['body']['$id']; $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -818,7 +842,7 @@ trait WebhooksBase $this->assertStringContainsString("teams.{$teamId}.memberships.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("teams.{$teamId}.memberships.{$membershipId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("teams.{$teamId}.memberships.{$membershipId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -875,6 +899,7 @@ trait WebhooksBase $this->assertEquals(204, $team['headers']['status-code']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -889,7 +914,7 @@ trait WebhooksBase $this->assertStringContainsString("teams.{$teamId}.memberships.*.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("teams.{$teamId}.memberships.{$membershipId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("teams.{$teamId}.memberships.{$membershipId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); diff --git a/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php b/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php index 6290c6e763..51aca7c261 100644 --- a/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php +++ b/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php @@ -39,15 +39,19 @@ class WebhooksCustomClientTest extends Scope $this->assertNotEmpty($account['body']); $webhook = $this->getLastRequest(); + $signatureKey = $this->getProject()['signatureKey']; + $payload = json_encode($webhook['data']); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); $this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString('users.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events'],); + $this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id']), true); @@ -111,6 +115,10 @@ class WebhooksCustomClientTest extends Scope $this->assertEquals($account['headers']['status-code'], 200); $webhook = $this->getLastRequest(); + $signatureKey = $this->getProject()['signatureKey']; + $payload = json_encode($webhook['data']); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -119,7 +127,7 @@ class WebhooksCustomClientTest extends Scope $this->assertStringContainsString('users.*.update.status', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.update.status", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -161,6 +169,10 @@ class WebhooksCustomClientTest extends Scope $session = $this->client->parseCookie((string)$accountSession['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $webhook = $this->getLastRequest(); + $signatureKey = $this->getProject()['signatureKey']; + $payload = json_encode($webhook['data']); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -175,7 +187,7 @@ class WebhooksCustomClientTest extends Scope $this->assertStringContainsString("users.{$id}.sessions.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.sessions.{$sessionId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.sessions.{$sessionId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id']), true); @@ -246,6 +258,10 @@ class WebhooksCustomClientTest extends Scope $this->assertEquals($accountSession['headers']['status-code'], 204); $webhook = $this->getLastRequest(); + $signatureKey = $this->getProject()['signatureKey']; + $payload = json_encode($webhook['data']); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -260,7 +276,7 @@ class WebhooksCustomClientTest extends Scope $this->assertStringContainsString("users.{$id}.sessions.*.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.sessions.{$sessionId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.sessions.{$sessionId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -328,6 +344,10 @@ class WebhooksCustomClientTest extends Scope $this->assertEquals($accountSession['headers']['status-code'], 204); $webhook = $this->getLastRequest(); + $signatureKey = $this->getProject()['signatureKey']; + $payload = json_encode($webhook['data']); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -342,7 +362,7 @@ class WebhooksCustomClientTest extends Scope $this->assertStringContainsString("users.{$id}.sessions.*.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.sessions.{$sessionId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.sessions.{$sessionId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -414,6 +434,11 @@ class WebhooksCustomClientTest extends Scope $this->assertIsArray($account['body']); $webhook = $this->getLastRequest(); + $signatureKey = $this->getProject()['signatureKey']; + $payload = json_encode($webhook['data']); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); + $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -424,7 +449,7 @@ class WebhooksCustomClientTest extends Scope $this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.update.name", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -463,6 +488,10 @@ class WebhooksCustomClientTest extends Scope $this->assertIsArray($account['body']); $webhook = $this->getLastRequest(); + $signatureKey = $this->getProject()['signatureKey']; + $payload = json_encode($webhook['data']); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -473,7 +502,7 @@ class WebhooksCustomClientTest extends Scope $this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.update.password", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -514,6 +543,10 @@ class WebhooksCustomClientTest extends Scope $this->assertIsArray($account['body']); $webhook = $this->getLastRequest(); + $signatureKey = $this->getProject()['signatureKey']; + $payload = json_encode($webhook['data']); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -524,7 +557,7 @@ class WebhooksCustomClientTest extends Scope $this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.update.email", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -566,6 +599,10 @@ class WebhooksCustomClientTest extends Scope $this->assertIsArray($account['body']); $webhook = $this->getLastRequest(); + $signatureKey = $this->getProject()['signatureKey']; + $payload = json_encode($webhook['data']); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -576,7 +613,7 @@ class WebhooksCustomClientTest extends Scope $this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.update.prefs", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -617,6 +654,10 @@ class WebhooksCustomClientTest extends Scope $this->assertIsArray($recovery['body']); $webhook = $this->getLastRequest(); + $signatureKey = $this->getProject()['signatureKey']; + $payload = json_encode($webhook['data']); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -631,7 +672,7 @@ class WebhooksCustomClientTest extends Scope $this->assertStringContainsString("users.{$id}.recovery.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.recovery.{$recoveryId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.recovery.{$recoveryId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-User-Id'], $id); @@ -673,6 +714,10 @@ class WebhooksCustomClientTest extends Scope $this->assertIsArray($recovery['body']); $webhook = $this->getLastRequest(); + $signatureKey = $this->getProject()['signatureKey']; + $payload = json_encode($webhook['data']); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -687,7 +732,7 @@ class WebhooksCustomClientTest extends Scope $this->assertStringContainsString("users.{$id}.recovery.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.recovery.{$recoveryId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.recovery.{$recoveryId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id']), true); @@ -725,6 +770,10 @@ class WebhooksCustomClientTest extends Scope $this->assertIsArray($verification['body']); $webhook = $this->getLastRequest(); + $signatureKey = $this->getProject()['signatureKey']; + $payload = json_encode($webhook['data']); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -739,7 +788,7 @@ class WebhooksCustomClientTest extends Scope $this->assertStringContainsString("users.{$id}.verification.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.verification.{$verificationId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.verification.{$verificationId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -779,6 +828,10 @@ class WebhooksCustomClientTest extends Scope $this->assertIsArray($verification['body']); $webhook = $this->getLastRequest(); + $signatureKey = $this->getProject()['signatureKey']; + $payload = json_encode($webhook['data']); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -793,7 +846,7 @@ class WebhooksCustomClientTest extends Scope $this->assertStringContainsString("users.{$id}.verification.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.verification.{$verificationId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.verification.{$verificationId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -833,6 +886,10 @@ class WebhooksCustomClientTest extends Scope $this->assertNotEmpty($team['body']['$id']); $webhook = $this->getLastRequest(); + $signatureKey = $this->getProject()['signatureKey']; + $payload = json_encode($webhook['data']); + $url = $webhook['url']; + $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -851,7 +908,7 @@ class WebhooksCustomClientTest extends Scope $this->assertStringContainsString("teams.{$teamUid}.memberships.{$membershipUid}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("teams.{$teamUid}.memberships.{$membershipUid}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("teams.{$teamUid}.memberships.{$membershipUid}.update.status", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), true); diff --git a/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php b/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php index 7c815595fe..541e81633a 100644 --- a/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php +++ b/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php @@ -38,6 +38,7 @@ class WebhooksCustomServerTest extends Scope $this->assertNotEmpty($actors['body']['$id']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -46,7 +47,7 @@ class WebhooksCustomServerTest extends Scope $this->assertStringContainsString('collections.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("collections.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("collections.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), true); @@ -86,6 +87,7 @@ class WebhooksCustomServerTest extends Scope sleep(5); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -100,7 +102,7 @@ class WebhooksCustomServerTest extends Scope $this->assertStringContainsString("collections.{$actorsId}.indexes.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("collections.{$actorsId}.indexes.{$actorsId}_{$indexKey}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("collections.{$actorsId}.indexes.{$actorsId}_{$indexKey}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), true); @@ -114,6 +116,7 @@ class WebhooksCustomServerTest extends Scope // // wait for database worker to remove index $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); // $this->assertEquals($webhook['method'], 'DELETE'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -128,7 +131,7 @@ class WebhooksCustomServerTest extends Scope $this->assertStringContainsString("collections.{$actorsId}.indexes.*.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("collections.{$actorsId}.indexes.{$actorsId}_{$indexKey}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("collections.{$actorsId}.indexes.{$actorsId}_{$indexKey}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), true); @@ -167,15 +170,16 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($actors['headers']['status-code'], 204); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); $this->assertStringContainsString('collections.*', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString('collections.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("collections.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events'],); + $this->assertStringContainsString("collections.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("collections.{$id}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), true); @@ -214,15 +218,16 @@ class WebhooksCustomServerTest extends Scope $id = $user['body']['$id']; $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); $this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString('users.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events'],); + $this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -261,6 +266,7 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($user['body']['a'], 'b'); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -271,7 +277,7 @@ class WebhooksCustomServerTest extends Scope $this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.update.prefs", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -301,6 +307,7 @@ class WebhooksCustomServerTest extends Scope $this->assertNotEmpty($user['body']['$id']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -311,7 +318,7 @@ class WebhooksCustomServerTest extends Scope $this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.update.status", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -344,6 +351,7 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($user['headers']['status-code'], 204); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -352,7 +360,7 @@ class WebhooksCustomServerTest extends Scope $this->assertStringContainsString('users.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("users.{$id}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); @@ -389,6 +397,7 @@ class WebhooksCustomServerTest extends Scope $this->assertNotEmpty($function['body']['$id']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -397,12 +406,12 @@ class WebhooksCustomServerTest extends Scope $this->assertStringContainsString('functions.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("functions.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("functions.{$id}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); /** - * Test for FAILURE + * Test for FAILURE */ return [ @@ -437,6 +446,7 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals($function['body']['vars'], ['key1' => 'value1']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -445,7 +455,7 @@ class WebhooksCustomServerTest extends Scope $this->assertStringContainsString('functions.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("functions.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("functions.{$id}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -481,6 +491,7 @@ class WebhooksCustomServerTest extends Scope $this->assertNotEmpty($deployment['body']['$id']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -491,7 +502,7 @@ class WebhooksCustomServerTest extends Scope $this->assertStringContainsString("functions.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("functions.{$id}.deployments.*", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("functions.{$id}.deployments.{$deploymentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -523,6 +534,7 @@ class WebhooksCustomServerTest extends Scope sleep(5); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -537,12 +549,12 @@ class WebhooksCustomServerTest extends Scope $this->assertStringContainsString("functions.{$id}.deployments.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("functions.{$id}.deployments.{$deploymentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("functions.{$id}.deployments.{$deploymentId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); /** - * Test for FAILURE + * Test for FAILURE */ return $data; @@ -569,7 +581,7 @@ class WebhooksCustomServerTest extends Scope $this->assertNotEmpty($execution['body']['$id']); $webhook = $this->getLastRequest(); - + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); $this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io'); @@ -583,7 +595,7 @@ class WebhooksCustomServerTest extends Scope $this->assertStringContainsString("functions.{$id}.executions.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("functions.{$id}.executions.{$executionId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("functions.{$id}.executions.{$executionId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -591,6 +603,7 @@ class WebhooksCustomServerTest extends Scope sleep(10); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -605,19 +618,19 @@ class WebhooksCustomServerTest extends Scope $this->assertStringContainsString("functions.{$id}.executions.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("functions.{$id}.executions.{$executionId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("functions.{$id}.executions.{$executionId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); /** - * Test for FAILURE + * Test for FAILURE */ return $data; } /** - * @depends testExecutions + * @depends testExecutions */ public function testDeleteDeployment($data): array { @@ -635,6 +648,7 @@ class WebhooksCustomServerTest extends Scope $this->assertEmpty($deployment['body']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -649,7 +663,7 @@ class WebhooksCustomServerTest extends Scope $this->assertStringContainsString("functions.{$id}.deployments.*.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("functions.{$id}.deployments.{$deploymentId}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("functions.{$id}.deployments.{$deploymentId}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); @@ -679,6 +693,7 @@ class WebhooksCustomServerTest extends Scope $this->assertEmpty($function['body']); $webhook = $this->getLastRequest(); + $signatureExpected = self::getWebhookSignature($webhook, $this->getProject()['signatureKey']); $this->assertEquals($webhook['method'], 'POST'); $this->assertEquals($webhook['headers']['Content-Type'], 'application/json'); @@ -687,7 +702,7 @@ class WebhooksCustomServerTest extends Scope $this->assertStringContainsString('functions.*.delete', $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("functions.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']); $this->assertStringContainsString("functions.{$id}.delete", $webhook['headers']['X-Appwrite-Webhook-Events']); - $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], 'not-yet-implemented'); + $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']); $this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']); diff --git a/tests/extensions/TestHook.php b/tests/extensions/TestHook.php index a8d86304ef..81cde164ae 100644 --- a/tests/extensions/TestHook.php +++ b/tests/extensions/TestHook.php @@ -1,4 +1,5 @@ { +module.exports = async(req, res) => { res.json({ 'APPWRITE_FUNCTION_ID' : req.env.APPWRITE_FUNCTION_ID, 'APPWRITE_FUNCTION_NAME' : req.env.APPWRITE_FUNCTION_NAME, diff --git a/tests/resources/functions/timeout/index.php b/tests/resources/functions/timeout/index.php index 420b62f147..c45ab5a5b8 100644 --- a/tests/resources/functions/timeout/index.php +++ b/tests/resources/functions/timeout/index.php @@ -2,4 +2,4 @@ return function ($request, $response) { sleep(5); -}; \ No newline at end of file +}; diff --git a/tests/unit/Auth/AuthTest.php b/tests/unit/Auth/AuthTest.php index c3b9d00758..fd917d613b 100644 --- a/tests/unit/Auth/AuthTest.php +++ b/tests/unit/Auth/AuthTest.php @@ -39,35 +39,35 @@ class AuthTest extends TestCase $this->assertEquals(Auth::encodeSession($id, $secret), $session); $this->assertEquals(Auth::decodeSession($session), ['id' => $id, 'secret' => $secret]); } - + public function testHash() { $secret = 'secret'; $this->assertEquals(Auth::hash($secret), '2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b'); } - + public function testPassword() { $secret = 'secret'; $static = '$2y$08$PDbMtV18J1KOBI9tIYabBuyUwBrtXPGhLxCy9pWP6xkldVOKLrLKy'; $dynamic = Auth::passwordHash($secret); - + $this->assertEquals(Auth::passwordVerify($secret, $dynamic), true); $this->assertEquals(Auth::passwordVerify($secret, $static), true); } - + public function testPasswordGenerator() { $this->assertEquals(\mb_strlen(Auth::passwordGenerator()), 40); $this->assertEquals(\mb_strlen(Auth::passwordGenerator(5)), 10); } - + public function testTokenGenerator() { $this->assertEquals(\mb_strlen(Auth::tokenGenerator()), 256); $this->assertEquals(\mb_strlen(Auth::tokenGenerator(5)), 10); } - + public function testSessionVerify() { $secret = 'secret1'; @@ -172,35 +172,35 @@ class AuthTest extends TestCase public function testIsPrivilegedUser() { $this->assertEquals(false, Auth::isPrivilegedUser([])); - $this->assertEquals(false, Auth::isPrivilegedUser(['role:'.Auth::USER_ROLE_GUEST])); - $this->assertEquals(false, Auth::isPrivilegedUser(['role:'.Auth::USER_ROLE_MEMBER])); - $this->assertEquals(true, Auth::isPrivilegedUser(['role:'.Auth::USER_ROLE_ADMIN])); - $this->assertEquals(true, Auth::isPrivilegedUser(['role:'.Auth::USER_ROLE_DEVELOPER])); - $this->assertEquals(true, Auth::isPrivilegedUser(['role:'.Auth::USER_ROLE_OWNER])); - $this->assertEquals(false, Auth::isPrivilegedUser(['role:'.Auth::USER_ROLE_APP])); - $this->assertEquals(false, Auth::isPrivilegedUser(['role:'.Auth::USER_ROLE_SYSTEM])); + $this->assertEquals(false, Auth::isPrivilegedUser(['role:' . Auth::USER_ROLE_GUEST])); + $this->assertEquals(false, Auth::isPrivilegedUser(['role:' . Auth::USER_ROLE_MEMBER])); + $this->assertEquals(true, Auth::isPrivilegedUser(['role:' . Auth::USER_ROLE_ADMIN])); + $this->assertEquals(true, Auth::isPrivilegedUser(['role:' . Auth::USER_ROLE_DEVELOPER])); + $this->assertEquals(true, Auth::isPrivilegedUser(['role:' . Auth::USER_ROLE_OWNER])); + $this->assertEquals(false, Auth::isPrivilegedUser(['role:' . Auth::USER_ROLE_APP])); + $this->assertEquals(false, Auth::isPrivilegedUser(['role:' . Auth::USER_ROLE_SYSTEM])); - $this->assertEquals(false, Auth::isPrivilegedUser(['role:'.Auth::USER_ROLE_APP, 'role:'.Auth::USER_ROLE_APP])); - $this->assertEquals(false, Auth::isPrivilegedUser(['role:'.Auth::USER_ROLE_APP, 'role:'.Auth::USER_ROLE_GUEST])); - $this->assertEquals(true, Auth::isPrivilegedUser(['role:'.Auth::USER_ROLE_OWNER, 'role:'.Auth::USER_ROLE_GUEST])); - $this->assertEquals(true, Auth::isPrivilegedUser(['role:'.Auth::USER_ROLE_OWNER, 'role:'.Auth::USER_ROLE_ADMIN, 'role:'.Auth::USER_ROLE_DEVELOPER])); + $this->assertEquals(false, Auth::isPrivilegedUser(['role:' . Auth::USER_ROLE_APP, 'role:' . Auth::USER_ROLE_APP])); + $this->assertEquals(false, Auth::isPrivilegedUser(['role:' . Auth::USER_ROLE_APP, 'role:' . Auth::USER_ROLE_GUEST])); + $this->assertEquals(true, Auth::isPrivilegedUser(['role:' . Auth::USER_ROLE_OWNER, 'role:' . Auth::USER_ROLE_GUEST])); + $this->assertEquals(true, Auth::isPrivilegedUser(['role:' . Auth::USER_ROLE_OWNER, 'role:' . Auth::USER_ROLE_ADMIN, 'role:' . Auth::USER_ROLE_DEVELOPER])); } - + public function testIsAppUser() { $this->assertEquals(false, Auth::isAppUser([])); - $this->assertEquals(false, Auth::isAppUser(['role:'.Auth::USER_ROLE_GUEST])); - $this->assertEquals(false, Auth::isAppUser(['role:'.Auth::USER_ROLE_MEMBER])); - $this->assertEquals(false, Auth::isAppUser(['role:'.Auth::USER_ROLE_ADMIN])); - $this->assertEquals(false, Auth::isAppUser(['role:'.Auth::USER_ROLE_DEVELOPER])); - $this->assertEquals(false, Auth::isAppUser(['role:'.Auth::USER_ROLE_OWNER])); - $this->assertEquals(true, Auth::isAppUser(['role:'.Auth::USER_ROLE_APP])); - $this->assertEquals(false, Auth::isAppUser(['role:'.Auth::USER_ROLE_SYSTEM])); + $this->assertEquals(false, Auth::isAppUser(['role:' . Auth::USER_ROLE_GUEST])); + $this->assertEquals(false, Auth::isAppUser(['role:' . Auth::USER_ROLE_MEMBER])); + $this->assertEquals(false, Auth::isAppUser(['role:' . Auth::USER_ROLE_ADMIN])); + $this->assertEquals(false, Auth::isAppUser(['role:' . Auth::USER_ROLE_DEVELOPER])); + $this->assertEquals(false, Auth::isAppUser(['role:' . Auth::USER_ROLE_OWNER])); + $this->assertEquals(true, Auth::isAppUser(['role:' . Auth::USER_ROLE_APP])); + $this->assertEquals(false, Auth::isAppUser(['role:' . Auth::USER_ROLE_SYSTEM])); - $this->assertEquals(true, Auth::isAppUser(['role:'.Auth::USER_ROLE_APP, 'role:'.Auth::USER_ROLE_APP])); - $this->assertEquals(true, Auth::isAppUser(['role:'.Auth::USER_ROLE_APP, 'role:'.Auth::USER_ROLE_GUEST])); - $this->assertEquals(false, Auth::isAppUser(['role:'.Auth::USER_ROLE_OWNER, 'role:'.Auth::USER_ROLE_GUEST])); - $this->assertEquals(false, Auth::isAppUser(['role:'.Auth::USER_ROLE_OWNER, 'role:'.Auth::USER_ROLE_ADMIN, 'role:'.Auth::USER_ROLE_DEVELOPER])); + $this->assertEquals(true, Auth::isAppUser(['role:' . Auth::USER_ROLE_APP, 'role:' . Auth::USER_ROLE_APP])); + $this->assertEquals(true, Auth::isAppUser(['role:' . Auth::USER_ROLE_APP, 'role:' . Auth::USER_ROLE_GUEST])); + $this->assertEquals(false, Auth::isAppUser(['role:' . Auth::USER_ROLE_OWNER, 'role:' . Auth::USER_ROLE_GUEST])); + $this->assertEquals(false, Auth::isAppUser(['role:' . Auth::USER_ROLE_OWNER, 'role:' . Auth::USER_ROLE_ADMIN, 'role:' . Auth::USER_ROLE_DEVELOPER])); } public function testGuestRoles() @@ -249,7 +249,7 @@ class AuthTest extends TestCase public function testPrivilegedUserRoles() { - Authorization::setRole('role:'.Auth::USER_ROLE_OWNER); + Authorization::setRole('role:' . Auth::USER_ROLE_OWNER); $user = new Document([ '$id' => '123', 'memberships' => [ @@ -283,7 +283,7 @@ class AuthTest extends TestCase public function testAppUserRoles() { - Authorization::setRole('role:'.Auth::USER_ROLE_APP); + Authorization::setRole('role:' . Auth::USER_ROLE_APP); $user = new Document([ '$id' => '123', 'memberships' => [ diff --git a/tests/unit/Detector/DetectorTest.php b/tests/unit/Detector/DetectorTest.php index 980851538c..a70ad44cf6 100644 --- a/tests/unit/Detector/DetectorTest.php +++ b/tests/unit/Detector/DetectorTest.php @@ -50,5 +50,4 @@ class DetectorTest extends TestCase 'deviceModel' => '', ]); } - } diff --git a/tests/unit/Docker/ComposeTest.php b/tests/unit/Docker/ComposeTest.php index c484fc17e8..ad3f40ab54 100644 --- a/tests/unit/Docker/ComposeTest.php +++ b/tests/unit/Docker/ComposeTest.php @@ -16,7 +16,7 @@ class ComposeTest extends TestCase public function setUp(): void { - $data = @file_get_contents(__DIR__.'/../../resources/docker/docker-compose.yml'); + $data = @file_get_contents(__DIR__ . '/../../resources/docker/docker-compose.yml'); if ($data === false) { throw new Exception('Failed to read compose file'); diff --git a/tests/unit/Docker/EnvTest.php b/tests/unit/Docker/EnvTest.php index 2fb3e6d558..f436354efa 100644 --- a/tests/unit/Docker/EnvTest.php +++ b/tests/unit/Docker/EnvTest.php @@ -16,7 +16,7 @@ class EnvTest extends TestCase public function setUp(): void { - $data = @file_get_contents(__DIR__.'/../../resources/docker/.env'); + $data = @file_get_contents(__DIR__ . '/../../resources/docker/.env'); if ($data === false) { throw new Exception('Failed to read compose file'); diff --git a/tests/unit/Event/Validator/EventValidatorTest.php b/tests/unit/Event/Validator/EventValidatorTest.php index e523999599..0f03547912 100644 --- a/tests/unit/Event/Validator/EventValidatorTest.php +++ b/tests/unit/Event/Validator/EventValidatorTest.php @@ -12,7 +12,7 @@ class EventValidatorTest extends TestCase public function setUp(): void { - Config::load('events', __DIR__.'/../../../../app/config/events.php'); + Config::load('events', __DIR__ . '/../../../../app/config/events.php'); $this->object = new Event(); } diff --git a/tests/unit/Migration/MigrationTest.php b/tests/unit/Migration/MigrationTest.php index 340e33772c..0c8c34cbc8 100644 --- a/tests/unit/Migration/MigrationTest.php +++ b/tests/unit/Migration/MigrationTest.php @@ -4,6 +4,7 @@ namespace Appwrite\Tests; use Appwrite\Migration\Migration; use PHPUnit\Framework\TestCase; +use ReflectionClass; use ReflectionMethod; use Utopia\Database\Document; @@ -36,12 +37,100 @@ abstract class MigrationTest extends TestCase */ public function testMigrationVersions() { - require_once __DIR__.'/../../../app/init.php'; + require_once __DIR__ . '/../../../app/init.php'; foreach (Migration::$versions as $class) { - $this->assertTrue(class_exists('Appwrite\\Migration\\Version\\'.$class)); + $this->assertTrue(class_exists('Appwrite\\Migration\\Version\\' . $class)); } // Test if current version exists - //$this->assertArrayHasKey(APP_VERSION_STABLE, Migration::$versions); + $this->assertArrayHasKey(APP_VERSION_STABLE, Migration::$versions); + } + + public function testHasDifference() + { + $this->assertFalse(Migration::hasDifference([], [])); + $this->assertFalse(Migration::hasDifference([ + 'bool' => true, + 'string' => 'abc', + 'int' => 123, + 'array' => ['a', 'b', 'c'], + 'assoc' => [ + 'a' => true, + 'b' => 'abc', + 'c' => 123, + 'd' => ['a', 'b', 'c'] + ] + ], [ + 'bool' => true, + 'string' => 'abc', + 'int' => 123, + 'array' => ['a', 'b', 'c'], + 'assoc' => [ + 'a' => true, + 'b' => 'abc', + 'c' => 123, + 'd' => ['a', 'b', 'c'] + ] + ])); + $this->assertFalse(Migration::hasDifference([ + 'bool' => true, + 'string' => 'abc', + 'int' => 123, + 'array' => ['a', 'b', 'c'], + 'assoc' => [ + 'a' => true, + 'b' => 'abc', + 'c' => 123, + 'd' => ['a', 'b', 'c'] + ] + ], [ + 'string' => 'abc', + 'assoc' => [ + 'a' => true, + 'b' => 'abc', + 'c' => 123, + 'd' => ['a', 'b', 'c'] + ], + 'int' => 123, + 'array' => ['a', 'b', 'c'], + 'bool' => true, + + ])); + $this->assertTrue(Migration::hasDifference([ + 'a' => true + ], [ + 'b' => true + ])); + $this->assertTrue(Migration::hasDifference([ + 'a' => 'true' + ], [ + 'a' => true + ])); + $this->assertTrue(Migration::hasDifference([ + 'a' => true + ], [ + 'a' => false + ])); + $this->assertTrue(Migration::hasDifference([ + 'nested' => [ + 'a' => true + ] + ], [ + 'nested' => [] + ])); + $this->assertTrue(Migration::hasDifference([ + 'assoc' => [ + 'bool' => true, + 'string' => 'abc', + 'int' => 123, + 'array' => ['a', 'b', 'c'] + ] + ], [ + 'nested' => [ + 'a' => true, + 'int' => '123', + 'array' => ['a', 'b', 'c'] + ] + ])); } } diff --git a/tests/unit/Network/Validators/CNAMETest.php b/tests/unit/Network/Validators/CNAMETest.php index d08656d847..5aa7a69db4 100644 --- a/tests/unit/Network/Validators/CNAMETest.php +++ b/tests/unit/Network/Validators/CNAMETest.php @@ -26,9 +26,7 @@ class CNAMETest extends TestCase $this->assertEquals($this->object->isValid(''), false); $this->assertEquals($this->object->isValid(null), false); $this->assertEquals($this->object->isValid(false), false); - $this->assertEquals($this->object->isValid('test1.appwrite.io'), true); - $this->assertEquals($this->object->isValid('test1.appwrite.io'), true); - $this->assertEquals($this->object->isValid('test1.appwrite.org'), false); + $this->assertEquals($this->object->isValid('cname-unit-test.appwrite.org'), true); $this->assertEquals($this->object->isValid('test1.appwrite.org'), false); } } diff --git a/tests/unit/Network/Validators/EmailTest.php b/tests/unit/Network/Validators/EmailTest.php index 5a7bf0f963..ca73509c65 100755 --- a/tests/unit/Network/Validators/EmailTest.php +++ b/tests/unit/Network/Validators/EmailTest.php @@ -1,4 +1,5 @@ email = new Email(); } - public function tearDown():void + public function tearDown(): void { $this->email = null; } diff --git a/tests/unit/Network/Validators/HostTest.php b/tests/unit/Network/Validators/HostTest.php index 724ad74152..a23911dc76 100755 --- a/tests/unit/Network/Validators/HostTest.php +++ b/tests/unit/Network/Validators/HostTest.php @@ -1,4 +1,5 @@ host = new Host(['appwrite.io', 'subdomain.appwrite.test', 'localhost']); } - public function tearDown():void + public function tearDown(): void { $this->host = null; } diff --git a/tests/unit/Network/Validators/IPTest.php b/tests/unit/Network/Validators/IPTest.php index 8ebd12dd03..0f5fc63ce9 100755 --- a/tests/unit/Network/Validators/IPTest.php +++ b/tests/unit/Network/Validators/IPTest.php @@ -1,4 +1,5 @@ validator = null; } diff --git a/tests/unit/Network/Validators/OriginTest.php b/tests/unit/Network/Validators/OriginTest.php index 4ba618f32e..414b380465 100644 --- a/tests/unit/Network/Validators/OriginTest.php +++ b/tests/unit/Network/Validators/OriginTest.php @@ -48,17 +48,17 @@ class OriginTest extends TestCase $this->assertEquals($validator->isValid('appwrite-ios://com.company.appname'), false); $this->assertEquals($validator->getDescription(), 'Invalid Origin. Register your new client (com.company.appname) as a new iOS platform on your project console dashboard'); - + $this->assertEquals($validator->isValid('appwrite-android://com.company.appname'), false); $this->assertEquals($validator->getDescription(), 'Invalid Origin. Register your new client (com.company.appname) as a new Android platform on your project console dashboard'); - + $this->assertEquals($validator->isValid('appwrite-macos://com.company.appname'), false); $this->assertEquals($validator->getDescription(), 'Invalid Origin. Register your new client (com.company.appname) as a new macOS platform on your project console dashboard'); - + $this->assertEquals($validator->isValid('appwrite-linux://com.company.appname'), false); $this->assertEquals($validator->getDescription(), 'Invalid Origin. Register your new client (com.company.appname) as a new Linux platform on your project console dashboard'); $this->assertEquals($validator->isValid('appwrite-windows://com.company.appname'), false); $this->assertEquals($validator->getDescription(), 'Invalid Origin. Register your new client (com.company.appname) as a new Windows platform on your project console dashboard'); } -} \ No newline at end of file +} diff --git a/tests/unit/Network/Validators/URLTest.php b/tests/unit/Network/Validators/URLTest.php index 84e3fb2e66..71bba7bb68 100755 --- a/tests/unit/Network/Validators/URLTest.php +++ b/tests/unit/Network/Validators/URLTest.php @@ -1,4 +1,5 @@ url = new URL(); } - public function tearDown():void + public function tearDown(): void { $this->url = null; } @@ -36,7 +37,7 @@ class URLTest extends TestCase $this->assertEquals(true, $this->url->isValid('https://example.com')); $this->assertEquals(true, $this->url->isValid('htts://example.com')); // does not validate protocol $this->assertEquals(false, $this->url->isValid('example.com')); // though, requires some kind of protocol - $this->assertEquals(false, $this->url->isValid('http:/example.com')); + $this->assertEquals(false, $this->url->isValid('http:/example.com')); $this->assertEquals(true, $this->url->isValid('http://exa-mple.com')); $this->assertEquals(false, $this->url->isValid('htt@s://example.com')); $this->assertEquals(true, $this->url->isValid('http://www.example.com/foo%2\u00c2\u00a9zbar')); diff --git a/tests/unit/Template/TemplateTest.php b/tests/unit/Template/TemplateTest.php index 444cc26a6a..1103cbc9a2 100644 --- a/tests/unit/Template/TemplateTest.php +++ b/tests/unit/Template/TemplateTest.php @@ -14,7 +14,7 @@ class TemplateTest extends TestCase public function setUp(): void { - $this->object = new Template(__DIR__.'/../../resources/template.tpl'); + $this->object = new Template(__DIR__ . '/../../resources/template.tpl'); $this->object ->setParam('{{world}}', 'WORLD') ; diff --git a/tests/unit/URL/URLTest.php b/tests/unit/URL/URLTest.php index 469b77dd82..0348153a4b 100644 --- a/tests/unit/URL/URLTest.php +++ b/tests/unit/URL/URLTest.php @@ -103,4 +103,4 @@ class URLTest extends TestCase $this->assertIsString($result); $this->assertEquals('param1=value1¶m2=value2', $result); } -} \ No newline at end of file +} diff --git a/tests/unit/Utopia/ResponseTest.php b/tests/unit/Utopia/ResponseTest.php index d59b81eb54..246380dee0 100644 --- a/tests/unit/Utopia/ResponseTest.php +++ b/tests/unit/Utopia/ResponseTest.php @@ -9,7 +9,6 @@ use Swoole\Http\Response as SwooleResponse; class ResponseTest extends TestCase { - /** * @var Response */ @@ -20,15 +19,15 @@ class ResponseTest extends TestCase $this->object = new Response(new SwooleResponse()); } - public function testSetFilter() + public function testSetFilter() { $this->assertEquals($this->object->hasFilter(), false); $this->assertEquals($this->object->getFilter(), null); $filter = new V11(); $this->object->setFilter($filter); - + $this->assertEquals($this->object->hasFilter(), true); $this->assertEquals($this->object->getFilter(), $filter); } -} \ No newline at end of file +}