mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Merge branch 'master' into feat-password-hash-algos
This commit is contained in:
@@ -57,7 +57,7 @@ _APP_SMTP_SECURE=
|
||||
_APP_SMTP_USERNAME=
|
||||
_APP_SMTP_PASSWORD=
|
||||
_APP_PHONE_PROVIDER=phone://mock
|
||||
_APP_PHONE_FROM=
|
||||
_APP_PHONE_FROM=+123456789
|
||||
_APP_STORAGE_LIMIT=30000000
|
||||
_APP_STORAGE_PREVIEW_LIMIT=20000000
|
||||
_APP_FUNCTIONS_SIZE_LIMIT=30000000
|
||||
|
||||
@@ -3,6 +3,7 @@ tasks:
|
||||
init: |
|
||||
docker compose pull
|
||||
docker compose build
|
||||
docker pull composer
|
||||
command: |
|
||||
docker run --rm --interactive --tty \
|
||||
--volume $PWD:/app \
|
||||
|
||||
+101
-1
@@ -1,4 +1,104 @@
|
||||
- Start using docker compose V2 (from `docker-compose` to `docker compose`)
|
||||
# Version 0.15.2
|
||||
## Bugs
|
||||
- Fixed Realtime Authentication for the Console by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/3506
|
||||
- Fixed Collection Usage by @stnguyen90 in https://github.com/appwrite/appwrite/pull/3505
|
||||
- Fixed `$createdAt` after updating document by @Meldiron in https://github.com/appwrite/appwrite/pull/3498
|
||||
- Fixed Redirect after deleting Collection in Console @TorstenDittmann in https://github.com/appwrite/appwrite/pull/3476
|
||||
- Fixed broken Link for Documents under Collections by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/3469
|
||||
|
||||
# Version 0.15.1
|
||||
## Bugs
|
||||
- Fixed SMS for `createVerification` by @christyjacob4 in https://github.com/appwrite/appwrite/pull/3454
|
||||
- Fixed missing Attributes when creating an Index by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/3461
|
||||
- Fixed broken Link for Documents under Collections by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/3461
|
||||
- Fixed all `$createdAt` and `$updatedAt` occurences in the UI by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/3461
|
||||
- Fixed Delete Document from the UI by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/3463
|
||||
- Fixed internal Attribute and Index key on Migration by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/3455
|
||||
|
||||
## Docs
|
||||
- Updated Phone Authentication by @christyjacob4 in https://github.com/appwrite/appwrite/pull/3456
|
||||
|
||||
# Version 0.15.0
|
||||
|
||||
## BREAKING CHANGES
|
||||
- Docker Compose V2 is required now
|
||||
- The `POST:/v1/account/sessions` endpoint is now `POST:/v1/account/sessions/email`
|
||||
- All `/v1/database/...` endpoints are now `/v1/databases/...`
|
||||
- `dateCreated` attribute is removed from Teams
|
||||
- `dateCreated` attribute is removed from Executions
|
||||
- `dateCreated` attribute is removed from Files
|
||||
- `dateCreated` and `dateUpdated` attributes are removed from Functions
|
||||
- `dateCreated` and `dateUpdated` attributes are removed from Deployments
|
||||
- `dateCreated` and `dateUpdated` attributes are removed from Buckets
|
||||
- Following Events for Webhooks and Functions are changed:
|
||||
- `collections.[COLLECTION_ID]` is now `databases.[DATABASE_ID].collections.[COLLECTION_ID]`
|
||||
- `collections.[COLLECTION_ID].documents.[DOCUMENT_ID]` is now `databases.[DATABASE_ID].collections.[COLLECTION_ID].documents.[DOCUMENT_ID]`
|
||||
- Following Realtime Channels are changed:
|
||||
- `collections.[COLLECTION_ID]` is now `databases.[DATABASE_ID].collections.[COLLECTION_ID]`
|
||||
- `collections.[COLLECTION_ID].documents` is now `databases.[DATABASE_ID].collections.[COLLECTION_ID].documents`
|
||||
- After Migration a Database called `default` is created for all your existing Database Collections
|
||||
|
||||
## Features
|
||||
- Added Phone Authentication by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/3357
|
||||
- Added Twilio Support
|
||||
- Added TextMagic Support
|
||||
- Added Telesign Support
|
||||
- Added Endpoint to create Phone Session (`POST:/v1/account/sessions/phone`)
|
||||
- Added Endpoint to confirm Phone Session (`PUT:/v1/account/sessions/phone`)
|
||||
- Added Endpoint to update Account Phone Number (`PATCH:/v1/account/phone`)
|
||||
- Added Endpoint to create Account Phone Verification (`POST:/v1/account/verification/phone`)
|
||||
- Added Endpoint to confirm Account Phone Verification (`PUT:/v1/account/verification/phone`)
|
||||
- Added `_APP_PHONE_PROVIDER` and `_APP_PHONE_FROM` Environment Variable
|
||||
- Added `phone` and `phoneVerification` Attribute to User
|
||||
- Added `$createdAt` and `$updatedAt` Attributes by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/3382
|
||||
- Bucket
|
||||
- Collection
|
||||
- Deployment
|
||||
- Document
|
||||
- Domain
|
||||
- Execution
|
||||
- File
|
||||
- Func
|
||||
- Key
|
||||
- Membership
|
||||
- Platform
|
||||
- Project
|
||||
- Team
|
||||
- User
|
||||
- Webhook
|
||||
- Session (only `$createdAt`)
|
||||
- Token (only `$createdAt`)
|
||||
- Added Databases Resource to the Database Service by @lohanidamodar in https://github.com/appwrite/appwrite/pull/3338
|
||||
- Added `databases.read` and `databases.write` Scopes for API Keys
|
||||
- Added New Runtimes
|
||||
- Dart 2.17
|
||||
- Deno 1.21
|
||||
- Java 18
|
||||
- Node 18
|
||||
- Webhooks now have a Signature Key for proof of Origin by @shimonewman in https://github.com/appwrite/appwrite/pull/3351
|
||||
- Start using Docker Compose V2 (from `docker-compose` to `docker compose`) by @Meldiron in https://github.com/appwrite/appwrite/pull/3362
|
||||
- Added support for selfhosted Gitlab (OAuth) by @Meldiron in https://github.com/appwrite/appwrite/pull/3366
|
||||
- Added Dailymotion OAuth Provider by @2002Bishwajeet in https://github.com/appwrite/appwrite/pull/3371
|
||||
- Added Autodesk OAuth Provider by @Haimantika in https://github.com/appwrite/appwrite/pull/3420
|
||||
- Ignore Service Checks when using API Key by @stnguyen90 in https://github.com/appwrite/appwrite/pull/3270
|
||||
- Added WebM as MIME- and Preview Type by @chuongtang in https://github.com/appwrite/appwrite/pull/3327
|
||||
- Expired User Sessions are now deleted by the Maintenance Worker by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/3324
|
||||
- Increased JWT rate-limit to 100 per hour by @abnegate in https://github.com/appwrite/appwrite/pull/3345
|
||||
- Internal Database Relations are now resolved using the Internal ID by @fogelito in https://github.com/appwrite/appwrite/pull/3383
|
||||
- Permissions for Documents can be updated without payload now by @gepd in https://github.com/appwrite/appwrite/pull/3346
|
||||
|
||||
## Bugs
|
||||
- Fixed Zoom OAuth scopes
|
||||
- Fixed empty build logs for Functions
|
||||
- Fixed unnecessary SMTP check on Team Invite using an API Key by @stnguyen90 in https://github.com/appwrite/appwrite/pull/3270
|
||||
- Fixed Error Message when adding Team Member to project by @stnguyen90 in https://github.com/appwrite/appwrite/pull/3296
|
||||
- Fixed .NET Runtime Logo by @adityaoberai in https://github.com/appwrite/appwrite/pull/3315
|
||||
- Fixed unnecessary Function execution delays by @Meldiron in https://github.com/appwrite/appwrite/pull/3348
|
||||
- Fixed Runtime race conditions on cold start by @PineappleIOnic in https://github.com/appwrite/appwrite/pull/3361
|
||||
- Fixed Malayalam translation by @varghesejose2020 in https://github.com/appwrite/appwrite/pull/2561
|
||||
- Fixed English translation by @MATsxm in https://github.com/appwrite/appwrite/pull/3337
|
||||
- Fixed spelling in Realtime Worker logs by @gireeshp in https://github.com/appwrite/appwrite/pull/1663
|
||||
- Fixed Docs URL for Yammer OAuth by @everly-gif in https://github.com/appwrite/appwrite/pull/3402
|
||||
|
||||
# Version 0.14.2
|
||||
|
||||
|
||||
+9
-9
@@ -51,19 +51,19 @@ $ git checkout -b [name_of_your_new_branch]
|
||||
4. Before you push your changes, make sure your code follows the `PSR12` coding standards , which is the standard Appwrite follows currently. You can easily do this by running the formatter.
|
||||
|
||||
```bash
|
||||
./vendor/bin/phpcbf <your file path>
|
||||
composer format <your file path>
|
||||
```
|
||||
|
||||
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 <your file path>
|
||||
composer lint <your file path>
|
||||
```
|
||||
|
||||
This will give you a list of errors for you to rectify , if there is an instance you need more information on the errors being displayed you can pass in additional command line arguments. More list of available arguments can be found [here](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage). A very useful command line argument is `--report=diff`. This will give you the expected changes by the linter for easy fixing of formatting issues.
|
||||
|
||||
```bash
|
||||
./vendor/bin/phpcs --report=diff <your file path>
|
||||
composer lint --report=diff <your file path>
|
||||
```
|
||||
|
||||
5. Push changes to GitHub
|
||||
@@ -317,7 +317,7 @@ The Runtimes for all supported cloud functions (multicore builds) can be found a
|
||||
|
||||
For generating a new console SDK follow the next steps:
|
||||
|
||||
1. Update the console spec file located at `app/config/specs/swagger2-0.12.x.console.json` from the dynamic version located at `https://localhost/specs/swagger2?platform=console`
|
||||
1. Update the console spec file located at `app/config/specs/swagger2-<version-number>.console.json` using Appwrite Tasks. Run the `php app/cli.php specs <version-number> normal` command in a running `appwrite/appwrite` container.
|
||||
2. Generate a new SDK using the command `php app/cli.php sdks`
|
||||
3. Change your working dir using `cd app/sdks/console-web`
|
||||
4. Build the new SDK `npm run build`
|
||||
@@ -413,18 +413,18 @@ We use some automation tools to help us keep a healthy codebase.
|
||||
|
||||
```bash
|
||||
# Run on all files
|
||||
./vendor/bin/phpcbf
|
||||
composer format
|
||||
# Run on single file or folder
|
||||
./vendor/bin/phpcbf <your file path>
|
||||
composer format <your file path>
|
||||
```
|
||||
|
||||
**Run Linter:**
|
||||
|
||||
```bash
|
||||
# Run on all files
|
||||
./vendor/bin/phpcs
|
||||
composer lint
|
||||
# Run on single file or folder
|
||||
./vendor/bin/phpcs <your file path>
|
||||
composer lint <your file path>
|
||||
```
|
||||
|
||||
## Tutorials
|
||||
@@ -462,4 +462,4 @@ 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!
|
||||
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!
|
||||
|
||||
+3
-5
@@ -31,7 +31,7 @@ ENV DEBUG=$DEBUG
|
||||
|
||||
ENV PHP_REDIS_VERSION=5.3.7 \
|
||||
PHP_MONGODB_VERSION=1.13.0 \
|
||||
PHP_SWOOLE_VERSION=v4.8.9 \
|
||||
PHP_SWOOLE_VERSION=v4.8.10 \
|
||||
PHP_IMAGICK_VERSION=3.7.0 \
|
||||
PHP_YAML_VERSION=2.2.2 \
|
||||
PHP_MAXMINDDB_VERSION=v1.11.0
|
||||
@@ -221,8 +221,6 @@ ENV _APP_SERVER=swoole \
|
||||
_APP_SMTP_USERNAME= \
|
||||
_APP_SMTP_PASSWORD= \
|
||||
_APP_PHONE_PROVIDER= \
|
||||
_APP_PHONE_USER= \
|
||||
_APP_PHONE_KEY= \
|
||||
_APP_PHONE_FROM= \
|
||||
_APP_FUNCTIONS_SIZE_LIMIT=30000000 \
|
||||
_APP_FUNCTIONS_TIMEOUT=900 \
|
||||
@@ -274,7 +272,7 @@ RUN \
|
||||
|
||||
RUN \
|
||||
mkdir -p $DOCKER_CONFIG/cli-plugins \
|
||||
&& ARCH=$(uname -m) && if [ $ARCH == "armv7l" ]; then $ARCH="armv7"; fi \
|
||||
&& ARCH=$(uname -m) && if [ $ARCH == "armv7l" ]; then ARCH="armv7"; fi \
|
||||
&& curl -SL https://github.com/docker/compose/releases/download/$DOCKER_COMPOSE_VERSION/docker-compose-linux-$ARCH -o $DOCKER_CONFIG/cli-plugins/docker-compose \
|
||||
&& chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
|
||||
|
||||
@@ -333,7 +331,7 @@ RUN chmod +x /usr/local/bin/doctor && \
|
||||
chmod +x /usr/local/bin/vars && \
|
||||
chmod +x /usr/local/bin/worker-audits && \
|
||||
chmod +x /usr/local/bin/worker-certificates && \
|
||||
chmod +x /usr/local/bin/worker-database && \
|
||||
chmod +x /usr/local/bin/worker-databases && \
|
||||
chmod +x /usr/local/bin/worker-deletes && \
|
||||
chmod +x /usr/local/bin/worker-functions && \
|
||||
chmod +x /usr/local/bin/worker-builds && \
|
||||
|
||||
+5
-5
@@ -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.15.0
|
||||
appwrite/appwrite:0.15.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.15.0
|
||||
appwrite/appwrite:0.15.2
|
||||
```
|
||||
|
||||
#### PowerShell
|
||||
@@ -81,13 +81,13 @@ 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.15.0
|
||||
appwrite/appwrite:0.15.2
|
||||
```
|
||||
|
||||
运行后,可以在浏览器上访问 http://localhost 找到 Appwrite 控制台。在非 Linux 的本机主机上完成安装后,服务器可能需要几分钟才能启动。
|
||||
|
||||
|
||||
需要自定义容器构架,请查看我们的 Docker [环境变量](https://appwrite.io/docs/environment-variables) 文档。您还可以参考我们的 [docker-compose.yml](https://gist.github.com/eldadfux/977869ff6bdd7312adfd4e629ee15cc5#file-docker-compose-yml) 文件手动设置环境。
|
||||
需要自定义容器构架,请查看我们的 Docker [环境变量](https://appwrite.io/docs/environment-variables) 文档。您还可以参考我们的 [docker-compose.yml](https://appwrite.io/install/compose) 和 [.env](https://appwrite.io/install/env) 文件手动设置环境。
|
||||
|
||||
### 从旧版本升级
|
||||
|
||||
@@ -109,7 +109,7 @@ docker run -it --rm ,
|
||||
* [**帐户**](https://appwrite.io/docs/client/account) -管理当前用户的帐户和登录方式。跟踪和管理用户 Session,登录设备,登录方法和查看相关记录。
|
||||
* [**用户**](https://appwrite.io/docs/server/users) - 在以管理员模式登录时管理和列出所有用户。
|
||||
* [**团队**](https://appwrite.io/docs/client/teams) - 管理用户分组。邀请成员,管理团队中的用户权限和用户角色。
|
||||
* [**数据库**](https://appwrite.io/docs/client/database) - 管理数据库文档和文档集。用检索界面来对文档和文档集进行读取,创建,更新,和删除。
|
||||
* [**数据库**](https://appwrite.io/docs/client/databases) - 管理数据库文档和文档集。用检索界面来对文档和文档集进行读取,创建,更新,和删除。
|
||||
* [**贮存**](https://appwrite.io/docs/client/storage) - 管理文件的阅读、创建、删除和预览。设置文件的预览来满足程序的个性化需求。所有文件都由 ClamAV 扫描并安全存储和加密。
|
||||
* [**云函数**](https://appwrite.io/docs/server/functions) - 在安全,隔离的环境中运行自定义代码。这些代码可以被事件,CRON,或者手动操作触发。
|
||||
* [**语言适配**](https://appwrite.io/docs/client/locale) - 根据用户所在的的国家和地区做出合适的语言适配。
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
> It's going to get cloudy! 🌩 ☂️
|
||||
> The Appwrite Cloud is coming soon! You can learn more about our upcoming hosted solution and signup for free credits at: https://appwrite.io/cloud
|
||||
|
||||
<br />
|
||||
<p align="center">
|
||||
<a href="https://appwrite.io" target="_blank"><img width="260" height="39" src="https://appwrite.io/images/appwrite.svg" alt="Appwrite Logo"></a>
|
||||
@@ -19,7 +22,7 @@
|
||||
|
||||
English | [简体中文](README-CN.md)
|
||||
|
||||
[**Appwrite 0.14 has been released! Learn what's new!**](https://dev.to/appwrite/announcing-appwrite-014-with-11-cloud-function-runtimes-36f5)
|
||||
[**Appwrite 0.15 has been released! Learn what's new!**](https://dev.to/appwrite/announcing-appwrite-015-with-phone-authentication-more-5cjj)
|
||||
|
||||
Appwrite is an end-to-end backend server for Web, Mobile, Native, or Backend apps packaged as a set of Docker<nobr> microservices. Appwrite abstracts the complexity and repetitiveness required to build a modern backend API from scratch and allows you to build secure apps faster.
|
||||
|
||||
@@ -62,7 +65,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.15.0
|
||||
appwrite/appwrite:0.15.2
|
||||
```
|
||||
|
||||
### Windows
|
||||
@@ -74,7 +77,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.15.0
|
||||
appwrite/appwrite:0.15.2
|
||||
```
|
||||
|
||||
#### PowerShell
|
||||
@@ -84,18 +87,42 @@ 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.15.0
|
||||
appwrite/appwrite:0.15.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.
|
||||
|
||||
|
||||
For advanced production and custom installation, check out our Docker [environment variables](https://appwrite.io/docs/environment-variables) docs. You can also use our public [docker-compose.yml](https://gist.github.com/eldadfux/977869ff6bdd7312adfd4e629ee15cc5#file-docker-compose-yml) file to manually set up an environment.
|
||||
For advanced production and custom installation, check out our Docker [environment variables](https://appwrite.io/docs/environment-variables) docs. You can also use our public [docker-compose.yml](https://appwrite.io/install/compose) and [.env](https://appwrite.io/install/env) files to manually set up an environment.
|
||||
|
||||
### Upgrade from an Older Version
|
||||
|
||||
If you are upgrading your Appwrite server from an older version, you should use the Appwrite migration tool once your setup is completed. For more information regarding this, check out the [Installation Docs](https://appwrite.io/docs/installation).
|
||||
|
||||
|
||||
## One-Click Setups
|
||||
|
||||
In addition to running Appwrite locally, you can also launch Appwrite using a pre-configured setup. This allows you to get up and running with Appwrite quickly without installing Docker on your local machine.
|
||||
|
||||
Choose from one of the providers below:
|
||||
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td align="center" width="100" height="100">
|
||||
<a href="https://marketplace.digitalocean.com/apps/appwrite">
|
||||
<img width="50" height="39" src="public/images/integrations/digitalocean-logo.svg" alt="DigitalOcean Logo" />
|
||||
<br /><sub><b>DigitalOcean</b></sub></a>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" width="100" height="100">
|
||||
<a href="https://gitpod.io/#https://github.com/appwrite/integration-for-gitpod">
|
||||
<img width="50" height="39" src="public/images/integrations/gitpod-logo.svg" alt="Gitpod Logo" />
|
||||
<br /><sub><b>Gitpod</b></sub></a>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Getting Started
|
||||
|
||||
Getting started with Appwrite is as easy as creating a new project, choosing your platform, and integrating its SDK into your code. You can easily get started with your platform of choice by reading one of our Getting Started tutorials.
|
||||
@@ -112,9 +139,10 @@ Getting started with Appwrite is as easy as creating a new project, choosing you
|
||||
* [**Account**](https://appwrite.io/docs/client/account) - Manage current user authentication and account. Track and manage the user sessions, devices, sign-in methods, and security logs.
|
||||
* [**Users**](https://appwrite.io/docs/server/users) - Manage and list all project users when in admin mode.
|
||||
* [**Teams**](https://appwrite.io/docs/client/teams) - Manage and group users in teams. Manage memberships, invites, and user roles within a team.
|
||||
* [**Database**](https://appwrite.io/docs/client/database) - Manage database collections and documents. Read, create, update, and delete documents and filter lists of document collections using advanced filters.
|
||||
* [**Databases**](https://appwrite.io/docs/client/databases) - Manage databases, collections and documents. Read, create, update, and delete documents and filter lists of document collections using advanced filters.
|
||||
* [**Storage**](https://appwrite.io/docs/client/storage) - Manage storage files. Read, create, delete, and preview files. Manipulate the preview of your files to fit your app perfectly. All files are scanned by ClamAV and stored in a secure and encrypted way.
|
||||
* [**Functions**](https://appwrite.io/docs/server/functions) - Customize your Appwrite server by executing your custom code in a secure, isolated environment. You can trigger your code on any Appwrite system event, manually or using a CRON schedule.
|
||||
* [**Realtime**](https://appwrite.io/docs/realtime) - Listen to real-time events for any of your Appwrite services including users, storage, functions, databases and more.
|
||||
* [**Locale**](https://appwrite.io/docs/client/locale) - Track your user's location, and manage your app locale-based data.
|
||||
* [**Avatars**](https://appwrite.io/docs/client/avatars) - Manage your users' avatars, countries' flags, browser icons, credit card symbols, and generate QR codes.
|
||||
|
||||
|
||||
+122
-13
@@ -17,11 +17,69 @@ $auth = Config::getParam('auth', []);
|
||||
*/
|
||||
|
||||
$collections = [
|
||||
'collections' => [
|
||||
'databases' => [
|
||||
'$collection' => Database::METADATA,
|
||||
'$id' => 'databases',
|
||||
'name' => 'Databases',
|
||||
'attributes' => [
|
||||
[
|
||||
'$id' => 'name',
|
||||
'type' => Database::VAR_STRING,
|
||||
'size' => 256,
|
||||
'required' => true,
|
||||
'signed' => true,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => 'search',
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 16384,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
],
|
||||
'indexes' => [
|
||||
[
|
||||
'$id' => '_fulltext_search',
|
||||
'type' => Database::INDEX_FULLTEXT,
|
||||
'attributes' => ['search'],
|
||||
'lengths' => [],
|
||||
'orders' => [],
|
||||
],
|
||||
],
|
||||
],
|
||||
'collections' => [
|
||||
'$collection' => 'databases',
|
||||
'$id' => 'collections',
|
||||
'name' => 'Collections',
|
||||
'attributes' => [
|
||||
[
|
||||
'$id' => 'databaseInternalId',
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => 'databaseId',
|
||||
'type' => Database::VAR_STRING,
|
||||
'signed' => true,
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'format' => '',
|
||||
'filters' => [],
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
],
|
||||
[
|
||||
'$id' => 'name',
|
||||
'type' => Database::VAR_STRING,
|
||||
@@ -98,6 +156,28 @@ $collections = [
|
||||
'$id' => 'attributes',
|
||||
'name' => 'Attributes',
|
||||
'attributes' => [
|
||||
[
|
||||
'$id' => 'databaseInternalId',
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => 'databaseId',
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => false,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => 'collectionInternalId',
|
||||
'type' => Database::VAR_STRING,
|
||||
@@ -115,7 +195,7 @@ $collections = [
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
@@ -239,11 +319,11 @@ $collections = [
|
||||
],
|
||||
'indexes' => [
|
||||
[
|
||||
'$id' => '_key_collection',
|
||||
'$id' => '_key_db_collection',
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['collectionInternalId'],
|
||||
'lengths' => [Database::LENGTH_KEY],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
'attributes' => ['databaseInternalId', 'collectionInternalId'],
|
||||
'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY],
|
||||
'orders' => [Database::ORDER_ASC, Database::ORDER_ASC],
|
||||
],
|
||||
],
|
||||
],
|
||||
@@ -253,6 +333,28 @@ $collections = [
|
||||
'$id' => 'indexes',
|
||||
'name' => 'Indexes',
|
||||
'attributes' => [
|
||||
[
|
||||
'$id' => 'databaseInternalId',
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => 'databaseId',
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => false,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => 'collectionInternalId',
|
||||
'type' => Database::VAR_STRING,
|
||||
@@ -270,7 +372,7 @@ $collections = [
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
@@ -344,12 +446,12 @@ $collections = [
|
||||
],
|
||||
'indexes' => [
|
||||
[
|
||||
'$id' => '_key_collection',
|
||||
'$id' => '_key_db_collection',
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['collectionInternalId'],
|
||||
'lengths' => [Database::LENGTH_KEY],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
]
|
||||
'attributes' => ['databaseInternalId', 'collectionInternalId'],
|
||||
'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY],
|
||||
'orders' => [Database::ORDER_ASC, Database::ORDER_ASC],
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
@@ -1200,6 +1302,13 @@ $collections = [
|
||||
'lengths' => [320],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => '_key_phone',
|
||||
'type' => Database::INDEX_UNIQUE,
|
||||
'attributes' => ['phone'],
|
||||
'lengths' => [16],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => '_key_search',
|
||||
'type' => Database::INDEX_FULLTEXT,
|
||||
@@ -1767,7 +1876,7 @@ $collections = [
|
||||
'orders' => [Database::ORDER_ASC, Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => '_key_internal',
|
||||
'$id' => '_key_user',
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['userInternalId'],
|
||||
'lengths' => [Database::LENGTH_KEY],
|
||||
|
||||
@@ -48,6 +48,11 @@ return [
|
||||
'description' => 'SMTP is disabled on your Appwrite instance. You can <a href="/docs/email-delivery">learn more about setting up SMTP</a> in our docs.',
|
||||
'code' => 503,
|
||||
],
|
||||
Exception::GENERAL_PHONE_DISABLED => [
|
||||
'name' => Exception::GENERAL_PHONE_DISABLED,
|
||||
'description' => 'Phone provider is not configured. Please check the _APP_PHONE_PROVIDER environment variable of your Appwrite server.',
|
||||
'code' => 503,
|
||||
],
|
||||
Exception::GENERAL_ARGUMENT_INVALID => [
|
||||
'name' => Exception::GENERAL_ARGUMENT_INVALID,
|
||||
'description' => 'The request contains one or more invalid arguments. Please refer to the endpoint documentation.',
|
||||
@@ -170,6 +175,16 @@ return [
|
||||
'description' => 'The requested authentication method is either disabled or unsupported. Please check the supported authentication methods in the Appwrite console.',
|
||||
'code' => 501,
|
||||
],
|
||||
Exception::USER_PHONE_ALREADY_EXISTS => [
|
||||
'name' => Exception::USER_PHONE_ALREADY_EXISTS,
|
||||
'description' => 'A user with the same phone number already exists in the current project.',
|
||||
'code' => 409,
|
||||
],
|
||||
Exception::USER_PHONE_NOT_FOUND => [
|
||||
'name' => Exception::USER_PHONE_NOT_FOUND,
|
||||
'description' => 'The current user does not have a phone number associated with their account.',
|
||||
'code' => 400,
|
||||
],
|
||||
|
||||
/** Teams */
|
||||
Exception::TEAM_NOT_FOUND => [
|
||||
|
||||
+48
-34
@@ -69,54 +69,68 @@ return [
|
||||
],
|
||||
]
|
||||
],
|
||||
'collections' => [
|
||||
'$model' => Response::MODEL_COLLECTION,
|
||||
'databases' => [
|
||||
'$model' => Response::MODEL_DATABASE,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any collection event.',
|
||||
'documents' => [
|
||||
'$model' => Response::MODEL_DOCUMENT,
|
||||
'$description' => 'This event triggers on any database event.',
|
||||
'collections' => [
|
||||
'$model' => Response::MODEL_COLLECTION,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any documents event.',
|
||||
'$description' => 'This event triggers on any collection event.',
|
||||
'documents' => [
|
||||
'$model' => Response::MODEL_DOCUMENT,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any documents event.',
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a document is created.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when a document is deleted.'
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a document is updated.'
|
||||
],
|
||||
],
|
||||
'indexes' => [
|
||||
'$model' => Response::MODEL_INDEX,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any indexes event.',
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when an index is created.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when an index is deleted.'
|
||||
]
|
||||
],
|
||||
'attributes' => [
|
||||
'$model' => Response::MODEL_ATTRIBUTE,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any attributes event.',
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when an attribute is created.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when an attribute is deleted.'
|
||||
]
|
||||
],
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a document is created.',
|
||||
'$description' => 'This event triggers when a collection is created.'
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when a document is deleted.'
|
||||
'$description' => 'This event triggers when a collection is deleted.',
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a document is updated.'
|
||||
],
|
||||
],
|
||||
'indexes' => [
|
||||
'$model' => Response::MODEL_INDEX,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any indexes event.',
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when an index is created.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when an index is deleted.'
|
||||
]
|
||||
],
|
||||
'attributes' => [
|
||||
'$model' => Response::MODEL_ATTRIBUTE,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any attributes event.',
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when an attribute is created.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when an attribute is deleted.'
|
||||
'$description' => 'This event triggers when a collection is updated.',
|
||||
]
|
||||
],
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a collection is created.'
|
||||
'$description' => 'This event triggers when a database is created.'
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when a collection is deleted.',
|
||||
'$description' => 'This event triggers when a database is deleted.',
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a collection is updated.',
|
||||
'$description' => 'This event triggers when a database is updated.',
|
||||
]
|
||||
],
|
||||
'buckets' => [
|
||||
|
||||
+14
-14
@@ -15,7 +15,7 @@ return [
|
||||
[
|
||||
'key' => 'web',
|
||||
'name' => 'Web',
|
||||
'version' => '8.0.1',
|
||||
'version' => '9.0.1',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-web',
|
||||
'package' => 'https://www.npmjs.com/package/appwrite',
|
||||
'enabled' => true,
|
||||
@@ -63,7 +63,7 @@ return [
|
||||
[
|
||||
'key' => 'flutter',
|
||||
'name' => 'Flutter',
|
||||
'version' => '5.0.0',
|
||||
'version' => '6.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-flutter',
|
||||
'package' => 'https://pub.dev/packages/appwrite',
|
||||
'enabled' => true,
|
||||
@@ -81,7 +81,7 @@ return [
|
||||
[
|
||||
'key' => 'apple',
|
||||
'name' => 'Apple',
|
||||
'version' => '0.5.0',
|
||||
'version' => '0.6.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-apple',
|
||||
'package' => 'https://github.com/appwrite/sdk-for-apple',
|
||||
'enabled' => true,
|
||||
@@ -116,7 +116,7 @@ return [
|
||||
[
|
||||
'key' => 'android',
|
||||
'name' => 'Android',
|
||||
'version' => '0.6.1',
|
||||
'version' => '0.7.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-android',
|
||||
'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-android',
|
||||
'enabled' => true,
|
||||
@@ -162,7 +162,7 @@ return [
|
||||
[
|
||||
'key' => 'web',
|
||||
'name' => 'Console',
|
||||
'version' => '5.0.0',
|
||||
'version' => '6.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-console',
|
||||
'package' => '',
|
||||
'enabled' => true,
|
||||
@@ -180,7 +180,7 @@ return [
|
||||
[
|
||||
'key' => 'cli',
|
||||
'name' => 'Command Line',
|
||||
'version' => '0.17.1',
|
||||
'version' => '0.18.3',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-cli',
|
||||
'package' => 'https://www.npmjs.com/package/appwrite-cli',
|
||||
'enabled' => true,
|
||||
@@ -208,7 +208,7 @@ return [
|
||||
[
|
||||
'key' => 'nodejs',
|
||||
'name' => 'Node.js',
|
||||
'version' => '6.0.0',
|
||||
'version' => '7.0.2',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-node',
|
||||
'package' => 'https://www.npmjs.com/package/node-appwrite',
|
||||
'enabled' => true,
|
||||
@@ -226,7 +226,7 @@ return [
|
||||
[
|
||||
'key' => 'deno',
|
||||
'name' => 'Deno',
|
||||
'version' => '4.0.0',
|
||||
'version' => '5.0.1',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-deno',
|
||||
'package' => 'https://deno.land/x/appwrite',
|
||||
'enabled' => true,
|
||||
@@ -244,7 +244,7 @@ return [
|
||||
[
|
||||
'key' => 'php',
|
||||
'name' => 'PHP',
|
||||
'version' => '5.0.0',
|
||||
'version' => '6.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-php',
|
||||
'package' => 'https://packagist.org/packages/appwrite/appwrite',
|
||||
'enabled' => true,
|
||||
@@ -262,7 +262,7 @@ return [
|
||||
[
|
||||
'key' => 'python',
|
||||
'name' => 'Python',
|
||||
'version' => '0.9.0',
|
||||
'version' => '0.10.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-python',
|
||||
'package' => 'https://pypi.org/project/appwrite/',
|
||||
'enabled' => true,
|
||||
@@ -280,7 +280,7 @@ return [
|
||||
[
|
||||
'key' => 'ruby',
|
||||
'name' => 'Ruby',
|
||||
'version' => '5.0.0',
|
||||
'version' => '6.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-ruby',
|
||||
'package' => 'https://rubygems.org/gems/appwrite',
|
||||
'enabled' => true,
|
||||
@@ -352,7 +352,7 @@ return [
|
||||
[
|
||||
'key' => 'dart',
|
||||
'name' => 'Dart',
|
||||
'version' => '5.0.1',
|
||||
'version' => '6.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-dart',
|
||||
'package' => 'https://pub.dev/packages/dart_appwrite',
|
||||
'enabled' => true,
|
||||
@@ -370,7 +370,7 @@ return [
|
||||
[
|
||||
'key' => 'kotlin',
|
||||
'name' => 'Kotlin',
|
||||
'version' => '0.5.0',
|
||||
'version' => '0.6.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-kotlin',
|
||||
'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-kotlin',
|
||||
'enabled' => true,
|
||||
@@ -392,7 +392,7 @@ return [
|
||||
[
|
||||
'key' => 'swift',
|
||||
'name' => 'Swift',
|
||||
'version' => '0.5.0',
|
||||
'version' => '0.6.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-swift',
|
||||
'package' => 'https://github.com/appwrite/sdk-for-swift',
|
||||
'enabled' => true,
|
||||
|
||||
@@ -31,6 +31,16 @@ return [ // Ordered by ABC.
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'autodesk' => [
|
||||
'name' => 'Autodesk',
|
||||
'developers' => 'https://forge.autodesk.com/en/docs/oauth/v2/developers_guide/overview/',
|
||||
'icon' => 'icon-autodesk',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
'bitbucket' => [
|
||||
'name' => 'BitBucket',
|
||||
'developers' => 'https://developer.atlassian.com/bitbucket',
|
||||
@@ -117,7 +127,7 @@ return [ // Ordered by ABC.
|
||||
'icon' => 'icon-gitlab',
|
||||
'enabled' => true,
|
||||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'form' => 'gitlab.phtml',
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
],
|
||||
|
||||
@@ -32,6 +32,8 @@ $admins = [
|
||||
'buckets.write',
|
||||
'users.read',
|
||||
'users.write',
|
||||
'databases.read',
|
||||
'databases.write',
|
||||
'collections.read',
|
||||
'collections.write',
|
||||
'platforms.read',
|
||||
|
||||
@@ -13,6 +13,12 @@ return [ // List of publicly visible scopes
|
||||
'teams.write' => [
|
||||
'description' => 'Access to create, update, and delete your project\'s teams',
|
||||
],
|
||||
'databases.read' => [
|
||||
'description' => 'Access to read your project\'s databases',
|
||||
],
|
||||
'databases.write' => [
|
||||
'description' => 'Access to create, update, and delete your project\'s databases',
|
||||
],
|
||||
'collections.read' => [
|
||||
'description' => 'Access to read your project\'s database collections',
|
||||
],
|
||||
|
||||
+11
-8
@@ -53,18 +53,21 @@ return [
|
||||
'optional' => true,
|
||||
'icon' => '/images/services/avatars.png',
|
||||
],
|
||||
'database' => [
|
||||
'key' => 'database',
|
||||
'name' => 'Database',
|
||||
'subtitle' => 'The Database service allows you to create structured collections of documents, query and filter lists of documents',
|
||||
'description' => '/docs/services/database.md',
|
||||
'controller' => 'api/database.php',
|
||||
'databases' => [
|
||||
'key' => 'databases',
|
||||
'name' => 'Databases',
|
||||
'subtitle' => 'The Databases service allows you to create structured collections of documents, query and filter lists of documents',
|
||||
'description' => '/docs/services/databases.md',
|
||||
'controller' => 'api/databases.php',
|
||||
'sdk' => true,
|
||||
'docs' => true,
|
||||
'docsUrl' => 'https://appwrite.io/docs/client/database',
|
||||
'docsUrl' => 'https://appwrite.io/docs/client/databases',
|
||||
'tests' => false,
|
||||
'optional' => true,
|
||||
'icon' => '/images/services/database.png',
|
||||
'icon' => '/images/services/databases.png',
|
||||
'globalAttributes' => [
|
||||
'databaseId'
|
||||
]
|
||||
],
|
||||
'locale' => [
|
||||
'key' => 'locale',
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -68,7 +68,7 @@ return [
|
||||
'default' => 'localhost',
|
||||
'required' => true,
|
||||
'question' => 'Enter a DNS A record hostname to serve as a CNAME for your custom domains.' . PHP_EOL . 'You can use the same value as used for the Appwrite hostname.',
|
||||
'filter' => ''
|
||||
'filter' => 'domainTarget'
|
||||
],
|
||||
[
|
||||
'name' => '_APP_CONSOLE_WHITELIST_ROOT',
|
||||
@@ -98,7 +98,7 @@ return [
|
||||
// ],
|
||||
[
|
||||
'name' => '_APP_CONSOLE_WHITELIST_IPS',
|
||||
'description' => 'This last option allows you to limit creation of users in Appwrite console for users sharing the same set of IP addresses. This option is very useful for team working with a VPN service or a company IP.\n\nTo enable/activate this option, pass a list of allowed IP addresses separated by a comma.',
|
||||
'description' => "This last option allows you to limit creation of users in Appwrite console for users sharing the same set of IP addresses. This option is very useful for team working with a VPN service or a company IP.\n\nTo enable/activate this option, pass a list of allowed IP addresses separated by a comma.",
|
||||
'introduction' => '',
|
||||
'default' => '',
|
||||
'required' => false,
|
||||
@@ -340,7 +340,7 @@ return [
|
||||
],
|
||||
[
|
||||
'category' => 'SMTP',
|
||||
'description' => 'Appwrite is using an SMTP server for emailing your projects users and server admins. The SMTP env vars are used to allow Appwrite server to connect to the SMTP container.\n\nIf running in production, it might be easier to use a 3rd party SMTP server as it might be a little more difficult to set up a production SMTP server that will not send all your emails into your user\'s SPAM folder.',
|
||||
'description' => "Appwrite is using an SMTP server for emailing your projects users and server admins. The SMTP env vars are used to allow Appwrite server to connect to the SMTP container.\n\nIf running in production, it might be easier to use a 3rd party SMTP server as it might be a little more difficult to set up a production SMTP server that will not send all your emails into your user\'s SPAM folder.",
|
||||
'variables' => [
|
||||
[
|
||||
'name' => '_APP_SMTP_HOST',
|
||||
@@ -395,7 +395,7 @@ return [
|
||||
'variables' => [
|
||||
[
|
||||
'name' => '_APP_PHONE_PROVIDER',
|
||||
'description' => 'Provider used for delivering SMS for Phone authentication. Use the following format: \'phone://[USER]:[SECRET]@[PROVIDER]\'. \n\nAvailable providers are twilio, text-magic and telesign.',
|
||||
'description' => "Provider used for delivering SMS for Phone authentication. Use the following format: 'phone://[USER]:[SECRET]@[PROVIDER]'. \n\nAvailable providers are twilio, text-magic and telesign.",
|
||||
'introduction' => '0.15.0',
|
||||
'default' => '',
|
||||
'required' => false,
|
||||
@@ -647,7 +647,7 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_TIMEOUT',
|
||||
'description' => 'The maximum number of seconds allowed as a timeout value when creating a new function. The default value is 900 seconds.',
|
||||
'description' => 'The maximum number of seconds allowed as a timeout value when creating a new function. The default value is 900 seconds. This is the global limit, timeout for individual functions are configured in the function\'s settings or in appwrite.json.',
|
||||
'introduction' => '0.7.0',
|
||||
'default' => '900',
|
||||
'required' => false,
|
||||
@@ -701,7 +701,7 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_RUNTIMES',
|
||||
'description' => "This option allows you to limit the available environments for cloud functions. This option is very useful for low-cost servers to safe disk space.\n\nTo enable/activate this option, pass a list of allowed environments separated by a comma.\n\nCurrently, supported environments are: " . \implode(', ', \array_keys(Config::getParam('runtimes'))),
|
||||
'description' => "This option allows you to enable or disable runtime environments for cloud functions. Disable unused runtimes to save disk space.\n\nTo enable cloud function runtimes, pass a list of enabled environments separated by a comma.\n\nCurrently, supported environments are: " . \implode(', ', \array_keys(Config::getParam('runtimes'))),
|
||||
'introduction' => '0.8.0',
|
||||
'default' => 'node-16.0,php-8.0,python-3.9,ruby-3.0',
|
||||
'required' => false,
|
||||
|
||||
@@ -134,6 +134,7 @@ App::post('/v1/account')
|
||||
});
|
||||
|
||||
App::post('/v1/account/sessions/email')
|
||||
->alias('/v1/account/sessions')
|
||||
->desc('Create Account Session with Email')
|
||||
->groups(['api', 'account', 'auth'])
|
||||
->label('event', 'users.[userId].sessions.[sessionId].create')
|
||||
@@ -268,7 +269,7 @@ App::get('/v1/account/sessions/oauth2/:provider')
|
||||
->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)
|
||||
->param('scopes', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), 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 ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true)
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
@@ -873,7 +874,7 @@ App::post('/v1/account/sessions/phone')
|
||||
->inject('phone')
|
||||
->action(function (string $userId, string $number, Request $request, Response $response, Document $project, Database $dbForProject, Audit $audits, Event $events, EventPhone $messaging, Phone $phone) {
|
||||
if (empty(App::getEnv('_APP_PHONE_PROVIDER'))) {
|
||||
throw new Exception('Phone Disabled', 503, Exception::GENERAL_SMTP_DISABLED);
|
||||
throw new Exception('Phone provider not configured', 503, Exception::GENERAL_PHONE_DISABLED);
|
||||
}
|
||||
|
||||
$roles = Authorization::getRoles();
|
||||
@@ -1608,7 +1609,7 @@ App::patch('/v1/account/phone')
|
||||
try {
|
||||
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
|
||||
} catch (Duplicate $th) {
|
||||
throw new Exception('Phone number already exists', 409, Exception::USER_EMAIL_ALREADY_EXISTS);
|
||||
throw new Exception('Phone number already exists', 409, Exception::USER_PHONE_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
$audits
|
||||
@@ -2276,12 +2277,12 @@ App::post('/v1/account/verification/phone')
|
||||
->inject('messaging')
|
||||
->action(function (Request $request, Response $response, Phone $phone, Document $user, Database $dbForProject, Audit $audits, Event $events, Stats $usage, EventPhone $messaging) {
|
||||
|
||||
if (empty(App::getEnv('_APP_SMTP_HOST'))) {
|
||||
throw new Exception('SMTP Disabled', 503, Exception::GENERAL_SMTP_DISABLED);
|
||||
if (empty(App::getEnv('_APP_PHONE_PROVIDER'))) {
|
||||
throw new Exception('Phone provider not configured', 503, Exception::GENERAL_PHONE_DISABLED);
|
||||
}
|
||||
|
||||
if (empty($user->getAttribute('phone'))) {
|
||||
throw new Exception('User has no phone number.', 400);
|
||||
throw new Exception('User has no phone number.', 400, Exception::USER_PHONE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$roles = Authorization::getRoles();
|
||||
@@ -2314,7 +2315,9 @@ App::post('/v1/account/verification/phone')
|
||||
|
||||
$messaging
|
||||
->setRecipient($user->getAttribute('phone'))
|
||||
->setMessage($secret);
|
||||
->setMessage($secret)
|
||||
->trigger()
|
||||
;
|
||||
|
||||
$events
|
||||
->setParam('userId', $user->getId())
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -33,6 +33,7 @@ use Utopia\Config\Config;
|
||||
use Cron\CronExpression;
|
||||
use Executor\Executor;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Database\Validator\Permissions;
|
||||
use Utopia\Validator\Boolean;
|
||||
|
||||
include_once __DIR__ . '/../shared/api.php';
|
||||
@@ -51,7 +52,7 @@ App::post('/v1/functions')
|
||||
->label('sdk.response.model', Response::MODEL_FUNCTION)
|
||||
->param('functionId', '', new CustomId(), 'Function 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('name', '', new Text(128), 'Function name. Max length: 128 chars.')
|
||||
->param('execute', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution permissions. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed, each 64 characters long.')
|
||||
->param('execute', [], new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution permissions. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed, each 64 characters long.')
|
||||
->param('runtime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Execution runtime.')
|
||||
->param('vars', [], new Assoc(), 'Key-value JSON object that will be passed to the function as environment variables.', true)
|
||||
->param('events', [], new ArrayList(new ValidatorEvent(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.', true)
|
||||
@@ -100,7 +101,7 @@ App::get('/v1/functions')
|
||||
->param('limit', 25, new Range(0, 100), 'Maximum number of functions to return in response. By default will return maximum 25 results. Maximum of 100 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 function used as the starting point for the query, excluding the function itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true)
|
||||
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor.', true)
|
||||
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor, can be either \'before\' or \'after\'.', true)
|
||||
->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
@@ -289,7 +290,7 @@ App::put('/v1/functions/:functionId')
|
||||
->label('sdk.response.model', Response::MODEL_FUNCTION)
|
||||
->param('functionId', '', new UID(), 'Function ID.')
|
||||
->param('name', '', new Text(128), 'Function name. Max length: 128 chars.')
|
||||
->param('execute', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution permissions. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed, each 64 characters long.')
|
||||
->param('execute', [], new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with execution permissions. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed, each 64 characters long.')
|
||||
->param('vars', [], new Assoc(), 'Key-value JSON object that will be passed to the function as environment variables.', true)
|
||||
->param('events', [], new ArrayList(new ValidatorEvent(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.', true)
|
||||
->param('schedule', '', new Cron(), 'Schedule CRON syntax.', true)
|
||||
@@ -467,7 +468,7 @@ App::post('/v1/functions/:functionId/deployments')
|
||||
->inject('project')
|
||||
->inject('deviceFunctions')
|
||||
->inject('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) {
|
||||
->action(function (string $functionId, string $entrypoint, mixed $code, bool $activate, Request $request, Response $response, Database $dbForProject, Stats $usage, Event $events, Document $project, Device $deviceFunctions, Device $deviceLocal) {
|
||||
|
||||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
|
||||
@@ -641,7 +642,7 @@ App::get('/v1/functions/:functionId/deployments')
|
||||
->param('limit', 25, new Range(0, 100), 'Maximum number of deployments to return in response. By default will return maximum 25 results. Maximum of 100 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 deployment used as the starting point for the query, excluding the deployment itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true)
|
||||
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor.', true)
|
||||
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor, can be either \'before\' or \'after\'.', true)
|
||||
->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
@@ -696,7 +697,7 @@ App::get('/v1/functions/:functionId/deployments/:deploymentId')
|
||||
->label('sdk.description', '/docs/references/functions/get-deployment.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_DEPLOYMENT_LIST)
|
||||
->label('sdk.response.model', Response::MODEL_DEPLOYMENT)
|
||||
->param('functionId', '', new UID(), 'Function ID.')
|
||||
->param('deploymentId', '', new UID(), 'Deployment ID.')
|
||||
->inject('response')
|
||||
@@ -805,7 +806,8 @@ App::post('/v1/functions/:functionId/executions')
|
||||
->inject('dbForProject')
|
||||
->inject('user')
|
||||
->inject('events')
|
||||
->action(function (string $functionId, string $data, bool $async, Response $response, Document $project, Database $dbForProject, Document $user, Event $events) {
|
||||
->inject('usage')
|
||||
->action(function (string $functionId, string $data, bool $async, Response $response, Document $project, Database $dbForProject, Document $user, Event $events, Stats $usage) {
|
||||
|
||||
$function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId));
|
||||
|
||||
@@ -889,7 +891,7 @@ App::post('/v1/functions/:functionId/executions')
|
||||
$events
|
||||
->setParam('functionId', $function->getId())
|
||||
->setParam('executionId', $execution->getId())
|
||||
->setContext($function);
|
||||
->setContext('function', $function);
|
||||
|
||||
if ($async) {
|
||||
$event = new Func();
|
||||
@@ -957,6 +959,12 @@ App::post('/v1/functions/:functionId/executions')
|
||||
|
||||
Authorization::skip(fn () => $dbForProject->updateDocument('executions', $executionId, $execution));
|
||||
|
||||
$usage
|
||||
->setParam('functionId', $function->getId())
|
||||
->setParam('functionExecution', 1)
|
||||
->setParam('functionStatus', $execution->getAttribute('status', ''))
|
||||
->setParam('functionExecutionTime', $execution->getAttribute('time') * 1000); // ms
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->dynamic($execution, Response::MODEL_EXECUTION);
|
||||
@@ -978,7 +986,7 @@ App::get('/v1/functions/:functionId/executions')
|
||||
->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('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
|
||||
->param('cursor', '', new UID(), 'ID of the execution used as the starting point for the query, excluding the execution itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true)
|
||||
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor.', true)
|
||||
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor, can be either \'before\' or \'after\'.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $functionId, int $limit, int $offset, string $search, string $cursor, string $cursorDirection, Response $response, Database $dbForProject) {
|
||||
|
||||
@@ -113,7 +113,7 @@ App::post('/v1/projects')
|
||||
$collections = Config::getParam('collections', []);
|
||||
|
||||
$dbForProject->setNamespace("_{$project->getInternalId()}");
|
||||
$dbForProject->create('appwrite');
|
||||
$dbForProject->create(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
|
||||
|
||||
$audit = new Audit($dbForProject);
|
||||
$audit->setup();
|
||||
@@ -173,7 +173,7 @@ App::get('/v1/projects')
|
||||
->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
|
||||
->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Results offset. The default value is 0. Use this param to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true)
|
||||
->param('cursor', '', new UID(), 'ID of the project used as the starting point for the query, excluding the project itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true)
|
||||
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor.', true)
|
||||
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor, can be either \'before\' or \'after\'.', true)
|
||||
->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true)
|
||||
->inject('response')
|
||||
->inject('dbForConsole')
|
||||
@@ -278,8 +278,8 @@ App::get('/v1/projects/:projectId/usage')
|
||||
'network',
|
||||
'executions',
|
||||
'users.count',
|
||||
'database.documents.count',
|
||||
'database.collections.count',
|
||||
'databases.documents.count',
|
||||
'databases.collections.count',
|
||||
'storage.total'
|
||||
];
|
||||
|
||||
@@ -326,8 +326,8 @@ App::get('/v1/projects/:projectId/usage')
|
||||
'requests' => $stats['requests'],
|
||||
'network' => $stats['network'],
|
||||
'functions' => $stats['executions'],
|
||||
'documents' => $stats['database.documents.count'],
|
||||
'collections' => $stats['database.collections.count'],
|
||||
'documents' => $stats['databases.documents.count'],
|
||||
'collections' => $stats['databases.collections.count'],
|
||||
'users' => $stats['users.count'],
|
||||
'storage' => $stats['storage.total']
|
||||
]);
|
||||
|
||||
@@ -56,8 +56,8 @@ App::post('/v1/storage/buckets')
|
||||
->param('bucketId', '', 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('name', '', new Text(128), 'Bucket name')
|
||||
->param('permission', null, new WhiteList(['file', 'bucket']), 'Permissions type model to use for reading files in this bucket. You can use bucket-level permission set once on the bucket using the `read` and `write` params, or you can set file-level permission where each file read and write params will decide who has access to read and write to each file individually. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||
->param('read', null, new Permissions(), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('write', null, new Permissions(), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('read', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('write', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true)
|
||||
->param('maximumFileSize', (int) App::getEnv('_APP_STORAGE_LIMIT', 0), new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '. For self-hosted setups you can change the max limit by changing the `_APP_STORAGE_LIMIT` environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)', true)
|
||||
->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true)
|
||||
@@ -156,7 +156,7 @@ App::get('/v1/storage/buckets')
|
||||
->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
|
||||
->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Results offset. The default value is 0. Use this param to manage pagination.', true)
|
||||
->param('cursor', '', new UID(), 'ID of the bucket used as the starting point for the query, excluding the bucket itself. Should be used for efficient pagination when working with large sets of data.', true)
|
||||
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor.', true)
|
||||
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor, can be either \'before\' or \'after\'.', true)
|
||||
->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
@@ -224,8 +224,8 @@ App::put('/v1/storage/buckets/:bucketId')
|
||||
->param('bucketId', '', new UID(), 'Bucket unique ID.')
|
||||
->param('name', null, new Text(128), 'Bucket name', false)
|
||||
->param('permission', null, new WhiteList(['file', 'bucket']), 'Permissions type model to use for reading files in this bucket. You can use bucket-level permission set once on the bucket using the `read` and `write` params, or you can set file-level permission where each file read and write params will decide who has access to read and write to each file individually. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||
->param('read', null, new Permissions(), 'An array of strings with read permissions. By default inherits the existing read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('write', null, new Permissions(), 'An array of strings with write permissions. By default inherits the existing write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('read', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with read permissions. By default inherits the existing read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('write', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with write permissions. By default inherits the existing write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true)
|
||||
->param('maximumFileSize', null, new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human((int)App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '. For self hosted version you can change the limit by changing _APP_STORAGE_LIMIT environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)', true)
|
||||
->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true)
|
||||
@@ -342,8 +342,8 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
||||
->param('bucketId', null, new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](/docs/server/storage#createBucket).')
|
||||
->param('fileId', '', new CustomId(), 'File 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('file', [], new File(), 'Binary file.', false)
|
||||
->param('read', null, new Permissions(), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('write', null, new Permissions(), 'An array of strings with write permissions. By default only the current user is granted with write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('read', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('write', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with write permissions. By default only the current user is granted with write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true)
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
@@ -354,7 +354,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
||||
->inject('mode')
|
||||
->inject('deviceFiles')
|
||||
->inject('deviceLocal')
|
||||
->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) {
|
||||
->action(function (string $bucketId, string $fileId, mixed $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 (
|
||||
@@ -650,7 +650,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
||||
$events
|
||||
->setParam('bucketId', $bucket->getId())
|
||||
->setParam('fileId', $file->getId())
|
||||
->setContext($bucket)
|
||||
->setContext('bucket', $bucket)
|
||||
;
|
||||
|
||||
$metadata = null; // was causing leaks as it was passed by reference
|
||||
@@ -676,7 +676,7 @@ App::get('/v1/storage/buckets/:bucketId/files')
|
||||
->param('limit', 25, new Range(0, 100), 'Maximum number of files to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
|
||||
->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this param to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true)
|
||||
->param('cursor', '', new UID(), 'ID of the file used as the starting point for the query, excluding the file itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true)
|
||||
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor.', true)
|
||||
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor, can be either \'before\' or \'after\'.', true)
|
||||
->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
@@ -1288,8 +1288,8 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
|
||||
->label('sdk.response.model', Response::MODEL_FILE)
|
||||
->param('bucketId', null, new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](/docs/server/storage#createBucket).')
|
||||
->param('fileId', '', new UID(), 'File unique ID.')
|
||||
->param('read', null, new Permissions(), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('write', null, new Permissions(), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('read', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true)
|
||||
->param('write', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('user')
|
||||
@@ -1357,7 +1357,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
|
||||
$events
|
||||
->setParam('bucketId', $bucket->getId())
|
||||
->setParam('fileId', $file->getId())
|
||||
->setContext($bucket)
|
||||
->setContext('bucket', $bucket)
|
||||
;
|
||||
|
||||
$audits->setResource('file/' . $file->getId());
|
||||
@@ -1459,7 +1459,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId')
|
||||
$events
|
||||
->setParam('bucketId', $bucket->getId())
|
||||
->setParam('fileId', $file->getId())
|
||||
->setContext($bucket)
|
||||
->setContext('bucket', $bucket)
|
||||
->setPayload($response->output($file, Response::MODEL_FILE))
|
||||
;
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ App::get('/v1/teams')
|
||||
->param('limit', 25, new Range(0, 100), 'Maximum number of teams to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
|
||||
->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this param to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true)
|
||||
->param('cursor', '', new UID(), 'ID of the team used as the starting point for the query, excluding the team itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true)
|
||||
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor.', true)
|
||||
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor, can be either \'before\' or \'after\'.', true)
|
||||
->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
@@ -451,7 +451,7 @@ App::get('/v1/teams/:teamId/memberships')
|
||||
->param('limit', 25, new Range(0, 100), 'Maximum number of memberships to return in response. By default will return maximum 25 results. Maximum of 100 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 membership used as the starting point for the query, excluding the membership itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true)
|
||||
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor.', true)
|
||||
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor, can be either \'before\' or \'after\'.', true)
|
||||
->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
||||
@@ -326,7 +326,7 @@ App::get('/v1/users')
|
||||
->param('limit', 25, new Range(0, 100), 'Maximum number of users to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
|
||||
->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this param to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true)
|
||||
->param('cursor', '', new UID(), 'ID of the user used as the starting point for the query, excluding the user itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true)
|
||||
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor.', true)
|
||||
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor, can be either \'before\' or \'after\'.', true)
|
||||
->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
||||
@@ -19,6 +19,7 @@ use Appwrite\Network\Validator\Origin;
|
||||
use Appwrite\Utopia\Response\Filters\V11 as ResponseV11;
|
||||
use Appwrite\Utopia\Response\Filters\V12 as ResponseV12;
|
||||
use Appwrite\Utopia\Response\Filters\V13 as ResponseV13;
|
||||
use Appwrite\Utopia\Response\Filters\V14 as ResponseV14;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
@@ -177,6 +178,9 @@ App::init(function (App $utopia, Request $request, Response $response, Document
|
||||
case version_compare($responseFormat, '0.13.4', '<='):
|
||||
Response::setFilter(new ResponseV13());
|
||||
break;
|
||||
case version_compare($responseFormat, '0.14.0', '<='):
|
||||
Response::setFilter(new ResponseV14());
|
||||
break;
|
||||
default:
|
||||
Response::setFilter(null);
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ App::post('/v1/mock/tests/general/upload')
|
||||
->param('file', [], new File(), 'Sample file param', false)
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->action(function (string $x, int $y, array $z, array $file, Request $request, Response $response) {
|
||||
->action(function (string $x, int $y, array $z, mixed $file, Request $request, Response $response) {
|
||||
|
||||
$file = $request->getFiles('file');
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
use Appwrite\Auth\Auth;
|
||||
use Appwrite\Event\Audit;
|
||||
use Appwrite\Event\Database as EventDatabase;
|
||||
use Appwrite\Event\Delete;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Event\Mail;
|
||||
@@ -18,7 +19,7 @@ use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Registry\Registry;
|
||||
|
||||
App::init(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Event $events, Audit $audits, Mail $mails, Stats $usage, Delete $deletes, Event $database, Database $dbForProject, string $mode) {
|
||||
App::init(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Event $events, Audit $audits, Mail $mails, Stats $usage, Delete $deletes, EventDatabase $database, Database $dbForProject, string $mode) {
|
||||
|
||||
$route = $utopia->match($request);
|
||||
|
||||
@@ -164,7 +165,7 @@ App::init(function (App $utopia, Request $request, Document $project) {
|
||||
}
|
||||
}, ['utopia', 'request', 'project'], 'auth');
|
||||
|
||||
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) {
|
||||
App::shutdown(function (App $utopia, Request $request, Response $response, Document $project, Event $events, Audit $audits, Stats $usage, Delete $deletes, EventDatabase $database, string $mode, Database $dbForProject) {
|
||||
|
||||
if (!empty($events->getEvent())) {
|
||||
if (empty($events->getPayload())) {
|
||||
@@ -192,16 +193,17 @@ App::shutdown(function (App $utopia, Request $request, Response $response, Docum
|
||||
if ($project->getId() !== 'console') {
|
||||
$allEvents = Event::generateEvents($events->getEvent(), $events->getParams());
|
||||
$payload = new Document($events->getPayload());
|
||||
$context = $events->getContext() ?? false;
|
||||
|
||||
$collection = ($context && $context->getCollection() === 'collections') ? $context : null;
|
||||
$bucket = ($context && $context->getCollection() === 'buckets') ? $context : null;
|
||||
$db = $events->getContext('database');
|
||||
$collection = $events->getContext('collection');
|
||||
$bucket = $events->getContext('bucket');
|
||||
|
||||
$target = Realtime::fromPayload(
|
||||
// Pass first, most verbose event pattern
|
||||
event: $allEvents[0],
|
||||
payload: $payload,
|
||||
project: $project,
|
||||
database: $db,
|
||||
collection: $collection,
|
||||
bucket: $bucket,
|
||||
);
|
||||
|
||||
@@ -215,21 +215,56 @@ App::get('/console/keys')
|
||||
->setParam('body', $page);
|
||||
});
|
||||
|
||||
App::get('/console/database')
|
||||
App::get('/console/databases')
|
||||
->groups(['web', 'console'])
|
||||
->label('permission', 'public')
|
||||
->label('scope', 'console')
|
||||
->inject('layout')
|
||||
->action(function (View $layout) {
|
||||
|
||||
$page = new View(__DIR__ . '/../../views/console/database/index.phtml');
|
||||
$page = new View(__DIR__ . '/../../views/console/databases/index.phtml');
|
||||
|
||||
$layout
|
||||
->setParam('title', APP_NAME . ' - Database')
|
||||
->setParam('body', $page);
|
||||
});
|
||||
|
||||
App::get('/console/database/collection')
|
||||
App::get('/console/databases/database')
|
||||
->groups(['web', 'console'])
|
||||
->label('permission', 'public')
|
||||
->label('scope', 'console')
|
||||
->param('id', '', new UID(), 'Database unique ID.')
|
||||
->inject('response')
|
||||
->inject('layout')
|
||||
->action(function (string $id, Response $response, View $layout) {
|
||||
|
||||
$logs = new View(__DIR__ . '/../../views/console/comps/logs.phtml');
|
||||
|
||||
$logs
|
||||
->setParam('interval', App::getEnv('_APP_MAINTENANCE_RETENTION_AUDIT', 0))
|
||||
->setParam('method', 'database.listLogs')
|
||||
->setParam('params', [
|
||||
'database-id' => '{{router.params.id}}',
|
||||
])
|
||||
;
|
||||
|
||||
$page = new View(__DIR__ . '/../../views/console/databases/database.phtml');
|
||||
|
||||
$page->setParam('logs', $logs);
|
||||
|
||||
$layout
|
||||
->setParam('title', APP_NAME . ' - Database')
|
||||
->setParam('body', $page)
|
||||
;
|
||||
|
||||
$response
|
||||
->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
|
||||
->addHeader('Expires', 0)
|
||||
->addHeader('Pragma', 'no-cache')
|
||||
;
|
||||
});
|
||||
|
||||
App::get('/console/databases/collection')
|
||||
->groups(['web', 'console'])
|
||||
->label('permission', 'public')
|
||||
->label('scope', 'console')
|
||||
@@ -242,13 +277,14 @@ App::get('/console/database/collection')
|
||||
|
||||
$logs
|
||||
->setParam('interval', App::getEnv('_APP_MAINTENANCE_RETENTION_AUDIT', 0))
|
||||
->setParam('method', 'database.listCollectionLogs')
|
||||
->setParam('method', 'databases.listCollectionLogs')
|
||||
->setParam('params', [
|
||||
'collection-id' => '{{router.params.id}}',
|
||||
'database-id' => '{{router.params.databaseId}}'
|
||||
])
|
||||
;
|
||||
|
||||
$page = new View(__DIR__ . '/../../views/console/database/collection.phtml');
|
||||
$page = new View(__DIR__ . '/../../views/console/databases/collection.phtml');
|
||||
|
||||
$page->setParam('logs', $logs);
|
||||
|
||||
@@ -264,29 +300,32 @@ App::get('/console/database/collection')
|
||||
;
|
||||
});
|
||||
|
||||
App::get('/console/database/document')
|
||||
App::get('/console/databases/document')
|
||||
->groups(['web', 'console'])
|
||||
->label('permission', 'public')
|
||||
->label('scope', 'console')
|
||||
->param('databaseId', '', new UID(), 'Database unique ID.')
|
||||
->param('collection', '', new UID(), 'Collection unique ID.')
|
||||
->inject('layout')
|
||||
->action(function (string $collection, View $layout) {
|
||||
->action(function (string $databaseId, string $collection, View $layout) {
|
||||
|
||||
$logs = new View(__DIR__ . '/../../views/console/comps/logs.phtml');
|
||||
|
||||
$logs
|
||||
->setParam('interval', App::getEnv('_APP_MAINTENANCE_RETENTION_AUDIT', 0))
|
||||
->setParam('method', 'database.listDocumentLogs')
|
||||
->setParam('method', 'databases.listDocumentLogs')
|
||||
->setParam('params', [
|
||||
'database-id' => '{{router.params.databaseId}}',
|
||||
'collection-id' => '{{router.params.collection}}',
|
||||
'document-id' => '{{router.params.id}}',
|
||||
])
|
||||
;
|
||||
|
||||
$page = new View(__DIR__ . '/../../views/console/database/document.phtml');
|
||||
$page = new View(__DIR__ . '/../../views/console/databases/document.phtml');
|
||||
|
||||
$page
|
||||
->setParam('new', false)
|
||||
->setParam('database', $databaseId)
|
||||
->setParam('collection', $collection)
|
||||
->setParam('logs', $logs)
|
||||
;
|
||||
@@ -296,18 +335,20 @@ App::get('/console/database/document')
|
||||
->setParam('body', $page);
|
||||
});
|
||||
|
||||
App::get('/console/database/document/new')
|
||||
App::get('/console/databases/document/new')
|
||||
->groups(['web', 'console'])
|
||||
->label('permission', 'public')
|
||||
->label('scope', 'console')
|
||||
->param('databaseId', '', new UID(), 'Database unique ID.')
|
||||
->param('collection', '', new UID(), 'Collection unique ID.')
|
||||
->inject('layout')
|
||||
->action(function (string $collection, View $layout) {
|
||||
->action(function (string $databaseId, string $collection, View $layout) {
|
||||
|
||||
$page = new View(__DIR__ . '/../../views/console/database/document.phtml');
|
||||
$page = new View(__DIR__ . '/../../views/console/databases/document.phtml');
|
||||
|
||||
$page
|
||||
->setParam('new', true)
|
||||
->setParam('database', $databaseId)
|
||||
->setParam('collection', $collection)
|
||||
->setParam('logs', new View())
|
||||
;
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -118,6 +118,13 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) {
|
||||
if (!$dbForConsole->getCollection($key)->isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
/**
|
||||
* Skip to prevent 0.15 migration issues.
|
||||
*/
|
||||
if ($key === 'databases' && $dbForConsole->exists(App::getEnv('_APP_DB_SCHEMA', 'appwrite'), 'collections')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Console::success('[Setup] - Creating collection: ' . $collection['$id'] . '...');
|
||||
|
||||
$attributes = [];
|
||||
|
||||
+15
-7
@@ -27,6 +27,8 @@ use Appwrite\Auth\Phone\Mock;
|
||||
use Appwrite\Auth\Phone\Telesign;
|
||||
use Appwrite\Auth\Phone\TextMagic;
|
||||
use Appwrite\Auth\Phone\Twilio;
|
||||
use Appwrite\Auth\Phone\Msg91;
|
||||
use Appwrite\Auth\Phone\Vonage;
|
||||
use Appwrite\DSN\DSN;
|
||||
use Appwrite\Event\Audit;
|
||||
use Appwrite\Event\Database as EventDatabase;
|
||||
@@ -84,9 +86,10 @@ 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_ARRAY_ELEMENT_SIZE = 4096; // Default maximum length of element in array parameter represented by maximum URL length.
|
||||
const APP_LIMIT_SUBQUERY = 1000;
|
||||
const APP_CACHE_BUSTER = 400;
|
||||
const APP_VERSION_STABLE = '0.15.0';
|
||||
const APP_CACHE_BUSTER = 402;
|
||||
const APP_VERSION_STABLE = '0.15.2';
|
||||
const APP_DATABASE_ATTRIBUTE_EMAIL = 'email';
|
||||
const APP_DATABASE_ATTRIBUTE_ENUM = 'enum';
|
||||
const APP_DATABASE_ATTRIBUTE_IP = 'ip';
|
||||
@@ -124,6 +127,7 @@ const DATABASE_TYPE_DELETE_INDEX = 'deleteIndex';
|
||||
const BUILD_TYPE_DEPLOYMENT = 'deployment';
|
||||
const BUILD_TYPE_RETRY = 'retry';
|
||||
// Deletion Types
|
||||
const DELETE_TYPE_DATABASES = 'databases';
|
||||
const DELETE_TYPE_DOCUMENT = 'document';
|
||||
const DELETE_TYPE_COLLECTIONS = 'collections';
|
||||
const DELETE_TYPE_PROJECTS = 'projects';
|
||||
@@ -263,8 +267,9 @@ Database::addFilter(
|
||||
function (mixed $value, Document $document, Database $database) {
|
||||
return $database
|
||||
->find('attributes', [
|
||||
new Query('collectionInternalId', Query::TYPE_EQUAL, [$document->getInternalId()])
|
||||
], $database->getAttributeLimit());
|
||||
new Query('collectionInternalId', Query::TYPE_EQUAL, [$document->getInternalId()]),
|
||||
new Query('databaseInternalId', Query::TYPE_EQUAL, [$document->getAttribute('databaseInternalId')])
|
||||
], $database->getAttributeLimit(), 0, []);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -276,7 +281,8 @@ Database::addFilter(
|
||||
function (mixed $value, Document $document, Database $database) {
|
||||
return $database
|
||||
->find('indexes', [
|
||||
new Query('collectionInternalId', Query::TYPE_EQUAL, [$document->getInternalId()])
|
||||
new Query('collectionInternalId', Query::TYPE_EQUAL, [$document->getInternalId()]),
|
||||
new Query('databaseInternalId', Query::TYPE_EQUAL, [$document->getAttribute('databaseInternalId')])
|
||||
], 64);
|
||||
}
|
||||
);
|
||||
@@ -433,7 +439,7 @@ Structure::addFormat(APP_DATABASE_ATTRIBUTE_FLOAT_RANGE, function ($attribute) {
|
||||
* Registry
|
||||
*/
|
||||
$register->set('logger', function () {
|
||||
// Register error logger
|
||||
// Register error logger
|
||||
$providerName = App::getEnv('_APP_LOGGING_PROVIDER', '');
|
||||
$providerConfig = App::getEnv('_APP_LOGGING_CONFIG', '');
|
||||
|
||||
@@ -553,7 +559,7 @@ $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-06.mmdb');
|
||||
});
|
||||
$register->set('db', function () {
|
||||
// This is usually for our workers or CLI commands scope
|
||||
@@ -986,6 +992,8 @@ App::setResource('phone', function () {
|
||||
'twilio' => new Twilio($user, $secret),
|
||||
'text-magic' => new TextMagic($user, $secret),
|
||||
'telesign' => new Telesign($user, $secret),
|
||||
'msg91' => new Msg91($user, $secret),
|
||||
'vonage' => new Vonage($user, $secret),
|
||||
default => null
|
||||
};
|
||||
});
|
||||
|
||||
+31
-21
@@ -112,8 +112,9 @@ function getDatabase(Registry &$register, string $namespace)
|
||||
if (!$database->exists($database->getDefaultDatabase(), 'realtime')) {
|
||||
throw new Exception('Collection not ready');
|
||||
}
|
||||
|
||||
break; // leave loop if successful
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Throwable $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());
|
||||
@@ -138,25 +139,30 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume
|
||||
/**
|
||||
* Create document for this worker to share stats across Containers.
|
||||
*/
|
||||
go(function () use ($register, $containerId, &$statsDocument, $logError) {
|
||||
try {
|
||||
[$database, $returnDatabase] = getDatabase($register, '_console');
|
||||
$document = new Document([
|
||||
'$id' => $database->getId(),
|
||||
'$collection' => 'realtime',
|
||||
'$read' => [],
|
||||
'$write' => [],
|
||||
'container' => $containerId,
|
||||
'timestamp' => time(),
|
||||
'value' => '{}'
|
||||
]);
|
||||
go(function () use ($register, $containerId, &$statsDocument) {
|
||||
$attempts = 0;
|
||||
[$database, $returnDatabase] = getDatabase($register, '_console');
|
||||
do {
|
||||
try {
|
||||
$attempts++;
|
||||
$document = new Document([
|
||||
'$id' => $database->getId(),
|
||||
'$collection' => 'realtime',
|
||||
'$read' => [],
|
||||
'$write' => [],
|
||||
'container' => $containerId,
|
||||
'timestamp' => time(),
|
||||
'value' => '{}'
|
||||
]);
|
||||
|
||||
$statsDocument = Authorization::skip(fn () => $database->createDocument('realtime', $document));
|
||||
} catch (\Throwable $th) {
|
||||
call_user_func($logError, $th, "createWorkerDocument");
|
||||
} finally {
|
||||
call_user_func($returnDatabase);
|
||||
}
|
||||
$statsDocument = Authorization::skip(fn () => $database->createDocument('realtime', $document));
|
||||
break;
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("Collection not ready. Retrying connection ({$attempts})...");
|
||||
sleep(DATABASE_RECONNECT_SLEEP);
|
||||
}
|
||||
} while (true);
|
||||
call_user_func($returnDatabase);
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -485,8 +491,12 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re
|
||||
$database = new Database(new MariaDB($db), $cache);
|
||||
$database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
|
||||
$database->setNamespace("_console");
|
||||
$project = Authorization::skip(fn() => $database->getDocument('projects', $realtime->connections[$connection]['projectId']));
|
||||
$database->setNamespace("_{$project->getInternalId()}");
|
||||
$projectId = $realtime->connections[$connection]['projectId'];
|
||||
|
||||
if ($projectId !== 'console') {
|
||||
$project = Authorization::skip(fn() => $database->getDocument('projects', $projectId));
|
||||
$database->setNamespace("_{$project->getInternalId()}");
|
||||
}
|
||||
|
||||
/*
|
||||
* Abuse Check
|
||||
|
||||
@@ -173,6 +173,16 @@ $cli
|
||||
if (empty($input[$var['name']])) {
|
||||
$input[$var['name']] = $var['default'];
|
||||
}
|
||||
|
||||
if ($var['filter'] === 'domainTarget') {
|
||||
if ($input[$var['name']] !== 'localhost') {
|
||||
Console::warning("\nIf you haven't already done so, set the following record for {$input[$var['name']]} on your DNS provider:\n");
|
||||
$mask = "%-15.15s %-10.10s %-30.30s\n";
|
||||
printf($mask, "Type", "Name", "Value");
|
||||
printf($mask, "A or AAAA", "@", "<YOUR PUBLIC IP>");
|
||||
Console::warning("\nUse 'AAAA' if you're using an IPv6 address and 'A' if you're using an IPv4 address.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$templateForCompose = new View(__DIR__ . '/../views/install/compose.phtml');
|
||||
|
||||
@@ -28,9 +28,9 @@ $cli
|
||||
Console::success('Starting Data Migration to version ' . $version);
|
||||
|
||||
$db = $register->get('db', true);
|
||||
$cache = $register->get('cache', true);
|
||||
|
||||
$cache = new Cache(new RedisCache($cache));
|
||||
$redis = $register->get('cache', true);
|
||||
$redis->flushAll();
|
||||
$cache = new Cache(new RedisCache($redis));
|
||||
|
||||
$projectDB = new Database(new MariaDB($db), $cache);
|
||||
$projectDB->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
|
||||
@@ -79,5 +79,6 @@ $cli
|
||||
}
|
||||
|
||||
Swoole\Event::wait(); // Wait for Coroutines to finish
|
||||
$redis->flushAll();
|
||||
Console::success('Data Migration Completed');
|
||||
});
|
||||
|
||||
+74
-84
@@ -123,104 +123,94 @@ $cli
|
||||
],
|
||||
];
|
||||
|
||||
foreach (['swagger2', 'open-api3'] as $format) {
|
||||
foreach ($platforms as $platform) {
|
||||
$routes = [];
|
||||
$models = [];
|
||||
$services = [];
|
||||
foreach ($platforms as $platform) {
|
||||
$routes = [];
|
||||
$models = [];
|
||||
$services = [];
|
||||
|
||||
foreach ($appRoutes as $key => $method) {
|
||||
foreach ($method as $route) {
|
||||
/** @var \Utopia\Route $route */
|
||||
$routeSecurity = $route->getLabel('sdk.auth', []);
|
||||
$sdkPlatofrms = [];
|
||||
foreach ($appRoutes as $key => $method) {
|
||||
foreach ($method as $route) {
|
||||
/** @var \Utopia\Route $route */
|
||||
$routeSecurity = $route->getLabel('sdk.auth', []);
|
||||
$sdkPlaforms = [];
|
||||
|
||||
foreach ($routeSecurity as $value) {
|
||||
switch ($value) {
|
||||
case APP_AUTH_TYPE_SESSION:
|
||||
$sdkPlatofrms[] = APP_PLATFORM_CLIENT;
|
||||
break;
|
||||
case APP_AUTH_TYPE_KEY:
|
||||
$sdkPlatofrms[] = APP_PLATFORM_SERVER;
|
||||
break;
|
||||
case APP_AUTH_TYPE_JWT:
|
||||
$sdkPlatofrms[] = APP_PLATFORM_SERVER;
|
||||
break;
|
||||
case APP_AUTH_TYPE_ADMIN:
|
||||
$sdkPlatofrms[] = APP_PLATFORM_CONSOLE;
|
||||
break;
|
||||
}
|
||||
foreach ($routeSecurity as $value) {
|
||||
switch ($value) {
|
||||
case APP_AUTH_TYPE_SESSION:
|
||||
$sdkPlaforms[] = APP_PLATFORM_CLIENT;
|
||||
break;
|
||||
case APP_AUTH_TYPE_KEY:
|
||||
$sdkPlaforms[] = APP_PLATFORM_SERVER;
|
||||
break;
|
||||
case APP_AUTH_TYPE_JWT:
|
||||
$sdkPlaforms[] = APP_PLATFORM_SERVER;
|
||||
break;
|
||||
case APP_AUTH_TYPE_ADMIN:
|
||||
$sdkPlaforms[] = APP_PLATFORM_CONSOLE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (empty($routeSecurity)) {
|
||||
$sdkPlatofrms[] = APP_PLATFORM_CLIENT;
|
||||
}
|
||||
|
||||
if (!$route->getLabel('docs', true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($route->getLabel('sdk.mock', false) && !$mocks) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$route->getLabel('sdk.mock', false) && $mocks) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (empty($route->getLabel('sdk.namespace', null))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($platform !== APP_PLATFORM_CONSOLE && !\in_array($platforms[$platform], $sdkPlatofrms)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$routes[] = $route;
|
||||
$modelLabel = $route->getLabel('sdk.response.model', 'none');
|
||||
\is_array($modelLabel) ? \array_map(function ($m) use ($response) {
|
||||
return $response->getModel($m);
|
||||
}, $modelLabel) : $response->getModel($modelLabel);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Config::getParam('services', []) as $service) {
|
||||
if (
|
||||
!isset($service['docs']) // Skip service if not part of the public API
|
||||
|| !isset($service['sdk'])
|
||||
|| !$service['docs']
|
||||
|| !$service['sdk']
|
||||
) {
|
||||
if (empty($routeSecurity)) {
|
||||
$sdkPlaforms[] = APP_PLATFORM_CLIENT;
|
||||
}
|
||||
|
||||
if (!$route->getLabel('docs', true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$services[] = [
|
||||
'name' => $service['key'] ?? '',
|
||||
'description' => $service['subtitle'] ?? '',
|
||||
];
|
||||
}
|
||||
|
||||
$models = $response->getModels();
|
||||
|
||||
foreach ($models as $key => $value) {
|
||||
if ($platform !== APP_PLATFORM_CONSOLE && !$value->isPublic()) {
|
||||
unset($models[$key]);
|
||||
if ($route->getLabel('sdk.mock', false) && !$mocks) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$route->getLabel('sdk.mock', false) && $mocks) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (empty($route->getLabel('sdk.namespace', null))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($platform !== APP_PLATFORM_CONSOLE && !\in_array($platforms[$platform], $sdkPlaforms)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$routes[] = $route;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Config::getParam('services', []) as $service) {
|
||||
if (
|
||||
!isset($service['docs']) // Skip service if not part of the public API
|
||||
|| !isset($service['sdk'])
|
||||
|| !$service['docs']
|
||||
|| !$service['sdk']
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ($format) {
|
||||
case 'swagger2':
|
||||
$formatInstance = new Swagger2(new App('UTC'), $services, $routes, $models, $keys[$platform], $authCounts[$platform] ?? 0);
|
||||
break;
|
||||
$services[] = [
|
||||
'name' => $service['key'] ?? '',
|
||||
'description' => $service['subtitle'] ?? '',
|
||||
'x-globalAttributes' => $service['globalAttributes'] ?? [],
|
||||
];
|
||||
}
|
||||
|
||||
case 'open-api3':
|
||||
$formatInstance = new OpenAPI3(new App('UTC'), $services, $routes, $models, $keys[$platform], $authCounts[$platform] ?? 0);
|
||||
break;
|
||||
$models = $response->getModels();
|
||||
|
||||
default:
|
||||
throw new Exception('Format not found: ' . $format);
|
||||
break;
|
||||
foreach ($models as $key => $value) {
|
||||
if ($platform !== APP_PLATFORM_CONSOLE && !$value->isPublic()) {
|
||||
unset($models[$key]);
|
||||
}
|
||||
}
|
||||
// var_dump($models);
|
||||
$arguments = [new App('UTC'), $services, $routes, $models, $keys[$platform], $authCounts[$platform] ?? 0];
|
||||
foreach (['swagger2', 'open-api3'] as $format) {
|
||||
$formatInstance = match ($format) {
|
||||
'swagger2' => new Swagger2(...$arguments),
|
||||
'open-api3' => new OpenAPI3(...$arguments),
|
||||
default => throw new Exception('Format not found: ' . $format)
|
||||
};
|
||||
|
||||
$specs = new Specification($formatInstance);
|
||||
$endpoint = App::getEnv('_APP_HOME', '[HOSTNAME]');
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@ $logError = function (Throwable $error, string $action = 'syncUsageStats') use (
|
||||
$version = App::getEnv('_APP_VERSION', 'UNKNOWN');
|
||||
|
||||
$log = new Log();
|
||||
$log->setNamespace("realtime");
|
||||
$log->setNamespace("usage");
|
||||
$log->setServer(\gethostname());
|
||||
$log->setVersion($version);
|
||||
$log->setType(Log::TYPE_ERROR);
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
|
||||
<ul class="links">
|
||||
<li>
|
||||
<a data-ls-attrs="href=/console/database?project={{router.params.project}}"
|
||||
<a data-ls-attrs="href=/console/databases?project={{router.params.project}}"
|
||||
data-analytics
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console/navigation"
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
<?php
|
||||
$key = $this->getParam('key', '');
|
||||
$type = $this->getParam('type', '');
|
||||
$required = $this->getParam('required', '');
|
||||
$comp = $this->getParam('comp', '');
|
||||
$namespace = $this->getParam('namespace', '');
|
||||
$list = $this->getParam('list', []);
|
||||
$collections = $this->getParam('collections', []);
|
||||
|
||||
$comp->setParam('namespace', 'node');
|
||||
|
||||
if($type === 'document') {
|
||||
$comp->setParam('key', null);
|
||||
}
|
||||
?>
|
||||
|
||||
<input type="hidden" name="<?php echo $this->escape($key); ?>"<?php if($required): ?> required<?php endif; ?> data-cast-to="array-empty">
|
||||
|
||||
<hr />
|
||||
|
||||
<ul data-ls-loop="<?php echo $this->escape($namespace); ?>" data-ls-as="node" class="sortable numbers">
|
||||
<li data-forms-move-up data-forms-move-down>
|
||||
<div class="drop-list bottom end settings" data-ls-ui-open="" data-button-text="" data-button-icon="icon-cog" data-button-aria="Options" data-button-selector="[data-toggler]" data-button-class="round dark small margin-bottom-small margin-top-tiny pull-end" data-blur="1">
|
||||
<ul class="arrow-end margin-top margin-end-negative-small">
|
||||
<li data-move-up>
|
||||
<button type="button" class="link"><i class="icon-up-dir"></i> Move Up</button>
|
||||
</li>
|
||||
<li data-move-down>
|
||||
<button type="button" class="link"><i class="icon-down-dir"></i> Move Down</button>
|
||||
</li>
|
||||
<li>
|
||||
<button type="button" data-ls-ui-trigger="splice-<?php echo $this->escape($namespace); ?>-{{$index}}" class="link"><i class="icon-cancel"></i> Remove</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<?php echo $comp->render(); ?>
|
||||
|
||||
<hr />
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<?php if(!empty($list) && $type === 'document'): ?>
|
||||
<div class="drop-list" data-ls-ui-open="" data-button-text="Add" data-button-aria="Add" data-button-icon="" data-button-selector="[data-toggler]" data-button-class="reverse margin-bottom-small" data-blur="1">
|
||||
<ul>
|
||||
<?php foreach($list as $item):
|
||||
$name = (isset($collections[$item])) ? $collections[$item]->getAttribute('name', '') : '';
|
||||
?>
|
||||
<li>
|
||||
<button type="button" class="link" data-ls-ui-trigger="collection-child-<?php echo $this->escape($namespace); ?>-<?php echo $this->escape($item); ?>"><i class="icon-edit"></i> Add <?php echo $this->escape($name); ?></button>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<button type="button" data-ls-ui-trigger="collection-child-<?php echo $this->escape($namespace); ?>" class="reverse margin-bottom-small">Add</button>
|
||||
<?php endif; ?>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?php
|
||||
$key = $this->getParam('key', '');
|
||||
$required = $this->getParam('required', '');
|
||||
$namespace = $this->getParam('namespace', '');
|
||||
?>
|
||||
|
||||
<input name="<?php echo $this->escape($key); ?>" type="hidden" data-forms-switch data-ls-bind="{{<?php echo $this->escape($namespace); ?>}}" data-cast-to="boolean"<?php if($required): ?> required<?php endif; ?> class="margin-bottom-no" />
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
$namespace = $this->getParam('namespace', '');
|
||||
$array = $this->getParam('array', false);
|
||||
$list = $this->getParam('list', []);
|
||||
$list = (is_array($list)) ? $list : [];
|
||||
$list = ($array) ? $list : array_shift($list);
|
||||
?>
|
||||
|
||||
<?php if($array): ?>
|
||||
<div data-ls-template="collection-array-{{<?php echo $this->escape($namespace); ?>.$collection}}" data-type="script" class="margin-bottom-negative-small"></div>
|
||||
<?php else: ?>
|
||||
<hr class="margin-top-no" />
|
||||
<div class="clear">
|
||||
<a data-ls-if="(!{{<?php echo $this->escape($namespace); ?>.$id}})" data-ls-attrs="href=/console/database/document?&collection=<?php echo $this->escape($list); ?>&project={{router.params.project}}" class="pull-end text-size-small">New Document <i class="icon-link-ext"></i></a>
|
||||
<a data-ls-if="({{<?php echo $this->escape($namespace); ?>.$id}})" data-ls-attrs="href=/console/database/document?id={{<?php echo $this->escape($namespace); ?>.$id}}&collection=<?php echo $this->escape($list); ?>&project={{router.params.project}}" class="pull-end text-size-small"><span data-ls-bind="Document #{{<?php echo $this->escape($namespace); ?>.$id}}"></span> <i class="icon-link-ext"></i></a>
|
||||
</div>
|
||||
<div data-ls-template="collection-<?php echo $this->escape($list); ?>" data-type="script" class="margin-bottom-negative-small"></div>
|
||||
<hr />
|
||||
<?php endif; ?>
|
||||
@@ -1,57 +0,0 @@
|
||||
<?php
|
||||
$key = $this->getParam('key', '');
|
||||
$required = $this->getParam('required', '');
|
||||
$namespace = $this->getParam('namespace', '');
|
||||
$collections = $this->getParam('collections', []);
|
||||
$array = $this->getParam('array', false);
|
||||
$list = $this->getParam('list', []);
|
||||
$list = (is_array($list)) ? $list : [];
|
||||
?>
|
||||
|
||||
<?php foreach($list as $item):
|
||||
$collection = $collections[$item] ?? null;
|
||||
|
||||
if(empty($collection)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$rules = $collection->getAttribute('rules', []);
|
||||
?>
|
||||
|
||||
|
||||
<div data-ls-if="({{<?php echo $this->escape($namespace); ?>}})"
|
||||
data-service="database.getDocument"
|
||||
data-param-collection-id="<?php echo $this->escape($collection->getId()); ?>"
|
||||
data-param-document-id="{{<?php echo $this->escape($namespace); ?>}}"
|
||||
data-scope="sdk"
|
||||
data-event="load,document-selected-<?php echo $this->escape($collection->getId()); ?>"
|
||||
data-name="project-document-preview"
|
||||
data-success="default">
|
||||
|
||||
<div class="box line margin-bottom-small padding-small fade-bottom">
|
||||
<ul>
|
||||
<?php foreach($rules as $i => $rule):
|
||||
$collectionLabel = $rule['label'] ?? '';
|
||||
$collectionKey = $rule['key'] ?? '';
|
||||
|
||||
if($i === 3) {break;}
|
||||
?>
|
||||
<li class="margin-bottom-small">
|
||||
<p><b><?php echo $this->escape($collectionLabel); ?>: </b> <span data-ls-bind="{{project-document-preview.<?php echo $this->escape($collectionKey); ?>|limit}}" data-unsync="1"></span></p>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<span class="label tag blue">preview</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input
|
||||
type="text" data-forms-document-preview="<?php echo $this->escape($collection->getId()); ?>"
|
||||
name="<?php echo $this->escape($key); ?>"
|
||||
data-ls-bind="{{<?php echo $this->escape($namespace); ?>}}"
|
||||
class="margin-bottom" disabled<?php if($required): ?> required<?php endif; ?>>
|
||||
|
||||
<button class="reverse margin-end-small" type="button"
|
||||
data-forms-document="open-document-serach-<?php echo $this->escape($collection->getId()); ?>"
|
||||
data-search="<?php echo $this->escape($namespace); ?>"><i class="icon-search"></i> <?php echo $this->escape($collection->getAttribute('name')); ?></button>
|
||||
<?php endforeach; ?>
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
$key = $this->getParam('key', '');
|
||||
$required = $this->getParam('required', '');
|
||||
$namespace = $this->getParam('namespace', '');
|
||||
?>
|
||||
<input name="<?php echo $this->escape($key); ?>" type="email" autocomplete="off" data-ls-bind="{{<?php echo $this->escape($namespace); ?>}}" placeholder="me@example.com"<?php if($required): ?> required<?php endif; ?> class="margin-bottom-no">
|
||||
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
$key = $this->getParam('key', '');
|
||||
$required = $this->getParam('required', '');
|
||||
$namespace = $this->getParam('namespace', '');
|
||||
?>
|
||||
<input
|
||||
type="hidden"
|
||||
name="<?php echo $this->escape($key); ?>"
|
||||
data-ls-bind="{{<?php echo $this->escape($namespace); ?>}}"
|
||||
data-read="<?php echo $this->escape(json_encode([])); ?>"
|
||||
data-write="<?php echo $this->escape(json_encode([])); ?>"
|
||||
data-accept=""
|
||||
data-forms-upload=""
|
||||
data-label-button="Upload"
|
||||
data-search="<?php echo $this->escape($namespace); ?>"
|
||||
data-scope="sdk"
|
||||
data-default=""
|
||||
data-project="{{router.params.project}}"
|
||||
<?php if($required): ?> required<?php endif; ?>
|
||||
class="margin-bottom-no">
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
$key = $this->getParam('key', '');
|
||||
$required = $this->getParam('required', '');
|
||||
$namespace = $this->getParam('namespace', '');
|
||||
?>
|
||||
<input name="<?php echo $this->escape($key); ?>" type="text" autocomplete="off" data-ls-bind="{{<?php echo $this->escape($namespace); ?>}}" minlength="7" maxlength="15" size="15" pattern="^((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$" title="Please enter a valid IPV4 address" placeholder="255.255.255.255"<?php if($required): ?> required<?php endif; ?> class="margin-bottom-no">
|
||||
@@ -1,7 +0,0 @@
|
||||
<?php
|
||||
$key = $this->getParam('key', '');
|
||||
$required = $this->getParam('required', '');
|
||||
$namespace = $this->getParam('namespace', '');
|
||||
?>
|
||||
|
||||
<textarea type="text" name="<?php echo $this->escape($key); ?>" data-forms-pell data-forms-text-direction data-ls-bind="{{<?php echo $this->escape($namespace); ?>}}"<?php if($required): ?> required<?php endif; ?>></textarea>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?php
|
||||
$key = $this->getParam('key', '');
|
||||
$required = $this->getParam('required', '');
|
||||
$namespace = $this->getParam('namespace', '');
|
||||
?>
|
||||
|
||||
<input name="<?php echo $this->escape($key); ?>" type="number" autocomplete="off" data-ls-bind="{{<?php echo $this->escape($namespace); ?>}}" data-cast-to="numeric"<?php if($required): ?> required<?php endif; ?> class="margin-bottom-no" step=any />
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
$key = $this->getParam('key', '');
|
||||
$required = $this->getParam('required', '');
|
||||
$namespace = $this->getParam('namespace', '');
|
||||
?>
|
||||
<input name="<?php echo $this->escape($key); ?>" type="text" autocomplete="off" data-ls-bind="{{<?php echo $this->escape($namespace); ?>}}" data-forms-text-direction data-forms-text-count<?php if($required): ?> required<?php endif; ?> />
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
$key = $this->getParam('key', '');
|
||||
$required = $this->getParam('required', '');
|
||||
$namespace = $this->getParam('namespace', '');
|
||||
?>
|
||||
<input name="<?php echo $this->escape($key); ?>" type="url" autocomplete="off" data-ls-bind="{{<?php echo $this->escape($namespace); ?>}}" placeholder="https://example.com"<?php if($required): ?> required<?php endif; ?> />
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
$key = $this->getParam('key', '');
|
||||
$required = $this->getParam('required', '');
|
||||
$namespace = $this->getParam('namespace', '');
|
||||
?>
|
||||
<textarea name="<?php echo $this->escape($key); ?>" type="text" autocomplete="off" data-ls-bind="{{<?php echo $this->escape($namespace); ?>}}" data-forms-text-direction data-forms-text-count<?php if($required): ?> required<?php endif; ?>></textarea>
|
||||
@@ -1,148 +0,0 @@
|
||||
|
||||
<?php
|
||||
$collection = $this->getParam('collection', []);
|
||||
$id = $collection->getId();
|
||||
$name = $collection->getAttribute('name', 'Collection');
|
||||
$rules = $collection->getAttribute('rules', []);
|
||||
?>
|
||||
|
||||
<div data-ui-modal class="modal sticky-footer width-large box close" data-button-hide="on" data-open-event="open-document-serach-<?php echo $this->escape($id); ?>" data-close-event="none">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
|
||||
<h2><?php echo $this->escape($name); ?> Search</h2>
|
||||
|
||||
<form class="search margin-bottom"
|
||||
data-service="database.listDocuments"
|
||||
data-event="submit"
|
||||
data-param-collection-id="<?php echo $this->escape($id); ?>"
|
||||
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
|
||||
data-param-offset="0"
|
||||
data-param-order-type="DESC"
|
||||
data-scope="sdk"
|
||||
data-name="project-documents"
|
||||
data-success="state"
|
||||
data-success-param-state-keys="search,offset">
|
||||
<input name="search" id="searchDocuments-<?php echo $this->escape($id); ?>" type="search" autocomplete="off" placeholder="Search" class="margin-bottom-no" data-ls-bind="{{router.params.search}}">
|
||||
</form>
|
||||
|
||||
<div
|
||||
data-service="database.listDocuments"
|
||||
data-event="open-document-serach-<?php echo $this->escape($id); ?>"
|
||||
data-param-collection-id="<?php echo $this->escape($id); ?>"
|
||||
data-param-search="{{router.params.search}}"
|
||||
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
|
||||
data-param-offset="0"
|
||||
data-param-order-type="DESC"
|
||||
data-scope="sdk"
|
||||
data-name="project-documents">
|
||||
|
||||
<div data-ls-if="0 == {{project-documents.total}}" class="margin-bottom">
|
||||
<h3 class="margin-bottom-small text-bold">No Documents Found</h3>
|
||||
|
||||
<p class="margin-bottom-no">Try a different search term.</p>
|
||||
</div>
|
||||
|
||||
<div data-ls-if="({{project-documents.total}})">
|
||||
<form class="scroll">
|
||||
<table class="margin-top-no margin-bottom-no">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="40"> </th>
|
||||
<?php foreach($rules as $rule):
|
||||
$label = $rule['label'] ?? '';
|
||||
?>
|
||||
<th width="120"><?php echo $this->escape($label); ?></th>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-ls-loop="project-documents.documents" data-ls-as="node">
|
||||
<tr>
|
||||
<td data-title="x" class="">
|
||||
<!-- <input type="radio" name="selected" data-ls-attrs="value={{file.$id}}" data-ls-bind="{{search.selected}}" /> -->
|
||||
<input type="radio" name="selected" data-ls-attrs="value={{node.$id}}" data-ls-bind="{{search.selected}}" />
|
||||
</td>
|
||||
<?php foreach($rules as $rule):
|
||||
$label = $rule['label'] ?? '';
|
||||
$key = $rule['key'] ?? '';
|
||||
$type = $rule['type'] ?? '';
|
||||
$array = $rule['array'] ?? '';
|
||||
?>
|
||||
<td data-title="<?php echo $this->escape($label); ?>" class="text-size-small text-height-small">
|
||||
<a data-ls-attrs="href=/console/database/document?id={{node.$id}}&collection=<?php echo $this->escape($id); ?>&project={{router.params.project}}" target="_blank">
|
||||
<?php if(!$array): ?>
|
||||
<?php switch($type):
|
||||
case 'fileId': ?>
|
||||
<img data-ls-if="{{node.<?php echo $this->escape($key); ?>}} != ''" src="" data-ls-attrs="src={{env.ENDPOINT}}/v1/storage/files/{{node.<?php echo $this->escape($key); ?>}}/preview?width=65&height=65&project={{router.params.project}}&mode=admin" class="avatar" width="30" height="30" loading="lazy" />
|
||||
<?php break; ?>
|
||||
<?php case 'document': ?>
|
||||
{...}
|
||||
<?php break; ?>
|
||||
<?php default: ?>
|
||||
<span data-ls-bind="{{node.<?php echo $this->escape($key); ?>}}" data-ls-attrs="title={{node.<?php echo $this->escape($key); ?>}}"></span>
|
||||
<?php break; ?>
|
||||
<?php endswitch; ?>
|
||||
<?php else: ?>
|
||||
[...]
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
</td>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<div class="clear text-align-center paging pull-end">
|
||||
<form
|
||||
data-service="database.listDocuments"
|
||||
data-event="submit"
|
||||
data-param-collection-id="<?php echo $this->escape($id); ?>"
|
||||
data-param-search="{{router.params.search}}"
|
||||
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
|
||||
data-param-order-type="DESC"
|
||||
data-scope="sdk"
|
||||
data-name="project-documents"
|
||||
data-success="state"
|
||||
data-success-param-state-keys="search,offset">
|
||||
<button name="offset" data-paging-back data-offset="{{router.params.offset}}" data-total="{{project-documents.total}}" class="margin-end round small" aria-label="Back"><i class="icon-left-open"></i></button>
|
||||
</form>
|
||||
|
||||
<span data-ls-bind="{{router.params.offset|pageCurrent}} / {{project-documents.total|pageTotal}}"></span>
|
||||
|
||||
<form
|
||||
data-service="database.listDocuments"
|
||||
data-event="submit"
|
||||
data-param-collection-id="<?php echo $this->escape($id); ?>"
|
||||
data-param-search="{{router.params.search}}"
|
||||
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
|
||||
data-param-order-type="DESC"
|
||||
data-scope="sdk"
|
||||
data-name="project-documents"
|
||||
data-success="state"
|
||||
data-success-param-state-keys="search,offset">
|
||||
<button name="offset" data-paging-next data-offset="{{router.params.offset}}" data-total="{{project-documents.total}}" class="margin-start round small" aria-label="Next"><i class="icon-right-open"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<form data-service="container.path"
|
||||
data-param-path="search.selected"
|
||||
data-param-type="assign"
|
||||
data-param-value="{{node.$id}}"
|
||||
data-success="trigger"
|
||||
data-success-param-trigger-events="modal-close,document-selected-<?php echo $this->escape($id); ?>"
|
||||
data-event="click"
|
||||
data-scope="window.ls">
|
||||
|
||||
<input type="hidden" name="path" data-ls-bind="{{search.path}}" />
|
||||
<input type="hidden" name="type" value="assign" />
|
||||
<input type="hidden" name="value" data-ls-bind="{{search.selected}}" />
|
||||
|
||||
<button data-ls-if="({{search.selected}})" type="button" class="">Select</button>
|
||||
<button data-ls-if="(!{{search.selected}})" type="button" class="" disabled>Select</button>
|
||||
</form>
|
||||
<button data-ui-modal-close="" type="button" class="reverse desktops-only-inline">Cancel</button>
|
||||
</footer>
|
||||
</div>
|
||||
@@ -1,131 +0,0 @@
|
||||
<div data-ui-modal class="modal sticky-footer width-large box close" data-button-hide="on" data-open-event="open-file-serach" data-close-event="none">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
|
||||
<h2>File Search</h2>
|
||||
|
||||
<form class="search margin-bottom"
|
||||
data-service="storage.listFiles"
|
||||
data-event="submit"
|
||||
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
|
||||
data-param-offset=""
|
||||
data-param-order-type="DESC"
|
||||
data-scope="sdk"
|
||||
data-name="project-files"
|
||||
data-success="state"
|
||||
data-success-param-state-keys="search,offset">
|
||||
<input name="search" id="searchFiles" type="search" autocomplete="off" placeholder="Search" class="margin-bottom-no" data-ls-bind="{{router.params.search}}">
|
||||
</form>
|
||||
|
||||
<div
|
||||
data-service="storage.listFiles"
|
||||
data-event="open-file-serach"
|
||||
data-param-search=""
|
||||
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
|
||||
data-param-offset="0"
|
||||
data-param-order-type="DESC"
|
||||
data-scope="sdk"
|
||||
data-name="project-files"
|
||||
data-success="state"
|
||||
data-success-param-state-keys="search,offset">
|
||||
|
||||
<div data-ls-if="0 == {{project-files.total}}" class="margin-bottom">
|
||||
<h3 class="margin-bottom-small text-bold">No Files Found</h3>
|
||||
|
||||
<p class="margin-bottom-no">Try a different search term.</p>
|
||||
</div>
|
||||
|
||||
<div data-ls-if="0 != {{project-files.total}}">
|
||||
<div class="scroll">
|
||||
<table class="margin-top-no margin-bottom-no">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="40"> </th>
|
||||
<th width="40"> </th>
|
||||
<th width="100">Filename</th>
|
||||
<th width="100">Type</th>
|
||||
<th width="100">Size</th>
|
||||
<th width="80">Created</th>
|
||||
<!-- <th width="30"></th> -->
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-ls-loop="project-files.files" data-ls-as="file">
|
||||
<tr>
|
||||
<td data-title="x" class="">
|
||||
<input type="radio" name="selected" data-ls-attrs="value={{file.$id}}" data-ls-bind="{{search.selected}}" />
|
||||
</td>
|
||||
<td data-title="x" class="">
|
||||
<img src="" data-ls-attrs="src={{env.ENDPOINT}}/v1/storage/files/{{file.$id}}/preview?width=65&height=65&project={{router.params.project}}&mode=admin" class="pull-start avatar" width="30" height="30" loading="lazy" />
|
||||
</td>
|
||||
<td data-title="Name: " class="text-one-liner">
|
||||
<span data-ls-bind="{{file.name}}" data-ls-attrs="title={{file.name}}" class="text-fade text-size-small"></span>
|
||||
</td>
|
||||
<td data-title="Type: ">
|
||||
<span data-ls-bind="{{file.mimeType}}" class="text-fade text-size-small"></span>
|
||||
</td>
|
||||
<td data-title="Size: ">
|
||||
<span class="text-fade text-size-small" data-ls-bind="{{file.sizeOriginal|humanFileSize}}"></span>
|
||||
<span class="text-fade text-size-small" data-ls-bind="{{file.sizeOriginal|humanFileUnit}}"></span>
|
||||
</td>
|
||||
<td data-title="Created: ">
|
||||
<span class="text-fade text-size-small" data-ls-bind="{{file.$createdAt|dateText}}"></span>
|
||||
</td>
|
||||
<!-- <td class="hide">
|
||||
<a target="_blank" data-ls-attrs="href="><i class="icon-link-ext"></i></a>
|
||||
</td> -->
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<div class="clear text-align-center paging pull-end">
|
||||
<form
|
||||
data-service="storage.listFiles"
|
||||
data-event="submit"
|
||||
data-param-search="{{router.params.search}}"
|
||||
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
|
||||
data-param-order-type="DESC"
|
||||
data-scope="sdk"
|
||||
data-name="project-files"
|
||||
data-success="state"
|
||||
data-success-param-state-keys="search,offset">
|
||||
<button name="offset" data-paging-back data-offset="{{router.params.offset}}" data-total="{{project-files.total}}" class="margin-end-small round small" aria-label="Back"><i class="icon-left-open"></i></button>
|
||||
</form>
|
||||
|
||||
<span data-ls-bind="{{router.params.offset|pageCurrent}} / {{project-files.total|pageTotal}}"></span>
|
||||
|
||||
<form
|
||||
data-service="storage.listFiles"
|
||||
data-event="submit"
|
||||
data-param-search="{{router.params.search}}"
|
||||
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
|
||||
data-param-order-type="DESC"
|
||||
data-scope="sdk"
|
||||
data-name="project-files"
|
||||
data-success="state"
|
||||
data-success-param-state-keys="search,offset">
|
||||
<button name="offset" data-paging-next data-offset="{{router.params.offset}}" data-total="{{project-files.total}}" class="margin-start-small round small" aria-label="Next"><i class="icon-right-open"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<form data-service="container.path"
|
||||
data-param-path="search.selected"
|
||||
data-param-type="assign"
|
||||
data-param-value="{{file.$id}}"
|
||||
data-success="trigger"
|
||||
data-success-param-trigger-events="modal-close"
|
||||
data-event="click"
|
||||
data-scope="window.ls">
|
||||
|
||||
<input type="hidden" name="path" data-ls-bind="{{search.path}}" />
|
||||
<input type="hidden" name="type" value="assign" />
|
||||
<input type="hidden" name="value" data-ls-bind="{{search.selected}}" />
|
||||
|
||||
<button data-ls-if="({{search.selected}})" type="button" class="">Select</button>
|
||||
<button data-ls-if="(!{{search.selected}})" type="button" class="" disabled>Select</button>
|
||||
</form>
|
||||
<button data-ui-modal-close="" type="button" class="reverse desktops-only-inline">Cancel</button>
|
||||
</footer>
|
||||
</div>
|
||||
+102
-59
@@ -4,20 +4,28 @@ $logs = $this->getParam('logs', null);
|
||||
|
||||
?>
|
||||
<div
|
||||
data-service="database.getCollection"
|
||||
data-service="databases.getCollection"
|
||||
data-param-database-id="{{router.params.databaseId}}"
|
||||
data-param-collection-id="{{router.params.id}}"
|
||||
data-scope="sdk"
|
||||
data-event="load,database.updateCollection,database.createAttribute,database.deleteAttribute,database.createIndex,database.deleteIndex"
|
||||
data-event="load,databases.updateCollection,databases.createAttribute,databases.deleteAttribute,databases.createIndex,databases.deleteIndex"
|
||||
data-name="project-collection">
|
||||
|
||||
<div class="cover">
|
||||
<h1 class="zone xl margin-bottom-large">
|
||||
<a data-ls-attrs="href=/console/database?project={{router.params.project}}" class="back text-size-small link-return-animation--start"><i class="icon-left-open"></i> Database</a>
|
||||
<div
|
||||
data-service="databases.get"
|
||||
data-param-database-id="{{router.params.databaseId}}"
|
||||
data-scope="sdk"
|
||||
data-event="load,databases.update"
|
||||
data-name="project-database">
|
||||
<div class="cover">
|
||||
<h1 class="zone xl margin-bottom-large">
|
||||
<a data-ls-attrs="href=/console/databases/database?id={{router.params.databaseId}}&project={{router.params.project}}" class="back text-size-small link-return-animation--start"><i class="icon-left-open"></i> <span data-ls-bind="{{project-database.name}}"> </span></a>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<span data-ls-bind="{{project-collection.name}}"> </span>
|
||||
</h1>
|
||||
<span data-ls-bind="{{project-collection.name}}"> </span>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-ui-modal class="modal width-large box close" data-button-hide="on" data-open-event="open-json">
|
||||
@@ -34,14 +42,15 @@ $logs = $this->getParam('logs', null);
|
||||
|
||||
<div class="zone xl">
|
||||
<ul class="phases clear" data-ui-phases data-selected="{{router.params.tab}}">
|
||||
<li data-state="/console/database/collection?id={{router.params.id}}&project={{router.params.project}}">
|
||||
<li data-state="/console/databases/collection?id={{router.params.id}}&databaseId={{router.params.databaseId}}&project={{router.params.project}}">
|
||||
|
||||
<h2>Documents</h2>
|
||||
|
||||
<div
|
||||
data-service="database.listDocuments"
|
||||
data-event="load,database.createDocument,database.updateDocument,database.deleteDocument"
|
||||
data-service="databases.listDocuments"
|
||||
data-event="load,databases.createDocument,databases.updateDocument,databases.deleteDocument"
|
||||
data-param-collection-id="{{router.params.id}}"
|
||||
data-param-database-id="{{router.params.databaseId}}"
|
||||
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
|
||||
data-param-order-types="DESC"
|
||||
data-param-order-types-cast-to="array"
|
||||
@@ -75,15 +84,15 @@ $logs = $this->getParam('logs', null);
|
||||
</template>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-ls-attrs="x-init=documents = {{project-documents.documents}}" x-data="{documents: []}">
|
||||
<tbody data-ls-attrs="x-init=documents = {{project-documents.documents}}; databaseId='{{router.params.databaseId}}'" x-data="{documents: []}">
|
||||
<template x-for="doc in documents">
|
||||
<tr>
|
||||
<td data-title="$id: ">
|
||||
<a :href="`/console/database/document?id=${doc.$id}&collection=${doc.$collection}&project=${project}`" x-text="doc.$id"></a>
|
||||
<a :href="`/console/databases/document?id=${doc.$id}&collection=${doc.$collection}&databaseId=${databaseId}&project=${project}`" x-text="doc.$id"></a>
|
||||
</td>
|
||||
<template x-for="attr in attributes">
|
||||
<td x-show="attr.status === 'available'" :data-title="attr.key + ':'">
|
||||
<a :href="`/console/database/document?id=${doc.$id}&collection=${doc.$collection}&project=${project}`">
|
||||
<a :href="`/console/databases/document?id=${doc.$id}&collection=${doc.$collection}&databaseId=${databaseId}&project=${project}`">
|
||||
<span x-text="doc[attr.key] ?? 'n/a'"></span>
|
||||
</a>
|
||||
</td>
|
||||
@@ -98,8 +107,9 @@ $logs = $this->getParam('logs', null);
|
||||
|
||||
<div class="pull-end text-align-center paging">
|
||||
<form
|
||||
data-service="database.listDocuments"
|
||||
data-service="databases.listDocuments"
|
||||
data-event="submit"
|
||||
data-param-database-id="{{router.params.databaseId}}"
|
||||
data-param-collection-id="{{router.params.id}}"
|
||||
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
|
||||
data-param-order-types="DESC"
|
||||
@@ -114,8 +124,9 @@ $logs = $this->getParam('logs', null);
|
||||
<span data-ls-bind="{{router.params.offset|pageCurrent}} / {{project-documents.total|pageTotal}}"></span>
|
||||
|
||||
<form
|
||||
data-service="database.listDocuments"
|
||||
data-service="databases.listDocuments"
|
||||
data-event="submit"
|
||||
data-param-database-id="{{router.params.databaseId}}"
|
||||
data-param-collection-id="{{router.params.id}}"
|
||||
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
|
||||
data-param-order-types="DESC"
|
||||
@@ -128,15 +139,15 @@ $logs = $this->getParam('logs', null);
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<a data-ls-if="0 < {{project-collection.attributes.length}}" data-ls-attrs="href=/console/database/document/new?collection={{router.params.id}}&project={{router.params.project}}" class="button">
|
||||
<a data-ls-if="0 < {{project-collection.attributes.length}}" data-ls-attrs="href=/console/databases/document/new?collection={{router.params.id}}&databaseId={{router.params.databaseId}}&project={{router.params.project}}" class="button">
|
||||
Add Document
|
||||
</a>
|
||||
<a data-ls-if="!{{project-collection.attributes.length}}" data-ls-attrs="href=/console/database/collection/attributes?id={{router.params.id}}&project={{router.params.project}}" class="button">
|
||||
<a data-ls-if="!{{project-collection.attributes.length}}" data-ls-attrs="href=/console/databases/collection/attributes?id={{router.params.id}}&databaseId={{router.params.databaseId}}&project={{router.params.project}}" class="button">
|
||||
Create Attribute
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
<li data-state="/console/database/collection/attributes?id={{router.params.id}}&project={{router.params.project}}">
|
||||
<li data-state="/console/databases/collection/attributes?id={{router.params.id}}&databaseId={{router.params.databaseId}}&project={{router.params.project}}">
|
||||
<h2>Attributes</h2>
|
||||
|
||||
<div class="clear box margin-bottom">
|
||||
@@ -266,13 +277,14 @@ $logs = $this->getParam('logs', null);
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Delete Collection Attribute"
|
||||
data-service="database.deleteAttribute"
|
||||
data-service="databases.deleteAttribute"
|
||||
data-scope="sdk"
|
||||
data-event="submit"
|
||||
data-confirm="Are you sure you want to delete this attribute?"
|
||||
data-param-database-id="{{router.params.databaseId}}"
|
||||
data-success="alert,trigger"
|
||||
data-success-param-alert-text="Deleted attribute successfully"
|
||||
data-success-param-trigger-events="database.deleteAttribute"
|
||||
data-success-param-trigger-events="databases.deleteAttribute"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to delete attribute"
|
||||
data-failure-param-alert-classname="error">
|
||||
@@ -320,7 +332,7 @@ $logs = $this->getParam('logs', null);
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li data-state="/console/database/collection/indexes?id={{router.params.id}}&project={{router.params.project}}">
|
||||
<li data-state="/console/databases/collection/indexes?id={{router.params.id}}&databaseId={{router.params.databaseId}}&project={{router.params.project}}">
|
||||
<h2>Indexes</h2>
|
||||
|
||||
<div class="clear box margin-bottom">
|
||||
@@ -382,13 +394,14 @@ $logs = $this->getParam('logs', null);
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Delete Collection Index"
|
||||
data-service="database.deleteIndex"
|
||||
data-service="databases.deleteIndex"
|
||||
data-scope="sdk"
|
||||
data-event="submit"
|
||||
data-confirm="Are you sure you want to delete this index?"
|
||||
data-param-database-id="{{router.params.databaseId}}"
|
||||
data-success="alert,trigger"
|
||||
data-success-param-alert-text="Deleted index successfully"
|
||||
data-success-param-trigger-events="database.deleteIndex"
|
||||
data-success-param-trigger-events="databases.deleteIndex"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to delete index"
|
||||
data-failure-param-alert-classname="error">
|
||||
@@ -407,18 +420,19 @@ $logs = $this->getParam('logs', null);
|
||||
|
||||
<button class="new-index">Add Index</button>
|
||||
</li>
|
||||
<li data-state="/console/database/collection/activity?id={{router.params.id}}&project={{router.params.project}}">
|
||||
<li data-state="/console/databases/collection/activity?id={{router.params.id}}&databaseId={{router.params.databaseId}}&project={{router.params.project}}">
|
||||
<h2>Activity</h2>
|
||||
|
||||
<?php echo $logs->render(); ?>
|
||||
</li>
|
||||
<li data-state="/console/database/collection/usage?id={{router.params.id}}&project={{router.params.project}}">
|
||||
<li data-state="/console/databases/collection/usage?id={{router.params.id}}&databaseId={{router.params.databaseId}}&project={{router.params.project}}">
|
||||
<form
|
||||
class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '90d'"
|
||||
data-service="database.getCollectionUsage"
|
||||
data-service="databases.getCollectionUsage"
|
||||
data-event="submit"
|
||||
data-name="usage"
|
||||
data-param-collection-id="{{router.params.id}}"
|
||||
data-param-database-id="{{router.params.databaseId}}"
|
||||
data-param-range="90d">
|
||||
<button class="tick">90d</button>
|
||||
</form>
|
||||
@@ -427,9 +441,10 @@ $logs = $this->getParam('logs', null);
|
||||
|
||||
<form
|
||||
class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '30d'"
|
||||
data-service="database.getCollectionUsage"
|
||||
data-service="databases.getCollectionUsage"
|
||||
data-event="submit"
|
||||
data-name="usage"
|
||||
data-param-database-id="{{router.params.databaseId}}"
|
||||
data-param-collection-id="{{router.params.id}}">
|
||||
<button class="tick">30d</button>
|
||||
</form>
|
||||
@@ -438,9 +453,10 @@ $logs = $this->getParam('logs', null);
|
||||
|
||||
<form
|
||||
class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '24h'"
|
||||
data-service="database.getCollectionUsage"
|
||||
data-service="databases.getCollectionUsage"
|
||||
data-event="submit"
|
||||
data-name="usage"
|
||||
data-param-database-id="{{router.params.databaseId}}"
|
||||
data-param-collection-id="{{router.params.id}}"
|
||||
data-param-range="24h">
|
||||
<button class="tick">24h</button>
|
||||
@@ -450,7 +466,7 @@ $logs = $this->getParam('logs', null);
|
||||
|
||||
<h2>Usage</h2>
|
||||
|
||||
<div data-service="database.getCollectionUsage" data-event="load" data-name="usage" data-param-collection-id="{{router.params.id}}">
|
||||
<div data-service="databases.getCollectionUsage" data-event="load" data-name="usage" data-param-collection-id="{{router.params.id}}" data-param-database-id="{{router.params.databaseId}}">
|
||||
<h3 class="margin-bottom-tiny">Documents</h3>
|
||||
<p class="text-fade">Count of documents over time</p>
|
||||
<div class="box margin-bottom-small">
|
||||
@@ -489,7 +505,7 @@ $logs = $this->getParam('logs', null);
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li data-state="/console/database/collection/settings?id={{router.params.id}}&project={{router.params.project}}">
|
||||
<li data-state="/console/databases/collection/settings?id={{router.params.id}}&databaseId={{router.params.databaseId}}&project={{router.params.project}}">
|
||||
<h2>Settings</h2>
|
||||
|
||||
<div class="row responsive margin-top-negative">
|
||||
@@ -500,13 +516,14 @@ $logs = $this->getParam('logs', null);
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Update Database Collection"
|
||||
data-service="database.updateCollection"
|
||||
data-service="databases.updateCollection"
|
||||
data-scope="sdk"
|
||||
data-event="submit"
|
||||
data-param-collection-id="{{router.params.id}}"
|
||||
data-param-database-id="{{router.params.databaseId}}"
|
||||
data-success="alert,trigger"
|
||||
data-success-param-alert-text="Updated collection successfully"
|
||||
data-success-param-trigger-events="database.updateCollection"
|
||||
data-success-param-trigger-events="databases.updateCollection"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to update collection"
|
||||
data-failure-param-alert-classname="error">
|
||||
@@ -567,26 +584,36 @@ $logs = $this->getParam('logs', null);
|
||||
</div>
|
||||
|
||||
<ul class="margin-bottom-large text-fade text-size-small">
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> <button data-ls-ui-trigger="open-json" class="link text-size-small">View as JSON</button></li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i>
|
||||
<button data-ls-ui-trigger="open-json"
|
||||
class="link text-size-small"
|
||||
data-analytics
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="View as JSON (Collection)">
|
||||
View as JSON
|
||||
</button>
|
||||
</li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> Last Updated: <span data-ls-bind="{{project-collection.$updatedAt|dateText}}"></span></li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> Created: <span data-ls-bind="{{project-collection.$createdAt|dateText}}"></span></li>
|
||||
</ul>
|
||||
|
||||
<form
|
||||
name="database.deleteCollection" class="margin-bottom"
|
||||
name="databases.deleteCollection" class="margin-bottom"
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Delete Database Collection"
|
||||
data-service="database.deleteCollection"
|
||||
data-service="databases.deleteCollection"
|
||||
data-event="submit"
|
||||
data-param-collection-id="{{router.params.id}}"
|
||||
data-param-database-id="{{router.params.databaseId}}"
|
||||
data-confirm="Are you sure you want to delete this collection?"
|
||||
data-success="alert,trigger,redirect"
|
||||
data-success-param-alert-text="Collection deleted successfully"
|
||||
data-success-param-trigger-events="database.deleteCollection"
|
||||
data-success-param-redirect-url="/console/database?project={{router.params.project}}"
|
||||
data-success-param-trigger-events="databases.deleteCollection"
|
||||
data-success-param-redirect-url="/console/databases?project={{router.params.project}}"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to delete collection"
|
||||
data-failure-param-alert-classname="error">
|
||||
@@ -611,12 +638,12 @@ $logs = $this->getParam('logs', null);
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Collection Attribute (string)"
|
||||
data-service="database.createStringAttribute"
|
||||
data-service="databases.createStringAttribute"
|
||||
data-scope="sdk"
|
||||
data-event="submit"
|
||||
data-success="alert,trigger,reset"
|
||||
data-success-param-alert-text="Created new attribute successfully"
|
||||
data-success-param-trigger-events="database.createAttribute"
|
||||
data-success-param-trigger-events="databases.createAttribute"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to create attribute"
|
||||
data-failure-param-alert-classname="error"
|
||||
@@ -625,6 +652,7 @@ $logs = $this->getParam('logs', null);
|
||||
|
||||
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
|
||||
<input type="hidden" name="collectionId" data-ls-bind="{{router.params.id}}" />
|
||||
<input type="hidden" name="databaseId" data-ls-bind="{{router.params.databaseId}}" />
|
||||
|
||||
<label for="string-key">Attribute ID</label>
|
||||
<input id="string-key" type="text" class="full-width" name="key" required autocomplete="off" maxlength="36" pattern="^[a-zA-Z0-9][a-zA-Z0-9._-]{0,35}$" />
|
||||
@@ -667,12 +695,12 @@ $logs = $this->getParam('logs', null);
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Collection Attribute (integer)"
|
||||
data-service="database.createIntegerAttribute"
|
||||
data-service="databases.createIntegerAttribute"
|
||||
data-scope="sdk"
|
||||
data-event="submit"
|
||||
data-success="alert,trigger,reset"
|
||||
data-success-param-alert-text="Created new attribute successfully"
|
||||
data-success-param-trigger-events="database.createAttribute"
|
||||
data-success-param-trigger-events="databases.createAttribute"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to create attribute"
|
||||
data-failure-param-alert-classname="error"
|
||||
@@ -680,6 +708,7 @@ $logs = $this->getParam('logs', null);
|
||||
x-data="{ array: false, required: false, min: null, max: null }">
|
||||
|
||||
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
|
||||
<input type="hidden" name="databaseId" data-ls-bind="{{router.params.databaseId}}" />
|
||||
<input type="hidden" name="collectionId" data-ls-bind="{{router.params.id}}" />
|
||||
|
||||
<label for="integer-key">Attribute ID</label>
|
||||
@@ -732,12 +761,12 @@ $logs = $this->getParam('logs', null);
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Collection Attribute (float)"
|
||||
data-service="database.createFloatAttribute"
|
||||
data-service="databases.createFloatAttribute"
|
||||
data-scope="sdk"
|
||||
data-event="submit"
|
||||
data-success="alert,trigger,reset"
|
||||
data-success-param-alert-text="Created new attribute successfully"
|
||||
data-success-param-trigger-events="database.createAttribute"
|
||||
data-success-param-trigger-events="databases.createAttribute"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to create attribute"
|
||||
data-failure-param-alert-classname="error"
|
||||
@@ -745,6 +774,7 @@ $logs = $this->getParam('logs', null);
|
||||
x-data="{ array: false, required: false, min: null, max: null }">
|
||||
|
||||
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
|
||||
<input type="hidden" name="databaseId" data-ls-bind="{{router.params.databaseId}}" />
|
||||
<input type="hidden" name="collectionId" data-ls-bind="{{router.params.id}}" />
|
||||
|
||||
<label for="float-key">Attribute ID</label>
|
||||
@@ -797,12 +827,12 @@ $logs = $this->getParam('logs', null);
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Collection Attribute (email)"
|
||||
data-service="database.createEmailAttribute"
|
||||
data-service="databases.createEmailAttribute"
|
||||
data-scope="sdk"
|
||||
data-event="submit"
|
||||
data-success="alert,trigger,reset"
|
||||
data-success-param-alert-text="Created new attribute successfully"
|
||||
data-success-param-trigger-events="database.createAttribute"
|
||||
data-success-param-trigger-events="databases.createAttribute"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to create attribute"
|
||||
data-failure-param-alert-classname="error"
|
||||
@@ -810,6 +840,7 @@ $logs = $this->getParam('logs', null);
|
||||
x-data="{ array: false, required: false }">
|
||||
|
||||
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
|
||||
<input type="hidden" name="databaseId" data-ls-bind="{{router.params.databaseId}}" />
|
||||
<input type="hidden" name="collectionId" data-ls-bind="{{router.params.id}}" />
|
||||
|
||||
<label for="email-key">Attribute ID</label>
|
||||
@@ -850,12 +881,12 @@ $logs = $this->getParam('logs', null);
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Collection Attribute (boolean)"
|
||||
data-service="database.createBooleanAttribute"
|
||||
data-service="databases.createBooleanAttribute"
|
||||
data-scope="sdk"
|
||||
data-event="submit"
|
||||
data-success="alert,trigger,reset"
|
||||
data-success-param-alert-text="Created new attribute successfully"
|
||||
data-success-param-trigger-events="database.createAttribute"
|
||||
data-success-param-trigger-events="databases.createAttribute"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to create attribute"
|
||||
data-failure-param-alert-classname="error"
|
||||
@@ -863,6 +894,7 @@ $logs = $this->getParam('logs', null);
|
||||
x-data="{ array: false, required: false }">
|
||||
|
||||
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
|
||||
<input type="hidden" name="databaseId" data-ls-bind="{{router.params.databaseId}}" />
|
||||
<input type="hidden" name="collectionId" data-ls-bind="{{router.params.id}}" />
|
||||
|
||||
<label for="boolean-key">Attribute ID</label>
|
||||
@@ -907,12 +939,12 @@ $logs = $this->getParam('logs', null);
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Collection Attribute (IP)"
|
||||
data-service="database.createIpAttribute"
|
||||
data-service="databases.createIpAttribute"
|
||||
data-scope="sdk"
|
||||
data-event="submit"
|
||||
data-success="alert,trigger,reset"
|
||||
data-success-param-alert-text="Created new attribute successfully"
|
||||
data-success-param-trigger-events="database.createAttribute"
|
||||
data-success-param-trigger-events="databases.createAttribute"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to create attribute"
|
||||
data-failure-param-alert-classname="error"
|
||||
@@ -920,6 +952,7 @@ $logs = $this->getParam('logs', null);
|
||||
x-data="{ array: false, required: false }">
|
||||
|
||||
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
|
||||
<input type="hidden" name="databaseId" data-ls-bind="{{router.params.databaseId}}" />
|
||||
<input type="hidden" name="collectionId" data-ls-bind="{{router.params.id}}" />
|
||||
|
||||
<label for="ip-key">Attribute ID</label>
|
||||
@@ -960,12 +993,12 @@ $logs = $this->getParam('logs', null);
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Collection Attribute (url)"
|
||||
data-service="database.createUrlAttribute"
|
||||
data-service="databases.createUrlAttribute"
|
||||
data-scope="sdk"
|
||||
data-event="submit"
|
||||
data-success="alert,trigger,reset"
|
||||
data-success-param-alert-text="Created new attribute successfully"
|
||||
data-success-param-trigger-events="database.createAttribute"
|
||||
data-success-param-trigger-events="databases.createAttribute"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to create attribute"
|
||||
data-failure-param-alert-classname="error"
|
||||
@@ -973,6 +1006,7 @@ $logs = $this->getParam('logs', null);
|
||||
x-data="{ array: false, required: false }">
|
||||
|
||||
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
|
||||
<input type="hidden" name="databaseId" data-ls-bind="{{router.params.databaseId}}" />
|
||||
<input type="hidden" name="collectionId" data-ls-bind="{{router.params.id}}" />
|
||||
|
||||
<label for="url-key">Attribute ID</label>
|
||||
@@ -1013,12 +1047,12 @@ $logs = $this->getParam('logs', null);
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Collection Attribute (enum)"
|
||||
data-service="database.createEnumAttribute"
|
||||
data-service="databases.createEnumAttribute"
|
||||
data-scope="sdk"
|
||||
data-event="submit"
|
||||
data-success="alert,trigger,reset"
|
||||
data-success-param-alert-text="Created new attribute successfully"
|
||||
data-success-param-trigger-events="database.createAttribute"
|
||||
data-success-param-trigger-events="databases.createAttribute"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to create attribute"
|
||||
data-failure-param-alert-classname="error"
|
||||
@@ -1026,6 +1060,7 @@ $logs = $this->getParam('logs', null);
|
||||
x-data="{ array: false, required: false }">
|
||||
|
||||
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
|
||||
<input type="hidden" name="databaseId" data-ls-bind="{{router.params.databaseId}}" />
|
||||
<input type="hidden" name="collectionId" data-ls-bind="{{router.params.id}}" />
|
||||
|
||||
<label for="enum-key">Attribute ID</label>
|
||||
@@ -1093,17 +1128,18 @@ $logs = $this->getParam('logs', null);
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Collection Index"
|
||||
data-service="database.createIndex"
|
||||
data-service="databases.createIndex"
|
||||
data-scope="sdk"
|
||||
data-event="submit"
|
||||
data-success="alert,trigger,reset"
|
||||
data-success-param-alert-text="Created new index successfully"
|
||||
data-success-param-trigger-events="database.createIndex"
|
||||
data-success-param-trigger-events="databases.createIndex"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to create index"
|
||||
data-failure-param-alert-classname="error">
|
||||
|
||||
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
|
||||
<input type="hidden" name="databaseId" data-ls-bind="{{router.params.databaseId}}" />
|
||||
<input type="hidden" name="collectionId" data-ls-bind="{{router.params.id}}" />
|
||||
|
||||
<label for="index-key">Index Key</label>
|
||||
@@ -1125,8 +1161,15 @@ $logs = $this->getParam('logs', null);
|
||||
<div data-forms-clone="" data-label="Add Attribute" data-target="attributes-section" data-first="1">
|
||||
<div class="row responsive thin margin-bottom-tiny">
|
||||
<div class="col span-7 margin-bottom-small">
|
||||
<select data-duplications data-ls-attrs="name=attributes" data-ls-loop="project-collection.attributes" data-ls-as="option" data-cast-to="array" class="margin-bottom-no">
|
||||
<option data-ls-attrs="value={{option.key}}" data-ls-bind="{{option.key}}"></option>
|
||||
<select data-duplications data-ls-attrs="name=attributes" data-cast-to="array" class="margin-bottom-no">
|
||||
<optgroup label="Internal">
|
||||
<option value="$id">$id</option>
|
||||
<option value="$createdAt">$createdAt</option>
|
||||
<option value="$updatedAt">$updatedAt</option>
|
||||
</optgroup>
|
||||
<optgroup label="Attributes" data-ls-loop="project-collection.attributes" data-ls-as="option">
|
||||
<option data-ls-attrs="value={{option.key}}" data-ls-bind="{{option.key}}"></option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col span-4 margin-bottom-small">
|
||||
@@ -1148,7 +1191,7 @@ $logs = $this->getParam('logs', null);
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="margin-top" data-service="database.listCollections" data-event="load,database.createCollection,database.updateCollection,database.deleteCollection" data-scope="sdk" data-param-limit="100" data-name="project-collections">
|
||||
<div class="margin-top" data-service="databases.listCollections" data-param-database-id="{{router.params.databaseId}}" data-event="load,databases.createCollection,databases.updateCollection,databases.deleteCollection" data-scope="sdk" data-param-limit="100" data-name="project-collections">
|
||||
</div>
|
||||
|
||||
<script type="text/html" id="template-attribute-title-first">
|
||||
@@ -0,0 +1,326 @@
|
||||
<div
|
||||
data-service="databases.get"
|
||||
data-param-database-id="{{router.params.id}}"
|
||||
data-scope="sdk"
|
||||
data-event="load,databases.update"
|
||||
data-name="project-database">
|
||||
<div class="cover">
|
||||
<h1 class="zone xl margin-bottom-large">
|
||||
<a data-ls-attrs="href=/console/databases?project={{router.params.project}}" class="back text-size-small link-return-animation--start"><i class="icon-left-open"></i> Database</a>
|
||||
<br />
|
||||
|
||||
<span data-ls-bind="{{project-database.name}}"> </span>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div data-ui-modal class="modal width-large box close" data-button-hide="on" data-open-event="open-json">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
|
||||
<h2>JSON View</h2>
|
||||
|
||||
<div class="margin-bottom">
|
||||
<input type="hidden" data-ls-bind="{{project-database}}" data-forms-code />
|
||||
</div>
|
||||
|
||||
<button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
|
||||
</div>
|
||||
|
||||
<div class="zone xl">
|
||||
<ul class="phases clear" data-ui-phases data-selected="{{router.params.tab}}">
|
||||
<li data-state="/console/databases/database?id={{router.params.id}}&project={{router.params.project}}">
|
||||
<h2>Collections</h2>
|
||||
|
||||
<div class="margin-top"
|
||||
data-service="databases.listCollections"
|
||||
data-event="load,databases.createCollection,databases.updateCollection,databases.deleteCollection"
|
||||
data-param-database-id="{{router.params.id}}"
|
||||
data-param-search="{{router.params.search}}"
|
||||
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
|
||||
data-param-offset="{{router.params.offset}}"
|
||||
data-param-order-type="ASC"
|
||||
data-scope="sdk"
|
||||
data-name="project-collections">
|
||||
|
||||
<div data-ls-if="(!{{project-collections.total}})" class="box dashboard margin-bottom">
|
||||
<div class="margin-bottom-small margin-top-small margin-end margin-start">
|
||||
<h3 class="margin-bottom-small text-bold">No Collections Found</h3>
|
||||
|
||||
<p class="margin-bottom-no">You haven't created any collections for your project yet.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-ls-if="0 != {{project-collections.total}}">
|
||||
<ul data-ls-loop="project-collections.collections" data-ls-as="collection" data-ls-append="" class="tiles cell-3 margin-bottom-small">
|
||||
<li class="margin-bottom">
|
||||
<a data-ls-attrs="href=/console/databases/collection?id={{collection.$id}}&databaseId={{router.params.id}}&project={{router.params.project}}" class="box">
|
||||
<div data-ls-bind="{{collection.name}}" class="text-one-liner margin-bottom text-bold"> </div>
|
||||
|
||||
<i class="icon-right-open"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="pull-end text-align-center paging">
|
||||
<form
|
||||
data-service="databases.listCollections"
|
||||
data-param-database-id="{{router.params.id}}"
|
||||
data-event="submit"
|
||||
data-param-search="{{router.params.search}}"
|
||||
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
|
||||
data-param-order-type="ASC"
|
||||
data-scope="sdk"
|
||||
data-name="project-collections"
|
||||
data-success="state"
|
||||
data-success-param-state-keys="search,offset">
|
||||
<button name="offset" data-paging-back data-offset="{{router.params.offset}}" data-total="{{project-collections.total}}" class="margin-end round small" aria-label="Back"><i class="icon-left-open"></i></button>
|
||||
</form>
|
||||
|
||||
<span data-ls-bind="{{router.params.offset|pageCurrent}} / {{project-collections.total|pageTotal}}"></span>
|
||||
|
||||
<form
|
||||
data-service="databases.listCollections"
|
||||
data-param-database-id="{{router.params.id}}"
|
||||
data-event="submit"
|
||||
data-param-search="{{router.params.search}}"
|
||||
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
|
||||
data-param-order-type="ASC"
|
||||
data-scope="sdk"
|
||||
data-name="project-collections"
|
||||
data-success="state"
|
||||
data-success-param-state-keys="search,offset">
|
||||
<button name="offset" data-paging-next data-offset="{{router.params.offset}}" data-total="{{project-collections.total}}" class="margin-start round small" aria-label="Next"><i class="icon-right-open"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div data-ui-modal class="modal close box sticky-footer" data-button-text="Add Collection">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
|
||||
<h1>New Collection</h1>
|
||||
|
||||
<form
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Database Collection"
|
||||
data-service="databases.createCollection"
|
||||
data-event="submit"
|
||||
data-scope="sdk"
|
||||
data-success="alert,reset,redirect,trigger"
|
||||
data-success-param-alert-text="Collection created successfully"
|
||||
data-success-param-redirect-url="/console/databases/collection/settings?id={{serviceData.$id}}&databaseId={{router.params.id}}&project={{router.params.project}}"
|
||||
data-success-param-trigger-events="databases.createCollection"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to create collection"
|
||||
data-failure-param-alert-classname="error">
|
||||
|
||||
<input type="hidden" name="databaseId" data-ls-bind="{{router.params.id}}" />
|
||||
|
||||
<label for="collection-id">Collection ID</label>
|
||||
<input
|
||||
type="hidden"
|
||||
data-custom-id
|
||||
data-id-type="auto"
|
||||
data-validator="databases.getCollection"
|
||||
required
|
||||
maxlength="36"
|
||||
pattern="^[a-zA-Z0-9][a-zA-Z0-9._-]{0,35}$"
|
||||
name="collectionId" />
|
||||
|
||||
<label for="collection-name">Name</label>
|
||||
<input type="text" class="full-width" id="collection-name" name="name" required autocomplete="off" maxlength="128" />
|
||||
|
||||
<input type="hidden" id="collection-permission" name="permission" required value="collection" />
|
||||
<input type="hidden" id="collection-read" name="read" required data-cast-to="json" value="<?php echo htmlentities(json_encode([])); ?>" />
|
||||
<input type="hidden" id="collection-write" name="write" required data-cast-to="json" value="<?php echo htmlentities(json_encode([])); ?>" />
|
||||
|
||||
<hr />
|
||||
|
||||
<button type="submit">Create</button> <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
<li data-state="/console/databases/database/usage?project={{router.params.project}}&id={{router.params.id}}">
|
||||
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '90d'"
|
||||
data-service="databases.getDatabaseUsage"
|
||||
data-event="submit"
|
||||
data-name="usage"
|
||||
data-param-database-id="{{router.params.id}}"
|
||||
data-param-range="90d">
|
||||
<button class="tick">90d</button>
|
||||
</form>
|
||||
|
||||
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '90d'" disabled>90d</button>
|
||||
|
||||
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '30d'"
|
||||
data-service="databases.getDatabaseUsage"
|
||||
data-param-database-id="{{router.params.id}}"
|
||||
data-event="submit"
|
||||
data-name="usage">
|
||||
<button class="tick">30d</button>
|
||||
</form>
|
||||
|
||||
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '30d'" disabled>30d</button>
|
||||
|
||||
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '24h'"
|
||||
data-service="databases.getDatabaseUsage"
|
||||
data-event="submit"
|
||||
data-name="usage"
|
||||
data-param-database-id="{{router.params.id}}"
|
||||
data-param-range="24h">
|
||||
<button class="tick">24h</button>
|
||||
</form>
|
||||
|
||||
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '24h'" disabled>24h</button>
|
||||
|
||||
<h2>Usage</h2>
|
||||
|
||||
<div
|
||||
data-service="databases.getDatabaseUsage"
|
||||
data-param-database-id="{{router.params.id}}"
|
||||
data-event="load"
|
||||
data-name="usage">
|
||||
<h3 class="margin-bottom-tiny">Objects</h3>
|
||||
<p class="text-fade">Count of collections and documents over time</p>
|
||||
<div class="box margin-bottom-small">
|
||||
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
|
||||
<div class="chart background-image-no border-no margin-bottom-no">
|
||||
<input
|
||||
type="hidden"
|
||||
data-ls-bind="{{usage}}"
|
||||
data-forms-chart="Collections=collectionsCount,Documents=documentsCount"
|
||||
data-show-y-axis="true"
|
||||
data-height="140" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="chart-notes margin-bottom-large">
|
||||
<li>Total Collections <span data-ls-bind="({{usage.collectionsCount|statsGetLast|statsTotal}})"></span></li>
|
||||
<li>Total Documents <span data-ls-bind="({{usage.documentsCount|statsGetLast|statsTotal}})"></span></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h3 class="margin-bottom-tiny">Collections</h3>
|
||||
<p class="text-fade">Count of collections create, read, update and delete operations over time</p>
|
||||
<div class="box margin-bottom-small">
|
||||
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
|
||||
<div class="chart background-image-no border-no margin-bottom-no">
|
||||
<input
|
||||
type="hidden"
|
||||
data-ls-bind="{{usage}}"
|
||||
data-forms-chart="Created=collectionsCreate,Read=collectionsRead,Updated=collectionsUpdate,Deleted=collectionsDelete"
|
||||
data-show-y-axis="true"
|
||||
data-colors="create,read,update,delete"
|
||||
data-height="140" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="chart-notes margin-bottom-large crud">
|
||||
<li>Created</li>
|
||||
<li>Read</li>
|
||||
<li>Updated</li>
|
||||
<li>Deleted</li>
|
||||
</ul>
|
||||
|
||||
<h3 class="margin-bottom-tiny">Documents</h3>
|
||||
<p class="text-fade">Count of documents create, read, update and delete operations over time</p>
|
||||
<div class="box margin-bottom-small">
|
||||
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
|
||||
<div class="chart background-image-no border-no margin-bottom-no">
|
||||
<input
|
||||
type="hidden"
|
||||
data-ls-bind="{{usage}}"
|
||||
data-forms-chart="Created=documentsCreate,Read=documentsRead,Updated=documentsUpdate,Deleted=documentsDelete"
|
||||
data-show-y-axis="true"
|
||||
data-colors="create,read,update,delete"
|
||||
data-height="140" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="chart-notes margin-bottom-large crud">
|
||||
<li>Created</li>
|
||||
<li>Read</li>
|
||||
<li>Updated</li>
|
||||
<li>Deleted</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li data-state="/console/databases/database/settings?id={{router.params.id}}&project={{router.params.project}}">
|
||||
<h2>Settings</h2>
|
||||
|
||||
<div class="row responsive margin-top-negative">
|
||||
<div class="col span-8 margin-bottom">
|
||||
<form
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Update Database"
|
||||
data-service="databases.update"
|
||||
data-scope="sdk"
|
||||
data-event="submit"
|
||||
data-param-database-id="{{router.params.id}}"
|
||||
data-success="alert,trigger"
|
||||
data-success-param-alert-text="Updated database successfully"
|
||||
data-success-param-trigger-events="databases.update"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to update database"
|
||||
data-failure-param-alert-classname="error">
|
||||
|
||||
<label> </label>
|
||||
|
||||
<div class="box">
|
||||
<label for="database-name">Name</label>
|
||||
<input name="name" id="database-name" type="text" autocomplete="off" data-ls-bind="{{project-database.name}}" data-forms-text-direction required placeholder="Database Name" maxlength="128" />
|
||||
|
||||
<hr class="margin-top-no" />
|
||||
|
||||
<button>Update</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col span-4 sticky-top">
|
||||
<label>Database ID</label>
|
||||
<div class="input-copy margin-bottom">
|
||||
<input id="id" type="text" autocomplete="off" placeholder="" data-ls-bind="{{project-database.$id}}" disabled data-forms-copy class="margin-bottom-no" />
|
||||
</div>
|
||||
|
||||
<ul class="margin-bottom-large text-fade text-size-small">
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> <button data-ls-ui-trigger="open-json" class="link text-size-small">View as JSON</button></li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> Last Updated: <span data-ls-bind="{{project-database.$updatedAt|dateText}}"></span></li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> Created: <span data-ls-bind="{{project-database.$createdAt|dateText}}"></span></li>
|
||||
</ul>
|
||||
|
||||
<form
|
||||
name="databases.delete" class="margin-bottom"
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Delete Database"
|
||||
data-service="databases.delete"
|
||||
data-event="submit"
|
||||
data-param-database-id="{{router.params.id}}"
|
||||
data-confirm="Are you sure you want to delete this Database?"
|
||||
data-success="alert,trigger,redirect"
|
||||
data-success-param-alert-text="Database deleted successfully"
|
||||
data-success-param-trigger-events="databases.delete"
|
||||
data-success-param-redirect-url="/console/databases?project={{router.params.project}}"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to delete database"
|
||||
data-failure-param-alert-classname="error">
|
||||
|
||||
<button type="submit" class="danger fill">Delete Database</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
+28
-15
@@ -5,15 +5,17 @@ $logs = $this->getParam('logs', null);
|
||||
|
||||
?>
|
||||
<div
|
||||
data-service="database.getCollection"
|
||||
data-service="databases.getCollection"
|
||||
data-param-collection-id="{{router.params.collection}}"
|
||||
data-param-database-id="{{router.params.databaseId}}"
|
||||
data-scope="sdk"
|
||||
data-event="load,database.updateDocument"
|
||||
data-event="load,databases.updateDocument"
|
||||
data-name="project-collection">
|
||||
|
||||
<div
|
||||
data-service="database.getDocument"
|
||||
data-service="databases.getDocument"
|
||||
data-param-collection-id="{{router.params.collection}}"
|
||||
data-param-database-id="{{router.params.databaseId}}"
|
||||
data-param-document-id="{{router.params.id}}"
|
||||
data-scope="sdk"
|
||||
data-event="load"
|
||||
@@ -22,7 +24,7 @@ $logs = $this->getParam('logs', null);
|
||||
|
||||
<div class="cover">
|
||||
<h1 class="zone xl margin-bottom-large">
|
||||
<a data-ls-attrs="href=/console/database/collection?id={{router.params.collection}}&project={{router.params.project}}" class="back text-size-small link-return-animation--start"><i class="icon-left-open"></i> <span data-ls-bind="{{project-collection.name}}"></span></a>
|
||||
<a data-ls-attrs="href=/console/databases/collection?id={{router.params.collection}}&databaseId={{router.params.databaseId}}&project={{router.params.project}}" class="back text-size-small link-return-animation--start"><i class="icon-left-open"></i> <span data-ls-bind="{{project-collection.name}}"></span></a>
|
||||
|
||||
<br />
|
||||
|
||||
@@ -45,7 +47,7 @@ $logs = $this->getParam('logs', null);
|
||||
|
||||
<div class="zone xl margin-bottom-no">
|
||||
<ul class="phases clear" data-ui-phases data-selected="{{router.params.tab}}">
|
||||
<li data-state="/console/database/document?id={{router.params.id}}&collection={{router.params.collection}}&project={{router.params.project}}">
|
||||
<li data-state="/console/databases/document?id={{router.params.id}}&collection={{router.params.collection}}&databaseId={{router.params.databaseId}}&project={{router.params.project}}">
|
||||
<h2 class="margin-bottom">Overview</h2>
|
||||
|
||||
<div class="row responsive">
|
||||
@@ -64,19 +66,20 @@ $logs = $this->getParam('logs', null);
|
||||
<?php if($new): ?>
|
||||
data-analytics-label="Create Database Document"
|
||||
data-success="trigger,redirect"
|
||||
data-success-param-trigger-events="database.createDocument"
|
||||
data-success-param-redirect-url="/console/database/collection?id={{project-collection.$id}}&project={{router.params.project}}"
|
||||
data-success-param-trigger-events="databases.createDocument"
|
||||
data-success-param-redirect-url="/console/databases/collection?id={{project-collection.$id}}&databaseId={{router.params.databaseId}}&project={{router.params.project}}"
|
||||
data-failure-param-alert-text="Failed to create document"
|
||||
<?php else: ?>
|
||||
data-analytics-label="Update Database Document"
|
||||
data-success="trigger,alert"
|
||||
data-success-param-trigger-events="database.updateDocument"
|
||||
data-success-param-trigger-events="databases.updateDocument"
|
||||
data-success-param-alert-text="Your document was updated"
|
||||
data-failure-param-alert-text="Failed to update document"
|
||||
<?php endif; ?>
|
||||
>
|
||||
|
||||
<input type="hidden" name="collectionId" data-ls-bind="{{project-collection.$id}}" />
|
||||
<input type="hidden" name="databaseId" data-ls-bind="{{router.params.databaseId}}" />
|
||||
<?php if(!$new): ?><input type="hidden" name="documentId" data-ls-bind="{{project-document.$id}}" /><?php endif; ?>
|
||||
|
||||
<div class="box">
|
||||
@@ -86,7 +89,7 @@ $logs = $this->getParam('logs', null);
|
||||
type="hidden"
|
||||
data-custom-id
|
||||
data-id-type="auto"
|
||||
data-validator="database.getDocument"
|
||||
data-validator="databases.getDocument"
|
||||
required
|
||||
maxlength="36"
|
||||
name="documentId"
|
||||
@@ -346,27 +349,37 @@ $logs = $this->getParam('logs', null);
|
||||
</div>
|
||||
|
||||
<ul class="margin-bottom-large text-fade text-size-small" data-ls-if="({{project-document.$id}})">
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> <button data-ls-ui-trigger="open-json" class="link text-size-small">View as JSON</button></li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i>
|
||||
<button data-ls-ui-trigger="open-json"
|
||||
class="link text-size-small"
|
||||
data-analytics
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="View as JSON (Document)">
|
||||
View as JSON
|
||||
</button>
|
||||
</li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> Last Updated: <span data-ls-bind="{{project-document.$updatedAt|dateText}}"></span></li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> Created: <span data-ls-bind="{{project-document.$createdAt|dateText}}"></span></li>
|
||||
</ul>
|
||||
|
||||
<div data-ls-if="({{project-document.$id}})">
|
||||
<form name="database.deleteDocument" class="margin-bottom"
|
||||
<form name="databases.deleteDocument" class="margin-bottom"
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Delete Collection Document"
|
||||
data-service="database.deleteDocument"
|
||||
data-service="databases.deleteDocument"
|
||||
data-event="submit"
|
||||
data-param-database-id="{{router.params.databaseId}}"
|
||||
data-param-collection-id="{{router.params.collection}}"
|
||||
data-param-document-id="{{project-document.$id}}"
|
||||
data-confirm="Are you sure you want to delete this document?"
|
||||
data-success="alert,trigger,redirect"
|
||||
data-success-param-alert-text="Document deleted successfully"
|
||||
data-success-param-trigger-events="database.deleteDocument"
|
||||
data-success-param-redirect-url="/console/database/collection?id={{router.params.collection}}&project={{router.params.project}}"
|
||||
data-success-param-trigger-events="databases.deleteDocument"
|
||||
data-success-param-redirect-url="/console/databases/collection?id={{router.params.collection}}&project={{router.params.project}}&databaseId={{router.params.databaseId}}"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to delete collection"
|
||||
data-failure-param-alert-classname="error">
|
||||
@@ -378,7 +391,7 @@ $logs = $this->getParam('logs', null);
|
||||
</div>
|
||||
</li>
|
||||
<?php if(!$new): ?>
|
||||
<li data-state="/console/database/document/activity?id={{router.params.id}}&collection={{router.params.collection}}&project={{router.params.project}}">
|
||||
<li data-state="/console/databases/document/activity?id={{router.params.id}}&collection={{router.params.collection}}&project={{router.params.project}}">
|
||||
<h2>Activity</h2>
|
||||
|
||||
<?php echo $logs->render(); ?>
|
||||
@@ -9,32 +9,32 @@
|
||||
|
||||
<div class="zone xl">
|
||||
<ul class="phases clear" data-ui-phases data-selected="{{router.params.tab}}">
|
||||
<li data-state="/console/database?project={{router.params.project}}">
|
||||
<h2>Collections</h2>
|
||||
<li data-state="/console/databases?project={{router.params.project}}">
|
||||
<h2>Databases</h2>
|
||||
|
||||
<div class="margin-top"
|
||||
data-service="database.listCollections"
|
||||
data-event="load,database.createCollection,database.updateCollection,database.deleteCollection"
|
||||
data-service="databases.list"
|
||||
data-event="load,databases.create,databases.update,databases.delete"
|
||||
data-param-search="{{router.params.search}}"
|
||||
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
|
||||
data-param-offset="{{router.params.offset}}"
|
||||
data-param-order-type="ASC"
|
||||
data-scope="sdk"
|
||||
data-name="project-collections">
|
||||
data-name="project-databases">
|
||||
|
||||
<div data-ls-if="(!{{project-collections.total}})" class="box dashboard margin-bottom">
|
||||
<div data-ls-if="(!{{project-databases.total}})" class="box dashboard margin-bottom">
|
||||
<div class="margin-bottom-small margin-top-small margin-end margin-start">
|
||||
<h3 class="margin-bottom-small text-bold">No Collections Found</h3>
|
||||
<h3 class="margin-bottom-small text-bold">No Databases Found</h3>
|
||||
|
||||
<p class="margin-bottom-no">You haven't created any collections for your project yet.</p>
|
||||
<p class="margin-bottom-no">You haven't created any databases for your project yet.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-ls-if="0 != {{project-collections.total}}">
|
||||
<ul data-ls-loop="project-collections.collections" data-ls-as="collection" data-ls-append="" class="tiles cell-3 margin-bottom-small">
|
||||
<div data-ls-if="0 != {{project-databases.total}}">
|
||||
<ul data-ls-loop="project-databases.databases" data-ls-as="database" data-ls-append="" class="tiles cell-3 margin-bottom-small">
|
||||
<li class="margin-bottom">
|
||||
<a data-ls-attrs="href=/console/database/collection?id={{collection.$id}}&project={{router.params.project}}" class="box">
|
||||
<div data-ls-bind="{{collection.name}}" class="text-one-liner margin-bottom text-bold"> </div>
|
||||
<a data-ls-attrs="href=/console/databases/database?id={{database.$id}}&project={{router.params.project}}" class="box">
|
||||
<div data-ls-bind="{{database.name}}" class="text-one-liner margin-bottom text-bold"> </div>
|
||||
|
||||
<i class="icon-right-open"></i>
|
||||
</a>
|
||||
@@ -44,84 +44,79 @@
|
||||
|
||||
<div class="pull-end text-align-center paging">
|
||||
<form
|
||||
data-service="database.listCollections"
|
||||
data-service="databases.list"
|
||||
data-event="submit"
|
||||
data-param-search="{{router.params.search}}"
|
||||
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
|
||||
data-param-order-type="ASC"
|
||||
data-scope="sdk"
|
||||
data-name="project-collections"
|
||||
data-name="project-databases"
|
||||
data-success="state"
|
||||
data-success-param-state-keys="search,offset">
|
||||
<button name="offset" data-paging-back data-offset="{{router.params.offset}}" data-total="{{project-collections.total}}" class="margin-end round small" aria-label="Back"><i class="icon-left-open"></i></button>
|
||||
<button name="offset" data-paging-back data-offset="{{router.params.offset}}" data-total="{{project-databases.total}}" class="margin-end round small" aria-label="Back"><i class="icon-left-open"></i></button>
|
||||
</form>
|
||||
|
||||
<span data-ls-bind="{{router.params.offset|pageCurrent}} / {{project-collections.total|pageTotal}}"></span>
|
||||
<span data-ls-bind="{{router.params.offset|pageCurrent}} / {{project-databases.total|pageTotal}}"></span>
|
||||
|
||||
<form
|
||||
data-service="database.listCollections"
|
||||
data-service="databases.list"
|
||||
data-event="submit"
|
||||
data-param-search="{{router.params.search}}"
|
||||
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
|
||||
data-param-order-type="ASC"
|
||||
data-scope="sdk"
|
||||
data-name="project-collections"
|
||||
data-name="project-databases"
|
||||
data-success="state"
|
||||
data-success-param-state-keys="search,offset">
|
||||
<button name="offset" data-paging-next data-offset="{{router.params.offset}}" data-total="{{project-collections.total}}" class="margin-start round small" aria-label="Next"><i class="icon-right-open"></i></button>
|
||||
<button name="offset" data-paging-next data-offset="{{router.params.offset}}" data-total="{{project-databases.total}}" class="margin-start round small" aria-label="Next"><i class="icon-right-open"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div data-ui-modal class="modal close box sticky-footer" data-button-text="Add Collection">
|
||||
<div data-ui-modal class="modal close box sticky-footer" data-button-text="Add Database">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
|
||||
<h1>New Collection</h1>
|
||||
<h1>New Database</h1>
|
||||
|
||||
<form
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Create Database Collection"
|
||||
data-service="database.createCollection"
|
||||
data-analytics-label="Create Database"
|
||||
data-service="databases.create"
|
||||
data-event="submit"
|
||||
data-scope="sdk"
|
||||
data-success="alert,reset,redirect,trigger"
|
||||
data-success-param-alert-text="Collection created successfully"
|
||||
data-success-param-redirect-url="/console/database/collection/settings?id={{serviceData.$id}}&project={{router.params.project}}"
|
||||
data-success-param-trigger-events="database.createCollection"
|
||||
data-success-param-alert-text="Database created successfully"
|
||||
data-success-param-redirect-url="/console/databases/database?id={{serviceData.$id}}&project={{router.params.project}}"
|
||||
data-success-param-trigger-events="databases.create"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to create collection"
|
||||
data-failure-param-alert-text="Failed to create database"
|
||||
data-failure-param-alert-classname="error">
|
||||
|
||||
<label for="collection-id">Collection ID</label>
|
||||
<label for="database-id">Database ID</label>
|
||||
<input
|
||||
type="hidden"
|
||||
data-custom-id
|
||||
data-id-type="auto"
|
||||
data-validator="database.getCollection"
|
||||
data-validator="databases.get"
|
||||
required
|
||||
maxlength="36"
|
||||
pattern="^[a-zA-Z0-9][a-zA-Z0-9._-]{0,35}$"
|
||||
name="collectionId" />
|
||||
|
||||
<label for="collection-name">Name</label>
|
||||
<input type="text" class="full-width" id="collection-name" name="name" required autocomplete="off" maxlength="128" />
|
||||
|
||||
<input type="hidden" id="collection-permission" name="permission" required value="collection" />
|
||||
<input type="hidden" id="collection-read" name="read" required data-cast-to="json" value="<?php echo htmlentities(json_encode([])); ?>" />
|
||||
<input type="hidden" id="collection-write" name="write" required data-cast-to="json" value="<?php echo htmlentities(json_encode([])); ?>" />
|
||||
name="databaseId" />
|
||||
|
||||
<label for="database-name">Name</label>
|
||||
<input type="text" class="full-width" id="database-name" name="name" required autocomplete="off" maxlength="128" />
|
||||
<hr />
|
||||
|
||||
<button type="submit">Create</button> <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
<li data-state="/console/database/usage?project={{router.params.project}}">
|
||||
</li><!-- TODO need to work on usage -->
|
||||
<li data-state="/console/databases/usage?project={{router.params.project}}">
|
||||
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '90d'"
|
||||
data-service="database.getUsage"
|
||||
data-service="databases.getUsage"
|
||||
data-event="submit"
|
||||
data-name="usage"
|
||||
data-param-range="90d">
|
||||
@@ -131,7 +126,7 @@
|
||||
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '90d'" disabled>90d</button>
|
||||
|
||||
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '30d'"
|
||||
data-service="database.getUsage"
|
||||
data-service="databases.getUsage"
|
||||
data-event="submit"
|
||||
data-name="usage">
|
||||
<button class="tick">30d</button>
|
||||
@@ -140,7 +135,7 @@
|
||||
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '30d'" disabled>30d</button>
|
||||
|
||||
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '24h'"
|
||||
data-service="database.getUsage"
|
||||
data-service="databases.getUsage"
|
||||
data-event="submit"
|
||||
data-name="usage"
|
||||
data-param-range="24h">
|
||||
@@ -152,7 +147,7 @@
|
||||
<h2>Usage</h2>
|
||||
|
||||
<div
|
||||
data-service="database.getUsage"
|
||||
data-service="databases.getUsage"
|
||||
data-event="load"
|
||||
data-name="usage">
|
||||
<h3 class="margin-bottom-tiny">Objects</h3>
|
||||
@@ -163,7 +158,7 @@
|
||||
<input
|
||||
type="hidden"
|
||||
data-ls-bind="{{usage}}"
|
||||
data-forms-chart="Collections=collectionsCount,Documents=documentsCount"
|
||||
data-forms-chart="Databases=databasesCount,Collections=collectionsCount,Documents=documentsCount"
|
||||
data-show-y-axis="true"
|
||||
data-height="140" />
|
||||
</div>
|
||||
@@ -171,10 +166,33 @@
|
||||
</div>
|
||||
|
||||
<ul class="chart-notes margin-bottom-large">
|
||||
<li>Total Databases <span data-ls-bind="({{usage.databasesCount|statsGetLast|statsTotal}})"></span></li>
|
||||
<li>Total Collections <span data-ls-bind="({{usage.collectionsCount|statsGetLast|statsTotal}})"></span></li>
|
||||
<li>Total Documents <span data-ls-bind="({{usage.documentsCount|statsGetLast|statsTotal}})"></span></li>
|
||||
</ul>
|
||||
|
||||
<h3 class="margin-bottom-tiny">Databases</h3>
|
||||
<p class="text-fade">Count of databases create, read, update and delete operations over time</p>
|
||||
<div class="box margin-bottom-small">
|
||||
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
|
||||
<div class="chart background-image-no border-no margin-bottom-no">
|
||||
<input
|
||||
type="hidden"
|
||||
data-ls-bind="{{usage}}"
|
||||
data-forms-chart="Created=databasesCreate,Read=databasesRead,Updated=databasesUpdate,Deleted=databasesDelete"
|
||||
data-show-y-axis="true"
|
||||
data-colors="create,read,update,delete"
|
||||
data-height="140" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="chart-notes margin-bottom-large crud">
|
||||
<li>Created</li>
|
||||
<li>Read</li>
|
||||
<li>Updated</li>
|
||||
<li>Deleted</li>
|
||||
</ul>
|
||||
|
||||
<h3 class="margin-bottom-tiny">Collections</h3>
|
||||
<p class="text-fade">Count of collections create, read, update and delete operations over time</p>
|
||||
@@ -4,7 +4,12 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
|
||||
$events = $this->getParam('events', []);
|
||||
$timeout = $this->getParam('timeout', 900);
|
||||
$usageStatsEnabled = $this->getParam('usageStatsEnabled', true);
|
||||
$patterns = [];
|
||||
$patterns = [
|
||||
'documents',
|
||||
'documents.create',
|
||||
'documents.update',
|
||||
'documents.delete',
|
||||
];
|
||||
|
||||
foreach ($events as $name => $event) {
|
||||
$patterns[] = $name;
|
||||
@@ -245,7 +250,16 @@ sort($patterns);
|
||||
</div>
|
||||
|
||||
<ul class="margin-bottom-large text-fade text-size-small">
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> <button data-ls-ui-trigger="open-json" class="link text-size-small">View as JSON</button></li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i>
|
||||
<button data-ls-ui-trigger="open-json"
|
||||
class="link text-size-small"
|
||||
data-analytics
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="View as JSON (Function)">
|
||||
View as JSON
|
||||
</button>
|
||||
</li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> Last Updated: <span data-ls-bind="{{project-function.$updatedAt|dateText}}"></span></li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> Created: <span data-ls-bind="{{project-function.$createdAt|dateText}}"></span></li>
|
||||
</ul>
|
||||
@@ -595,7 +609,16 @@ sort($patterns);
|
||||
</div>
|
||||
|
||||
<ul class="margin-bottom-large text-fade text-size-small">
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> <button data-ls-ui-trigger="open-json" class="link text-size-small">View as JSON</button></li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i>
|
||||
<button data-ls-ui-trigger="open-json"
|
||||
class="link text-size-small"
|
||||
data-analytics
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="View as JSON (Function)">
|
||||
View as JSON
|
||||
</button>
|
||||
</li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> Last Updated: <span data-ls-bind="{{project-function.$updatedAt|dateText}}"></span></li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> Created: <span data-ls-bind="{{project-function.$createdAt|dateText}}"></span></li>
|
||||
</ul>
|
||||
@@ -644,6 +667,11 @@ sort($patterns);
|
||||
<input id="subResource" type="text" :placeholder="subResourceName" x-model="subResource" maxlength="36" pattern="^[a-zA-Z0-9][a-zA-Z0-9_-]{0,35}$">
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Leave empty for wildcard</div>
|
||||
</div>
|
||||
<div x-show="hasSubSubResource">
|
||||
<label x-text="subSubResourceName + ' (optional)'" for="subSubResource"></label>
|
||||
<input id="subSubResource" type="text" :placeholder="subSubResourceName" x-model="subSubResource" maxlength="36" pattern="^[a-zA-Z0-9][a-zA-Z0-9_-]{0,35}$">
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Leave empty for wildcard</div>
|
||||
</div>
|
||||
<div x-show="hasAttribute">
|
||||
<label for="attribute">Add Attribute (optional)</label>
|
||||
<select id="attribute" x-model="attribute">
|
||||
|
||||
@@ -471,7 +471,16 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
|
||||
</div>
|
||||
|
||||
<ul class="margin-bottom-large text-fade text-size-small">
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> <button data-ls-ui-trigger="open-json" class="link text-size-small">View as JSON</button></li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i>
|
||||
<button data-ls-ui-trigger="open-json"
|
||||
class="link text-size-small"
|
||||
data-analytics
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="View as JSON (Bucket)">
|
||||
View as JSON
|
||||
</button>
|
||||
</li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> Last Updated: <span data-ls-bind="{{project-bucket.$updatedAt|dateText}}"></span></li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> Created: <span data-ls-bind="{{project-bucket.$createdAt|dateText}}"></span></li>
|
||||
</ul>
|
||||
|
||||
@@ -80,19 +80,19 @@ $smtpEnabled = $this->getParam('smtpEnabled', false);
|
||||
<td data-title="Name: ">
|
||||
<a data-ls-attrs="href=/console/users/user?id={{user.$id}}&project={{router.params.project}}">
|
||||
<span data-ls-bind="{{user.name}}" data-ls-attrs="title={{user.name}}"></span>
|
||||
<span data-ls-if="{{user.name|escape}} === '' && {{user.email}} !== ''">Unknown</span>
|
||||
<span data-ls-if="{{user.name|escape}} === '' && {{user.email}} === ''">Anonymous User</span>
|
||||
<span data-ls-if="{{user.name|escape}} === '' && ({{user.email}} !== '' || {{user.phone}} !== '')">Unknown</span>
|
||||
<span data-ls-if="{{user.name|escape}} === '' && {{user.email}} === '' && {{user.phone}} === ''">Anonymous User</span>
|
||||
</a>
|
||||
</td>
|
||||
<td data-title="Email: ">
|
||||
<small data-ls-bind="{{user.email}}" data-ls-attrs="title={{user.email}}"></span>
|
||||
<span data-ls-bind="{{user.email}}" data-ls-attrs="title={{user.email}}"></span>
|
||||
</td>
|
||||
<td data-title="Status: ">
|
||||
<span data-ls-if="{{user.emailVerification}} === true && {{user.status}} === true">
|
||||
<span data-ls-if="({{user.emailVerification}} || {{user.phoneVerification}}) && {{user.status}} === true">
|
||||
<span class="tag green">Verified</span>
|
||||
</span>
|
||||
|
||||
<span data-ls-if="{{user.emailVerification}} !== true && {{user.status}} === true">
|
||||
<span data-ls-if="!({{user.emailVerification}} || {{user.phoneVerification}}) && {{user.status}} === true">
|
||||
<span class="tag">Unverified</span>
|
||||
</span>
|
||||
|
||||
@@ -453,7 +453,7 @@ $smtpEnabled = $this->getParam('smtpEnabled', false);
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Update Project OAuth2"
|
||||
data-analytics-label="Update Project OAuth2 (<?php echo $this->escape($name); ?>)"
|
||||
data-service="projects.updateOAuth2"
|
||||
data-scope="console"
|
||||
data-event="submit"
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
$provider = $this->getParam('provider', '');
|
||||
?>
|
||||
|
||||
<label for="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid">App ID</label>
|
||||
<input name="appId" id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid" type="text" autocomplete="off" data-ls-bind="{{console-project.provider<?php echo $this->escape(ucfirst($provider)); ?>Appid}}" />
|
||||
<label for="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret">App Secret</label>
|
||||
<input name="clientSecret" id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>ClientSecret" type="text" autocomplete="off" data-ls-bind="{{console-project.provider<?php echo $this->escape(ucfirst($provider)); ?>ClientSecret}}" />
|
||||
<label for="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Endpoint">Endpoint (optional)<span class="tooltip" data-tooltip="If you have self-hosted instance, provide the host."><i class="icon-info-circled"></i></span></label>
|
||||
<input name="endpoint" id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Endpoint" type="text" autocomplete="off" data-ls-bind="{{console-project.provider<?php echo $this->escape(ucfirst($provider)); ?>Endpoint}}" placeholder="https://gitlab.com" />
|
||||
|
||||
<input name="secret" data-forms-oauth-custom="<?php echo $this->escape(ucfirst($provider)); ?>" id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret" type="hidden" autocomplete="off" data-ls-bind="{{console-project.provider<?php echo $this->escape(ucfirst($provider)); ?>Secret}}" />
|
||||
@@ -206,7 +206,16 @@
|
||||
</div>
|
||||
|
||||
<ul class="margin-bottom-large text-fade text-size-small">
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> <button data-ls-ui-trigger="open-json" class="link text-size-small">View as JSON</button></li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i>
|
||||
<button data-ls-ui-trigger="open-json"
|
||||
class="link text-size-small"
|
||||
data-analytics
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="View as JSON (Team)">
|
||||
View as JSON
|
||||
</button>
|
||||
</li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> Created: <span data-ls-bind="{{team.$createdAt|dateText}}"></span></li>
|
||||
</ul>
|
||||
|
||||
|
||||
@@ -286,7 +286,16 @@
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> <button data-ls-ui-trigger="open-update-email" class="link text-size-small">Update Email</button></li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> <button data-ls-ui-trigger="open-update-phone" class="link text-size-small">Update Phone</button></li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> <button data-ls-ui-trigger="open-update-password" class="link text-size-small">Update Password</button></li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> <button data-ls-ui-trigger="open-json" class="link text-size-small">View as JSON</button></li>
|
||||
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i>
|
||||
<button data-ls-ui-trigger="open-json"
|
||||
class="link text-size-small"
|
||||
data-analytics
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="View as JSON (User)">
|
||||
View as JSON
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div data-ls-if="{{user.email}} && {{user.emailVerification}} === false" style="display: none">
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
<?php
|
||||
$new = $this->getParam('new', false);
|
||||
$events = $this->getParam('events', []);
|
||||
$patterns = [];
|
||||
$patterns = [
|
||||
'documents',
|
||||
'documents.create',
|
||||
'documents.update',
|
||||
'documents.delete',
|
||||
];
|
||||
|
||||
foreach ($events as $name => $event) {
|
||||
$patterns[] = $name;
|
||||
@@ -30,7 +35,7 @@ sort($patterns);
|
||||
data-service="projects.getWebhook"
|
||||
data-name="project-webhook"
|
||||
data-scope="console"
|
||||
data-event="load,projects.createWebhook, projects.deleteWebhook, projects.updateWebhook"
|
||||
data-event="load,projects.createWebhook,projects.deleteWebhook,projects.updateWebhook,projects.updateWebhookSignature"
|
||||
data-param-project-id="{{router.params.project}}"
|
||||
data-param-webhook-id="{{router.params.id}}"
|
||||
data-success="trigger"
|
||||
@@ -91,9 +96,6 @@ sort($patterns);
|
||||
<label data-ls-attrs="for=url-{{webhook.$id}}">POST URL</label>
|
||||
<input type="url" class="full-width" data-ls-attrs="id=url-{{project-webhook.$id}}" name="url" required autocomplete="off" placeholder="https://example.com/callback" data-ls-bind="{{project-webhook.url}}" />
|
||||
|
||||
<label data-ls-attrs="for=signatureKey-{{webhook.$id}}">Signature Key</label>
|
||||
<input type="text" class="full-width" data-ls-attrs="id=signatureKey-{{project-webhook.$id}}" name="signatureKey" required autocomplete="off" placeholder="ad3d581ca230e2b7059c545e5a" data-ls-bind="{{project-webhook.signatureKey}}" />
|
||||
|
||||
<section class="margin-bottom-small" data-ls-attrs="x-init=load({{project-webhook.events}})">
|
||||
<label class="margin-bottom-small">Events <span class="tooltip small" data-tooltip="Set events that will trigger your webhook."><i class="icon-info-circled"></i></span></label>
|
||||
<div>
|
||||
@@ -159,7 +161,53 @@ sort($patterns);
|
||||
<input id="uid" type="text" autocomplete="off" placeholder="" data-ls-bind="{{project-webhook.$id}}" disabled data-forms-copy>
|
||||
</div>
|
||||
|
||||
<form class="margin-bottom" data-analytics data-analytics-activity data-analytics-event="submit" data-analytics-category="console" data-analytics-label="Delete Project Webhook" data-service="projects.deleteWebhook" data-scope="console" data-event="submit" data-confirm="Are you sure you want to delete this webhook?" data-success="alert,redirect" data-success-param-redirect-url="/console/webhooks?project={{router.params.project}}" data-success-param-alert-text="Deleted webhook successfully" data-success-param-trigger-events="projects.deleteWebhook" data-failure="alert" data-failure-param-alert-text="Failed to delete webhook" data-failure-param-alert-classname="error">
|
||||
<label>Signature Key <span class="tooltip small" data-tooltip="Can be used to validate your Webhooks."><i class="icon-info-circled"></i></span></label>
|
||||
<div class="input-copy margin-bottom">
|
||||
<input id="signatureKey" type="text" autocomplete="off" placeholder="" data-ls-bind="{{project-webhook.signatureKey}}" disabled data-forms-copy>
|
||||
</div>
|
||||
|
||||
<form
|
||||
class="margin-bottom"
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Update Project Webhook Signature"
|
||||
data-service="projects.updateWebhookSignature"
|
||||
data-scope="console"
|
||||
data-event="submit"
|
||||
data-confirm="Are you sure you want to generate a new Signature Key?"
|
||||
data-success="trigger"
|
||||
data-success-param-alert-text="Updated webhook signature key successfully"
|
||||
data-success-param-trigger-events="projects.updateWebhookSignature"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to update webhook signature key"
|
||||
data-failure-param-alert-classname="error">
|
||||
|
||||
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
|
||||
<input type="hidden" name="webhookId" data-ls-bind="{{project-webhook.$id}}" />
|
||||
|
||||
<button class="fill">Update Signature Key</button>
|
||||
</form>
|
||||
|
||||
<form
|
||||
class="margin-bottom"
|
||||
data-analytics
|
||||
data-analytics-activity
|
||||
data-analytics-event="submit"
|
||||
data-analytics-category="console"
|
||||
data-analytics-label="Delete Project Webhook"
|
||||
data-service="projects.deleteWebhook"
|
||||
data-scope="console"
|
||||
data-event="submit"
|
||||
data-confirm="Are you sure you want to delete this webhook?"
|
||||
data-success="alert,redirect"
|
||||
data-success-param-redirect-url="/console/webhooks?project={{router.params.project}}"
|
||||
data-success-param-alert-text="Deleted webhook successfully"
|
||||
data-success-param-trigger-events="projects.deleteWebhook"
|
||||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to delete webhook"
|
||||
data-failure-param-alert-classname="error">
|
||||
|
||||
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
|
||||
<input type="hidden" name="webhookId" data-ls-bind="{{project-webhook.$id}}" />
|
||||
@@ -190,6 +238,11 @@ sort($patterns);
|
||||
<input id="subResource" type="text" :placeholder="subResourceName" x-model="subResource" maxlength="36" pattern="^[a-zA-Z0-9][a-zA-Z0-9_-]{0,35}$">
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Leave empty for wildcard</div>
|
||||
</div>
|
||||
<div x-show="hasSubSubResource">
|
||||
<label x-text="subSubResourceName + ' (optional)'" for="subSubResource"></label>
|
||||
<input id="subSubResource" type="text" :placeholder="subSubResourceName" x-model="subSubResource" maxlength="36" pattern="^[a-zA-Z0-9][a-zA-Z0-9_-]{0,35}$">
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Leave empty for wildcard</div>
|
||||
</div>
|
||||
<div x-show="hasAttribute">
|
||||
<label for="attribute">Add Attribute (optional)</label>
|
||||
<select id="attribute" x-model="attribute">
|
||||
|
||||
@@ -149,6 +149,8 @@ services:
|
||||
- _APP_MAINTENANCE_RETENTION_EXECUTION
|
||||
- _APP_MAINTENANCE_RETENTION_ABUSE
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||
- _APP_PHONE_PROVIDER
|
||||
- _APP_PHONE_SECRET
|
||||
|
||||
appwrite-realtime:
|
||||
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
|
||||
@@ -295,11 +297,11 @@ services:
|
||||
- _APP_EXECUTOR_SECRET
|
||||
- _APP_EXECUTOR_HOST
|
||||
|
||||
appwrite-worker-database:
|
||||
appwrite-worker-databases:
|
||||
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
|
||||
entrypoint: worker-database
|
||||
entrypoint: worker-databases
|
||||
<<: *x-logging
|
||||
container_name: appwrite-worker-database
|
||||
container_name: appwrite-worker-databases
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
@@ -497,6 +499,26 @@ services:
|
||||
- _APP_LOGGING_PROVIDER
|
||||
- _APP_LOGGING_CONFIG
|
||||
|
||||
appwrite-worker-messaging:
|
||||
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
|
||||
entrypoint: worker-messaging
|
||||
<<: *x-logging
|
||||
container_name: appwrite-worker-messaging
|
||||
networks:
|
||||
- appwrite
|
||||
depends_on:
|
||||
- redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_PHONE_PROVIDER
|
||||
- _APP_PHONE_FROM
|
||||
- _APP_LOGGING_PROVIDER
|
||||
- _APP_LOGGING_CONFIG
|
||||
|
||||
appwrite-maintenance:
|
||||
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
|
||||
entrypoint: maintenance
|
||||
@@ -593,6 +615,11 @@ services:
|
||||
container_name: appwrite-redis
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
command: >
|
||||
redis-server
|
||||
--maxmemory 512mb
|
||||
--maxmemory-policy allkeys-lru
|
||||
--maxmemory-samples 5
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
|
||||
@@ -23,6 +23,7 @@ class DatabaseV1 extends Worker
|
||||
$project = new Document($this->args['project']);
|
||||
$collection = new Document($this->args['collection'] ?? []);
|
||||
$document = new Document($this->args['document'] ?? []);
|
||||
$database = new Document($this->args['database'] ?? []);
|
||||
|
||||
if ($collection->isEmpty()) {
|
||||
throw new Exception('Missing collection');
|
||||
@@ -34,16 +35,16 @@ class DatabaseV1 extends Worker
|
||||
|
||||
switch (strval($type)) {
|
||||
case DATABASE_TYPE_CREATE_ATTRIBUTE:
|
||||
$this->createAttribute($collection, $document, $project->getId());
|
||||
$this->createAttribute($database, $collection, $document, $project->getId());
|
||||
break;
|
||||
case DATABASE_TYPE_DELETE_ATTRIBUTE:
|
||||
$this->deleteAttribute($collection, $document, $project->getId());
|
||||
$this->deleteAttribute($database, $collection, $document, $project->getId());
|
||||
break;
|
||||
case DATABASE_TYPE_CREATE_INDEX:
|
||||
$this->createIndex($collection, $document, $project->getId());
|
||||
$this->createIndex($database, $collection, $document, $project->getId());
|
||||
break;
|
||||
case DATABASE_TYPE_DELETE_INDEX:
|
||||
$this->deleteIndex($collection, $document, $project->getId());
|
||||
$this->deleteIndex($database, $collection, $document, $project->getId());
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -57,16 +58,18 @@ class DatabaseV1 extends Worker
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Document $database
|
||||
* @param Document $collection
|
||||
* @param Document $attribute
|
||||
* @param string $projectId
|
||||
*/
|
||||
protected function createAttribute(Document $collection, Document $attribute, string $projectId): void
|
||||
protected function createAttribute(Document $database, Document $collection, Document $attribute, string $projectId): void
|
||||
{
|
||||
$dbForConsole = $this->getConsoleDB();
|
||||
$dbForProject = $this->getProjectDB($projectId);
|
||||
|
||||
$events = Event::generateEvents('collections.[collectionId].attributes.[attributeId].update', [
|
||||
$events = Event::generateEvents('databases.[databaseId].collections.[collectionId].attributes.[attributeId].update', [
|
||||
'databaseId' => $database->getId(),
|
||||
'collectionId' => $collection->getId(),
|
||||
'attributeId' => $attribute->getId()
|
||||
]);
|
||||
@@ -89,7 +92,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('database_' . $database->getInternalId() . '_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'));
|
||||
@@ -101,7 +104,7 @@ class DatabaseV1 extends Worker
|
||||
// Pass first, most verbose event pattern
|
||||
event: $events[0],
|
||||
payload: $attribute,
|
||||
project: $project
|
||||
project: $project,
|
||||
);
|
||||
|
||||
Realtime::send(
|
||||
@@ -112,25 +115,28 @@ class DatabaseV1 extends Worker
|
||||
roles: $target['roles'],
|
||||
options: [
|
||||
'projectId' => $projectId,
|
||||
'databaseId' => $database->getId(),
|
||||
'collectionId' => $collection->getId()
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('collections', $collectionId);
|
||||
$dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Document $database
|
||||
* @param Document $collection
|
||||
* @param Document $attribute
|
||||
* @param string $projectId
|
||||
*/
|
||||
protected function deleteAttribute(Document $collection, Document $attribute, string $projectId): void
|
||||
protected function deleteAttribute(Document $database, Document $collection, Document $attribute, string $projectId): void
|
||||
{
|
||||
$dbForConsole = $this->getConsoleDB();
|
||||
$dbForProject = $this->getProjectDB($projectId);
|
||||
|
||||
$events = Event::generateEvents('collections.[collectionId].attributes.[attributeId].delete', [
|
||||
$events = Event::generateEvents('databases.[databaseId].collections.[collectionId].attributes.[attributeId].delete', [
|
||||
'databaseId' => $database->getId(),
|
||||
'collectionId' => $collection->getId(),
|
||||
'attributeId' => $attribute->getId()
|
||||
]);
|
||||
@@ -146,7 +152,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('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) {
|
||||
throw new Exception('Failed to delete Attribute');
|
||||
}
|
||||
$dbForProject->deleteDocument('attributes', $attribute->getId());
|
||||
@@ -169,6 +175,7 @@ class DatabaseV1 extends Worker
|
||||
roles: $target['roles'],
|
||||
options: [
|
||||
'projectId' => $projectId,
|
||||
'databaseId' => $database->getId(),
|
||||
'collectionId' => $collection->getId()
|
||||
]
|
||||
);
|
||||
@@ -218,7 +225,7 @@ class DatabaseV1 extends Worker
|
||||
}
|
||||
|
||||
if ($exists) { // Delete the duplicate if created, else update in db
|
||||
$this->deleteIndex($collection, $index, $projectId);
|
||||
$this->deleteIndex($database, $collection, $index, $projectId);
|
||||
} else {
|
||||
$dbForProject->updateDocument('indexes', $index->getId(), $index);
|
||||
}
|
||||
@@ -226,21 +233,23 @@ class DatabaseV1 extends Worker
|
||||
}
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('collections', $collectionId);
|
||||
$dbForProject->deleteCachedCollection('collection_' . $collection->getInternalId());
|
||||
$dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
$dbForProject->deleteCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Document $database
|
||||
* @param Document $collection
|
||||
* @param Document $index
|
||||
* @param string $projectId
|
||||
*/
|
||||
protected function createIndex(Document $collection, Document $index, string $projectId): void
|
||||
protected function createIndex(Document $database, Document $collection, Document $index, string $projectId): void
|
||||
{
|
||||
$dbForConsole = $this->getConsoleDB();
|
||||
$dbForProject = $this->getProjectDB($projectId);
|
||||
|
||||
$events = Event::generateEvents('collections.[collectionId].indexes.[indexId].update', [
|
||||
$events = Event::generateEvents('databases.[databaseId].collections.[collectionId].indexes.[indexId].update', [
|
||||
'databaseId' => $database->getId(),
|
||||
'collectionId' => $collection->getId(),
|
||||
'indexId' => $index->getId()
|
||||
]);
|
||||
@@ -253,7 +262,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('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $attributes, $lengths, $orders)) {
|
||||
throw new Exception('Failed to create Index');
|
||||
}
|
||||
$dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'available'));
|
||||
@@ -276,25 +285,28 @@ class DatabaseV1 extends Worker
|
||||
roles: $target['roles'],
|
||||
options: [
|
||||
'projectId' => $projectId,
|
||||
'databaseId' => $database->getId(),
|
||||
'collectionId' => $collection->getId()
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('collections', $collectionId);
|
||||
$dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Document $database
|
||||
* @param Document $collection
|
||||
* @param Document $index
|
||||
* @param string $projectId
|
||||
*/
|
||||
protected function deleteIndex(Document $collection, Document $index, string $projectId): void
|
||||
protected function deleteIndex(Document $database, Document $collection, Document $index, string $projectId): void
|
||||
{
|
||||
$dbForConsole = $this->getConsoleDB();
|
||||
$dbForProject = $this->getProjectDB($projectId);
|
||||
|
||||
$events = Event::generateEvents('collections.[collectionId].indexes.[indexId].delete', [
|
||||
$events = Event::generateEvents('databases.[databaseId].collections.[collectionId].indexes.[indexId].delete', [
|
||||
'databaseId' => $database->getId(),
|
||||
'collectionId' => $collection->getId(),
|
||||
'indexId' => $index->getId()
|
||||
]);
|
||||
@@ -303,7 +315,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('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) {
|
||||
throw new Exception('Failed to delete index');
|
||||
}
|
||||
$dbForProject->deleteDocument('indexes', $index->getId());
|
||||
@@ -326,11 +338,12 @@ class DatabaseV1 extends Worker
|
||||
roles: $target['roles'],
|
||||
options: [
|
||||
'projectId' => $projectId,
|
||||
'databaseId' => $database->getId(),
|
||||
'collectionId' => $collection->getId()
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('collections', $collection->getId());
|
||||
$dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collection->getId());
|
||||
}
|
||||
}
|
||||
+26
-3
@@ -44,6 +44,9 @@ class DeletesV1 extends Worker
|
||||
$document = new Document($this->args['document'] ?? []);
|
||||
|
||||
switch ($document->getCollection()) {
|
||||
case DELETE_TYPE_DATABASES:
|
||||
$this->deleteDatabase($document, $project->getId());
|
||||
break;
|
||||
case DELETE_TYPE_COLLECTIONS:
|
||||
$this->deleteCollection($document, $project->getId());
|
||||
break;
|
||||
@@ -76,8 +79,8 @@ class DeletesV1 extends Worker
|
||||
break;
|
||||
|
||||
case DELETE_TYPE_AUDIT:
|
||||
$timestamp = $payload['timestamp'] ?? 0;
|
||||
$document = new Document($payload['document'] ?? []);
|
||||
$timestamp = $this->args['timestamp'] ?? 0;
|
||||
$document = new Document($this->args['document'] ?? []);
|
||||
|
||||
if (!empty($timestamp)) {
|
||||
$this->deleteAuditLogs($this->args['timestamp']);
|
||||
@@ -119,6 +122,25 @@ class DeletesV1 extends Worker
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Document $document database document
|
||||
* @param string $projectId
|
||||
*/
|
||||
protected function deleteDatabase(Document $document, string $projectId): void
|
||||
{
|
||||
$databaseId = $document->getId();
|
||||
|
||||
$dbForProject = $this->getProjectDB($projectId);
|
||||
|
||||
$this->deleteByGroup('database_' . $document->getInternalId(), [], $dbForProject, function ($document) use ($projectId) {
|
||||
$this->deleteCollection($document, $projectId);
|
||||
});
|
||||
|
||||
$dbForProject->deleteCollection('database_' . $document->getInternalId());
|
||||
|
||||
$this->deleteAuditLogsByResource('database/' . $databaseId, $projectId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Document $document teams document
|
||||
* @param string $projectId
|
||||
@@ -126,10 +148,11 @@ class DeletesV1 extends Worker
|
||||
protected function deleteCollection(Document $document, string $projectId): void
|
||||
{
|
||||
$collectionId = $document->getId();
|
||||
$databaseId = str_replace('database_', '', $document->getCollection());
|
||||
|
||||
$dbForProject = $this->getProjectDB($projectId);
|
||||
|
||||
$dbForProject->deleteCollection('collection_' . $document->getInternalId());
|
||||
$dbForProject->deleteCollection('database_' . $databaseId . '_collection_' . $document->getInternalId());
|
||||
|
||||
$this->deleteByGroup('attributes', [
|
||||
new Query('collectionId', Query::TYPE_EQUAL, [$collectionId])
|
||||
|
||||
@@ -5,6 +5,8 @@ use Appwrite\Auth\Phone\Mock;
|
||||
use Appwrite\Auth\Phone\Telesign;
|
||||
use Appwrite\Auth\Phone\TextMagic;
|
||||
use Appwrite\Auth\Phone\Twilio;
|
||||
use Appwrite\Auth\Phone\Msg91;
|
||||
use Appwrite\Auth\Phone\Vonage;
|
||||
use Appwrite\DSN\DSN;
|
||||
use Appwrite\Resque\Worker;
|
||||
use Utopia\App;
|
||||
@@ -36,8 +38,12 @@ class MessagingV1 extends Worker
|
||||
'twilio' => new Twilio($user, $secret),
|
||||
'text-magic' => new TextMagic($user, $secret),
|
||||
'telesign' => new Telesign($user, $secret),
|
||||
'msg91' => new Msg91($user, $secret),
|
||||
'vonage' => new Vonage($user, $secret),
|
||||
default => null
|
||||
};
|
||||
|
||||
$this->from = App::getEnv('_APP_PHONE_FROM');
|
||||
}
|
||||
|
||||
public function run(): void
|
||||
@@ -47,6 +53,11 @@ class MessagingV1 extends Worker
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($this->from)) {
|
||||
Console::info('Skipped sms processing. No phone number has been set.');
|
||||
return;
|
||||
}
|
||||
|
||||
$recipient = $this->args['recipient'];
|
||||
$message = $this->args['message'];
|
||||
|
||||
|
||||
@@ -7,4 +7,4 @@ else
|
||||
REDIS_BACKEND="redis://${_APP_REDIS_USER}:${_APP_REDIS_PASS}@${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
|
||||
fi
|
||||
|
||||
INTERVAL=0.1 QUEUE='v1-database' APP_INCLUDE='/usr/src/code/app/workers/database.php' php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php
|
||||
INTERVAL=0.1 QUEUE='v1-database' APP_INCLUDE='/usr/src/code/app/workers/databases.php' php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php
|
||||
+11
-6
@@ -9,6 +9,11 @@
|
||||
"email": "eldad@appwrite.io"
|
||||
}
|
||||
],
|
||||
"scripts": {
|
||||
"test": "vendor/bin/phpunit",
|
||||
"lint": "vendor/bin/phpcs",
|
||||
"format": "vendor/bin/phpcbf"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Appwrite\\": "src/Appwrite",
|
||||
@@ -36,14 +41,14 @@
|
||||
"ext-zlib": "*",
|
||||
"ext-sockets": "*",
|
||||
"appwrite/php-clamav": "1.1.*",
|
||||
"appwrite/php-runtimes": "0.9.*",
|
||||
"appwrite/php-runtimes": "0.10.*",
|
||||
"utopia-php/framework": "0.19.*",
|
||||
"utopia-php/logger": "0.3.*",
|
||||
"utopia-php/abuse": "0.7.*",
|
||||
"utopia-php/analytics": "0.2.*",
|
||||
"utopia-php/audit": "0.8.*",
|
||||
"utopia-php/cache": "0.6.*",
|
||||
"utopia-php/cli": "0.12.*",
|
||||
"utopia-php/cli": "0.13.*",
|
||||
"utopia-php/config": "0.2.*",
|
||||
"utopia-php/database": "0.18.*",
|
||||
"utopia-php/locale": "0.4.*",
|
||||
@@ -54,7 +59,7 @@
|
||||
"utopia-php/storage": "0.9.*",
|
||||
"utopia-php/websocket": "0.1.0",
|
||||
"utopia-php/image": "0.5.*",
|
||||
"utopia-php/orchestration": "0.4.*",
|
||||
"utopia-php/orchestration": "0.6.*",
|
||||
"resque/php-resque": "1.3.6",
|
||||
"matomo/device-detector": "6.0.0",
|
||||
"dragonmantank/cron-expression": "3.3.1",
|
||||
@@ -62,8 +67,7 @@
|
||||
"phpmailer/phpmailer": "6.6.0",
|
||||
"chillerlan/php-qrcode": "4.3.3",
|
||||
"adhocore/jwt": "1.1.2",
|
||||
"slickdeals/statsd": "3.1.0",
|
||||
"squizlabs/php_codesniffer": "^3.6"
|
||||
"slickdeals/statsd": "3.1.0"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
@@ -72,8 +76,9 @@
|
||||
}
|
||||
],
|
||||
"require-dev": {
|
||||
"appwrite/sdk-generator": "0.18.8",
|
||||
"appwrite/sdk-generator": "0.19.5",
|
||||
"phpunit/phpunit": "9.5.20",
|
||||
"squizlabs/php_codesniffer": "^3.6",
|
||||
"swoole/ide-helper": "4.8.9",
|
||||
"textalk/websocket": "1.5.7"
|
||||
},
|
||||
|
||||
Generated
+79
-79
@@ -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": "1593c7304ba026d4073de336227858f3",
|
||||
"content-hash": "677b1b47c8567f0b7b05645e2bbc7bc7",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/jwt",
|
||||
@@ -115,11 +115,11 @@
|
||||
},
|
||||
{
|
||||
"name": "appwrite/php-runtimes",
|
||||
"version": "0.9.1",
|
||||
"version": "0.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/appwrite/runtimes.git",
|
||||
"reference": "01acf8741f539f64248d54a9f0f6c4d39195d16c"
|
||||
"reference": "09874846c6bdb7be58c97b12323d2b35ec995409"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0",
|
||||
@@ -154,7 +154,7 @@
|
||||
"php",
|
||||
"runtimes"
|
||||
],
|
||||
"time": "2022-05-19T11:48:16+00:00"
|
||||
"time": "2022-06-28T05:26:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "chillerlan/php-qrcode",
|
||||
@@ -1581,62 +1581,6 @@
|
||||
},
|
||||
"time": "2021-06-04T20:33:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "squizlabs/php_codesniffer",
|
||||
"version": "3.7.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
|
||||
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619",
|
||||
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"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": "2022-06-18T07:21:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
"version": "v3.1.1",
|
||||
@@ -2003,16 +1947,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/cli",
|
||||
"version": "0.12.0",
|
||||
"version": "0.13.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/cli.git",
|
||||
"reference": "6d164b752efeb1ca089e3a517bc274d8b383474b"
|
||||
"reference": "69e68f8ed525fe162fae950a0507ed28a0f179bc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/cli/zipball/6d164b752efeb1ca089e3a517bc274d8b383474b",
|
||||
"reference": "6d164b752efeb1ca089e3a517bc274d8b383474b",
|
||||
"url": "https://api.github.com/repos/utopia-php/cli/zipball/69e68f8ed525fe162fae950a0507ed28a0f179bc",
|
||||
"reference": "69e68f8ed525fe162fae950a0507ed28a0f179bc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2050,9 +1994,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/cli/issues",
|
||||
"source": "https://github.com/utopia-php/cli/tree/0.12.0"
|
||||
"source": "https://github.com/utopia-php/cli/tree/0.13.0"
|
||||
},
|
||||
"time": "2022-02-18T22:10:41+00:00"
|
||||
"time": "2022-04-26T08:41:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/config",
|
||||
@@ -2443,21 +2387,21 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/orchestration",
|
||||
"version": "0.4.1",
|
||||
"version": "0.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/orchestration.git",
|
||||
"reference": "67cf0ab15a096d274c093ea918aa4ace14ac7af7"
|
||||
"reference": "94263976413871efb6b16157a7101a81df3b6d78"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/orchestration/zipball/67cf0ab15a096d274c093ea918aa4ace14ac7af7",
|
||||
"reference": "67cf0ab15a096d274c093ea918aa4ace14ac7af7",
|
||||
"url": "https://api.github.com/repos/utopia-php/orchestration/zipball/94263976413871efb6b16157a7101a81df3b6d78",
|
||||
"reference": "94263976413871efb6b16157a7101a81df3b6d78",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0",
|
||||
"utopia-php/cli": "0.12.*"
|
||||
"utopia-php/cli": "0.13.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.3",
|
||||
@@ -2492,9 +2436,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/orchestration/issues",
|
||||
"source": "https://github.com/utopia-php/orchestration/tree/0.4.1"
|
||||
"source": "https://github.com/utopia-php/orchestration/tree/0.6.0"
|
||||
},
|
||||
"time": "2022-02-20T09:23:06+00:00"
|
||||
"time": "2022-07-13T16:47:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/preloader",
|
||||
@@ -2884,16 +2828,16 @@
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "appwrite/sdk-generator",
|
||||
"version": "0.18.8",
|
||||
"version": "0.19.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/appwrite/sdk-generator.git",
|
||||
"reference": "8ba45dfb74ff6062f96c0e4d10d7c4fae94768b1"
|
||||
"reference": "04de540cf683e2b08b3192c137dde7f2c37003d9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/8ba45dfb74ff6062f96c0e4d10d7c4fae94768b1",
|
||||
"reference": "8ba45dfb74ff6062f96c0e4d10d7c4fae94768b1",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/04de540cf683e2b08b3192c137dde7f2c37003d9",
|
||||
"reference": "04de540cf683e2b08b3192c137dde7f2c37003d9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2928,9 +2872,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.8"
|
||||
"source": "https://github.com/appwrite/sdk-generator/tree/0.19.5"
|
||||
},
|
||||
"time": "2022-05-19T10:34:06+00:00"
|
||||
"time": "2022-07-06T11:05:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/instantiator",
|
||||
@@ -4963,6 +4907,62 @@
|
||||
],
|
||||
"time": "2020-09-28T06:39:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "squizlabs/php_codesniffer",
|
||||
"version": "3.7.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
|
||||
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619",
|
||||
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"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": "2022-06-18T07:21:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "swoole/ide-helper",
|
||||
"version": "4.8.9",
|
||||
|
||||
+9
-8
@@ -103,7 +103,7 @@ services:
|
||||
- ./phpunit.xml:/usr/src/code/phpunit.xml
|
||||
- ./tests:/usr/src/code/tests
|
||||
- ./app:/usr/src/code/app
|
||||
# - ./vendor:/usr/src/code/vendor
|
||||
# - ./vendor/utopia/database:/usr/src/code/vendor/utopia/database
|
||||
- ./docs:/usr/src/code/docs
|
||||
- ./public:/usr/src/code/public
|
||||
- ./src:/usr/src/code/src
|
||||
@@ -176,8 +176,6 @@ services:
|
||||
- _APP_MAINTENANCE_RETENTION_ABUSE
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||
- _APP_PHONE_PROVIDER
|
||||
- _APP_PHONE_FROM
|
||||
- _APP_PHONE_USER
|
||||
- _APP_PHONE_SECRET
|
||||
|
||||
appwrite-realtime:
|
||||
@@ -321,10 +319,10 @@ services:
|
||||
- _APP_EXECUTOR_SECRET
|
||||
- _APP_EXECUTOR_HOST
|
||||
|
||||
appwrite-worker-database:
|
||||
entrypoint: worker-database
|
||||
appwrite-worker-databases:
|
||||
entrypoint: worker-databases
|
||||
<<: *x-logging
|
||||
container_name: appwrite-worker-database
|
||||
container_name: appwrite-worker-databases
|
||||
build:
|
||||
context: .
|
||||
networks:
|
||||
@@ -548,8 +546,6 @@ services:
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_PHONE_PROVIDER
|
||||
- _APP_PHONE_USER
|
||||
- _APP_PHONE_SECRET
|
||||
- _APP_PHONE_FROM
|
||||
- _APP_LOGGING_PROVIDER
|
||||
- _APP_LOGGING_CONFIG
|
||||
@@ -675,6 +671,11 @@ services:
|
||||
image: redis:6.2-alpine
|
||||
<<: *x-logging
|
||||
container_name: appwrite-redis
|
||||
command: >
|
||||
redis-server
|
||||
--maxmemory 512mb
|
||||
--maxmemory-policy allkeys-lru
|
||||
--maxmemory-samples 5
|
||||
ports:
|
||||
- "6379:6379"
|
||||
networks:
|
||||
|
||||
+3
-3
@@ -3,7 +3,7 @@ import android.os.Bundle
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import io.appwrite.Client
|
||||
import io.appwrite.services.Database
|
||||
import io.appwrite.services.Databases
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
@@ -16,9 +16,9 @@ public class MainActivity extends AppCompatActivity {
|
||||
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
|
||||
.setProject("5df5acd0d48c2"); // Your project ID
|
||||
|
||||
Database database = new Database(client);
|
||||
Databases databases = new Databases(client, "[DATABASE_ID]");
|
||||
|
||||
database.createDocument(
|
||||
databases.createDocument(
|
||||
"[COLLECTION_ID]",
|
||||
"[DOCUMENT_ID]",
|
||||
mapOf( "a" to "b" ),
|
||||
+3
-3
@@ -3,7 +3,7 @@ import android.os.Bundle
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import io.appwrite.Client
|
||||
import io.appwrite.services.Database
|
||||
import io.appwrite.services.Databases
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
@@ -16,9 +16,9 @@ public class MainActivity extends AppCompatActivity {
|
||||
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
|
||||
.setProject("5df5acd0d48c2"); // Your project ID
|
||||
|
||||
Database database = new Database(client);
|
||||
Databases databases = new Databases(client, "[DATABASE_ID]");
|
||||
|
||||
database.deleteDocument(
|
||||
databases.deleteDocument(
|
||||
"[COLLECTION_ID]",
|
||||
"[DOCUMENT_ID]"
|
||||
new Continuation<Object>() {
|
||||
+3
-3
@@ -3,7 +3,7 @@ import android.os.Bundle
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import io.appwrite.Client
|
||||
import io.appwrite.services.Database
|
||||
import io.appwrite.services.Databases
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
@@ -16,9 +16,9 @@ public class MainActivity extends AppCompatActivity {
|
||||
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
|
||||
.setProject("5df5acd0d48c2"); // Your project ID
|
||||
|
||||
Database database = new Database(client);
|
||||
Databases databases = new Databases(client, "[DATABASE_ID]");
|
||||
|
||||
database.getDocument(
|
||||
databases.getDocument(
|
||||
"[COLLECTION_ID]",
|
||||
"[DOCUMENT_ID]"
|
||||
new Continuation<Object>() {
|
||||
+3
-3
@@ -3,7 +3,7 @@ import android.os.Bundle
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import io.appwrite.Client
|
||||
import io.appwrite.services.Database
|
||||
import io.appwrite.services.Databases
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
@@ -16,9 +16,9 @@ public class MainActivity extends AppCompatActivity {
|
||||
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
|
||||
.setProject("5df5acd0d48c2"); // Your project ID
|
||||
|
||||
Database database = new Database(client);
|
||||
Databases databases = new Databases(client, "[DATABASE_ID]");
|
||||
|
||||
database.listDocuments(
|
||||
databases.listDocuments(
|
||||
"[COLLECTION_ID]",
|
||||
new Continuation<Object>() {
|
||||
@NotNull
|
||||
+3
-4
@@ -3,7 +3,7 @@ import android.os.Bundle
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import io.appwrite.Client
|
||||
import io.appwrite.services.Database
|
||||
import io.appwrite.services.Databases
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
@@ -16,12 +16,11 @@ public class MainActivity extends AppCompatActivity {
|
||||
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
|
||||
.setProject("5df5acd0d48c2"); // Your project ID
|
||||
|
||||
Database database = new Database(client);
|
||||
Databases databases = new Databases(client, "[DATABASE_ID]");
|
||||
|
||||
database.updateDocument(
|
||||
databases.updateDocument(
|
||||
"[COLLECTION_ID]",
|
||||
"[DOCUMENT_ID]",
|
||||
mapOf( "a" to "b" ),
|
||||
new Continuation<Object>() {
|
||||
@NotNull
|
||||
@Override
|
||||
@@ -21,7 +21,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
storage.createFile(
|
||||
"[BUCKET_ID]",
|
||||
"[FILE_ID]",
|
||||
File("file.png"),
|
||||
InputFile.fromPath("file.png"),
|
||||
new Continuation<Object>() {
|
||||
@NotNull
|
||||
@Override
|
||||
|
||||
+3
-3
@@ -3,7 +3,7 @@ import android.os.Bundle
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import io.appwrite.Client
|
||||
import io.appwrite.services.Database
|
||||
import io.appwrite.services.Databases
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -14,10 +14,10 @@ class MainActivity : AppCompatActivity() {
|
||||
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
|
||||
.setProject("5df5acd0d48c2") // Your project ID
|
||||
|
||||
val database = Database(client)
|
||||
val databases = Databases(client, "[DATABASE_ID]")
|
||||
|
||||
GlobalScope.launch {
|
||||
val response = database.createDocument(
|
||||
val response = databases.createDocument(
|
||||
collectionId = "[COLLECTION_ID]",
|
||||
documentId = "[DOCUMENT_ID]",
|
||||
data = mapOf( "a" to "b" ),
|
||||
+3
-3
@@ -3,7 +3,7 @@ import android.os.Bundle
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import io.appwrite.Client
|
||||
import io.appwrite.services.Database
|
||||
import io.appwrite.services.Databases
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -14,10 +14,10 @@ class MainActivity : AppCompatActivity() {
|
||||
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
|
||||
.setProject("5df5acd0d48c2") // Your project ID
|
||||
|
||||
val database = Database(client)
|
||||
val databases = Databases(client, "[DATABASE_ID]")
|
||||
|
||||
GlobalScope.launch {
|
||||
val response = database.deleteDocument(
|
||||
val response = databases.deleteDocument(
|
||||
collectionId = "[COLLECTION_ID]",
|
||||
documentId = "[DOCUMENT_ID]"
|
||||
)
|
||||
+3
-3
@@ -3,7 +3,7 @@ import android.os.Bundle
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import io.appwrite.Client
|
||||
import io.appwrite.services.Database
|
||||
import io.appwrite.services.Databases
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -14,10 +14,10 @@ class MainActivity : AppCompatActivity() {
|
||||
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
|
||||
.setProject("5df5acd0d48c2") // Your project ID
|
||||
|
||||
val database = Database(client)
|
||||
val databases = Databases(client, "[DATABASE_ID]")
|
||||
|
||||
GlobalScope.launch {
|
||||
val response = database.getDocument(
|
||||
val response = databases.getDocument(
|
||||
collectionId = "[COLLECTION_ID]",
|
||||
documentId = "[DOCUMENT_ID]"
|
||||
)
|
||||
+3
-3
@@ -3,7 +3,7 @@ import android.os.Bundle
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import io.appwrite.Client
|
||||
import io.appwrite.services.Database
|
||||
import io.appwrite.services.Databases
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -14,10 +14,10 @@ class MainActivity : AppCompatActivity() {
|
||||
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
|
||||
.setProject("5df5acd0d48c2") // Your project ID
|
||||
|
||||
val database = Database(client)
|
||||
val databases = Databases(client, "[DATABASE_ID]")
|
||||
|
||||
GlobalScope.launch {
|
||||
val response = database.listDocuments(
|
||||
val response = databases.listDocuments(
|
||||
collectionId = "[COLLECTION_ID]",
|
||||
)
|
||||
val json = response.body?.string()
|
||||
+3
-4
@@ -3,7 +3,7 @@ import android.os.Bundle
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import io.appwrite.Client
|
||||
import io.appwrite.services.Database
|
||||
import io.appwrite.services.Databases
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -14,13 +14,12 @@ class MainActivity : AppCompatActivity() {
|
||||
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
|
||||
.setProject("5df5acd0d48c2") // Your project ID
|
||||
|
||||
val database = Database(client)
|
||||
val databases = Databases(client, "[DATABASE_ID]")
|
||||
|
||||
GlobalScope.launch {
|
||||
val response = database.updateDocument(
|
||||
val response = databases.updateDocument(
|
||||
collectionId = "[COLLECTION_ID]",
|
||||
documentId = "[DOCUMENT_ID]",
|
||||
data = mapOf( "a" to "b" ),
|
||||
)
|
||||
val json = response.body?.string()
|
||||
}
|
||||
@@ -20,7 +20,7 @@ class MainActivity : AppCompatActivity() {
|
||||
val response = storage.createFile(
|
||||
bucketId = "[BUCKET_ID]",
|
||||
fileId = "[FILE_ID]",
|
||||
file = File("file.png"),
|
||||
file = InputFile.fromPath("file.png"),
|
||||
)
|
||||
val json = response.body?.string()
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ func main() async throws {
|
||||
.setProject("5df5acd0d48c2") // Your project ID
|
||||
let account = Account(client)
|
||||
let user = try await account.updatePrefs(
|
||||
prefs:
|
||||
prefs: [:]
|
||||
)
|
||||
|
||||
print(String(describing: user)
|
||||
|
||||
+3
-3
@@ -4,11 +4,11 @@ func main() async throws {
|
||||
let client = Client()
|
||||
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
|
||||
.setProject("5df5acd0d48c2") // Your project ID
|
||||
let database = Database(client)
|
||||
let document = try await database.createDocument(
|
||||
let databases = Databases(client, "[DATABASE_ID]")
|
||||
let document = try await databases.createDocument(
|
||||
collectionId: "[COLLECTION_ID]",
|
||||
documentId: "[DOCUMENT_ID]",
|
||||
data:
|
||||
data: [:]
|
||||
)
|
||||
|
||||
print(String(describing: document)
|
||||
+2
-2
@@ -4,8 +4,8 @@ func main() async throws {
|
||||
let client = Client()
|
||||
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
|
||||
.setProject("5df5acd0d48c2") // Your project ID
|
||||
let database = Database(client)
|
||||
let result = try await database.deleteDocument(
|
||||
let databases = Databases(client, "[DATABASE_ID]")
|
||||
let result = try await databases.deleteDocument(
|
||||
collectionId: "[COLLECTION_ID]",
|
||||
documentId: "[DOCUMENT_ID]"
|
||||
)
|
||||
+2
-2
@@ -4,8 +4,8 @@ func main() async throws {
|
||||
let client = Client()
|
||||
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
|
||||
.setProject("5df5acd0d48c2") // Your project ID
|
||||
let database = Database(client)
|
||||
let document = try await database.getDocument(
|
||||
let databases = Databases(client, "[DATABASE_ID]")
|
||||
let document = try await databases.getDocument(
|
||||
collectionId: "[COLLECTION_ID]",
|
||||
documentId: "[DOCUMENT_ID]"
|
||||
)
|
||||
+2
-2
@@ -4,8 +4,8 @@ func main() async throws {
|
||||
let client = Client()
|
||||
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
|
||||
.setProject("5df5acd0d48c2") // Your project ID
|
||||
let database = Database(client)
|
||||
let documentList = try await database.listDocuments(
|
||||
let databases = Databases(client, "[DATABASE_ID]")
|
||||
let documentList = try await databases.listDocuments(
|
||||
collectionId: "[COLLECTION_ID]"
|
||||
)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user