mirror of
https://github.com/appwrite/appwrite
synced 2026-04-21 13:37:16 +00:00
Merge remote-tracking branch 'origin/feat-mongodb' into feat-installer
# Conflicts: # .github/workflows/tests.yml # Dockerfile # app/views/install/compose.phtml # composer.lock # mongo-entrypoint.sh # src/Appwrite/Platform/Tasks/Install.php # src/Appwrite/Platform/Tasks/Upgrade.php # tests/e2e/Client.php # tests/e2e/Services/Databases/DatabasesBase.php # tests/e2e/Services/Databases/Legacy/DatabasesCustomClientTest.php # tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php # tests/e2e/Services/Databases/TablesDB/DatabasesBase.php # tests/e2e/Services/Databases/TablesDB/DatabasesCustomClientTest.php # tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php # tests/e2e/Services/Databases/Transactions/TransactionsBase.php # tests/e2e/Services/GraphQL/Legacy/DatabaseServerTest.php # tests/e2e/Services/GraphQL/TablesDB/DatabaseServerTest.php # tests/e2e/Services/Projects/ProjectsConsoleClientTest.php # tests/e2e/Services/Teams/TeamsCustomClientTest.php
This commit is contained in:
commit
b41678d57a
462 changed files with 12441 additions and 8860 deletions
8
.env
8
.env
|
|
@ -10,6 +10,7 @@ _APP_CONSOLE_SESSION_ALERTS=enabled
|
|||
_APP_CONSOLE_WHITELIST_IPS=
|
||||
_APP_CONSOLE_COUNTRIES_DENYLIST=AQ
|
||||
_APP_CONSOLE_HOSTNAMES=localhost,appwrite.io,*.appwrite.io
|
||||
_APP_MIGRATION_HOST=appwrite
|
||||
_APP_SYSTEM_EMAIL_NAME=Appwrite
|
||||
_APP_SYSTEM_EMAIL_ADDRESS=noreply@appwrite.io
|
||||
_APP_SYSTEM_TEAM_EMAIL=team@appwrite.io
|
||||
|
|
@ -25,6 +26,7 @@ _APP_OPENSSL_KEY_V1=your-secret-key
|
|||
_APP_DNS=172.16.238.100 # CoreDNS
|
||||
_APP_DOMAIN=appwrite.test
|
||||
_APP_CONSOLE_DOMAIN=localhost
|
||||
_APP_CONSOLE_TRUSTED_PROJECTS=trusted-project,another-trusted-project
|
||||
_APP_DOMAIN_FUNCTIONS=functions.localhost
|
||||
_APP_DOMAIN_SITES=sites.localhost,rebranded.localhost
|
||||
_APP_DOMAIN_TARGET_CNAME=cname.localhost
|
||||
|
|
@ -36,8 +38,10 @@ _APP_REDIS_HOST=redis
|
|||
_APP_REDIS_PORT=6379
|
||||
_APP_REDIS_PASS=
|
||||
_APP_REDIS_USER=
|
||||
_APP_DB_HOST=mariadb
|
||||
_APP_DB_PORT=3306
|
||||
COMPOSE_PROFILES=mongodb
|
||||
_APP_DB_ADAPTER=mongodb
|
||||
_APP_DB_HOST=mongodb
|
||||
_APP_DB_PORT=27017
|
||||
_APP_DB_SCHEMA=appwrite
|
||||
_APP_DB_USER=user
|
||||
_APP_DB_PASS=password
|
||||
|
|
|
|||
8
.github/workflows/benchmark.yml
vendored
8
.github/workflows/benchmark.yml
vendored
|
|
@ -3,6 +3,7 @@ concurrency:
|
|||
group: '${{ github.workflow }}-${{ github.ref }}'
|
||||
cancel-in-progress: true
|
||||
env:
|
||||
COMPOSE_FILE: docker-compose.yml
|
||||
IMAGE: appwrite-dev
|
||||
CACHE_KEY: 'appwrite-dev-${{ github.event.pull_request.head.sha }}'
|
||||
'on':
|
||||
|
|
@ -13,7 +14,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Set up Docker Buildx
|
||||
|
|
@ -28,6 +29,7 @@ jobs:
|
|||
cache-from: type=gha
|
||||
cache-to: 'type=gha,mode=max'
|
||||
outputs: 'type=docker,dest=/tmp/${{ env.IMAGE }}.tar'
|
||||
target: development
|
||||
build-args: |
|
||||
DEBUG=false
|
||||
TESTING=true
|
||||
|
|
@ -45,7 +47,7 @@ jobs:
|
|||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
|
|
@ -97,7 +99,7 @@ jobs:
|
|||
echo "| 200 | $(jq -r '.statusCodeDistribution."200"|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark.json) | $(jq -r '.statusCodeDistribution."200"|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark-latest.json) | " >> benchmark.txt
|
||||
echo "| P99 | $(jq -r '.latencyPercentiles.p99' benchmark.json ) | $(jq -r '.latencyPercentiles.p99' benchmark-latest.json ) | " >> benchmark.txt
|
||||
- name: Save results
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
if: '${{ !cancelled() }}'
|
||||
with:
|
||||
name: benchmark.json
|
||||
|
|
|
|||
2
.github/workflows/cleanup-cache.yml
vendored
2
.github/workflows/cleanup-cache.yml
vendored
|
|
@ -10,7 +10,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cleanup
|
||||
run: |
|
||||
|
|
|
|||
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
|
|
@ -34,7 +34,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
|
|
|
|||
6
.github/workflows/linter.yml
vendored
6
.github/workflows/linter.yml
vendored
|
|
@ -12,7 +12,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
|
|
@ -20,9 +20,9 @@ jobs:
|
|||
|
||||
- name: Validate composer.json and composer.lock
|
||||
run: |
|
||||
docker run --rm -v $PWD:/app composer sh -c \
|
||||
docker run --rm -v $PWD:/app composer:2.8 sh -c \
|
||||
"composer validate"
|
||||
- name: Run Linter
|
||||
run: |
|
||||
docker run --rm -v $PWD:/app composer sh -c \
|
||||
docker run --rm -v $PWD:/app composer:2.8 sh -c \
|
||||
"composer install --profile --ignore-platform-reqs && composer lint"
|
||||
|
|
|
|||
6
.github/workflows/nightly.yml
vendored
6
.github/workflows/nightly.yml
vendored
|
|
@ -10,11 +10,11 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build the Docker image
|
||||
run: docker build . -t appwrite_image:latest
|
||||
run: DOCKER_BUILDKIT=1 docker build . --target production -t appwrite_image:latest
|
||||
- name: Run Trivy vulnerability scanner on image
|
||||
uses: aquasecurity/trivy-action@0.20.0
|
||||
with:
|
||||
|
|
@ -33,7 +33,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
- name: Run Trivy vulnerability scanner on filesystem
|
||||
uses: aquasecurity/trivy-action@0.20.0
|
||||
with:
|
||||
|
|
|
|||
9
.github/workflows/pr-scan.yml
vendored
9
.github/workflows/pr-scan.yml
vendored
|
|
@ -11,19 +11,20 @@ jobs:
|
|||
pull-requests: write
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Build the Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: false
|
||||
load: true
|
||||
tags: pr_image:${{ github.sha }}
|
||||
target: production
|
||||
|
||||
- name: Run Trivy vulnerability scanner on image
|
||||
uses: aquasecurity/trivy-action@0.20.0
|
||||
|
|
@ -44,7 +45,7 @@ jobs:
|
|||
|
||||
- name: Process Trivy scan results
|
||||
id: process-results
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
|
|
|||
4
.github/workflows/publish.yml
vendored
4
.github/workflows/publish.yml
vendored
|
|
@ -12,7 +12,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 2
|
||||
submodules: recursive
|
||||
|
|
@ -38,7 +38,7 @@ jobs:
|
|||
type=ref,event=tag
|
||||
|
||||
- name: Build & Publish to DockerHub
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
|
|
|||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
|
|
@ -11,7 +11,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
|
|
@ -42,7 +42,7 @@ jobs:
|
|||
type=semver,pattern={{major}}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
|
|
|||
5
.github/workflows/sdk-preview.yml
vendored
5
.github/workflows/sdk-preview.yml
vendored
|
|
@ -1,5 +1,8 @@
|
|||
name: "SDK Preview"
|
||||
|
||||
env:
|
||||
COMPOSE_FILE: docker-compose.yml
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
|
|
@ -19,7 +22,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set SDK type
|
||||
id: set-sdk
|
||||
|
|
|
|||
4
.github/workflows/static-analysis.yml
vendored
4
.github/workflows/static-analysis.yml
vendored
|
|
@ -8,11 +8,11 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Run CodeQL
|
||||
run: |
|
||||
docker run --rm -v $PWD:/app composer:2.6 sh -c \
|
||||
docker run --rm -v $PWD:/app composer:2.8 sh -c \
|
||||
"composer install --profile --ignore-platform-reqs && composer check"
|
||||
|
||||
- name: Run Locale check
|
||||
|
|
|
|||
268
.github/workflows/tests.yml
vendored
268
.github/workflows/tests.yml
vendored
|
|
@ -5,6 +5,7 @@ concurrency:
|
|||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
COMPOSE_FILE: docker-compose.yml
|
||||
IMAGE: appwrite-dev
|
||||
CACHE_KEY: appwrite-dev-${{ github.event.pull_request.head.sha }}
|
||||
|
||||
|
|
@ -26,7 +27,7 @@ jobs:
|
|||
database_changed: ${{ steps.check.outputs.database_changed }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Fetch base branch
|
||||
run: git fetch origin ${{ github.event.pull_request.base.ref }}
|
||||
|
|
@ -48,7 +49,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
|
@ -65,6 +66,7 @@ jobs:
|
|||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
outputs: type=docker,dest=/tmp/${{ env.IMAGE }}.tar
|
||||
target: development
|
||||
build-args: |
|
||||
DEBUG=false
|
||||
TESTING=true
|
||||
|
|
@ -80,10 +82,13 @@ jobs:
|
|||
name: Unit Test
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
|
|
@ -108,18 +113,28 @@ jobs:
|
|||
run: docker compose exec -T appwrite vars
|
||||
|
||||
- name: Run Unit Tests
|
||||
run: |
|
||||
docker compose exec \
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
|
||||
uses: itznotabug/php-retry@v3
|
||||
with:
|
||||
max_attempts: 3
|
||||
timeout_minutes: 30
|
||||
job_id: ${{ job.check_run_id }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
test_dir: tests/unit
|
||||
command: >-
|
||||
docker compose exec
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}"
|
||||
appwrite test /usr/src/code/tests/unit
|
||||
|
||||
e2e_general_test:
|
||||
name: E2E General Test
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
|
|
@ -143,26 +158,39 @@ jobs:
|
|||
done
|
||||
|
||||
- name: Run General Tests
|
||||
run: |
|
||||
docker compose exec -T \
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
|
||||
uses: itznotabug/php-retry@v3
|
||||
with:
|
||||
max_attempts: 3
|
||||
timeout_minutes: 30
|
||||
job_id: ${{ job.check_run_id }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
test_dir: tests/e2e/General
|
||||
command: >-
|
||||
docker compose exec -T
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}"
|
||||
appwrite test /usr/src/code/tests/e2e/General --debug
|
||||
|
||||
- name: Failure Logs
|
||||
if: failure()
|
||||
run: |
|
||||
echo "=== Appwrite Worker Builds Logs ==="
|
||||
docker compose logs appwrite-worker-builds
|
||||
echo "=== OpenRuntimes Executor Logs ==="
|
||||
docker compose logs openruntimes-executor
|
||||
echo "=== Appwrite Logs ==="
|
||||
docker compose logs
|
||||
|
||||
e2e_service_test:
|
||||
name: E2E Service Test
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
db_adapter: [
|
||||
MARIADB,
|
||||
POSTGRESQL,
|
||||
MONGODB
|
||||
]
|
||||
service: [
|
||||
Account,
|
||||
Avatars,
|
||||
|
|
@ -188,7 +216,7 @@ jobs:
|
|||
]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
|
|
@ -197,10 +225,31 @@ jobs:
|
|||
path: /tmp/${{ env.IMAGE }}.tar
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: Set DB Adapter environment
|
||||
id: set-db-env
|
||||
run: |
|
||||
DB_ADAPTER_LOWER=$(echo "${{ matrix.db_adapter }}" | tr 'A-Z' 'a-z')
|
||||
echo "COMPOSE_PROFILES=${DB_ADAPTER_LOWER}" >> $GITHUB_ENV
|
||||
|
||||
if [ "${{ matrix.db_adapter }}" = "MARIADB" ]; then
|
||||
echo "_APP_DB_ADAPTER=mariadb" >> $GITHUB_ENV
|
||||
echo "_APP_DB_HOST=mariadb" >> $GITHUB_ENV
|
||||
echo "_APP_DB_PORT=3306" >> $GITHUB_ENV
|
||||
elif [ "${{ matrix.db_adapter }}" = "MONGODB" ]; then
|
||||
echo "_APP_DB_ADAPTER=mongodb" >> $GITHUB_ENV
|
||||
echo "_APP_DB_HOST=mongodb" >> $GITHUB_ENV
|
||||
echo "_APP_DB_PORT=27017" >> $GITHUB_ENV
|
||||
elif [ "${{ matrix.db_adapter }}" = "POSTGRESQL" ]; then
|
||||
echo "_APP_DB_ADAPTER=postgresql" >> $GITHUB_ENV
|
||||
echo "_APP_DB_HOST=postgresql" >> $GITHUB_ENV
|
||||
echo "_APP_DB_PORT=5432" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Load and Start Appwrite
|
||||
env:
|
||||
_APP_BROWSER_HOST: http://invalid-browser/v1
|
||||
run: |
|
||||
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||
sed -i 's|^_APP_BROWSER_HOST=.*|_APP_BROWSER_HOST=http://invalid-browser/v1|' .env
|
||||
docker compose up -d
|
||||
sleep 30
|
||||
|
||||
|
|
@ -213,19 +262,29 @@ jobs:
|
|||
done
|
||||
|
||||
- name: Run ${{ matrix.service }} tests with Project table mode
|
||||
run: |
|
||||
echo "Using project tables"
|
||||
export _APP_DATABASE_SHARED_TABLES=
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=
|
||||
uses: itznotabug/php-retry@v3
|
||||
env:
|
||||
_APP_DB_SCHEMA: appwrite
|
||||
with:
|
||||
max_attempts: 3
|
||||
timeout_minutes: 30
|
||||
job_id: ${{ job.check_run_id }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
test_dir: tests/e2e/Services/${{ matrix.service }}
|
||||
command: |
|
||||
echo "Using project tables"
|
||||
|
||||
SERVICE_PATH="/usr/src/code/tests/e2e/Services/${{ matrix.service }}"
|
||||
SERVICE_PATH="/usr/src/code/tests/e2e/Services/${{ matrix.service }}"
|
||||
|
||||
echo "Running with paratest (parallel) for: ${{ matrix.service }}"
|
||||
docker compose exec -T \
|
||||
-e _APP_DATABASE_SHARED_TABLES \
|
||||
-e _APP_DATABASE_SHARED_TABLES_V1 \
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
|
||||
appwrite vendor/bin/paratest --processes $(nproc) "$SERVICE_PATH" --exclude-group abuseEnabled --exclude-group screenshots
|
||||
docker compose exec -T \
|
||||
-e _APP_DATABASE_SHARED_TABLES="" \
|
||||
-e _APP_DATABASE_SHARED_TABLES_V1="" \
|
||||
-e _APP_DB_ADAPTER="${{ env._APP_DB_ADAPTER }}" \
|
||||
-e _APP_DB_HOST="${{ env._APP_DB_HOST }}" \
|
||||
-e _APP_DB_PORT="${{ env._APP_DB_PORT }}" \
|
||||
-e _APP_DB_SCHEMA="${{ env._APP_DB_SCHEMA }}" \
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
|
||||
appwrite vendor/bin/paratest --processes $(nproc) "$SERVICE_PATH" --exclude-group abuseEnabled --exclude-group screenshots
|
||||
|
||||
- name: Failure Logs
|
||||
if: failure()
|
||||
|
|
@ -238,6 +297,9 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
needs: [ setup, check_database_changes ]
|
||||
if: needs.check_database_changes.outputs.database_changed == 'true'
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
|
@ -272,7 +334,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
|
|
@ -328,9 +390,12 @@ jobs:
|
|||
name: E2E Service Test (Abuse enabled)
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
|
|
@ -347,16 +412,23 @@ jobs:
|
|||
sleep 30
|
||||
|
||||
- name: Run Projects tests in dedicated table mode
|
||||
run: |
|
||||
echo "Using project tables"
|
||||
export _APP_DATABASE_SHARED_TABLES=
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=
|
||||
uses: itznotabug/php-retry@v3
|
||||
with:
|
||||
max_attempts: 3
|
||||
timeout_minutes: 30
|
||||
job_id: ${{ job.check_run_id }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
test_dir: tests/e2e/Services/Projects
|
||||
command: |
|
||||
echo "Using project tables"
|
||||
export _APP_DATABASE_SHARED_TABLES=
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=
|
||||
|
||||
docker compose exec -T \
|
||||
-e _APP_DATABASE_SHARED_TABLES \
|
||||
-e _APP_DATABASE_SHARED_TABLES_V1 \
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
|
||||
appwrite test /usr/src/code/tests/e2e/Services/Projects --debug --group=abuseEnabled
|
||||
docker compose exec -T \
|
||||
-e _APP_DATABASE_SHARED_TABLES \
|
||||
-e _APP_DATABASE_SHARED_TABLES_V1 \
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
|
||||
appwrite vendor/bin/paratest --processes $(nproc) /usr/src/code/tests/e2e/Services/Projects --group abuseEnabled
|
||||
|
||||
- name: Failure Logs
|
||||
if: failure()
|
||||
|
|
@ -371,6 +443,9 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
needs: [ setup, check_database_changes ]
|
||||
if: needs.check_database_changes.outputs.database_changed == 'true'
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
|
@ -380,7 +455,7 @@ jobs:
|
|||
]
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
|
|
@ -397,22 +472,29 @@ jobs:
|
|||
sleep 30
|
||||
|
||||
- name: Run Projects tests in ${{ matrix.tables-mode }} table mode
|
||||
run: |
|
||||
if [ "${{ matrix.tables-mode }}" == "Shared V1" ]; then
|
||||
echo "Using shared tables V1"
|
||||
export _APP_DATABASE_SHARED_TABLES=database_db_main
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=database_db_main
|
||||
elif [ "${{ matrix.tables-mode }}" == "Shared V2" ]; then
|
||||
echo "Using shared tables V2"
|
||||
export _APP_DATABASE_SHARED_TABLES=database_db_main
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=
|
||||
fi
|
||||
uses: itznotabug/php-retry@v3
|
||||
with:
|
||||
max_attempts: 3
|
||||
timeout_minutes: 30
|
||||
job_id: ${{ job.check_run_id }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
test_dir: tests/e2e/Services/Projects
|
||||
command: |
|
||||
if [ "${{ matrix.tables-mode }}" == "Shared V1" ]; then
|
||||
echo "Using shared tables V1"
|
||||
export _APP_DATABASE_SHARED_TABLES=database_db_main
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=database_db_main
|
||||
elif [ "${{ matrix.tables-mode }}" == "Shared V2" ]; then
|
||||
echo "Using shared tables V2"
|
||||
export _APP_DATABASE_SHARED_TABLES=database_db_main
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=
|
||||
fi
|
||||
|
||||
docker compose exec -T \
|
||||
-e _APP_DATABASE_SHARED_TABLES \
|
||||
-e _APP_DATABASE_SHARED_TABLES_V1 \
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
|
||||
appwrite test /usr/src/code/tests/e2e/Services/Projects --debug --group=abuseEnabled
|
||||
docker compose exec -T \
|
||||
-e _APP_DATABASE_SHARED_TABLES \
|
||||
-e _APP_DATABASE_SHARED_TABLES_V1 \
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
|
||||
appwrite vendor/bin/paratest --processes $(nproc) /usr/src/code/tests/e2e/Services/Projects --group abuseEnabled
|
||||
|
||||
- name: Failure Logs
|
||||
if: failure()
|
||||
|
|
@ -426,9 +508,12 @@ jobs:
|
|||
name: E2E Service Test (Site Screenshots)
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
|
|
@ -445,17 +530,24 @@ jobs:
|
|||
sleep 30
|
||||
|
||||
- name: Run Site tests with browser connected in dedicated table mode
|
||||
run: |
|
||||
echo "Keeping original value of _APP_BROWSER_HOST"
|
||||
echo "Using project tables"
|
||||
export _APP_DATABASE_SHARED_TABLES=
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=
|
||||
uses: itznotabug/php-retry@v3
|
||||
with:
|
||||
max_attempts: 3
|
||||
timeout_minutes: 30
|
||||
job_id: ${{ job.check_run_id }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
test_dir: tests/e2e/Services/Sites
|
||||
command: |
|
||||
echo "Keeping original value of _APP_BROWSER_HOST"
|
||||
echo "Using project tables"
|
||||
export _APP_DATABASE_SHARED_TABLES=
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=
|
||||
|
||||
docker compose exec -T \
|
||||
-e _APP_DATABASE_SHARED_TABLES \
|
||||
-e _APP_DATABASE_SHARED_TABLES_V1 \
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
|
||||
appwrite test /usr/src/code/tests/e2e/Services/Sites --debug --group=screenshots
|
||||
docker compose exec -T \
|
||||
-e _APP_DATABASE_SHARED_TABLES \
|
||||
-e _APP_DATABASE_SHARED_TABLES_V1 \
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
|
||||
appwrite vendor/bin/paratest --processes $(nproc) /usr/src/code/tests/e2e/Services/Sites --group screenshots
|
||||
|
||||
- name: Failure Logs
|
||||
if: failure()
|
||||
|
|
@ -470,6 +562,9 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
needs: [ setup, check_database_changes ]
|
||||
if: needs.check_database_changes.outputs.database_changed == 'true'
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
|
@ -479,7 +574,7 @@ jobs:
|
|||
]
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
|
|
@ -496,23 +591,30 @@ jobs:
|
|||
sleep 30
|
||||
|
||||
- name: Run Site tests with browser connected in ${{ matrix.tables-mode }} table mode
|
||||
run: |
|
||||
echo "Keeping original value of _APP_BROWSER_HOST"
|
||||
if [ "${{ matrix.tables-mode }}" == "Shared V1" ]; then
|
||||
echo "Using shared tables V1"
|
||||
export _APP_DATABASE_SHARED_TABLES=database_db_main
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=database_db_main
|
||||
elif [ "${{ matrix.tables-mode }}" == "Shared V2" ]; then
|
||||
echo "Using shared tables V2"
|
||||
export _APP_DATABASE_SHARED_TABLES=database_db_main
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=
|
||||
fi
|
||||
uses: itznotabug/php-retry@v3
|
||||
with:
|
||||
max_attempts: 3
|
||||
timeout_minutes: 30
|
||||
job_id: ${{ job.check_run_id }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
test_dir: tests/e2e/Services/Sites
|
||||
command: |
|
||||
echo "Keeping original value of _APP_BROWSER_HOST"
|
||||
if [ "${{ matrix.tables-mode }}" == "Shared V1" ]; then
|
||||
echo "Using shared tables V1"
|
||||
export _APP_DATABASE_SHARED_TABLES=database_db_main
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=database_db_main
|
||||
elif [ "${{ matrix.tables-mode }}" == "Shared V2" ]; then
|
||||
echo "Using shared tables V2"
|
||||
export _APP_DATABASE_SHARED_TABLES=database_db_main
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=
|
||||
fi
|
||||
|
||||
docker compose exec -T \
|
||||
-e _APP_DATABASE_SHARED_TABLES \
|
||||
-e _APP_DATABASE_SHARED_TABLES_V1 \
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
|
||||
appwrite test /usr/src/code/tests/e2e/Services/Sites --debug --group=screenshots
|
||||
docker compose exec -T \
|
||||
-e _APP_DATABASE_SHARED_TABLES \
|
||||
-e _APP_DATABASE_SHARED_TABLES_V1 \
|
||||
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
|
||||
appwrite vendor/bin/paratest --processes $(nproc) /usr/src/code/tests/e2e/Services/Sites --group screenshots
|
||||
|
||||
- name: Failure Logs
|
||||
if: failure()
|
||||
|
|
@ -520,4 +622,4 @@ jobs:
|
|||
echo "=== Appwrite Worker Builds Logs ==="
|
||||
docker compose logs appwrite-worker-builds
|
||||
echo "=== OpenRuntimes Executor Logs ==="
|
||||
docker compose logs openruntimes-executor
|
||||
docker compose logs openruntimes-executor
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ RUN composer install --ignore-platform-reqs --optimize-autoloader \
|
|||
--no-plugins --no-scripts --prefer-dist \
|
||||
`if [ "$TESTING" != "true" ]; then echo "--no-dev"; fi`
|
||||
|
||||
FROM appwrite/base:0.11.5 AS base
|
||||
FROM appwrite/base:1.0.0 AS base
|
||||
|
||||
LABEL maintainer="team@appwrite.io"
|
||||
|
||||
|
|
@ -38,6 +38,7 @@ COPY ./public /usr/src/code/public
|
|||
COPY ./bin /usr/local/bin
|
||||
COPY ./src /usr/src/code/src
|
||||
COPY ./dev /usr/src/code/dev
|
||||
COPY ./mongo-init.js /usr/src/code/mongo-init.js
|
||||
COPY ./mongo-entrypoint.sh /usr/src/code/mongo-entrypoint.sh
|
||||
|
||||
# Set Volumes
|
||||
|
|
@ -83,6 +84,7 @@ RUN chmod +x /usr/local/bin/doctor && \
|
|||
chmod +x /usr/local/bin/worker-certificates && \
|
||||
chmod +x /usr/local/bin/worker-databases && \
|
||||
chmod +x /usr/local/bin/worker-deletes && \
|
||||
chmod +x /usr/local/bin/worker-executions && \
|
||||
chmod +x /usr/local/bin/worker-functions && \
|
||||
chmod +x /usr/local/bin/worker-mails && \
|
||||
chmod +x /usr/local/bin/worker-messaging && \
|
||||
|
|
|
|||
89
app/cli.php
89
app/cli.php
|
|
@ -16,13 +16,13 @@ use Swoole\Timer;
|
|||
use Utopia\Cache\Adapter\Pool as CachePool;
|
||||
use Utopia\Cache\Adapter\Sharding;
|
||||
use Utopia\Cache\Cache;
|
||||
use Utopia\CLI\CLI;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Console;
|
||||
use Utopia\Database\Adapter\Pool as DatabasePool;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\DI\Dependency;
|
||||
use Utopia\DSN\DSN;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\Platform\Service;
|
||||
|
|
@ -45,9 +45,32 @@ Config::setParam('runtimes', (new Runtimes('v5'))->getAll(supported: false));
|
|||
require_once __DIR__ . '/controllers/general.php';
|
||||
|
||||
global $register;
|
||||
CLI::setResource('register', fn () => $register);
|
||||
|
||||
CLI::setResource('cache', function ($pools) {
|
||||
$platform = new Appwrite();
|
||||
$args = $platform->getEnv('argv');
|
||||
|
||||
\array_shift($args);
|
||||
if (!isset($args[0])) {
|
||||
Console::error('Missing task name');
|
||||
Console::exit(1);
|
||||
}
|
||||
|
||||
$taskName = $args[0];
|
||||
$platform->init(Service::TYPE_TASK);
|
||||
$cli = $platform->getCli();
|
||||
|
||||
$setResource = function (string $name, callable $callback, array $injections = []) use ($cli) {
|
||||
$dependency = new Dependency();
|
||||
$dependency->setName($name)->setCallback($callback);
|
||||
foreach ($injections as $injection) {
|
||||
$dependency->inject($injection);
|
||||
}
|
||||
$cli->setResource($dependency);
|
||||
};
|
||||
|
||||
$setResource('register', fn () => $register, []);
|
||||
|
||||
$setResource('cache', function ($pools) {
|
||||
$list = Config::getParam('pools-cache', []);
|
||||
$adapters = [];
|
||||
|
||||
|
|
@ -58,17 +81,17 @@ CLI::setResource('cache', function ($pools) {
|
|||
return new Cache(new Sharding($adapters));
|
||||
}, ['pools']);
|
||||
|
||||
CLI::setResource('pools', function (Registry $register) {
|
||||
$setResource('pools', function (Registry $register) {
|
||||
return $register->get('pools');
|
||||
}, ['register']);
|
||||
|
||||
CLI::setResource('authorization', function () {
|
||||
$setResource('authorization', function () {
|
||||
$authorization = new Authorization();
|
||||
$authorization->disable();
|
||||
return $authorization;
|
||||
}, []);
|
||||
|
||||
CLI::setResource('dbForPlatform', function ($pools, $cache, $authorization) {
|
||||
$setResource('dbForPlatform', function ($pools, $cache, $authorization) {
|
||||
$sleep = 3;
|
||||
$maxAttempts = 5;
|
||||
$attempts = 0;
|
||||
|
|
@ -111,16 +134,17 @@ CLI::setResource('dbForPlatform', function ($pools, $cache, $authorization) {
|
|||
return $dbForPlatform;
|
||||
}, ['pools', 'cache', 'authorization']);
|
||||
|
||||
CLI::setResource('console', function () {
|
||||
$setResource('console', function () {
|
||||
return new Document(Config::getParam('console'));
|
||||
}, []);
|
||||
|
||||
CLI::setResource(
|
||||
$setResource(
|
||||
'isResourceBlocked',
|
||||
fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false
|
||||
fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false,
|
||||
[]
|
||||
);
|
||||
|
||||
CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, $authorization) {
|
||||
$setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache, $authorization) {
|
||||
$databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools
|
||||
|
||||
return function (Document $project) use ($pools, $dbForPlatform, $cache, $authorization, &$databases) {
|
||||
|
|
@ -182,7 +206,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform
|
|||
};
|
||||
}, ['pools', 'dbForPlatform', 'cache', 'authorization']);
|
||||
|
||||
CLI::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) {
|
||||
$setResource('getLogsDB', function (Group $pools, Cache $cache, Authorization $authorization) {
|
||||
$database = null;
|
||||
|
||||
return function (?Document $project = null) use ($pools, $cache, $database, $authorization) {
|
||||
|
|
@ -210,40 +234,40 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorizatio
|
|||
return $database;
|
||||
};
|
||||
}, ['pools', 'cache', 'authorization']);
|
||||
CLI::setResource('publisher', function (Group $pools) {
|
||||
$setResource('publisher', function (Group $pools) {
|
||||
return new BrokerPool(publisher: $pools->get('publisher'));
|
||||
}, ['pools']);
|
||||
CLI::setResource('publisherDatabases', function (BrokerPool $publisher) {
|
||||
$setResource('publisherDatabases', function (BrokerPool $publisher) {
|
||||
return $publisher;
|
||||
}, ['publisher']);
|
||||
CLI::setResource('publisherFunctions', function (BrokerPool $publisher) {
|
||||
$setResource('publisherFunctions', function (BrokerPool $publisher) {
|
||||
return $publisher;
|
||||
}, ['publisher']);
|
||||
CLI::setResource('publisherMigrations', function (BrokerPool $publisher) {
|
||||
$setResource('publisherMigrations', function (BrokerPool $publisher) {
|
||||
return $publisher;
|
||||
}, ['publisher']);
|
||||
CLI::setResource('publisherStatsUsage', function (BrokerPool $publisher) {
|
||||
$setResource('publisherStatsUsage', function (BrokerPool $publisher) {
|
||||
return $publisher;
|
||||
}, ['publisher']);
|
||||
CLI::setResource('publisherMessaging', function (BrokerPool $publisher) {
|
||||
$setResource('publisherMessaging', function (BrokerPool $publisher) {
|
||||
return $publisher;
|
||||
}, ['publisher']);
|
||||
CLI::setResource('queueForStatsUsage', function (Publisher $publisher) {
|
||||
$setResource('queueForStatsUsage', function (Publisher $publisher) {
|
||||
return new StatsUsage($publisher);
|
||||
}, ['publisher']);
|
||||
CLI::setResource('queueForStatsResources', function (Publisher $publisher) {
|
||||
$setResource('queueForStatsResources', function (Publisher $publisher) {
|
||||
return new StatsResources($publisher);
|
||||
}, ['publisher']);
|
||||
CLI::setResource('queueForFunctions', function (Publisher $publisher) {
|
||||
$setResource('queueForFunctions', function (Publisher $publisher) {
|
||||
return new Func($publisher);
|
||||
}, ['publisher']);
|
||||
CLI::setResource('queueForDeletes', function (Publisher $publisher) {
|
||||
$setResource('queueForDeletes', function (Publisher $publisher) {
|
||||
return new Delete($publisher);
|
||||
}, ['publisher']);
|
||||
CLI::setResource('queueForCertificates', function (Publisher $publisher) {
|
||||
$setResource('queueForCertificates', function (Publisher $publisher) {
|
||||
return new Certificate($publisher);
|
||||
}, ['publisher']);
|
||||
CLI::setResource('logError', function (Registry $register) {
|
||||
$setResource('logError', function (Registry $register) {
|
||||
return function (Throwable $error, string $namespace, string $action) use ($register) {
|
||||
Console::error('[Error] Timestamp: ' . date('c', time()));
|
||||
Console::error('[Error] Type: ' . get_class($error));
|
||||
|
|
@ -295,22 +319,9 @@ CLI::setResource('logError', function (Registry $register) {
|
|||
};
|
||||
}, ['register']);
|
||||
|
||||
CLI::setResource('executor', fn () => new Executor());
|
||||
$setResource('executor', fn () => new Executor(), []);
|
||||
|
||||
CLI::setResource('telemetry', fn () => new NoTelemetry());
|
||||
|
||||
$platform = new Appwrite();
|
||||
$args = $platform->getEnv('argv');
|
||||
|
||||
if (!isset($args[0])) {
|
||||
Console::error('Missing task name');
|
||||
Console::exit(1);
|
||||
}
|
||||
|
||||
\array_shift($args);
|
||||
$taskName = $args[0];
|
||||
$platform->init(Service::TYPE_TASK);
|
||||
$cli = $platform->getCli();
|
||||
$setResource('telemetry', fn () => new NoTelemetry(), []);
|
||||
|
||||
$cli
|
||||
->error()
|
||||
|
|
|
|||
|
|
@ -1617,13 +1617,6 @@ return [
|
|||
],
|
||||
],
|
||||
'indexes' => [
|
||||
[
|
||||
'$id' => ID::custom('_fulltext_name'),
|
||||
'type' => Database::INDEX_FULLTEXT,
|
||||
'attributes' => ['name'],
|
||||
'lengths' => [],
|
||||
'orders' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('_key_search'),
|
||||
'type' => Database::INDEX_FULLTEXT,
|
||||
|
|
@ -1853,13 +1846,6 @@ return [
|
|||
'lengths' => [],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('_key_name'),
|
||||
'type' => Database::INDEX_FULLTEXT,
|
||||
'attributes' => ['name'],
|
||||
'lengths' => [],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('_key_type'),
|
||||
'type' => Database::INDEX_KEY,
|
||||
|
|
@ -2127,14 +2113,8 @@ return [
|
|||
'filters' => ['topicSearch'],
|
||||
],
|
||||
],
|
||||
|
||||
'indexes' => [
|
||||
[
|
||||
'$id' => ID::custom('_key_name'),
|
||||
'type' => Database::INDEX_FULLTEXT,
|
||||
'attributes' => ['name'],
|
||||
'lengths' => [],
|
||||
'orders' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('_key_search'),
|
||||
'type' => Database::INDEX_FULLTEXT,
|
||||
|
|
|
|||
|
|
@ -342,6 +342,17 @@ $platformCollections = [
|
|||
'array' => true,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => 'status',
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 100,
|
||||
'signed' => false,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
],
|
||||
'indexes' => [
|
||||
[
|
||||
|
|
|
|||
|
|
@ -139,6 +139,11 @@ return [
|
|||
'description' => 'There was an error processing your request. Please check the inputs and try again.',
|
||||
'code' => 400,
|
||||
],
|
||||
Exception::GENERAL_FEATURE_UNSUPPORTED => [
|
||||
'name' => Exception::GENERAL_FEATURE_UNSUPPORTED,
|
||||
'description' => 'This feature is not supported with your current configuration.',
|
||||
'code' => 400,
|
||||
],
|
||||
|
||||
/** User Errors */
|
||||
Exception::USER_COUNT_EXCEEDED => [
|
||||
|
|
@ -1139,6 +1144,11 @@ return [
|
|||
'description' => 'Key with the requested ID could not be found.',
|
||||
'code' => 404,
|
||||
],
|
||||
Exception::KEY_ALREADY_EXISTS => [
|
||||
'name' => Exception::KEY_ALREADY_EXISTS,
|
||||
'description' => 'Key with the same ID already exists. Try again with a different ID.',
|
||||
'code' => 409,
|
||||
],
|
||||
Exception::PLATFORM_NOT_FOUND => [
|
||||
'name' => Exception::PLATFORM_NOT_FOUND,
|
||||
'description' => 'Platform with the requested ID could not be found.',
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ return [
|
|||
'hostnames' => array_filter(array_unique([
|
||||
System::getEnv('_APP_DOMAIN', 'localhost'),
|
||||
System::getEnv('_APP_CONSOLE_DOMAIN', 'localhost'),
|
||||
System::getEnv('_APP_MIGRATION_HOST'),
|
||||
])),
|
||||
'platformName' => APP_EMAIL_PLATFORM_NAME,
|
||||
'logoUrl' => APP_EMAIL_LOGO_URL,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ return [
|
|||
[
|
||||
'key' => 'web',
|
||||
'name' => 'Web',
|
||||
'version' => '22.0.0',
|
||||
'version' => '22.1.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-web',
|
||||
'package' => 'https://www.npmjs.com/package/appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -60,7 +60,7 @@ return [
|
|||
[
|
||||
'key' => 'flutter',
|
||||
'name' => 'Flutter',
|
||||
'version' => '21.0.0',
|
||||
'version' => '21.1.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-flutter',
|
||||
'package' => 'https://pub.dev/packages/appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -79,7 +79,7 @@ return [
|
|||
[
|
||||
'key' => 'apple',
|
||||
'name' => 'Apple',
|
||||
'version' => '14.0.0',
|
||||
'version' => '14.1.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-apple',
|
||||
'package' => 'https://github.com/appwrite/sdk-for-apple',
|
||||
'enabled' => true,
|
||||
|
|
@ -117,7 +117,7 @@ return [
|
|||
'key' => 'android',
|
||||
'name' => 'Android',
|
||||
'namespace' => 'io.appwrite',
|
||||
'version' => '12.0.0',
|
||||
'version' => '12.1.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-android',
|
||||
'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-android',
|
||||
'enabled' => true,
|
||||
|
|
@ -140,7 +140,7 @@ return [
|
|||
[
|
||||
'key' => 'react-native',
|
||||
'name' => 'React Native',
|
||||
'version' => '0.20.0',
|
||||
'version' => '0.21.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-react-native',
|
||||
'package' => 'https://npmjs.com/package/react-native-appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -227,7 +227,7 @@ return [
|
|||
[
|
||||
'key' => 'cli',
|
||||
'name' => 'Command Line',
|
||||
'version' => '13.2.1',
|
||||
'version' => '13.4.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-cli',
|
||||
'package' => 'https://www.npmjs.com/package/appwrite-cli',
|
||||
'enabled' => true,
|
||||
|
|
@ -253,7 +253,7 @@ return [
|
|||
[
|
||||
'key' => 'markdown',
|
||||
'name' => 'Markdown',
|
||||
'version' => '0.2.0',
|
||||
'version' => '0.3.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-md.git',
|
||||
'package' => 'https://www.npmjs.com/package/@appwrite.io/docs',
|
||||
'enabled' => true,
|
||||
|
|
@ -270,6 +270,25 @@ return [
|
|||
'repoBranch' => 'main',
|
||||
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/md/CHANGELOG.md'),
|
||||
],
|
||||
[
|
||||
'key' => 'agent-skills',
|
||||
'name' => 'AgentSkills',
|
||||
'version' => '0.1.0',
|
||||
'url' => 'https://github.com/appwrite/agent-skills.git',
|
||||
'enabled' => true,
|
||||
'beta' => false,
|
||||
'dev' => false,
|
||||
'hidden' => false,
|
||||
'family' => APP_SDK_PLATFORM_CONSOLE,
|
||||
'prism' => 'agent-skills',
|
||||
'source' => \realpath(__DIR__ . '/../sdks/console-agent-skills'),
|
||||
'gitUrl' => 'git@github.com:appwrite/agent-skills.git',
|
||||
'gitRepoName' => 'agent-skills',
|
||||
'gitUserName' => 'appwrite',
|
||||
'gitBranch' => 'dev',
|
||||
'repoBranch' => 'main',
|
||||
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/agent-skills/CHANGELOG.md'),
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
|
|
@ -283,7 +302,7 @@ return [
|
|||
[
|
||||
'key' => 'nodejs',
|
||||
'name' => 'Node.js',
|
||||
'version' => '22.0.0',
|
||||
'version' => '22.0.1',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-node',
|
||||
'package' => 'https://www.npmjs.com/package/node-appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -302,7 +321,7 @@ return [
|
|||
[
|
||||
'key' => 'php',
|
||||
'name' => 'PHP',
|
||||
'version' => '20.0.0',
|
||||
'version' => '20.0.1',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-php',
|
||||
'package' => 'https://packagist.org/packages/appwrite/appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -321,7 +340,7 @@ return [
|
|||
[
|
||||
'key' => 'python',
|
||||
'name' => 'Python',
|
||||
'version' => '15.0.0',
|
||||
'version' => '15.1.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-python',
|
||||
'package' => 'https://pypi.org/project/appwrite/',
|
||||
'enabled' => true,
|
||||
|
|
@ -340,7 +359,7 @@ return [
|
|||
[
|
||||
'key' => 'ruby',
|
||||
'name' => 'Ruby',
|
||||
'version' => '21.0.0',
|
||||
'version' => '21.0.1',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-ruby',
|
||||
'package' => 'https://rubygems.org/gems/appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -359,7 +378,7 @@ return [
|
|||
[
|
||||
'key' => 'go',
|
||||
'name' => 'Go',
|
||||
'version' => 'v0.16.0',
|
||||
'version' => 'v0.16.1',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-go',
|
||||
'package' => 'https://github.com/appwrite/sdk-for-go',
|
||||
'enabled' => true,
|
||||
|
|
@ -378,7 +397,7 @@ return [
|
|||
[
|
||||
'key' => 'dotnet',
|
||||
'name' => '.NET',
|
||||
'version' => '0.25.0',
|
||||
'version' => '0.26.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-dotnet',
|
||||
'package' => 'https://www.nuget.org/packages/Appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -397,7 +416,7 @@ return [
|
|||
[
|
||||
'key' => 'dart',
|
||||
'name' => 'Dart',
|
||||
'version' => '21.0.0',
|
||||
'version' => '21.0.1',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-dart',
|
||||
'package' => 'https://pub.dev/packages/dart_appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -417,7 +436,7 @@ return [
|
|||
'key' => 'kotlin',
|
||||
'name' => 'Kotlin',
|
||||
'namespace' => 'io.appwrite',
|
||||
'version' => '14.0.0',
|
||||
'version' => '14.0.1',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-kotlin',
|
||||
'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-kotlin',
|
||||
'enabled' => true,
|
||||
|
|
@ -440,7 +459,7 @@ return [
|
|||
[
|
||||
'key' => 'swift',
|
||||
'name' => 'Swift',
|
||||
'version' => '15.0.0',
|
||||
'version' => '15.1.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-swift',
|
||||
'package' => 'https://github.com/appwrite/sdk-for-swift',
|
||||
'enabled' => true,
|
||||
|
|
|
|||
|
|
@ -555,7 +555,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMFA",
|
||||
"group": "mfa",
|
||||
"weight": 253,
|
||||
"weight": 239,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa.md",
|
||||
|
|
@ -627,7 +627,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 255,
|
||||
"weight": 241,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-authenticator.md",
|
||||
|
|
@ -751,7 +751,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 256,
|
||||
"weight": 242,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-authenticator.md",
|
||||
|
|
@ -891,7 +891,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 257,
|
||||
"weight": 243,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/delete-mfa-authenticator.md",
|
||||
|
|
@ -1015,7 +1015,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 261,
|
||||
"weight": 247,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-challenge.md",
|
||||
|
|
@ -1149,7 +1149,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 262,
|
||||
"weight": 248,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-challenge.md",
|
||||
|
|
@ -1287,7 +1287,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listMfaFactors",
|
||||
"group": "mfa",
|
||||
"weight": 254,
|
||||
"weight": 240,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/list-mfa-factors.md",
|
||||
|
|
@ -1388,7 +1388,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 260,
|
||||
"weight": 246,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/get-mfa-recovery-codes.md",
|
||||
|
|
@ -1487,7 +1487,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 258,
|
||||
"weight": 244,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-recovery-codes.md",
|
||||
|
|
@ -1586,7 +1586,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 259,
|
||||
"weight": 245,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-recovery-codes.md",
|
||||
|
|
@ -4051,7 +4051,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getBrowser",
|
||||
"group": null,
|
||||
"weight": 264,
|
||||
"weight": 250,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-browser.md",
|
||||
|
|
@ -4179,7 +4179,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getCreditCard",
|
||||
"group": null,
|
||||
"weight": 263,
|
||||
"weight": 249,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-credit-card.md",
|
||||
|
|
@ -4313,7 +4313,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFavicon",
|
||||
"group": null,
|
||||
"weight": 267,
|
||||
"weight": 253,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-favicon.md",
|
||||
|
|
@ -4373,7 +4373,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFlag",
|
||||
"group": null,
|
||||
"weight": 265,
|
||||
"weight": 251,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-flag.md",
|
||||
|
|
@ -4863,7 +4863,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getImage",
|
||||
"group": null,
|
||||
"weight": 266,
|
||||
"weight": 252,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-image.md",
|
||||
|
|
@ -4947,7 +4947,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getInitials",
|
||||
"group": null,
|
||||
"weight": 269,
|
||||
"weight": 255,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-initials.md",
|
||||
|
|
@ -5041,7 +5041,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getQR",
|
||||
"group": null,
|
||||
"weight": 268,
|
||||
"weight": 254,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-qr.md",
|
||||
|
|
@ -5135,7 +5135,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getScreenshot",
|
||||
"group": null,
|
||||
"weight": 270,
|
||||
"weight": 256,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-screenshot.md",
|
||||
|
|
@ -5888,7 +5888,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listTransactions",
|
||||
"group": "transactions",
|
||||
"weight": 346,
|
||||
"weight": 332,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/list-transactions.md",
|
||||
|
|
@ -5955,7 +5955,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 342,
|
||||
"weight": 328,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/create-transaction.md",
|
||||
|
|
@ -6026,7 +6026,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 343,
|
||||
"weight": 329,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/get-transaction.md",
|
||||
|
|
@ -6090,7 +6090,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 344,
|
||||
"weight": 330,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/update-transaction.md",
|
||||
|
|
@ -6168,7 +6168,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 345,
|
||||
"weight": 331,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/delete-transaction.md",
|
||||
|
|
@ -6234,7 +6234,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createOperations",
|
||||
"group": "transactions",
|
||||
"weight": 347,
|
||||
"weight": 333,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/create-operations.md",
|
||||
|
|
@ -6319,7 +6319,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listDocuments",
|
||||
"group": "documents",
|
||||
"weight": 297,
|
||||
"weight": 283,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/list-documents.md",
|
||||
|
|
@ -6431,7 +6431,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createDocument",
|
||||
"group": "documents",
|
||||
"weight": 289,
|
||||
"weight": 275,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/create-document.md",
|
||||
|
|
@ -6592,7 +6592,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getDocument",
|
||||
"group": "documents",
|
||||
"weight": 290,
|
||||
"weight": 276,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/get-document.md",
|
||||
|
|
@ -6703,7 +6703,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "upsertDocument",
|
||||
"group": "documents",
|
||||
"weight": 293,
|
||||
"weight": 279,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/upsert-document.md",
|
||||
|
|
@ -6858,7 +6858,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateDocument",
|
||||
"group": "documents",
|
||||
"weight": 291,
|
||||
"weight": 277,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/update-document.md",
|
||||
|
|
@ -6970,7 +6970,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteDocument",
|
||||
"group": "documents",
|
||||
"weight": 295,
|
||||
"weight": 281,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/delete-document.md",
|
||||
|
|
@ -7077,7 +7077,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "decrementDocumentAttribute",
|
||||
"group": "documents",
|
||||
"weight": 300,
|
||||
"weight": 286,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/decrement-document-attribute.md",
|
||||
|
|
@ -7206,7 +7206,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "incrementDocumentAttribute",
|
||||
"group": "documents",
|
||||
"weight": 299,
|
||||
"weight": 285,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/increment-document-attribute.md",
|
||||
|
|
@ -7335,7 +7335,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listExecutions",
|
||||
"group": "executions",
|
||||
"weight": 447,
|
||||
"weight": 436,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "functions\/list-executions.md",
|
||||
|
|
@ -7422,7 +7422,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createExecution",
|
||||
"group": "executions",
|
||||
"weight": 445,
|
||||
"weight": 434,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "functions\/create-execution.md",
|
||||
|
|
@ -7540,7 +7540,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getExecution",
|
||||
"group": "executions",
|
||||
"weight": 446,
|
||||
"weight": 435,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "functions\/get-execution.md",
|
||||
|
|
@ -7615,7 +7615,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "query",
|
||||
"group": "graphql",
|
||||
"weight": 190,
|
||||
"weight": 176,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"demo": "graphql\/query.md",
|
||||
|
|
@ -7669,7 +7669,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "mutation",
|
||||
"group": "graphql",
|
||||
"weight": 189,
|
||||
"weight": 175,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"demo": "graphql\/mutation.md",
|
||||
|
|
@ -8155,7 +8155,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 237,
|
||||
"weight": 223,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "messaging\/create-subscriber.md",
|
||||
|
|
@ -8239,7 +8239,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 241,
|
||||
"weight": 227,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "messaging\/delete-subscriber.md",
|
||||
|
|
@ -8315,7 +8315,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listFiles",
|
||||
"group": "files",
|
||||
"weight": 543,
|
||||
"weight": 532,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/list-files.md",
|
||||
|
|
@ -8414,7 +8414,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createFile",
|
||||
"group": "files",
|
||||
"weight": 541,
|
||||
"weight": 530,
|
||||
"cookies": false,
|
||||
"type": "upload",
|
||||
"demo": "storage\/create-file.md",
|
||||
|
|
@ -8516,7 +8516,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFile",
|
||||
"group": "files",
|
||||
"weight": 542,
|
||||
"weight": 531,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/get-file.md",
|
||||
|
|
@ -8590,7 +8590,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateFile",
|
||||
"group": "files",
|
||||
"weight": 544,
|
||||
"weight": 533,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/update-file.md",
|
||||
|
|
@ -8682,7 +8682,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteFile",
|
||||
"group": "files",
|
||||
"weight": 545,
|
||||
"weight": 534,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/delete-file.md",
|
||||
|
|
@ -8751,7 +8751,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFileDownload",
|
||||
"group": "files",
|
||||
"weight": 547,
|
||||
"weight": 536,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "storage\/get-file-download.md",
|
||||
|
|
@ -8831,7 +8831,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFilePreview",
|
||||
"group": "files",
|
||||
"weight": 546,
|
||||
"weight": 535,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "storage\/get-file-preview.md",
|
||||
|
|
@ -9061,7 +9061,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFileView",
|
||||
"group": "files",
|
||||
"weight": 548,
|
||||
"weight": 537,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "storage\/get-file-view.md",
|
||||
|
|
@ -9148,7 +9148,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listTransactions",
|
||||
"group": "transactions",
|
||||
"weight": 419,
|
||||
"weight": 405,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/list-transactions.md",
|
||||
|
|
@ -9218,7 +9218,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 415,
|
||||
"weight": 401,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/create-transaction.md",
|
||||
|
|
@ -9292,7 +9292,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 416,
|
||||
"weight": 402,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/get-transaction.md",
|
||||
|
|
@ -9359,7 +9359,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 417,
|
||||
"weight": 403,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/update-transaction.md",
|
||||
|
|
@ -9440,7 +9440,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 418,
|
||||
"weight": 404,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/delete-transaction.md",
|
||||
|
|
@ -9509,7 +9509,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createOperations",
|
||||
"group": "transactions",
|
||||
"weight": 420,
|
||||
"weight": 406,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/create-operations.md",
|
||||
|
|
@ -9597,7 +9597,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listRows",
|
||||
"group": "rows",
|
||||
"weight": 411,
|
||||
"weight": 397,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/list-rows.md",
|
||||
|
|
@ -9708,7 +9708,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createRow",
|
||||
"group": "rows",
|
||||
"weight": 403,
|
||||
"weight": 389,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/create-row.md",
|
||||
|
|
@ -9864,7 +9864,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getRow",
|
||||
"group": "rows",
|
||||
"weight": 404,
|
||||
"weight": 390,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/get-row.md",
|
||||
|
|
@ -9974,7 +9974,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "upsertRow",
|
||||
"group": "rows",
|
||||
"weight": 407,
|
||||
"weight": 393,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/upsert-row.md",
|
||||
|
|
@ -10124,7 +10124,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateRow",
|
||||
"group": "rows",
|
||||
"weight": 405,
|
||||
"weight": 391,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/update-row.md",
|
||||
|
|
@ -10235,7 +10235,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteRow",
|
||||
"group": "rows",
|
||||
"weight": 409,
|
||||
"weight": 395,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/delete-row.md",
|
||||
|
|
@ -10341,7 +10341,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "decrementRowColumn",
|
||||
"group": "rows",
|
||||
"weight": 414,
|
||||
"weight": 400,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/decrement-row-column.md",
|
||||
|
|
@ -10469,7 +10469,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "incrementRowColumn",
|
||||
"group": "rows",
|
||||
"weight": 413,
|
||||
"weight": 399,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/increment-row-column.md",
|
||||
|
|
@ -10597,7 +10597,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "list",
|
||||
"group": "teams",
|
||||
"weight": 110,
|
||||
"weight": 107,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/list.md",
|
||||
|
|
@ -10686,7 +10686,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "create",
|
||||
"group": "teams",
|
||||
"weight": 109,
|
||||
"weight": 106,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/create.md",
|
||||
|
|
@ -10773,7 +10773,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"group": "teams",
|
||||
"weight": 111,
|
||||
"weight": 108,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get.md",
|
||||
|
|
@ -10837,7 +10837,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateName",
|
||||
"group": "teams",
|
||||
"weight": 113,
|
||||
"weight": 110,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-name.md",
|
||||
|
|
@ -10913,7 +10913,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "delete",
|
||||
"group": "teams",
|
||||
"weight": 115,
|
||||
"weight": 112,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/delete.md",
|
||||
|
|
@ -10979,7 +10979,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listMemberships",
|
||||
"group": "memberships",
|
||||
"weight": 117,
|
||||
"weight": 114,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/list-memberships.md",
|
||||
|
|
@ -11078,7 +11078,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMembership",
|
||||
"group": "memberships",
|
||||
"weight": 116,
|
||||
"weight": 113,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/create-membership.md",
|
||||
|
|
@ -11146,14 +11146,7 @@
|
|||
"description": "Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.",
|
||||
"x-example": null,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"admin",
|
||||
"developer",
|
||||
"owner"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
|
|
@ -11201,7 +11194,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getMembership",
|
||||
"group": "memberships",
|
||||
"weight": 118,
|
||||
"weight": 115,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get-membership.md",
|
||||
|
|
@ -11275,7 +11268,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMembership",
|
||||
"group": "memberships",
|
||||
"weight": 119,
|
||||
"weight": 116,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-membership.md",
|
||||
|
|
@ -11336,14 +11329,7 @@
|
|||
"description": "An array of strings. Use this param to set the user's roles in the team. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.",
|
||||
"x-example": null,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"admin",
|
||||
"developer",
|
||||
"owner"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -11371,7 +11357,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteMembership",
|
||||
"group": "memberships",
|
||||
"weight": 121,
|
||||
"weight": 118,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/delete-membership.md",
|
||||
|
|
@ -11447,7 +11433,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMembershipStatus",
|
||||
"group": "memberships",
|
||||
"weight": 120,
|
||||
"weight": 117,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-membership-status.md",
|
||||
|
|
@ -11547,7 +11533,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getPrefs",
|
||||
"group": "teams",
|
||||
"weight": 112,
|
||||
"weight": 109,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get-prefs.md",
|
||||
|
|
@ -11610,7 +11596,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updatePrefs",
|
||||
"group": "teams",
|
||||
"weight": 114,
|
||||
"weight": 111,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-prefs.md",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -555,7 +555,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMFA",
|
||||
"group": "mfa",
|
||||
"weight": 253,
|
||||
"weight": 239,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa.md",
|
||||
|
|
@ -627,7 +627,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 255,
|
||||
"weight": 241,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-authenticator.md",
|
||||
|
|
@ -751,7 +751,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 256,
|
||||
"weight": 242,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-authenticator.md",
|
||||
|
|
@ -891,7 +891,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 257,
|
||||
"weight": 243,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/delete-mfa-authenticator.md",
|
||||
|
|
@ -1015,7 +1015,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 261,
|
||||
"weight": 247,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-challenge.md",
|
||||
|
|
@ -1149,7 +1149,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 262,
|
||||
"weight": 248,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-challenge.md",
|
||||
|
|
@ -1287,7 +1287,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listMfaFactors",
|
||||
"group": "mfa",
|
||||
"weight": 254,
|
||||
"weight": 240,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/list-mfa-factors.md",
|
||||
|
|
@ -1388,7 +1388,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 260,
|
||||
"weight": 246,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/get-mfa-recovery-codes.md",
|
||||
|
|
@ -1487,7 +1487,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 258,
|
||||
"weight": 244,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-recovery-codes.md",
|
||||
|
|
@ -1586,7 +1586,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 259,
|
||||
"weight": 245,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-recovery-codes.md",
|
||||
|
|
@ -4051,7 +4051,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getBrowser",
|
||||
"group": null,
|
||||
"weight": 264,
|
||||
"weight": 250,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-browser.md",
|
||||
|
|
@ -4179,7 +4179,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getCreditCard",
|
||||
"group": null,
|
||||
"weight": 263,
|
||||
"weight": 249,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-credit-card.md",
|
||||
|
|
@ -4313,7 +4313,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFavicon",
|
||||
"group": null,
|
||||
"weight": 267,
|
||||
"weight": 253,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-favicon.md",
|
||||
|
|
@ -4373,7 +4373,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFlag",
|
||||
"group": null,
|
||||
"weight": 265,
|
||||
"weight": 251,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-flag.md",
|
||||
|
|
@ -4863,7 +4863,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getImage",
|
||||
"group": null,
|
||||
"weight": 266,
|
||||
"weight": 252,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-image.md",
|
||||
|
|
@ -4947,7 +4947,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getInitials",
|
||||
"group": null,
|
||||
"weight": 269,
|
||||
"weight": 255,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-initials.md",
|
||||
|
|
@ -5041,7 +5041,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getQR",
|
||||
"group": null,
|
||||
"weight": 268,
|
||||
"weight": 254,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-qr.md",
|
||||
|
|
@ -5135,7 +5135,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getScreenshot",
|
||||
"group": null,
|
||||
"weight": 270,
|
||||
"weight": 256,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-screenshot.md",
|
||||
|
|
@ -5888,7 +5888,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listTransactions",
|
||||
"group": "transactions",
|
||||
"weight": 346,
|
||||
"weight": 332,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/list-transactions.md",
|
||||
|
|
@ -5955,7 +5955,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 342,
|
||||
"weight": 328,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/create-transaction.md",
|
||||
|
|
@ -6026,7 +6026,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 343,
|
||||
"weight": 329,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/get-transaction.md",
|
||||
|
|
@ -6090,7 +6090,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 344,
|
||||
"weight": 330,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/update-transaction.md",
|
||||
|
|
@ -6168,7 +6168,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 345,
|
||||
"weight": 331,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/delete-transaction.md",
|
||||
|
|
@ -6234,7 +6234,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createOperations",
|
||||
"group": "transactions",
|
||||
"weight": 347,
|
||||
"weight": 333,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/create-operations.md",
|
||||
|
|
@ -6319,7 +6319,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listDocuments",
|
||||
"group": "documents",
|
||||
"weight": 297,
|
||||
"weight": 283,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/list-documents.md",
|
||||
|
|
@ -6431,7 +6431,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createDocument",
|
||||
"group": "documents",
|
||||
"weight": 289,
|
||||
"weight": 275,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/create-document.md",
|
||||
|
|
@ -6592,7 +6592,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getDocument",
|
||||
"group": "documents",
|
||||
"weight": 290,
|
||||
"weight": 276,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/get-document.md",
|
||||
|
|
@ -6703,7 +6703,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "upsertDocument",
|
||||
"group": "documents",
|
||||
"weight": 293,
|
||||
"weight": 279,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/upsert-document.md",
|
||||
|
|
@ -6858,7 +6858,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateDocument",
|
||||
"group": "documents",
|
||||
"weight": 291,
|
||||
"weight": 277,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/update-document.md",
|
||||
|
|
@ -6970,7 +6970,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteDocument",
|
||||
"group": "documents",
|
||||
"weight": 295,
|
||||
"weight": 281,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/delete-document.md",
|
||||
|
|
@ -7077,7 +7077,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "decrementDocumentAttribute",
|
||||
"group": "documents",
|
||||
"weight": 300,
|
||||
"weight": 286,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/decrement-document-attribute.md",
|
||||
|
|
@ -7206,7 +7206,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "incrementDocumentAttribute",
|
||||
"group": "documents",
|
||||
"weight": 299,
|
||||
"weight": 285,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/increment-document-attribute.md",
|
||||
|
|
@ -7335,7 +7335,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listExecutions",
|
||||
"group": "executions",
|
||||
"weight": 447,
|
||||
"weight": 436,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "functions\/list-executions.md",
|
||||
|
|
@ -7422,7 +7422,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createExecution",
|
||||
"group": "executions",
|
||||
"weight": 445,
|
||||
"weight": 434,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "functions\/create-execution.md",
|
||||
|
|
@ -7540,7 +7540,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getExecution",
|
||||
"group": "executions",
|
||||
"weight": 446,
|
||||
"weight": 435,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "functions\/get-execution.md",
|
||||
|
|
@ -7615,7 +7615,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "query",
|
||||
"group": "graphql",
|
||||
"weight": 190,
|
||||
"weight": 176,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"demo": "graphql\/query.md",
|
||||
|
|
@ -7669,7 +7669,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "mutation",
|
||||
"group": "graphql",
|
||||
"weight": 189,
|
||||
"weight": 175,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"demo": "graphql\/mutation.md",
|
||||
|
|
@ -8155,7 +8155,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 237,
|
||||
"weight": 223,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "messaging\/create-subscriber.md",
|
||||
|
|
@ -8239,7 +8239,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 241,
|
||||
"weight": 227,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "messaging\/delete-subscriber.md",
|
||||
|
|
@ -8315,7 +8315,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listFiles",
|
||||
"group": "files",
|
||||
"weight": 543,
|
||||
"weight": 532,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/list-files.md",
|
||||
|
|
@ -8414,7 +8414,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createFile",
|
||||
"group": "files",
|
||||
"weight": 541,
|
||||
"weight": 530,
|
||||
"cookies": false,
|
||||
"type": "upload",
|
||||
"demo": "storage\/create-file.md",
|
||||
|
|
@ -8516,7 +8516,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFile",
|
||||
"group": "files",
|
||||
"weight": 542,
|
||||
"weight": 531,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/get-file.md",
|
||||
|
|
@ -8590,7 +8590,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateFile",
|
||||
"group": "files",
|
||||
"weight": 544,
|
||||
"weight": 533,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/update-file.md",
|
||||
|
|
@ -8682,7 +8682,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteFile",
|
||||
"group": "files",
|
||||
"weight": 545,
|
||||
"weight": 534,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/delete-file.md",
|
||||
|
|
@ -8751,7 +8751,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFileDownload",
|
||||
"group": "files",
|
||||
"weight": 547,
|
||||
"weight": 536,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "storage\/get-file-download.md",
|
||||
|
|
@ -8831,7 +8831,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFilePreview",
|
||||
"group": "files",
|
||||
"weight": 546,
|
||||
"weight": 535,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "storage\/get-file-preview.md",
|
||||
|
|
@ -9061,7 +9061,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFileView",
|
||||
"group": "files",
|
||||
"weight": 548,
|
||||
"weight": 537,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "storage\/get-file-view.md",
|
||||
|
|
@ -9148,7 +9148,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listTransactions",
|
||||
"group": "transactions",
|
||||
"weight": 419,
|
||||
"weight": 405,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/list-transactions.md",
|
||||
|
|
@ -9218,7 +9218,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 415,
|
||||
"weight": 401,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/create-transaction.md",
|
||||
|
|
@ -9292,7 +9292,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 416,
|
||||
"weight": 402,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/get-transaction.md",
|
||||
|
|
@ -9359,7 +9359,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 417,
|
||||
"weight": 403,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/update-transaction.md",
|
||||
|
|
@ -9440,7 +9440,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 418,
|
||||
"weight": 404,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/delete-transaction.md",
|
||||
|
|
@ -9509,7 +9509,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createOperations",
|
||||
"group": "transactions",
|
||||
"weight": 420,
|
||||
"weight": 406,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/create-operations.md",
|
||||
|
|
@ -9597,7 +9597,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listRows",
|
||||
"group": "rows",
|
||||
"weight": 411,
|
||||
"weight": 397,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/list-rows.md",
|
||||
|
|
@ -9708,7 +9708,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createRow",
|
||||
"group": "rows",
|
||||
"weight": 403,
|
||||
"weight": 389,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/create-row.md",
|
||||
|
|
@ -9864,7 +9864,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getRow",
|
||||
"group": "rows",
|
||||
"weight": 404,
|
||||
"weight": 390,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/get-row.md",
|
||||
|
|
@ -9974,7 +9974,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "upsertRow",
|
||||
"group": "rows",
|
||||
"weight": 407,
|
||||
"weight": 393,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/upsert-row.md",
|
||||
|
|
@ -10124,7 +10124,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateRow",
|
||||
"group": "rows",
|
||||
"weight": 405,
|
||||
"weight": 391,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/update-row.md",
|
||||
|
|
@ -10235,7 +10235,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteRow",
|
||||
"group": "rows",
|
||||
"weight": 409,
|
||||
"weight": 395,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/delete-row.md",
|
||||
|
|
@ -10341,7 +10341,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "decrementRowColumn",
|
||||
"group": "rows",
|
||||
"weight": 414,
|
||||
"weight": 400,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/decrement-row-column.md",
|
||||
|
|
@ -10469,7 +10469,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "incrementRowColumn",
|
||||
"group": "rows",
|
||||
"weight": 413,
|
||||
"weight": 399,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/increment-row-column.md",
|
||||
|
|
@ -10597,7 +10597,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "list",
|
||||
"group": "teams",
|
||||
"weight": 110,
|
||||
"weight": 107,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/list.md",
|
||||
|
|
@ -10686,7 +10686,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "create",
|
||||
"group": "teams",
|
||||
"weight": 109,
|
||||
"weight": 106,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/create.md",
|
||||
|
|
@ -10773,7 +10773,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"group": "teams",
|
||||
"weight": 111,
|
||||
"weight": 108,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get.md",
|
||||
|
|
@ -10837,7 +10837,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateName",
|
||||
"group": "teams",
|
||||
"weight": 113,
|
||||
"weight": 110,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-name.md",
|
||||
|
|
@ -10913,7 +10913,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "delete",
|
||||
"group": "teams",
|
||||
"weight": 115,
|
||||
"weight": 112,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/delete.md",
|
||||
|
|
@ -10979,7 +10979,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listMemberships",
|
||||
"group": "memberships",
|
||||
"weight": 117,
|
||||
"weight": 114,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/list-memberships.md",
|
||||
|
|
@ -11078,7 +11078,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMembership",
|
||||
"group": "memberships",
|
||||
"weight": 116,
|
||||
"weight": 113,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/create-membership.md",
|
||||
|
|
@ -11146,14 +11146,7 @@
|
|||
"description": "Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.",
|
||||
"x-example": null,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"admin",
|
||||
"developer",
|
||||
"owner"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
|
|
@ -11201,7 +11194,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getMembership",
|
||||
"group": "memberships",
|
||||
"weight": 118,
|
||||
"weight": 115,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get-membership.md",
|
||||
|
|
@ -11275,7 +11268,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMembership",
|
||||
"group": "memberships",
|
||||
"weight": 119,
|
||||
"weight": 116,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-membership.md",
|
||||
|
|
@ -11336,14 +11329,7 @@
|
|||
"description": "An array of strings. Use this param to set the user's roles in the team. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.",
|
||||
"x-example": null,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"admin",
|
||||
"developer",
|
||||
"owner"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -11371,7 +11357,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteMembership",
|
||||
"group": "memberships",
|
||||
"weight": 121,
|
||||
"weight": 118,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/delete-membership.md",
|
||||
|
|
@ -11447,7 +11433,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMembershipStatus",
|
||||
"group": "memberships",
|
||||
"weight": 120,
|
||||
"weight": 117,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-membership-status.md",
|
||||
|
|
@ -11547,7 +11533,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getPrefs",
|
||||
"group": "teams",
|
||||
"weight": 112,
|
||||
"weight": 109,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get-prefs.md",
|
||||
|
|
@ -11610,7 +11596,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updatePrefs",
|
||||
"group": "teams",
|
||||
"weight": 114,
|
||||
"weight": 111,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-prefs.md",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -612,7 +612,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMFA",
|
||||
"group": "mfa",
|
||||
"weight": 253,
|
||||
"weight": 239,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa.md",
|
||||
|
|
@ -687,7 +687,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 255,
|
||||
"weight": 241,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-authenticator.md",
|
||||
|
|
@ -811,7 +811,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 256,
|
||||
"weight": 242,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-authenticator.md",
|
||||
|
|
@ -952,7 +952,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 257,
|
||||
"weight": 243,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/delete-mfa-authenticator.md",
|
||||
|
|
@ -1076,7 +1076,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 261,
|
||||
"weight": 247,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-challenge.md",
|
||||
|
|
@ -1213,7 +1213,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 262,
|
||||
"weight": 248,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-challenge.md",
|
||||
|
|
@ -1353,7 +1353,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listMfaFactors",
|
||||
"group": "mfa",
|
||||
"weight": 254,
|
||||
"weight": 240,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/list-mfa-factors.md",
|
||||
|
|
@ -1454,7 +1454,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 260,
|
||||
"weight": 246,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/get-mfa-recovery-codes.md",
|
||||
|
|
@ -1555,7 +1555,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 258,
|
||||
"weight": 244,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-recovery-codes.md",
|
||||
|
|
@ -1656,7 +1656,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 259,
|
||||
"weight": 245,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-recovery-codes.md",
|
||||
|
|
@ -4203,7 +4203,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getBrowser",
|
||||
"group": null,
|
||||
"weight": 264,
|
||||
"weight": 250,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-browser.md",
|
||||
|
|
@ -4329,7 +4329,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getCreditCard",
|
||||
"group": null,
|
||||
"weight": 263,
|
||||
"weight": 249,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-credit-card.md",
|
||||
|
|
@ -4461,7 +4461,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFavicon",
|
||||
"group": null,
|
||||
"weight": 267,
|
||||
"weight": 253,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-favicon.md",
|
||||
|
|
@ -4525,7 +4525,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFlag",
|
||||
"group": null,
|
||||
"weight": 265,
|
||||
"weight": 251,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-flag.md",
|
||||
|
|
@ -5013,7 +5013,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getImage",
|
||||
"group": null,
|
||||
"weight": 266,
|
||||
"weight": 252,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-image.md",
|
||||
|
|
@ -5097,7 +5097,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getInitials",
|
||||
"group": null,
|
||||
"weight": 269,
|
||||
"weight": 255,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-initials.md",
|
||||
|
|
@ -5189,7 +5189,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getQR",
|
||||
"group": null,
|
||||
"weight": 268,
|
||||
"weight": 254,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-qr.md",
|
||||
|
|
@ -5281,7 +5281,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getScreenshot",
|
||||
"group": null,
|
||||
"weight": 270,
|
||||
"weight": 256,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-screenshot.md",
|
||||
|
|
@ -5994,7 +5994,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listTransactions",
|
||||
"group": "transactions",
|
||||
"weight": 346,
|
||||
"weight": 332,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/list-transactions.md",
|
||||
|
|
@ -6061,7 +6061,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 342,
|
||||
"weight": 328,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/create-transaction.md",
|
||||
|
|
@ -6132,7 +6132,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 343,
|
||||
"weight": 329,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/get-transaction.md",
|
||||
|
|
@ -6195,7 +6195,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 344,
|
||||
"weight": 330,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/update-transaction.md",
|
||||
|
|
@ -6274,7 +6274,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 345,
|
||||
"weight": 331,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/delete-transaction.md",
|
||||
|
|
@ -6339,7 +6339,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createOperations",
|
||||
"group": "transactions",
|
||||
"weight": 347,
|
||||
"weight": 333,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/create-operations.md",
|
||||
|
|
@ -6420,7 +6420,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listDocuments",
|
||||
"group": "documents",
|
||||
"weight": 297,
|
||||
"weight": 283,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/list-documents.md",
|
||||
|
|
@ -6524,7 +6524,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createDocument",
|
||||
"group": "documents",
|
||||
"weight": 289,
|
||||
"weight": 275,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/create-document.md",
|
||||
|
|
@ -6683,7 +6683,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getDocument",
|
||||
"group": "documents",
|
||||
"weight": 290,
|
||||
"weight": 276,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/get-document.md",
|
||||
|
|
@ -6786,7 +6786,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "upsertDocument",
|
||||
"group": "documents",
|
||||
"weight": 293,
|
||||
"weight": 279,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/upsert-document.md",
|
||||
|
|
@ -6937,7 +6937,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateDocument",
|
||||
"group": "documents",
|
||||
"weight": 291,
|
||||
"weight": 277,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/update-document.md",
|
||||
|
|
@ -7047,7 +7047,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteDocument",
|
||||
"group": "documents",
|
||||
"weight": 295,
|
||||
"weight": 281,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/delete-document.md",
|
||||
|
|
@ -7148,7 +7148,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "decrementDocumentAttribute",
|
||||
"group": "documents",
|
||||
"weight": 300,
|
||||
"weight": 286,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/decrement-document-attribute.md",
|
||||
|
|
@ -7271,7 +7271,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "incrementDocumentAttribute",
|
||||
"group": "documents",
|
||||
"weight": 299,
|
||||
"weight": 285,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/increment-document-attribute.md",
|
||||
|
|
@ -7392,7 +7392,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listExecutions",
|
||||
"group": "executions",
|
||||
"weight": 447,
|
||||
"weight": 436,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "functions\/list-executions.md",
|
||||
|
|
@ -7475,7 +7475,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createExecution",
|
||||
"group": "executions",
|
||||
"weight": 445,
|
||||
"weight": 434,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "functions\/create-execution.md",
|
||||
|
|
@ -7594,7 +7594,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getExecution",
|
||||
"group": "executions",
|
||||
"weight": 446,
|
||||
"weight": 435,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "functions\/get-execution.md",
|
||||
|
|
@ -7666,7 +7666,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "query",
|
||||
"group": "graphql",
|
||||
"weight": 190,
|
||||
"weight": 176,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"demo": "graphql\/query.md",
|
||||
|
|
@ -7741,7 +7741,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "mutation",
|
||||
"group": "graphql",
|
||||
"weight": 189,
|
||||
"weight": 175,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"demo": "graphql\/mutation.md",
|
||||
|
|
@ -8240,7 +8240,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 237,
|
||||
"weight": 223,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "messaging\/create-subscriber.md",
|
||||
|
|
@ -8325,7 +8325,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 241,
|
||||
"weight": 227,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "messaging\/delete-subscriber.md",
|
||||
|
|
@ -8396,7 +8396,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listFiles",
|
||||
"group": "files",
|
||||
"weight": 543,
|
||||
"weight": 532,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/list-files.md",
|
||||
|
|
@ -8489,7 +8489,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createFile",
|
||||
"group": "files",
|
||||
"weight": 541,
|
||||
"weight": 530,
|
||||
"cookies": false,
|
||||
"type": "upload",
|
||||
"demo": "storage\/create-file.md",
|
||||
|
|
@ -8580,7 +8580,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFile",
|
||||
"group": "files",
|
||||
"weight": 542,
|
||||
"weight": 531,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/get-file.md",
|
||||
|
|
@ -8651,7 +8651,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateFile",
|
||||
"group": "files",
|
||||
"weight": 544,
|
||||
"weight": 533,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/update-file.md",
|
||||
|
|
@ -8742,7 +8742,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteFile",
|
||||
"group": "files",
|
||||
"weight": 545,
|
||||
"weight": 534,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/delete-file.md",
|
||||
|
|
@ -8813,7 +8813,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFileDownload",
|
||||
"group": "files",
|
||||
"weight": 547,
|
||||
"weight": 536,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "storage\/get-file-download.md",
|
||||
|
|
@ -8893,7 +8893,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFilePreview",
|
||||
"group": "files",
|
||||
"weight": 546,
|
||||
"weight": 535,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "storage\/get-file-preview.md",
|
||||
|
|
@ -9101,7 +9101,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFileView",
|
||||
"group": "files",
|
||||
"weight": 548,
|
||||
"weight": 537,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "storage\/get-file-view.md",
|
||||
|
|
@ -9181,7 +9181,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listTransactions",
|
||||
"group": "transactions",
|
||||
"weight": 419,
|
||||
"weight": 405,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/list-transactions.md",
|
||||
|
|
@ -9251,7 +9251,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 415,
|
||||
"weight": 401,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/create-transaction.md",
|
||||
|
|
@ -9325,7 +9325,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 416,
|
||||
"weight": 402,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/get-transaction.md",
|
||||
|
|
@ -9391,7 +9391,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 417,
|
||||
"weight": 403,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/update-transaction.md",
|
||||
|
|
@ -9473,7 +9473,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 418,
|
||||
"weight": 404,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/delete-transaction.md",
|
||||
|
|
@ -9541,7 +9541,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createOperations",
|
||||
"group": "transactions",
|
||||
"weight": 420,
|
||||
"weight": 406,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/create-operations.md",
|
||||
|
|
@ -9625,7 +9625,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listRows",
|
||||
"group": "rows",
|
||||
"weight": 411,
|
||||
"weight": 397,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/list-rows.md",
|
||||
|
|
@ -9728,7 +9728,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createRow",
|
||||
"group": "rows",
|
||||
"weight": 403,
|
||||
"weight": 389,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/create-row.md",
|
||||
|
|
@ -9882,7 +9882,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getRow",
|
||||
"group": "rows",
|
||||
"weight": 404,
|
||||
"weight": 390,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/get-row.md",
|
||||
|
|
@ -9984,7 +9984,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "upsertRow",
|
||||
"group": "rows",
|
||||
"weight": 407,
|
||||
"weight": 393,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/upsert-row.md",
|
||||
|
|
@ -10130,7 +10130,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateRow",
|
||||
"group": "rows",
|
||||
"weight": 405,
|
||||
"weight": 391,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/update-row.md",
|
||||
|
|
@ -10239,7 +10239,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteRow",
|
||||
"group": "rows",
|
||||
"weight": 409,
|
||||
"weight": 395,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/delete-row.md",
|
||||
|
|
@ -10339,7 +10339,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "decrementRowColumn",
|
||||
"group": "rows",
|
||||
"weight": 414,
|
||||
"weight": 400,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/decrement-row-column.md",
|
||||
|
|
@ -10461,7 +10461,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "incrementRowColumn",
|
||||
"group": "rows",
|
||||
"weight": 413,
|
||||
"weight": 399,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/increment-row-column.md",
|
||||
|
|
@ -10581,7 +10581,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "list",
|
||||
"group": "teams",
|
||||
"weight": 110,
|
||||
"weight": 107,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/list.md",
|
||||
|
|
@ -10666,7 +10666,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "create",
|
||||
"group": "teams",
|
||||
"weight": 109,
|
||||
"weight": 106,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/create.md",
|
||||
|
|
@ -10757,7 +10757,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"group": "teams",
|
||||
"weight": 111,
|
||||
"weight": 108,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get.md",
|
||||
|
|
@ -10820,7 +10820,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateName",
|
||||
"group": "teams",
|
||||
"weight": 113,
|
||||
"weight": 110,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-name.md",
|
||||
|
|
@ -10896,7 +10896,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "delete",
|
||||
"group": "teams",
|
||||
"weight": 115,
|
||||
"weight": 112,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/delete.md",
|
||||
|
|
@ -10959,7 +10959,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listMemberships",
|
||||
"group": "memberships",
|
||||
"weight": 117,
|
||||
"weight": 114,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/list-memberships.md",
|
||||
|
|
@ -11052,7 +11052,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMembership",
|
||||
"group": "memberships",
|
||||
"weight": 116,
|
||||
"weight": 113,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/create-membership.md",
|
||||
|
|
@ -11120,14 +11120,7 @@
|
|||
"default": null,
|
||||
"x-example": null,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"admin",
|
||||
"developer",
|
||||
"owner"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
|
|
@ -11176,7 +11169,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getMembership",
|
||||
"group": "memberships",
|
||||
"weight": 118,
|
||||
"weight": 115,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get-membership.md",
|
||||
|
|
@ -11247,7 +11240,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMembership",
|
||||
"group": "memberships",
|
||||
"weight": 119,
|
||||
"weight": 116,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-membership.md",
|
||||
|
|
@ -11303,14 +11296,7 @@
|
|||
"default": null,
|
||||
"x-example": null,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"admin",
|
||||
"developer",
|
||||
"owner"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -11341,7 +11327,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteMembership",
|
||||
"group": "memberships",
|
||||
"weight": 121,
|
||||
"weight": 118,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/delete-membership.md",
|
||||
|
|
@ -11414,7 +11400,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMembershipStatus",
|
||||
"group": "memberships",
|
||||
"weight": 120,
|
||||
"weight": 117,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-membership-status.md",
|
||||
|
|
@ -11510,7 +11496,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getPrefs",
|
||||
"group": "teams",
|
||||
"weight": 112,
|
||||
"weight": 109,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get-prefs.md",
|
||||
|
|
@ -11573,7 +11559,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updatePrefs",
|
||||
"group": "teams",
|
||||
"weight": 114,
|
||||
"weight": 111,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-prefs.md",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -612,7 +612,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMFA",
|
||||
"group": "mfa",
|
||||
"weight": 253,
|
||||
"weight": 239,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa.md",
|
||||
|
|
@ -687,7 +687,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 255,
|
||||
"weight": 241,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-authenticator.md",
|
||||
|
|
@ -811,7 +811,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 256,
|
||||
"weight": 242,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-authenticator.md",
|
||||
|
|
@ -952,7 +952,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 257,
|
||||
"weight": 243,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/delete-mfa-authenticator.md",
|
||||
|
|
@ -1076,7 +1076,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 261,
|
||||
"weight": 247,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-challenge.md",
|
||||
|
|
@ -1213,7 +1213,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 262,
|
||||
"weight": 248,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-challenge.md",
|
||||
|
|
@ -1353,7 +1353,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listMfaFactors",
|
||||
"group": "mfa",
|
||||
"weight": 254,
|
||||
"weight": 240,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/list-mfa-factors.md",
|
||||
|
|
@ -1454,7 +1454,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 260,
|
||||
"weight": 246,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/get-mfa-recovery-codes.md",
|
||||
|
|
@ -1555,7 +1555,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 258,
|
||||
"weight": 244,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/create-mfa-recovery-codes.md",
|
||||
|
|
@ -1656,7 +1656,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 259,
|
||||
"weight": 245,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "account\/update-mfa-recovery-codes.md",
|
||||
|
|
@ -4203,7 +4203,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getBrowser",
|
||||
"group": null,
|
||||
"weight": 264,
|
||||
"weight": 250,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-browser.md",
|
||||
|
|
@ -4329,7 +4329,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getCreditCard",
|
||||
"group": null,
|
||||
"weight": 263,
|
||||
"weight": 249,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-credit-card.md",
|
||||
|
|
@ -4461,7 +4461,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFavicon",
|
||||
"group": null,
|
||||
"weight": 267,
|
||||
"weight": 253,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-favicon.md",
|
||||
|
|
@ -4525,7 +4525,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFlag",
|
||||
"group": null,
|
||||
"weight": 265,
|
||||
"weight": 251,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-flag.md",
|
||||
|
|
@ -5013,7 +5013,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getImage",
|
||||
"group": null,
|
||||
"weight": 266,
|
||||
"weight": 252,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-image.md",
|
||||
|
|
@ -5097,7 +5097,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getInitials",
|
||||
"group": null,
|
||||
"weight": 269,
|
||||
"weight": 255,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-initials.md",
|
||||
|
|
@ -5189,7 +5189,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getQR",
|
||||
"group": null,
|
||||
"weight": 268,
|
||||
"weight": 254,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-qr.md",
|
||||
|
|
@ -5281,7 +5281,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getScreenshot",
|
||||
"group": null,
|
||||
"weight": 270,
|
||||
"weight": 256,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "avatars\/get-screenshot.md",
|
||||
|
|
@ -5994,7 +5994,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listTransactions",
|
||||
"group": "transactions",
|
||||
"weight": 346,
|
||||
"weight": 332,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/list-transactions.md",
|
||||
|
|
@ -6061,7 +6061,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 342,
|
||||
"weight": 328,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/create-transaction.md",
|
||||
|
|
@ -6132,7 +6132,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 343,
|
||||
"weight": 329,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/get-transaction.md",
|
||||
|
|
@ -6195,7 +6195,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 344,
|
||||
"weight": 330,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/update-transaction.md",
|
||||
|
|
@ -6274,7 +6274,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 345,
|
||||
"weight": 331,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/delete-transaction.md",
|
||||
|
|
@ -6339,7 +6339,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createOperations",
|
||||
"group": "transactions",
|
||||
"weight": 347,
|
||||
"weight": 333,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/create-operations.md",
|
||||
|
|
@ -6420,7 +6420,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listDocuments",
|
||||
"group": "documents",
|
||||
"weight": 297,
|
||||
"weight": 283,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/list-documents.md",
|
||||
|
|
@ -6524,7 +6524,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createDocument",
|
||||
"group": "documents",
|
||||
"weight": 289,
|
||||
"weight": 275,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/create-document.md",
|
||||
|
|
@ -6683,7 +6683,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getDocument",
|
||||
"group": "documents",
|
||||
"weight": 290,
|
||||
"weight": 276,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/get-document.md",
|
||||
|
|
@ -6786,7 +6786,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "upsertDocument",
|
||||
"group": "documents",
|
||||
"weight": 293,
|
||||
"weight": 279,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/upsert-document.md",
|
||||
|
|
@ -6937,7 +6937,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateDocument",
|
||||
"group": "documents",
|
||||
"weight": 291,
|
||||
"weight": 277,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/update-document.md",
|
||||
|
|
@ -7047,7 +7047,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteDocument",
|
||||
"group": "documents",
|
||||
"weight": 295,
|
||||
"weight": 281,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/delete-document.md",
|
||||
|
|
@ -7148,7 +7148,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "decrementDocumentAttribute",
|
||||
"group": "documents",
|
||||
"weight": 300,
|
||||
"weight": 286,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/decrement-document-attribute.md",
|
||||
|
|
@ -7271,7 +7271,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "incrementDocumentAttribute",
|
||||
"group": "documents",
|
||||
"weight": 299,
|
||||
"weight": 285,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "databases\/increment-document-attribute.md",
|
||||
|
|
@ -7392,7 +7392,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listExecutions",
|
||||
"group": "executions",
|
||||
"weight": 447,
|
||||
"weight": 436,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "functions\/list-executions.md",
|
||||
|
|
@ -7475,7 +7475,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createExecution",
|
||||
"group": "executions",
|
||||
"weight": 445,
|
||||
"weight": 434,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "functions\/create-execution.md",
|
||||
|
|
@ -7594,7 +7594,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getExecution",
|
||||
"group": "executions",
|
||||
"weight": 446,
|
||||
"weight": 435,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "functions\/get-execution.md",
|
||||
|
|
@ -7666,7 +7666,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "query",
|
||||
"group": "graphql",
|
||||
"weight": 190,
|
||||
"weight": 176,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"demo": "graphql\/query.md",
|
||||
|
|
@ -7741,7 +7741,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "mutation",
|
||||
"group": "graphql",
|
||||
"weight": 189,
|
||||
"weight": 175,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"demo": "graphql\/mutation.md",
|
||||
|
|
@ -8240,7 +8240,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 237,
|
||||
"weight": 223,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "messaging\/create-subscriber.md",
|
||||
|
|
@ -8325,7 +8325,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 241,
|
||||
"weight": 227,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "messaging\/delete-subscriber.md",
|
||||
|
|
@ -8396,7 +8396,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listFiles",
|
||||
"group": "files",
|
||||
"weight": 543,
|
||||
"weight": 532,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/list-files.md",
|
||||
|
|
@ -8489,7 +8489,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createFile",
|
||||
"group": "files",
|
||||
"weight": 541,
|
||||
"weight": 530,
|
||||
"cookies": false,
|
||||
"type": "upload",
|
||||
"demo": "storage\/create-file.md",
|
||||
|
|
@ -8580,7 +8580,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFile",
|
||||
"group": "files",
|
||||
"weight": 542,
|
||||
"weight": 531,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/get-file.md",
|
||||
|
|
@ -8651,7 +8651,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateFile",
|
||||
"group": "files",
|
||||
"weight": 544,
|
||||
"weight": 533,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/update-file.md",
|
||||
|
|
@ -8742,7 +8742,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteFile",
|
||||
"group": "files",
|
||||
"weight": 545,
|
||||
"weight": 534,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "storage\/delete-file.md",
|
||||
|
|
@ -8813,7 +8813,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFileDownload",
|
||||
"group": "files",
|
||||
"weight": 547,
|
||||
"weight": 536,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "storage\/get-file-download.md",
|
||||
|
|
@ -8893,7 +8893,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFilePreview",
|
||||
"group": "files",
|
||||
"weight": 546,
|
||||
"weight": 535,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "storage\/get-file-preview.md",
|
||||
|
|
@ -9101,7 +9101,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFileView",
|
||||
"group": "files",
|
||||
"weight": 548,
|
||||
"weight": 537,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"demo": "storage\/get-file-view.md",
|
||||
|
|
@ -9181,7 +9181,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listTransactions",
|
||||
"group": "transactions",
|
||||
"weight": 419,
|
||||
"weight": 405,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/list-transactions.md",
|
||||
|
|
@ -9251,7 +9251,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 415,
|
||||
"weight": 401,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/create-transaction.md",
|
||||
|
|
@ -9325,7 +9325,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 416,
|
||||
"weight": 402,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/get-transaction.md",
|
||||
|
|
@ -9391,7 +9391,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 417,
|
||||
"weight": 403,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/update-transaction.md",
|
||||
|
|
@ -9473,7 +9473,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteTransaction",
|
||||
"group": "transactions",
|
||||
"weight": 418,
|
||||
"weight": 404,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/delete-transaction.md",
|
||||
|
|
@ -9541,7 +9541,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createOperations",
|
||||
"group": "transactions",
|
||||
"weight": 420,
|
||||
"weight": 406,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/create-operations.md",
|
||||
|
|
@ -9625,7 +9625,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listRows",
|
||||
"group": "rows",
|
||||
"weight": 411,
|
||||
"weight": 397,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/list-rows.md",
|
||||
|
|
@ -9728,7 +9728,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createRow",
|
||||
"group": "rows",
|
||||
"weight": 403,
|
||||
"weight": 389,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/create-row.md",
|
||||
|
|
@ -9882,7 +9882,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getRow",
|
||||
"group": "rows",
|
||||
"weight": 404,
|
||||
"weight": 390,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/get-row.md",
|
||||
|
|
@ -9984,7 +9984,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "upsertRow",
|
||||
"group": "rows",
|
||||
"weight": 407,
|
||||
"weight": 393,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/upsert-row.md",
|
||||
|
|
@ -10130,7 +10130,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateRow",
|
||||
"group": "rows",
|
||||
"weight": 405,
|
||||
"weight": 391,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/update-row.md",
|
||||
|
|
@ -10239,7 +10239,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteRow",
|
||||
"group": "rows",
|
||||
"weight": 409,
|
||||
"weight": 395,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/delete-row.md",
|
||||
|
|
@ -10339,7 +10339,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "decrementRowColumn",
|
||||
"group": "rows",
|
||||
"weight": 414,
|
||||
"weight": 400,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/decrement-row-column.md",
|
||||
|
|
@ -10461,7 +10461,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "incrementRowColumn",
|
||||
"group": "rows",
|
||||
"weight": 413,
|
||||
"weight": 399,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "tablesdb\/increment-row-column.md",
|
||||
|
|
@ -10581,7 +10581,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "list",
|
||||
"group": "teams",
|
||||
"weight": 110,
|
||||
"weight": 107,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/list.md",
|
||||
|
|
@ -10666,7 +10666,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "create",
|
||||
"group": "teams",
|
||||
"weight": 109,
|
||||
"weight": 106,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/create.md",
|
||||
|
|
@ -10757,7 +10757,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"group": "teams",
|
||||
"weight": 111,
|
||||
"weight": 108,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get.md",
|
||||
|
|
@ -10820,7 +10820,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateName",
|
||||
"group": "teams",
|
||||
"weight": 113,
|
||||
"weight": 110,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-name.md",
|
||||
|
|
@ -10896,7 +10896,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "delete",
|
||||
"group": "teams",
|
||||
"weight": 115,
|
||||
"weight": 112,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/delete.md",
|
||||
|
|
@ -10959,7 +10959,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listMemberships",
|
||||
"group": "memberships",
|
||||
"weight": 117,
|
||||
"weight": 114,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/list-memberships.md",
|
||||
|
|
@ -11052,7 +11052,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMembership",
|
||||
"group": "memberships",
|
||||
"weight": 116,
|
||||
"weight": 113,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/create-membership.md",
|
||||
|
|
@ -11120,14 +11120,7 @@
|
|||
"default": null,
|
||||
"x-example": null,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"admin",
|
||||
"developer",
|
||||
"owner"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
|
|
@ -11176,7 +11169,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getMembership",
|
||||
"group": "memberships",
|
||||
"weight": 118,
|
||||
"weight": 115,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get-membership.md",
|
||||
|
|
@ -11247,7 +11240,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMembership",
|
||||
"group": "memberships",
|
||||
"weight": 119,
|
||||
"weight": 116,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-membership.md",
|
||||
|
|
@ -11303,14 +11296,7 @@
|
|||
"default": null,
|
||||
"x-example": null,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"admin",
|
||||
"developer",
|
||||
"owner"
|
||||
],
|
||||
"x-enum-name": null,
|
||||
"x-enum-keys": []
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -11341,7 +11327,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteMembership",
|
||||
"group": "memberships",
|
||||
"weight": 121,
|
||||
"weight": 118,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/delete-membership.md",
|
||||
|
|
@ -11414,7 +11400,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMembershipStatus",
|
||||
"group": "memberships",
|
||||
"weight": 120,
|
||||
"weight": 117,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-membership-status.md",
|
||||
|
|
@ -11510,7 +11496,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getPrefs",
|
||||
"group": "teams",
|
||||
"weight": 112,
|
||||
"weight": 109,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/get-prefs.md",
|
||||
|
|
@ -11573,7 +11559,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updatePrefs",
|
||||
"group": "teams",
|
||||
"weight": 114,
|
||||
"weight": 111,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"demo": "teams\/update-prefs.md",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -369,6 +369,75 @@ return [
|
|||
]
|
||||
],
|
||||
],
|
||||
[
|
||||
'category' => 'Database',
|
||||
'description' => 'Appwrite uses a database for storing user and meta data. You can choose between MariaDB, MongoDB or PostgreSQL.',
|
||||
'variables' => [
|
||||
[
|
||||
'name' => '_APP_DB_ADAPTER',
|
||||
'description' => 'Which database to use. Must be one of: MariaDB, MongoDB, or PostgreSQL',
|
||||
'introduction' => '1.9.0',
|
||||
'default' => 'mongodb',
|
||||
'required' => true,
|
||||
'question' => 'Choose your database (mariadb|mongodb|postgresql)',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DB_HOST',
|
||||
'description' => 'Database server host name address. Default value is: \'mongodb\'.',
|
||||
'introduction' => '',
|
||||
'default' => 'mongodb',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DB_PORT',
|
||||
'description' => 'Database server TCP port. Default value is: \'27017\'.',
|
||||
'introduction' => '',
|
||||
'default' => '27017',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DB_SCHEMA',
|
||||
'description' => 'Database server database schema. Default value is: \'appwrite\'.',
|
||||
'introduction' => '',
|
||||
'default' => 'appwrite',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DB_USER',
|
||||
'description' => 'Database server user name. Default value is: \'user\'.',
|
||||
'introduction' => '',
|
||||
'default' => 'user',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DB_PASS',
|
||||
'description' => 'Database server user password. Default value is: \'password\'.',
|
||||
'introduction' => '',
|
||||
'default' => 'password',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => 'password'
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DB_ROOT_PASS',
|
||||
'description' => 'Database server root password. Default value is: \'rootsecretpassword\'.',
|
||||
'introduction' => '',
|
||||
'default' => 'rootsecretpassword',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => 'password'
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'category' => 'Redis',
|
||||
'description' => 'Appwrite uses a Redis server for managing cache, queues and scheduled tasks. The Redis env vars are used to allow Appwrite server to connect to the Redis container.',
|
||||
|
|
@ -411,66 +480,6 @@ return [
|
|||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'category' => 'MariaDB',
|
||||
'description' => 'Appwrite is using a MariaDB server for managing persistent database data. The MariaDB env vars are used to allow Appwrite server to connect to the MariaDB container.',
|
||||
'variables' => [
|
||||
[
|
||||
'name' => '_APP_DB_HOST',
|
||||
'description' => 'MariaDB server host name address. Default value is: \'mariadb\'.',
|
||||
'introduction' => '',
|
||||
'default' => 'mariadb',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DB_PORT',
|
||||
'description' => 'MariaDB server TCP port. Default value is: \'3306\'.',
|
||||
'introduction' => '',
|
||||
'default' => '3306',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DB_SCHEMA',
|
||||
'description' => 'MariaDB server database schema. Default value is: \'appwrite\'.',
|
||||
'introduction' => '',
|
||||
'default' => 'appwrite',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DB_USER',
|
||||
'description' => 'MariaDB server user name. Default value is: \'user\'.',
|
||||
'introduction' => '',
|
||||
'default' => 'user',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DB_PASS',
|
||||
'description' => 'MariaDB server user password. Default value is: \'password\'.',
|
||||
'introduction' => '',
|
||||
'default' => 'password',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => 'password'
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DB_ROOT_PASS',
|
||||
'description' => 'MariaDB server root password. Default value is: \'rootsecretpassword\'.',
|
||||
'introduction' => '',
|
||||
'default' => 'rootsecretpassword',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => 'password'
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'category' => 'InfluxDB',
|
||||
'description' => 'Deprecated since 1.4.8.',
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ use Utopia\Database\Validator\Query\Limit;
|
|||
use Utopia\Database\Validator\Query\Offset;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Emails\Email;
|
||||
use Utopia\Http;
|
||||
use Utopia\Http\Http;
|
||||
use Utopia\Locale\Locale;
|
||||
use Utopia\Storage\Validator\FileName;
|
||||
use Utopia\System\System;
|
||||
|
|
@ -367,7 +367,7 @@ Http::post('/v1/account')
|
|||
contentType: ContentType::JSON
|
||||
))
|
||||
->label('abuse-limit', 10)
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, $project->getAttribute('auths', [])['passwordDictionary'] ?? false), 'New user password. Must be between 8 and 256 chars.', false, ['project', 'passwordsDictionary'])
|
||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||
|
|
@ -728,7 +728,7 @@ Http::get('/v1/account/sessions/:sessionId')
|
|||
],
|
||||
contentType: ContentType::JSON
|
||||
))
|
||||
->param('sessionId', '', new UID(), 'Session ID. Use the string \'current\' to get the current device session.')
|
||||
->param('sessionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Session ID. Use the string \'current\' to get the current device session.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
->inject('locale')
|
||||
|
|
@ -780,7 +780,7 @@ Http::delete('/v1/account/sessions/:sessionId')
|
|||
contentType: ContentType::NONE
|
||||
))
|
||||
->label('abuse-limit', 100)
|
||||
->param('sessionId', '', new UID(), 'Session ID. Use the string \'current\' to delete the current device session.')
|
||||
->param('sessionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Session ID. Use the string \'current\' to delete the current device session.', false, ['dbForProject'])
|
||||
->inject('requestTimestamp')
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
|
|
@ -868,7 +868,7 @@ Http::patch('/v1/account/sessions/:sessionId')
|
|||
contentType: ContentType::JSON
|
||||
))
|
||||
->label('abuse-limit', 10)
|
||||
->param('sessionId', '', new UID(), 'Session ID. Use the string \'current\' to update the current device session.')
|
||||
->param('sessionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Session ID. Use the string \'current\' to update the current device session.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -1262,7 +1262,7 @@ Http::post('/v1/account/sessions/token')
|
|||
->label('abuse-limit', 10)
|
||||
->label('abuse-key', 'ip:{ip},userId:{param-userId}')
|
||||
->label('abuse-reset', [201])
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('secret', '', new Text(256), 'Secret of a token generated by login methods. For example, the `createMagicURLToken` or `createPhoneToken` methods.')
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
|
|
@ -1469,13 +1469,14 @@ Http::get('/v1/account/sessions/oauth2/:provider/redirect')
|
|||
->inject('devKey')
|
||||
->inject('user')
|
||||
->inject('dbForProject')
|
||||
->inject('dbForPlatform')
|
||||
->inject('geodb')
|
||||
->inject('queueForEvents')
|
||||
->inject('store')
|
||||
->inject('proofForPassword')
|
||||
->inject('proofForToken')
|
||||
->inject('authorization')
|
||||
->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Validator $redirectValidator, Document $devKey, User $user, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) use ($oauthDefaultSuccess) {
|
||||
->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Validator $redirectValidator, Document $devKey, User $user, Database $dbForProject, Database $dbForPlatform, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken, Authorization $authorization) use ($oauthDefaultSuccess) {
|
||||
$protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https';
|
||||
$port = $request->getPort();
|
||||
$callbackBase = $protocol . '://' . $request->getHostname();
|
||||
|
|
@ -1484,6 +1485,7 @@ Http::get('/v1/account/sessions/oauth2/:provider/redirect')
|
|||
} elseif ($protocol === 'http' && $port !== '80') {
|
||||
$callbackBase .= ':' . $port;
|
||||
}
|
||||
|
||||
$callback = $callbackBase . '/v1/account/sessions/oauth2/callback/' . $provider . '/' . $project->getId();
|
||||
$defaultState = ['success' => $project->getAttribute('url', ''), 'failure' => ''];
|
||||
$appId = $project->getAttribute('oAuthProviders', [])[$provider . 'Appid'] ?? '';
|
||||
|
|
@ -1512,6 +1514,29 @@ Http::get('/v1/account/sessions/oauth2/:provider/redirect')
|
|||
$state = $defaultState;
|
||||
}
|
||||
|
||||
// Allow redirect to rule URL if related to project
|
||||
// Check if $redirectValidator is instance of Redirect class
|
||||
if ($redirectValidator instanceof Redirect) {
|
||||
$domains = \array_filter([
|
||||
parse_url($state['success'], PHP_URL_HOST) ?? '',
|
||||
parse_url($state['failure'], PHP_URL_HOST) ?? ''
|
||||
], fn ($domain) => \is_string($domain) && $domain !== '');
|
||||
|
||||
if (!empty($domains)) {
|
||||
$rules = $authorization->skip(fn () => $dbForPlatform->find('rules', [
|
||||
Query::equal('domain', \array_values(\array_unique($domains))),
|
||||
Query::equal('projectInternalId', [$project->getSequence()]),
|
||||
Query::limit(2)
|
||||
]));
|
||||
|
||||
foreach ($rules as $rule) {
|
||||
$allowedHostnames = $redirectValidator->getAllowedHostnames();
|
||||
$allowedHostnames[] = $rule->getAttribute('domain', '');
|
||||
$redirectValidator->setAllowedHostnames($allowedHostnames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($devKey->isEmpty() && !$redirectValidator->isValid($state['success'])) {
|
||||
throw new Exception(Exception::PROJECT_INVALID_SUCCESS_URL);
|
||||
}
|
||||
|
|
@ -1523,6 +1548,7 @@ Http::get('/v1/account/sessions/oauth2/:provider/redirect')
|
|||
if (!empty($state['failure'])) {
|
||||
$failure = URLParser::parse($state['failure']);
|
||||
}
|
||||
|
||||
$failureRedirect = (function (string $type, ?string $message = null, ?int $code = null) use ($failure, $response) {
|
||||
$exception = new Exception($type, $message, $code);
|
||||
if (!empty($failure)) {
|
||||
|
|
@ -1568,7 +1594,9 @@ Http::get('/v1/account/sessions/oauth2/:provider/redirect')
|
|||
$accessToken = $oauth2->getAccessToken($code);
|
||||
$refreshToken = $oauth2->getRefreshToken($code);
|
||||
$accessTokenExpiry = $oauth2->getAccessTokenExpiry($code);
|
||||
|
||||
} catch (OAuth2Exception $ex) {
|
||||
|
||||
$failureRedirect(
|
||||
$ex->getType(),
|
||||
'Failed to obtain access token. The ' . $providerName . ' OAuth2 provider returned an error: ' . $ex->getMessage(),
|
||||
|
|
@ -2068,7 +2096,7 @@ Http::post('/v1/account/tokens/magic-url')
|
|||
))
|
||||
->label('abuse-limit', 60)
|
||||
->label('abuse-key', ['url:{url},email:{param-email}', 'url:{url},ip:{ip}'])
|
||||
->param('userId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. 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. If the email address has never been used, a new account is created using the provided userId. Otherwise, if the email address is already attached to an account, the user ID is ignored.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. 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. If the email address has never been used, a new account is created using the provided userId. Otherwise, if the email address is already attached to an account, the user ID is ignored.', false, ['dbForProject'])
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('url', '', fn ($redirectValidator) => $redirectValidator, 'URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['redirectValidator'])
|
||||
->param('phrase', false, new Boolean(), 'Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.', true)
|
||||
|
|
@ -2348,7 +2376,7 @@ Http::post('/v1/account/tokens/email')
|
|||
))
|
||||
->label('abuse-limit', 10)
|
||||
->label('abuse-key', ['url:{url},email:{param-email}', 'url:{url},ip:{ip}'])
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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. If the email address has never been used, a new account is created using the provided userId. Otherwise, if the email address is already attached to an account, the user ID is ignored.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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. If the email address has never been used, a new account is created using the provided userId. Otherwise, if the email address is already attached to an account, the user ID is ignored.', false, ['dbForProject'])
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('phrase', false, new Boolean(), 'Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.', true)
|
||||
->inject('request')
|
||||
|
|
@ -2655,7 +2683,7 @@ Http::put('/v1/account/sessions/magic-url')
|
|||
->label('abuse-limit', 10)
|
||||
->label('abuse-key', 'ip:{ip},userId:{param-userId}')
|
||||
->label('abuse-reset', [201])
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('secret', '', new Text(256), 'Valid verification token.')
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
|
|
@ -2704,7 +2732,7 @@ Http::put('/v1/account/sessions/phone')
|
|||
))
|
||||
->label('abuse-limit', 10)
|
||||
->label('abuse-key', 'ip:{ip},userId:{param-userId}')
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('secret', '', new Text(256), 'Valid verification token.')
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
|
|
@ -2747,7 +2775,7 @@ Http::post('/v1/account/tokens/phone')
|
|||
))
|
||||
->label('abuse-limit', 10)
|
||||
->label('abuse-key', ['url:{url},phone:{param-phone}', 'url:{url},ip:{ip}'])
|
||||
->param('userId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. 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. If the phone number has never been used, a new account is created using the provided userId. Otherwise, if the phone number is already attached to an account, the user ID is ignored.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. 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. If the phone number has never been used, a new account is created using the provided userId. Otherwise, if the phone number is already attached to an account, the user ID is ignored.', false, ['dbForProject'])
|
||||
->param('phone', '', new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.')
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
|
|
@ -3725,7 +3753,7 @@ Http::put('/v1/account/recovery')
|
|||
))
|
||||
->label('abuse-limit', 10)
|
||||
->label('abuse-key', 'url:{url},userId:{param-userId}')
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('secret', '', new Text(256), 'Valid reset token.')
|
||||
->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, $project->getAttribute('auths', [])['passwordDictionary'] ?? false), 'New user password. Must be between 8 and 256 chars.', false, ['project', 'passwordsDictionary'])
|
||||
->inject('response')
|
||||
|
|
@ -4076,7 +4104,7 @@ Http::put('/v1/account/verifications/email')
|
|||
])
|
||||
->label('abuse-limit', 10)
|
||||
->label('abuse-key', 'url:{url},userId:{param-userId}')
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('secret', '', new Text(256), 'Valid verification token.')
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
|
|
@ -4292,7 +4320,7 @@ Http::put('/v1/account/verifications/phone')
|
|||
))
|
||||
->label('abuse-limit', 10)
|
||||
->label('abuse-key', 'userId:{param-userId}')
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('secret', '', new Text(256), 'Valid verification token.')
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
|
|
@ -4357,9 +4385,9 @@ Http::post('/v1/account/targets/push')
|
|||
],
|
||||
contentType: ContentType::JSON
|
||||
))
|
||||
->param('targetId', '', new CustomId(), 'Target ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('targetId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Target ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)')
|
||||
->param('providerId', '', new UID(), 'Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.', true)
|
||||
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.', true, ['dbForProject'])
|
||||
->inject('queueForEvents')
|
||||
->inject('user')
|
||||
->inject('request')
|
||||
|
|
@ -4441,7 +4469,7 @@ Http::put('/v1/account/targets/:targetId/push')
|
|||
],
|
||||
contentType: ContentType::JSON
|
||||
))
|
||||
->param('targetId', '', new UID(), 'Target ID.')
|
||||
->param('targetId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Target ID.', false, ['dbForProject'])
|
||||
->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)')
|
||||
->inject('queueForEvents')
|
||||
->inject('user')
|
||||
|
|
@ -4507,7 +4535,7 @@ Http::delete('/v1/account/targets/:targetId/push')
|
|||
],
|
||||
contentType: ContentType::NONE
|
||||
))
|
||||
->param('targetId', '', new UID(), 'Target ID.')
|
||||
->param('targetId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Target ID.', false, ['dbForProject'])
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForDeletes')
|
||||
->inject('user')
|
||||
|
|
@ -4574,16 +4602,10 @@ Http::get('/v1/account/identities')
|
|||
|
||||
$queries[] = Query::equal('userInternalId', [$user->getSequence()]);
|
||||
|
||||
/**
|
||||
* Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries
|
||||
*/
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
/** @var Query $cursor */
|
||||
$cursor = Query::getCursorQueries($queries, false);
|
||||
$cursor = \reset($cursor);
|
||||
|
||||
if ($cursor !== false) {
|
||||
$validator = new Cursor();
|
||||
if (!$validator->isValid($cursor)) {
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
|
||||
|
|
@ -4635,7 +4657,7 @@ Http::delete('/v1/account/identities/:identityId')
|
|||
],
|
||||
contentType: ContentType::NONE
|
||||
))
|
||||
->param('identityId', '', new UID(), 'Identity ID.')
|
||||
->param('identityId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Identity ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ use GraphQL\Validator\Rules\QueryDepth;
|
|||
use Swoole\Coroutine\WaitGroup;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Http;
|
||||
use Utopia\Http\Http;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\JSON;
|
||||
use Utopia\Validator\Text;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use Appwrite\Utopia\Response;
|
|||
use MaxMind\Db\Reader;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Http;
|
||||
use Utopia\Http\Http;
|
||||
use Utopia\Locale\Locale;
|
||||
|
||||
Http::get('/v1/locale')
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ use Utopia\Database\Validator\Query\Limit;
|
|||
use Utopia\Database\Validator\Query\Offset;
|
||||
use Utopia\Database\Validator\Roles;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Http;
|
||||
use Utopia\Http\Http;
|
||||
use Utopia\Locale\Locale;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\ArrayList;
|
||||
|
|
@ -78,7 +78,7 @@ Http::post('/v1/messaging/providers/mailgun')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.')
|
||||
->param('apiKey', '', new Text(0), 'Mailgun API Key.', true)
|
||||
->param('domain', '', new Text(0), 'Mailgun Domain.', true)
|
||||
|
|
@ -172,7 +172,7 @@ Http::post('/v1/messaging/providers/sendgrid')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.')
|
||||
->param('apiKey', '', new Text(0), 'Sendgrid API key.', true)
|
||||
->param('fromName', '', new Text(128, 0), 'Sender Name.', true)
|
||||
|
|
@ -254,7 +254,7 @@ Http::post('/v1/messaging/providers/resend')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.')
|
||||
->param('apiKey', '', new Text(0), 'Resend API key.', true)
|
||||
->param('fromName', '', new Text(128, 0), 'Sender Name.', true)
|
||||
|
|
@ -356,7 +356,7 @@ Http::post('/v1/messaging/providers/smtp')
|
|||
]
|
||||
)
|
||||
])
|
||||
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.')
|
||||
->param('host', '', new Text(0), 'SMTP hosts. Either a single hostname or multiple semicolon-delimited hostnames. You can also specify a different port for each host such as `smtp1.example.com:25;smtp2.example.com`. You can also specify encryption type, for example: `tls://smtp1.example.com:587;ssl://smtp2.example.com:465"`. Hosts will be tried in order.')
|
||||
->param('port', 587, new Range(1, 65535), 'The default SMTP server port.', true)
|
||||
|
|
@ -451,7 +451,7 @@ Http::post('/v1/messaging/providers/msg91')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.')
|
||||
->param('templateId', '', new Text(0), 'Msg91 template ID', true)
|
||||
->param('senderId', '', new Text(0), 'Msg91 sender ID.', true)
|
||||
|
|
@ -534,7 +534,7 @@ Http::post('/v1/messaging/providers/telesign')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.')
|
||||
->param('from', '', new Phone(), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
|
||||
->param('customerId', '', new Text(0), 'Telesign customer ID.', true)
|
||||
|
|
@ -618,7 +618,7 @@ Http::post('/v1/messaging/providers/textmagic')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.')
|
||||
->param('from', '', new Phone(), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
|
||||
->param('username', '', new Text(0), 'Textmagic username.', true)
|
||||
|
|
@ -702,7 +702,7 @@ Http::post('/v1/messaging/providers/twilio')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.')
|
||||
->param('from', '', new Phone(), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
|
||||
->param('accountSid', '', new Text(0), 'Twilio account secret ID.', true)
|
||||
|
|
@ -786,7 +786,7 @@ Http::post('/v1/messaging/providers/vonage')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.')
|
||||
->param('from', '', new Phone(), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
|
||||
->param('apiKey', '', new Text(0), 'Vonage API key.', true)
|
||||
|
|
@ -890,7 +890,7 @@ Http::post('/v1/messaging/providers/fcm')
|
|||
]
|
||||
)
|
||||
])
|
||||
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.')
|
||||
->param('serviceAccountJSON', null, new Nullable(new JSON()), 'FCM service account JSON.', true)
|
||||
->param('enabled', null, new Nullable(new Boolean()), 'Set as enabled.', true)
|
||||
|
|
@ -980,7 +980,7 @@ Http::post('/v1/messaging/providers/apns')
|
|||
]
|
||||
)
|
||||
])
|
||||
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('providerId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.')
|
||||
->param('authKey', '', new Text(0), 'APNS authentication key.', true)
|
||||
->param('authKeyId', '', new Text(0), 'APNS authentication key ID.', true)
|
||||
|
|
@ -1087,15 +1087,10 @@ Http::get('/v1/messaging/providers')
|
|||
$queries[] = Query::search('search', $search);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries
|
||||
*/
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
$cursor = Query::getCursorQueries($queries, false);
|
||||
$cursor = \reset($cursor);
|
||||
|
||||
if ($cursor) {
|
||||
if ($cursor !== false) {
|
||||
$validator = new Cursor();
|
||||
if (!$validator->isValid($cursor)) {
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
|
||||
|
|
@ -1140,7 +1135,7 @@ Http::get('/v1/messaging/providers/:providerId/logs')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('providerId', '', new UID(), 'Provider ID.')
|
||||
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
|
||||
->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true)
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('response')
|
||||
|
|
@ -1236,7 +1231,7 @@ Http::get('/v1/messaging/providers/:providerId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('providerId', '', new UID(), 'Provider ID.')
|
||||
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
|
||||
->inject('dbForProject')
|
||||
->inject('response')
|
||||
->action(function (string $providerId, Database $dbForProject, Response $response) {
|
||||
|
|
@ -1270,7 +1265,7 @@ Http::patch('/v1/messaging/providers/mailgun/:providerId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('providerId', '', new UID(), 'Provider ID.')
|
||||
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.', true)
|
||||
->param('apiKey', '', new Text(0), 'Mailgun API Key.', true)
|
||||
->param('domain', '', new Text(0), 'Mailgun Domain.', true)
|
||||
|
|
@ -1383,7 +1378,7 @@ Http::patch('/v1/messaging/providers/sendgrid/:providerId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('providerId', '', new UID(), 'Provider ID.')
|
||||
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.', true)
|
||||
->param('enabled', null, new Nullable(new Boolean()), 'Set as enabled.', true)
|
||||
->param('apiKey', '', new Text(0), 'Sendgrid API key.', true)
|
||||
|
|
@ -1481,7 +1476,7 @@ Http::patch('/v1/messaging/providers/resend/:providerId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('providerId', '', new UID(), 'Provider ID.')
|
||||
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.', true)
|
||||
->param('enabled', null, new Nullable(new Boolean()), 'Set as enabled.', true)
|
||||
->param('apiKey', '', new Text(0), 'Resend API key.', true)
|
||||
|
|
@ -1599,7 +1594,7 @@ Http::patch('/v1/messaging/providers/smtp/:providerId')
|
|||
]
|
||||
)
|
||||
])
|
||||
->param('providerId', '', new UID(), 'Provider ID.')
|
||||
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.', true)
|
||||
->param('host', '', new Text(0), 'SMTP hosts. Either a single hostname or multiple semicolon-delimited hostnames. You can also specify a different port for each host such as `smtp1.example.com:25;smtp2.example.com`. You can also specify encryption type, for example: `tls://smtp1.example.com:587;ssl://smtp2.example.com:465"`. Hosts will be tried in order.', true)
|
||||
->param('port', null, new Nullable(new Range(1, 65535)), 'SMTP port.', true)
|
||||
|
|
@ -1728,7 +1723,7 @@ Http::patch('/v1/messaging/providers/msg91/:providerId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('providerId', '', new UID(), 'Provider ID.')
|
||||
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.', true)
|
||||
->param('enabled', null, new Nullable(new Boolean()), 'Set as enabled.', true)
|
||||
->param('templateId', '', new Text(0), 'Msg91 template ID.', true)
|
||||
|
|
@ -1815,7 +1810,7 @@ Http::patch('/v1/messaging/providers/telesign/:providerId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('providerId', '', new UID(), 'Provider ID.')
|
||||
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.', true)
|
||||
->param('enabled', null, new Nullable(new Boolean()), 'Set as enabled.', true)
|
||||
->param('customerId', '', new Text(0), 'Telesign customer ID.', true)
|
||||
|
|
@ -1904,7 +1899,7 @@ Http::patch('/v1/messaging/providers/textmagic/:providerId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('providerId', '', new UID(), 'Provider ID.')
|
||||
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.', true)
|
||||
->param('enabled', null, new Nullable(new Boolean()), 'Set as enabled.', true)
|
||||
->param('username', '', new Text(0), 'Textmagic username.', true)
|
||||
|
|
@ -1993,7 +1988,7 @@ Http::patch('/v1/messaging/providers/twilio/:providerId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('providerId', '', new UID(), 'Provider ID.')
|
||||
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.', true)
|
||||
->param('enabled', null, new Nullable(new Boolean()), 'Set as enabled.', true)
|
||||
->param('accountSid', '', new Text(0), 'Twilio account secret ID.', true)
|
||||
|
|
@ -2082,7 +2077,7 @@ Http::patch('/v1/messaging/providers/vonage/:providerId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('providerId', '', new UID(), 'Provider ID.')
|
||||
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.', true)
|
||||
->param('enabled', null, new Nullable(new Boolean()), 'Set as enabled.', true)
|
||||
->param('apiKey', '', new Text(0), 'Vonage API key.', true)
|
||||
|
|
@ -2191,7 +2186,7 @@ Http::patch('/v1/messaging/providers/fcm/:providerId')
|
|||
]
|
||||
)
|
||||
])
|
||||
->param('providerId', '', new UID(), 'Provider ID.')
|
||||
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.', true)
|
||||
->param('enabled', null, new Nullable(new Boolean()), 'Set as enabled.', true)
|
||||
->param('serviceAccountJSON', null, new Nullable(new JSON()), 'FCM service account JSON.', true)
|
||||
|
|
@ -2287,7 +2282,7 @@ Http::patch('/v1/messaging/providers/apns/:providerId')
|
|||
]
|
||||
)
|
||||
])
|
||||
->param('providerId', '', new UID(), 'Provider ID.')
|
||||
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Provider name.', true)
|
||||
->param('enabled', null, new Nullable(new Boolean()), 'Set as enabled.', true)
|
||||
->param('authKey', '', new Text(0), 'APNS authentication key.', true)
|
||||
|
|
@ -2390,7 +2385,7 @@ Http::delete('/v1/messaging/providers/:providerId')
|
|||
],
|
||||
contentType: ContentType::NONE
|
||||
))
|
||||
->param('providerId', '', new UID(), 'Provider ID.')
|
||||
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID.', false, ['dbForProject'])
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForProject')
|
||||
->inject('response')
|
||||
|
|
@ -2432,7 +2427,7 @@ Http::post('/v1/messaging/topics')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('topicId', '', new CustomId(), 'Topic ID. Choose a custom Topic ID or a new Topic ID.')
|
||||
->param('topicId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Topic ID. Choose a custom Topic ID or a new Topic ID.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Topic Name.')
|
||||
->param('subscribe', [Role::users()], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https://appwrite.io/docs/permissions#permission-roles). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true)
|
||||
->inject('queueForEvents')
|
||||
|
|
@ -2496,15 +2491,10 @@ Http::get('/v1/messaging/topics')
|
|||
$queries[] = Query::search('search', $search);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries
|
||||
*/
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
$cursor = Query::getCursorQueries($queries, false);
|
||||
$cursor = \reset($cursor);
|
||||
|
||||
if ($cursor) {
|
||||
if ($cursor !== false) {
|
||||
$validator = new Cursor();
|
||||
if (!$validator->isValid($cursor)) {
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
|
||||
|
|
@ -2549,7 +2539,7 @@ Http::get('/v1/messaging/topics/:topicId/logs')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('topicId', '', new UID(), 'Topic ID.')
|
||||
->param('topicId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Topic ID.', false, ['dbForProject'])
|
||||
->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true)
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('response')
|
||||
|
|
@ -2646,7 +2636,7 @@ Http::get('/v1/messaging/topics/:topicId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('topicId', '', new UID(), 'Topic ID.')
|
||||
->param('topicId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Topic ID.', false, ['dbForProject'])
|
||||
->inject('dbForProject')
|
||||
->inject('response')
|
||||
->action(function (string $topicId, Database $dbForProject, Response $response) {
|
||||
|
|
@ -2681,7 +2671,7 @@ Http::patch('/v1/messaging/topics/:topicId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('topicId', '', new UID(), 'Topic ID.')
|
||||
->param('topicId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Topic ID.', false, ['dbForProject'])
|
||||
->param('name', null, new Nullable(new Text(128)), 'Topic Name.', true)
|
||||
->param('subscribe', null, new Nullable(new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE)), 'An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https://appwrite.io/docs/permissions#permission-roles). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true)
|
||||
->inject('queueForEvents')
|
||||
|
|
@ -2733,7 +2723,7 @@ Http::delete('/v1/messaging/topics/:topicId')
|
|||
],
|
||||
contentType: ContentType::NONE
|
||||
))
|
||||
->param('topicId', '', new UID(), 'Topic ID.')
|
||||
->param('topicId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Topic ID.', false, ['dbForProject'])
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForDeletes')
|
||||
|
|
@ -2780,9 +2770,9 @@ Http::post('/v1/messaging/topics/:topicId/subscribers')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('subscriberId', '', new CustomId(), 'Subscriber ID. Choose a custom Subscriber ID or a new Subscriber ID.')
|
||||
->param('topicId', '', new UID(), 'Topic ID. The topic ID to subscribe to.')
|
||||
->param('targetId', '', new UID(), 'Target ID. The target ID to link to the specified Topic ID.')
|
||||
->param('subscriberId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Subscriber ID. Choose a custom Subscriber ID or a new Subscriber ID.', false, ['dbForProject'])
|
||||
->param('topicId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Topic ID. The topic ID to subscribe to.', false, ['dbForProject'])
|
||||
->param('targetId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Target ID. The target ID to link to the specified Topic ID.', false, ['dbForProject'])
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
|
|
@ -2878,8 +2868,8 @@ Http::get('/v1/messaging/topics/:topicId/subscribers')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.')
|
||||
->param('queries', [], new Subscribers(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Providers::ALLOWED_ATTRIBUTES), true)
|
||||
->param('topicId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Topic ID. The topic ID subscribed to.', false, ['dbForProject'])
|
||||
->param('queries', [], new Subscribers(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Subscribers::ALLOWED_ATTRIBUTES), true)
|
||||
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('dbForProject')
|
||||
|
|
@ -2904,15 +2894,10 @@ Http::get('/v1/messaging/topics/:topicId/subscribers')
|
|||
|
||||
$queries[] = Query::equal('topicInternalId', [$topic->getSequence()]);
|
||||
|
||||
/**
|
||||
* Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries
|
||||
*/
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
$cursor = Query::getCursorQueries($queries, false);
|
||||
$cursor = \reset($cursor);
|
||||
|
||||
if ($cursor) {
|
||||
if ($cursor !== false) {
|
||||
$validator = new Cursor();
|
||||
if (!$validator->isValid($cursor)) {
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
|
||||
|
|
@ -2969,7 +2954,7 @@ Http::get('/v1/messaging/subscribers/:subscriberId/logs')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('subscriberId', '', new UID(), 'Subscriber ID.')
|
||||
->param('subscriberId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Subscriber ID.', false, ['dbForProject'])
|
||||
->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true)
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('response')
|
||||
|
|
@ -3066,8 +3051,8 @@ Http::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.')
|
||||
->param('subscriberId', '', new UID(), 'Subscriber ID.')
|
||||
->param('topicId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Topic ID. The topic ID subscribed to.', false, ['dbForProject'])
|
||||
->param('subscriberId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Subscriber ID.', false, ['dbForProject'])
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('response')
|
||||
|
|
@ -3117,8 +3102,8 @@ Http::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId')
|
|||
],
|
||||
contentType: ContentType::NONE
|
||||
))
|
||||
->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.')
|
||||
->param('subscriberId', '', new UID(), 'Subscriber ID.')
|
||||
->param('topicId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Topic ID. The topic ID subscribed to.', false, ['dbForProject'])
|
||||
->param('subscriberId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Subscriber ID.', false, ['dbForProject'])
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
|
|
@ -3184,14 +3169,14 @@ Http::post('/v1/messaging/messages/email')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('messageId', '', new CustomId(), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('messageId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('subject', '', new Text(998), 'Email Subject.')
|
||||
->param('content', '', new Text(64230), 'Email Content.')
|
||||
->param('topics', [], new ArrayList(new UID()), 'List of Topic IDs.', true)
|
||||
->param('users', [], new ArrayList(new UID()), 'List of User IDs.', true)
|
||||
->param('targets', [], new ArrayList(new UID()), 'List of Targets IDs.', true)
|
||||
->param('cc', [], new ArrayList(new UID()), 'Array of target IDs to be added as CC.', true)
|
||||
->param('bcc', [], new ArrayList(new UID()), 'Array of target IDs to be added as BCC.', true)
|
||||
->param('topics', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'List of Topic IDs.', true, ['dbForProject'])
|
||||
->param('users', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'List of User IDs.', true, ['dbForProject'])
|
||||
->param('targets', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'List of Targets IDs.', true, ['dbForProject'])
|
||||
->param('cc', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'Array of target IDs to be added as CC.', true, ['dbForProject'])
|
||||
->param('bcc', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'Array of target IDs to be added as BCC.', true, ['dbForProject'])
|
||||
->param('attachments', [], new ArrayList(new CompoundUID()), 'Array of compound ID strings of bucket IDs and file IDs to be attached to the email. They should be formatted as <BUCKET_ID>:<FILE_ID>.', true)
|
||||
->param('draft', false, new Boolean(), 'Is message a draft', true)
|
||||
->param('html', false, new Boolean(), 'Is content of type HTML', true)
|
||||
|
|
@ -3363,11 +3348,11 @@ Http::post('/v1/messaging/messages/sms')
|
|||
]
|
||||
)
|
||||
])
|
||||
->param('messageId', '', new CustomId(), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('messageId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('content', '', new Text(64230), 'SMS Content.')
|
||||
->param('topics', [], new ArrayList(new UID()), 'List of Topic IDs.', true)
|
||||
->param('users', [], new ArrayList(new UID()), 'List of User IDs.', true)
|
||||
->param('targets', [], new ArrayList(new UID()), 'List of Targets IDs.', true)
|
||||
->param('topics', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'List of Topic IDs.', true, ['dbForProject'])
|
||||
->param('users', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'List of User IDs.', true, ['dbForProject'])
|
||||
->param('targets', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'List of Targets IDs.', true, ['dbForProject'])
|
||||
->param('draft', false, new Boolean(), 'Is message a draft', true)
|
||||
->param('scheduledAt', null, new Nullable(new DatetimeValidator(requireDateInFuture: true)), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true)
|
||||
->inject('queueForEvents')
|
||||
|
|
@ -3486,12 +3471,12 @@ Http::post('/v1/messaging/messages/push')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('messageId', '', new CustomId(), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('messageId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('title', '', new Text(256), 'Title for push notification.', true)
|
||||
->param('body', '', new Text(64230), 'Body for push notification.', true)
|
||||
->param('topics', [], new ArrayList(new UID()), 'List of Topic IDs.', true)
|
||||
->param('users', [], new ArrayList(new UID()), 'List of User IDs.', true)
|
||||
->param('targets', [], new ArrayList(new UID()), 'List of Targets IDs.', true)
|
||||
->param('topics', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'List of Topic IDs.', true, ['dbForProject'])
|
||||
->param('users', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'List of User IDs.', true, ['dbForProject'])
|
||||
->param('targets', [], fn (Database $dbForProject) => new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength())), 'List of Targets IDs.', true, ['dbForProject'])
|
||||
->param('data', null, new Nullable(new JSON()), 'Additional key-value pair data for push notification.', true)
|
||||
->param('action', '', new Text(256), 'Action for push notification.', true)
|
||||
->param('image', '', new CompoundUID(), 'Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as <BUCKET_ID>:<FILE_ID>.', true)
|
||||
|
|
@ -3719,15 +3704,10 @@ Http::get('/v1/messaging/messages')
|
|||
$queries[] = Query::search('search', $search);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries
|
||||
*/
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
$cursor = Query::getCursorQueries($queries, false);
|
||||
$cursor = \reset($cursor);
|
||||
|
||||
if ($cursor) {
|
||||
if ($cursor !== false) {
|
||||
$validator = new Cursor();
|
||||
if (!$validator->isValid($cursor)) {
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
|
||||
|
|
@ -3772,7 +3752,7 @@ Http::get('/v1/messaging/messages/:messageId/logs')
|
|||
)
|
||||
],
|
||||
))
|
||||
->param('messageId', '', new UID(), 'Message ID.')
|
||||
->param('messageId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID.', false, ['dbForProject'])
|
||||
->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true)
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('response')
|
||||
|
|
@ -3869,7 +3849,7 @@ Http::get('/v1/messaging/messages/:messageId/targets')
|
|||
)
|
||||
],
|
||||
))
|
||||
->param('messageId', '', new UID(), 'Message ID.')
|
||||
->param('messageId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID.', false, ['dbForProject'])
|
||||
->param('queries', [], new Targets(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Targets::ALLOWED_ATTRIBUTES), true)
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('response')
|
||||
|
|
@ -3899,15 +3879,10 @@ Http::get('/v1/messaging/messages/:messageId/targets')
|
|||
|
||||
$queries[] = Query::equal('$id', $targetIDs);
|
||||
|
||||
/**
|
||||
* Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries
|
||||
*/
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
$cursor = Query::getCursorQueries($queries, false);
|
||||
$cursor = \reset($cursor);
|
||||
|
||||
if ($cursor) {
|
||||
if ($cursor !== false) {
|
||||
$validator = new Cursor();
|
||||
if (!$validator->isValid($cursor)) {
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
|
||||
|
|
@ -3952,7 +3927,7 @@ Http::get('/v1/messaging/messages/:messageId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('messageId', '', new UID(), 'Message ID.')
|
||||
->param('messageId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID.', false, ['dbForProject'])
|
||||
->inject('dbForProject')
|
||||
->inject('response')
|
||||
->action(function (string $messageId, Database $dbForProject, Response $response) {
|
||||
|
|
@ -3986,16 +3961,16 @@ Http::patch('/v1/messaging/messages/email/:messageId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('messageId', '', new UID(), 'Message ID.')
|
||||
->param('topics', null, new Nullable(new ArrayList(new UID())), 'List of Topic IDs.', true)
|
||||
->param('users', null, new Nullable(new ArrayList(new UID())), 'List of User IDs.', true)
|
||||
->param('targets', null, new Nullable(new ArrayList(new UID())), 'List of Targets IDs.', true)
|
||||
->param('messageId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID.', false, ['dbForProject'])
|
||||
->param('topics', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'List of Topic IDs.', true, ['dbForProject'])
|
||||
->param('users', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'List of User IDs.', true, ['dbForProject'])
|
||||
->param('targets', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'List of Targets IDs.', true, ['dbForProject'])
|
||||
->param('subject', null, new Nullable(new Text(998)), 'Email Subject.', true)
|
||||
->param('content', null, new Nullable(new Text(64230)), 'Email Content.', true)
|
||||
->param('draft', null, new Nullable(new Boolean()), 'Is message a draft', true)
|
||||
->param('html', null, new Nullable(new Boolean()), 'Is content of type HTML', true)
|
||||
->param('cc', null, new Nullable(new ArrayList(new UID())), 'Array of target IDs to be added as CC.', true)
|
||||
->param('bcc', null, new Nullable(new ArrayList(new UID())), 'Array of target IDs to be added as BCC.', true)
|
||||
->param('cc', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'Array of target IDs to be added as CC.', true, ['dbForProject'])
|
||||
->param('bcc', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'Array of target IDs to be added as BCC.', true, ['dbForProject'])
|
||||
->param('scheduledAt', null, new Nullable(new DatetimeValidator(requireDateInFuture: true)), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true)
|
||||
->param('attachments', null, new Nullable(new ArrayList(new CompoundUID())), 'Array of compound ID strings of bucket IDs and file IDs to be attached to the email. They should be formatted as <BUCKET_ID>:<FILE_ID>.', true)
|
||||
->inject('queueForEvents')
|
||||
|
|
@ -4213,10 +4188,10 @@ Http::patch('/v1/messaging/messages/sms/:messageId')
|
|||
]
|
||||
)
|
||||
])
|
||||
->param('messageId', '', new UID(), 'Message ID.')
|
||||
->param('topics', null, new Nullable(new ArrayList(new UID())), 'List of Topic IDs.', true)
|
||||
->param('users', null, new Nullable(new ArrayList(new UID())), 'List of User IDs.', true)
|
||||
->param('targets', null, new Nullable(new ArrayList(new UID())), 'List of Targets IDs.', true)
|
||||
->param('messageId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID.', false, ['dbForProject'])
|
||||
->param('topics', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'List of Topic IDs.', true, ['dbForProject'])
|
||||
->param('users', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'List of User IDs.', true, ['dbForProject'])
|
||||
->param('targets', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'List of Targets IDs.', true, ['dbForProject'])
|
||||
->param('content', null, new Nullable(new Text(64230)), 'Email Content.', true)
|
||||
->param('draft', null, new Nullable(new Boolean()), 'Is message a draft', true)
|
||||
->param('scheduledAt', null, new Nullable(new DatetimeValidator(requireDateInFuture: true)), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true)
|
||||
|
|
@ -4375,10 +4350,10 @@ Http::patch('/v1/messaging/messages/push/:messageId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('messageId', '', new UID(), 'Message ID.')
|
||||
->param('topics', null, new Nullable(new ArrayList(new UID())), 'List of Topic IDs.', true)
|
||||
->param('users', null, new Nullable(new ArrayList(new UID())), 'List of User IDs.', true)
|
||||
->param('targets', null, new Nullable(new ArrayList(new UID())), 'List of Targets IDs.', true)
|
||||
->param('messageId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID.', false, ['dbForProject'])
|
||||
->param('topics', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'List of Topic IDs.', true, ['dbForProject'])
|
||||
->param('users', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'List of User IDs.', true, ['dbForProject'])
|
||||
->param('targets', null, fn (Database $dbForProject) => new Nullable(new ArrayList(new UID($dbForProject->getAdapter()->getMaxUIDLength()))), 'List of Targets IDs.', true, ['dbForProject'])
|
||||
->param('title', null, new Nullable(new Text(256)), 'Title for push notification.', true)
|
||||
->param('body', null, new Nullable(new Text(64230)), 'Body for push notification.', true)
|
||||
->param('data', null, new Nullable(new JSON()), 'Additional Data for push notification.', true)
|
||||
|
|
@ -4637,7 +4612,7 @@ Http::delete('/v1/messaging/messages/:messageId')
|
|||
],
|
||||
contentType: ContentType::NONE
|
||||
))
|
||||
->param('messageId', '', new UID(), 'Message ID.')
|
||||
->param('messageId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Message ID.', false, ['dbForProject'])
|
||||
->inject('dbForProject')
|
||||
->inject('dbForPlatform')
|
||||
->inject('queueForEvents')
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ use Utopia\Database\Validator\Authorization;
|
|||
use Utopia\Database\Validator\Queries\Documents;
|
||||
use Utopia\Database\Validator\Query\Cursor;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Http;
|
||||
use Utopia\Http\Http;
|
||||
use Utopia\Migration\Resource;
|
||||
use Utopia\Migration\Sources\Appwrite;
|
||||
use Utopia\Migration\Sources\CSV;
|
||||
|
|
@ -64,7 +64,7 @@ Http::post('/v1/migrations/appwrite')
|
|||
))
|
||||
->param('resources', [], new ArrayList(new WhiteList(Appwrite::getSupportedResources())), 'List of resources to migrate')
|
||||
->param('endpoint', '', new URL(), 'Source Appwrite endpoint')
|
||||
->param('projectId', '', new UID(), 'Source Project ID')
|
||||
->param('projectId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Source Project ID', false, ['dbForProject'])
|
||||
->param('apiKey', '', new Text(512), 'Source API Key')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -335,8 +335,8 @@ Http::post('/v1/migrations/csv/imports')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).')
|
||||
->param('fileId', '', new UID(), 'File ID.')
|
||||
->param('bucketId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).', false, ['dbForProject'])
|
||||
->param('fileId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'File ID.', false, ['dbForProject'])
|
||||
->param('resourceId', null, new CompoundUID(), 'Composite ID in the format {databaseId:collectionId}, identifying a collection within a database.')
|
||||
->param('internalFile', false, new Boolean(), 'Is the file stored in an internal bucket?', true)
|
||||
->inject('response')
|
||||
|
|
@ -629,16 +629,10 @@ Http::get('/v1/migrations')
|
|||
$queries[] = Query::search('search', $search);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries
|
||||
*/
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
/** @var Query $cursor */
|
||||
$cursor = Query::getCursorQueries($queries, false);
|
||||
$cursor = \reset($cursor);
|
||||
|
||||
if ($cursor !== false) {
|
||||
$validator = new Cursor();
|
||||
if (!$validator->isValid($cursor)) {
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
|
||||
|
|
@ -684,7 +678,7 @@ Http::get('/v1/migrations/:migrationId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('migrationId', '', new UID(), 'Migration unique ID.')
|
||||
->param('migrationId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Migration unique ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $migrationId, Response $response, Database $dbForProject) {
|
||||
|
|
@ -917,7 +911,7 @@ Http::patch('/v1/migrations/:migrationId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('migrationId', '', new UID(), 'Migration unique ID.')
|
||||
->param('migrationId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Migration unique ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('project')
|
||||
|
|
@ -971,7 +965,7 @@ Http::delete('/v1/migrations/:migrationId')
|
|||
],
|
||||
contentType: ContentType::NONE
|
||||
))
|
||||
->param('migrationId', '', new UID(), 'Migration ID.')
|
||||
->param('migrationId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Migration ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use Utopia\Database\Query;
|
|||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Datetime as DateTimeValidator;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Http;
|
||||
use Utopia\Http\Http;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Nullable;
|
||||
use Utopia\Validator\Text;
|
||||
|
|
@ -496,7 +496,7 @@ Http::get('/v1/project/variables/:variableId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('variableId', '', new UID(), 'Variable unique ID.', false)
|
||||
->param('variableId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Variable unique ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -526,7 +526,7 @@ Http::put('/v1/project/variables/:variableId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('variableId', '', new UID(), 'Variable unique ID.', false)
|
||||
->param('variableId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Variable unique ID.', false, ['dbForProject'])
|
||||
->param('key', null, new Text(255), 'Variable key. Max length: 255 chars.', false)
|
||||
->param('value', null, new Nullable(new Text(8192, 0)), 'Variable value. Max length: 8192 chars.', true)
|
||||
->param('secret', null, new Nullable(new Boolean()), 'Secret variables can be updated or deleted, but only projects can read them during build and runtime.', true)
|
||||
|
|
@ -585,7 +585,7 @@ Http::delete('/v1/project/variables/:variableId')
|
|||
],
|
||||
contentType: ContentType::NONE
|
||||
))
|
||||
->param('variableId', '', new UID(), 'Variable unique ID.', false)
|
||||
->param('variableId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Variable unique ID.', false, ['dbForProject'])
|
||||
->inject('project')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ use Appwrite\Event\Delete;
|
|||
use Appwrite\Event\Mail;
|
||||
use Appwrite\Event\Validator\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Hooks\Hooks;
|
||||
use Appwrite\Network\Platform;
|
||||
use Appwrite\Network\Validator\Email;
|
||||
use Appwrite\SDK\AuthType;
|
||||
|
|
@ -15,31 +14,25 @@ use Appwrite\SDK\Deprecated;
|
|||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Template\Template;
|
||||
use Appwrite\Utopia\Database\Validator\ProjectId;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Projects;
|
||||
use Appwrite\Utopia\Request;
|
||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Keys;
|
||||
use Appwrite\Utopia\Response;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use Utopia\Audit\Adapter\Database as AdapterDatabase;
|
||||
use Utopia\Audit\Audit;
|
||||
use Utopia\Cache\Cache;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Adapter\Pool as DatabasePool;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Duplicate;
|
||||
use Utopia\Database\Exception\Query as QueryException;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Datetime as DatetimeValidator;
|
||||
use Utopia\Database\Validator\Query\Cursor;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Domains\Validator\PublicDomain;
|
||||
use Utopia\DSN\DSN;
|
||||
use Utopia\Http;
|
||||
use Utopia\Http\Http;
|
||||
use Utopia\Locale\Locale;
|
||||
use Utopia\Pools\Group;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\ArrayList;
|
||||
use Utopia\Validator\Boolean;
|
||||
|
|
@ -61,251 +54,6 @@ Http::init()
|
|||
}
|
||||
});
|
||||
|
||||
Http::post('/v1/projects')
|
||||
->desc('Create project')
|
||||
->groups(['api', 'projects'])
|
||||
->label('audits.event', 'projects.create')
|
||||
->label('audits.resource', 'project/{response.$id}')
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk', new Method(
|
||||
namespace: 'projects',
|
||||
group: 'projects',
|
||||
name: 'create',
|
||||
description: '/docs/references/projects/create.md',
|
||||
auth: [AuthType::ADMIN],
|
||||
responses: [
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_CREATED,
|
||||
model: Response::MODEL_PROJECT,
|
||||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new ProjectId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, and hyphen. Can\'t start with a special char. Max length is 36 chars.')
|
||||
->param('name', null, new Text(128), 'Project name. Max length: 128 chars.')
|
||||
->param('teamId', '', new UID(), 'Team unique ID.')
|
||||
->param('region', System::getEnv('_APP_REGION', 'default'), new Whitelist(array_keys(array_filter(Config::getParam('regions'), fn ($config) => !$config['disabled']))), 'Project Region.', true)
|
||||
->param('description', '', new Text(256), 'Project description. Max length: 256 chars.', true)
|
||||
->param('logo', '', new Text(1024), 'Project logo.', true)
|
||||
->param('url', '', new URL(), 'Project URL.', true)
|
||||
->param('legalName', '', new Text(256), 'Project legal Name. Max length: 256 chars.', true)
|
||||
->param('legalCountry', '', new Text(256), 'Project legal Country. Max length: 256 chars.', true)
|
||||
->param('legalState', '', new Text(256), 'Project legal State. Max length: 256 chars.', true)
|
||||
->param('legalCity', '', new Text(256), 'Project legal City. Max length: 256 chars.', true)
|
||||
->param('legalAddress', '', new Text(256), 'Project legal Address. Max length: 256 chars.', true)
|
||||
->param('legalTaxId', '', new Text(256), 'Project legal Tax ID. Max length: 256 chars.', true)
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->inject('cache')
|
||||
->inject('pools')
|
||||
->inject('hooks')
|
||||
->action(function (string $projectId, string $name, string $teamId, string $region, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Request $request, Response $response, Database $dbForPlatform, Cache $cache, Group $pools, Hooks $hooks) {
|
||||
|
||||
$team = $dbForPlatform->getDocument('teams', $teamId);
|
||||
|
||||
if ($team->isEmpty()) {
|
||||
throw new Exception(Exception::TEAM_NOT_FOUND);
|
||||
}
|
||||
|
||||
$allowList = \array_filter(\explode(',', System::getEnv('_APP_PROJECT_REGIONS', '')));
|
||||
|
||||
if (!empty($allowList) && !\in_array($region, $allowList)) {
|
||||
throw new Exception(Exception::PROJECT_REGION_UNSUPPORTED, 'Region "' . $region . '" is not supported');
|
||||
}
|
||||
|
||||
$auth = Config::getParam('auth', []);
|
||||
$auths = [
|
||||
'limit' => 0,
|
||||
'maxSessions' => APP_LIMIT_USER_SESSIONS_DEFAULT,
|
||||
'passwordHistory' => 0,
|
||||
'passwordDictionary' => false,
|
||||
'duration' => TOKEN_EXPIRATION_LOGIN_LONG,
|
||||
'personalDataCheck' => false,
|
||||
'mockNumbers' => [],
|
||||
'sessionAlerts' => false,
|
||||
'membershipsUserName' => false,
|
||||
'membershipsUserEmail' => false,
|
||||
'membershipsMfa' => false,
|
||||
'invalidateSessions' => true
|
||||
];
|
||||
|
||||
foreach ($auth as $method) {
|
||||
$auths[$method['key'] ?? ''] = true;
|
||||
}
|
||||
|
||||
$projectId = ($projectId == 'unique()') ? ID::unique() : $projectId;
|
||||
|
||||
if ($projectId === 'console') {
|
||||
throw new Exception(Exception::PROJECT_RESERVED_PROJECT, "'console' is a reserved project.");
|
||||
}
|
||||
|
||||
$databases = Config::getParam('pools-database', []);
|
||||
|
||||
if ($region !== 'default') {
|
||||
$databaseKeys = System::getEnv('_APP_DATABASE_KEYS', '');
|
||||
$keys = explode(',', $databaseKeys);
|
||||
$databases = array_filter($keys, function ($value) use ($region) {
|
||||
return str_contains($value, $region);
|
||||
});
|
||||
}
|
||||
|
||||
$databaseOverride = System::getEnv('_APP_DATABASE_OVERRIDE');
|
||||
$index = \array_search($databaseOverride, $databases);
|
||||
if ($index !== false) {
|
||||
$dsn = $databases[$index];
|
||||
} else {
|
||||
$dsn = $databases[array_rand($databases)];
|
||||
}
|
||||
|
||||
// TODO: Temporary until all projects are using shared tables.
|
||||
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
|
||||
|
||||
if (\in_array($dsn, $sharedTables)) {
|
||||
$schema = 'appwrite';
|
||||
$database = 'appwrite';
|
||||
$namespace = System::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '');
|
||||
$dsn = $schema . '://' . $dsn . '?database=' . $database;
|
||||
|
||||
if (!empty($namespace)) {
|
||||
$dsn .= '&namespace=' . $namespace;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$project = $dbForPlatform->createDocument('projects', new Document([
|
||||
'$id' => $projectId,
|
||||
'$permissions' => [
|
||||
Permission::read(Role::team(ID::custom($teamId))),
|
||||
Permission::update(Role::team(ID::custom($teamId), 'owner')),
|
||||
Permission::update(Role::team(ID::custom($teamId), 'developer')),
|
||||
Permission::delete(Role::team(ID::custom($teamId), 'owner')),
|
||||
Permission::delete(Role::team(ID::custom($teamId), 'developer')),
|
||||
],
|
||||
'name' => $name,
|
||||
'teamInternalId' => $team->getSequence(),
|
||||
'teamId' => $team->getId(),
|
||||
'region' => $region,
|
||||
'description' => $description,
|
||||
'logo' => $logo,
|
||||
'url' => $url,
|
||||
'version' => APP_VERSION_STABLE,
|
||||
'legalName' => $legalName,
|
||||
'legalCountry' => $legalCountry,
|
||||
'legalState' => $legalState,
|
||||
'legalCity' => $legalCity,
|
||||
'legalAddress' => $legalAddress,
|
||||
'legalTaxId' => ID::custom($legalTaxId),
|
||||
'services' => new stdClass(),
|
||||
'platforms' => null,
|
||||
'oAuthProviders' => [],
|
||||
'webhooks' => null,
|
||||
'keys' => null,
|
||||
'auths' => $auths,
|
||||
'accessedAt' => DateTime::now(),
|
||||
'search' => implode(' ', [$projectId, $name]),
|
||||
'database' => $dsn,
|
||||
'labels' => [],
|
||||
]));
|
||||
} catch (Duplicate) {
|
||||
throw new Exception(Exception::PROJECT_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
try {
|
||||
$dsn = new DSN($dsn);
|
||||
} catch (\InvalidArgumentException) {
|
||||
// TODO: Temporary until all projects are using shared tables
|
||||
$dsn = new DSN('mysql://' . $dsn);
|
||||
}
|
||||
|
||||
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
|
||||
$sharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES_V1', ''));
|
||||
$projectTables = !\in_array($dsn->getHost(), $sharedTables);
|
||||
$sharedTablesV1 = \in_array($dsn->getHost(), $sharedTablesV1);
|
||||
$sharedTablesV2 = !$projectTables && !$sharedTablesV1;
|
||||
$sharedTables = $sharedTablesV1 || $sharedTablesV2;
|
||||
|
||||
if (!$sharedTablesV2) {
|
||||
$adapter = new DatabasePool($pools->get($dsn->getHost()));
|
||||
$dbForProject = new Database($adapter, $cache);
|
||||
$dbForProject->setDatabase(APP_DATABASE);
|
||||
|
||||
if ($sharedTables) {
|
||||
$dbForProject
|
||||
->setSharedTables(true)
|
||||
->setTenant($sharedTablesV1 ? (int)$project->getSequence() : null)
|
||||
->setNamespace($dsn->getParam('namespace'));
|
||||
} else {
|
||||
$dbForProject
|
||||
->setSharedTables(false)
|
||||
->setTenant(null)
|
||||
->setNamespace('_' . $project->getSequence());
|
||||
}
|
||||
|
||||
$create = true;
|
||||
|
||||
try {
|
||||
$dbForProject->create();
|
||||
} catch (Duplicate) {
|
||||
$create = false;
|
||||
}
|
||||
|
||||
if ($create || $projectTables) {
|
||||
$adapter = new AdapterDatabase($dbForProject);
|
||||
$audit = new Audit($adapter);
|
||||
$audit->setup();
|
||||
}
|
||||
|
||||
if (!$create && $sharedTablesV1) {
|
||||
$adapter = new AdapterDatabase($dbForProject);
|
||||
$attributes = $adapter->getAttributeDocuments();
|
||||
$indexes = $adapter->getIndexDocuments();
|
||||
$dbForProject->createDocument(Database::METADATA, new Document([
|
||||
'$id' => ID::custom('audit'),
|
||||
'$permissions' => [Permission::create(Role::any())],
|
||||
'name' => 'audit',
|
||||
'attributes' => $attributes,
|
||||
'indexes' => $indexes,
|
||||
'documentSecurity' => true
|
||||
]));
|
||||
}
|
||||
|
||||
if ($create || $sharedTablesV1) {
|
||||
/** @var array $collections */
|
||||
$collections = Config::getParam('collections', [])['projects'] ?? [];
|
||||
|
||||
foreach ($collections as $key => $collection) {
|
||||
if (($collection['$collection'] ?? '') !== Database::METADATA) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$attributes = \array_map(fn ($attribute) => new Document($attribute), $collection['attributes']);
|
||||
$indexes = \array_map(fn (array $index) => new Document($index), $collection['indexes']);
|
||||
|
||||
try {
|
||||
$dbForProject->createCollection($key, $attributes, $indexes);
|
||||
} catch (Duplicate) {
|
||||
$dbForProject->createDocument(Database::METADATA, new Document([
|
||||
'$id' => ID::custom($key),
|
||||
'$permissions' => [Permission::create(Role::any())],
|
||||
'name' => $key,
|
||||
'attributes' => $attributes,
|
||||
'indexes' => $indexes,
|
||||
'documentSecurity' => true
|
||||
]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hook allowing instant project mirroring during migration
|
||||
// Outside of migration, hook is not registered and has no effect
|
||||
$hooks->trigger('afterProjectCreation', [$project, $pools, $cache]);
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->dynamic($project, Response::MODEL_PROJECT);
|
||||
});
|
||||
|
||||
Http::get('/v1/projects/:projectId')
|
||||
->desc('Get project')
|
||||
->groups(['api', 'projects'])
|
||||
|
|
@ -323,7 +71,7 @@ Http::get('/v1/projects/:projectId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $projectId, Response $response, Database $dbForPlatform) {
|
||||
|
|
@ -337,137 +85,6 @@ Http::get('/v1/projects/:projectId')
|
|||
$response->dynamic($project, Response::MODEL_PROJECT);
|
||||
});
|
||||
|
||||
Http::patch('/v1/projects/:projectId')
|
||||
->desc('Update project')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('audits.event', 'projects.update')
|
||||
->label('audits.resource', 'project/{request.projectId}')
|
||||
->label('sdk', new Method(
|
||||
namespace: 'projects',
|
||||
group: 'projects',
|
||||
name: 'update',
|
||||
description: '/docs/references/projects/update.md',
|
||||
auth: [AuthType::ADMIN],
|
||||
responses: [
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_OK,
|
||||
model: Response::MODEL_PROJECT,
|
||||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('name', null, new Text(128), 'Project name. Max length: 128 chars.')
|
||||
->param('description', '', new Text(256), 'Project description. Max length: 256 chars.', true)
|
||||
->param('logo', '', new Text(1024), 'Project logo.', true)
|
||||
->param('url', '', new URL(), 'Project URL.', true)
|
||||
->param('legalName', '', new Text(256), 'Project legal name. Max length: 256 chars.', true)
|
||||
->param('legalCountry', '', new Text(256), 'Project legal country. Max length: 256 chars.', true)
|
||||
->param('legalState', '', new Text(256), 'Project legal state. Max length: 256 chars.', true)
|
||||
->param('legalCity', '', new Text(256), 'Project legal city. Max length: 256 chars.', true)
|
||||
->param('legalAddress', '', new Text(256), 'Project legal address. Max length: 256 chars.', true)
|
||||
->param('legalTaxId', '', new Text(256), 'Project legal tax ID. Max length: 256 chars.', true)
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $projectId, string $name, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Response $response, Database $dbForPlatform) {
|
||||
|
||||
$project = $dbForPlatform->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$project = $dbForPlatform->updateDocument('projects', $project->getId(), $project
|
||||
->setAttribute('name', $name)
|
||||
->setAttribute('description', $description)
|
||||
->setAttribute('logo', $logo)
|
||||
->setAttribute('url', $url)
|
||||
->setAttribute('legalName', $legalName)
|
||||
->setAttribute('legalCountry', $legalCountry)
|
||||
->setAttribute('legalState', $legalState)
|
||||
->setAttribute('legalCity', $legalCity)
|
||||
->setAttribute('legalAddress', $legalAddress)
|
||||
->setAttribute('legalTaxId', $legalTaxId)
|
||||
->setAttribute('search', implode(' ', [$projectId, $name])));
|
||||
|
||||
$response->dynamic($project, Response::MODEL_PROJECT);
|
||||
});
|
||||
|
||||
Http::patch('/v1/projects/:projectId/team')
|
||||
->desc('Update project team')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk', new Method(
|
||||
namespace: 'projects',
|
||||
group: 'projects',
|
||||
name: 'updateTeam',
|
||||
description: '/docs/references/projects/update-team.md',
|
||||
auth: [AuthType::ADMIN],
|
||||
responses: [
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_OK,
|
||||
model: Response::MODEL_PROJECT,
|
||||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('teamId', '', new UID(), 'Team ID of the team to transfer project to.')
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $projectId, string $teamId, Response $response, Database $dbForPlatform) {
|
||||
|
||||
$project = $dbForPlatform->getDocument('projects', $projectId);
|
||||
$team = $dbForPlatform->getDocument('teams', $teamId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($team->isEmpty()) {
|
||||
throw new Exception(Exception::TEAM_NOT_FOUND);
|
||||
}
|
||||
|
||||
$permissions = [
|
||||
Permission::read(Role::team(ID::custom($teamId))),
|
||||
Permission::update(Role::team(ID::custom($teamId), 'owner')),
|
||||
Permission::update(Role::team(ID::custom($teamId), 'developer')),
|
||||
Permission::delete(Role::team(ID::custom($teamId), 'owner')),
|
||||
Permission::delete(Role::team(ID::custom($teamId), 'developer')),
|
||||
];
|
||||
|
||||
$project
|
||||
->setAttribute('teamId', $teamId)
|
||||
->setAttribute('teamInternalId', $team->getSequence())
|
||||
->setAttribute('$permissions', $permissions);
|
||||
$project = $dbForPlatform->updateDocument('projects', $project->getId(), $project);
|
||||
|
||||
$installations = $dbForPlatform->find('installations', [
|
||||
Query::equal('projectInternalId', [$project->getSequence()]),
|
||||
]);
|
||||
foreach ($installations as $installation) {
|
||||
$installation->getAttribute('$permissions', $permissions);
|
||||
$dbForPlatform->updateDocument('installations', $installation->getId(), $installation);
|
||||
}
|
||||
|
||||
$repositories = $dbForPlatform->find('repositories', [
|
||||
Query::equal('projectInternalId', [$project->getSequence()]),
|
||||
]);
|
||||
foreach ($repositories as $repository) {
|
||||
$repository->getAttribute('$permissions', $permissions);
|
||||
$dbForPlatform->updateDocument('repositories', $repository->getId(), $repository);
|
||||
}
|
||||
|
||||
$vcsComments = $dbForPlatform->find('vcsComments', [
|
||||
Query::equal('projectInternalId', [$project->getSequence()]),
|
||||
]);
|
||||
foreach ($vcsComments as $vcsComment) {
|
||||
$vcsComment->getAttribute('$permissions', $permissions);
|
||||
$dbForPlatform->updateDocument('vcsComments', $vcsComment->getId(), $vcsComment);
|
||||
}
|
||||
|
||||
$response->dynamic($project, Response::MODEL_PROJECT);
|
||||
});
|
||||
|
||||
Http::patch('/v1/projects/:projectId/service')
|
||||
->desc('Update service status')
|
||||
->groups(['api', 'projects'])
|
||||
|
|
@ -485,7 +102,7 @@ Http::patch('/v1/projects/:projectId/service')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('service', '', new WhiteList(array_keys(array_filter(Config::getParam('services'), fn ($element) => $element['optional'])), true), 'Service name.')
|
||||
->param('status', null, new Boolean(), 'Service status.')
|
||||
->inject('response')
|
||||
|
|
@ -523,7 +140,7 @@ Http::patch('/v1/projects/:projectId/service/all')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('status', null, new Boolean(), 'Service status.')
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
|
|
@ -584,7 +201,7 @@ Http::patch('/v1/projects/:projectId/api')
|
|||
]
|
||||
)
|
||||
])
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('api', '', new WhiteList(array_keys(Config::getParam('apis')), true), 'API name.')
|
||||
->param('status', null, new Boolean(), 'API status.')
|
||||
->inject('response')
|
||||
|
|
@ -642,7 +259,7 @@ Http::patch('/v1/projects/:projectId/api/all')
|
|||
]
|
||||
)
|
||||
])
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('status', null, new Boolean(), 'API status.')
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
|
|
@ -683,7 +300,7 @@ Http::patch('/v1/projects/:projectId/oauth2')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('provider', '', new WhiteList(\array_keys(Config::getParam('oAuthProviders')), true), 'Provider Name')
|
||||
->param('appId', null, new Nullable(new Text(256)), 'Provider app ID. Max length: 256 chars.', true)
|
||||
->param('secret', null, new Nullable(new text(512)), 'Provider secret key. Max length: 512 chars.', true)
|
||||
|
|
@ -734,7 +351,7 @@ Http::patch('/v1/projects/:projectId/auth/session-alerts')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('alerts', false, new Boolean(true), 'Set to true to enable session emails.')
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
|
|
@ -772,7 +389,7 @@ Http::patch('/v1/projects/:projectId/auth/memberships-privacy')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('userName', true, new Boolean(true), 'Set to true to show userName to members of a team.')
|
||||
->param('userEmail', true, new Boolean(true), 'Set to true to show email to members of a team.')
|
||||
->param('mfa', true, new Boolean(true), 'Set to true to show mfa to members of a team.')
|
||||
|
|
@ -814,7 +431,7 @@ Http::patch('/v1/projects/:projectId/auth/limit')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('limit', false, new Range(0, APP_LIMIT_USERS), 'Set the max number of users allowed in this project. Use 0 for unlimited.')
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
|
|
@ -852,7 +469,7 @@ Http::patch('/v1/projects/:projectId/auth/duration')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('duration', 31536000, new Range(0, 31536000), 'Project session length in seconds. Max length: 31536000 seconds.')
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
|
|
@ -890,7 +507,7 @@ Http::patch('/v1/projects/:projectId/auth/:method')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('method', '', new WhiteList(\array_keys(Config::getParam('auth')), true), 'Auth Method. Possible values: ' . implode(',', \array_keys(Config::getParam('auth'))), false)
|
||||
->param('status', false, new Boolean(true), 'Set the status of this auth method.')
|
||||
->inject('response')
|
||||
|
|
@ -931,7 +548,7 @@ Http::patch('/v1/projects/:projectId/auth/password-history')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('limit', 0, new Range(0, APP_LIMIT_USER_PASSWORD_HISTORY), 'Set the max number of passwords to store in user history. User can\'t choose a new password that is already stored in the password history list. Max number of passwords allowed in history is' . APP_LIMIT_USER_PASSWORD_HISTORY . '. Default value is 0')
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
|
|
@ -969,7 +586,7 @@ Http::patch('/v1/projects/:projectId/auth/password-dictionary')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('enabled', false, new Boolean(false), 'Set whether or not to enable checking user\'s password against most commonly used passwords. Default is false.')
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
|
|
@ -1007,7 +624,7 @@ Http::patch('/v1/projects/:projectId/auth/personal-data')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('enabled', false, new Boolean(false), 'Set whether or not to check a password for similarity with personal data. Default is false.')
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
|
|
@ -1045,7 +662,7 @@ Http::patch('/v1/projects/:projectId/auth/max-sessions')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('limit', false, new Range(1, APP_LIMIT_USER_SESSIONS_MAX), 'Set the max number of users allowed in this project. Value allowed is between 1-' . APP_LIMIT_USER_SESSIONS_MAX . '. Default is ' . APP_LIMIT_USER_SESSIONS_DEFAULT)
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
|
|
@ -1083,7 +700,7 @@ Http::patch('/v1/projects/:projectId/auth/mock-numbers')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('numbers', '', new ArrayList(new MockNumber(), 10), 'An array of mock numbers and their corresponding verification codes (OTPs). Each number should be a valid E.164 formatted phone number. Maximum of 10 numbers are allowed.')
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
|
|
@ -1132,7 +749,7 @@ Http::delete('/v1/projects/:projectId')
|
|||
],
|
||||
contentType: ContentType::NONE
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
->inject('dbForPlatform')
|
||||
|
|
@ -1175,7 +792,7 @@ Http::post('/v1/projects/:projectId/webhooks')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.')
|
||||
->param('enabled', true, new Boolean(true), 'Enable or disable a webhook.', true)
|
||||
->param('events', null, new ArrayList(new Event(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.')
|
||||
|
|
@ -1240,7 +857,7 @@ Http::get('/v1/projects/:projectId/webhooks')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
|
|
@ -1280,8 +897,8 @@ Http::get('/v1/projects/:projectId/webhooks/:webhookId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('webhookId', '', new UID(), 'Webhook unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('webhookId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Webhook unique ID.', false, ['dbForPlatform'])
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $projectId, string $webhookId, Response $response, Database $dbForPlatform) {
|
||||
|
|
@ -1321,8 +938,8 @@ Http::put('/v1/projects/:projectId/webhooks/:webhookId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('webhookId', '', new UID(), 'Webhook unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('webhookId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Webhook unique ID.', false, ['dbForPlatform'])
|
||||
->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.')
|
||||
->param('enabled', true, new Boolean(true), 'Enable or disable a webhook.', true)
|
||||
->param('events', null, new ArrayList(new Event(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.')
|
||||
|
|
@ -1387,8 +1004,8 @@ Http::patch('/v1/projects/:projectId/webhooks/:webhookId/signature')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('webhookId', '', new UID(), 'Webhook unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('webhookId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Webhook unique ID.', false, ['dbForPlatform'])
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $projectId, string $webhookId, Response $response, Database $dbForPlatform) {
|
||||
|
|
@ -1434,8 +1051,8 @@ Http::delete('/v1/projects/:projectId/webhooks/:webhookId')
|
|||
],
|
||||
contentType: ContentType::NONE
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('webhookId', '', new UID(), 'Webhook unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('webhookId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Webhook unique ID.', false, ['dbForPlatform'])
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $projectId, string $webhookId, Response $response, Database $dbForPlatform) {
|
||||
|
|
@ -1481,13 +1098,15 @@ Http::post('/v1/projects/:projectId/keys')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('name', null, new Text(128), 'Key name. Max length: 128 chars.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
// TODO: When migrating to Platform API, mark keyId required for consistency
|
||||
->param('keyId', 'unique()', fn (Database $dbForPlatform) => new CustomId($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Key ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', true, ['dbForPlatform'])->param('name', null, new Text(128), 'Key name. Max length: 128 chars.')
|
||||
->param('scopes', null, new Nullable(new ArrayList(new WhiteList(array_keys(Config::getParam('projectScopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE)), 'Key scopes list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed.')
|
||||
->param('expire', null, new Nullable(new DatetimeValidator()), 'Expiration time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Use null for unlimited expiration.', true)
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $projectId, string $name, array $scopes, ?string $expire, Response $response, Database $dbForPlatform) {
|
||||
->action(function (string $projectId, string $keyId, string $name, array $scopes, ?string $expire, Response $response, Database $dbForPlatform) {
|
||||
$keyId = $keyId == 'unique()' ? ID::unique() : $keyId;
|
||||
|
||||
$project = $dbForPlatform->getDocument('projects', $projectId);
|
||||
|
||||
|
|
@ -1496,7 +1115,7 @@ Http::post('/v1/projects/:projectId/keys')
|
|||
}
|
||||
|
||||
$key = new Document([
|
||||
'$id' => ID::unique(),
|
||||
'$id' => $keyId,
|
||||
'$permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
|
|
@ -1513,7 +1132,11 @@ Http::post('/v1/projects/:projectId/keys')
|
|||
'secret' => API_KEY_STANDARD . '_' . \bin2hex(\random_bytes(128)),
|
||||
]);
|
||||
|
||||
$key = $dbForPlatform->createDocument('keys', $key);
|
||||
try {
|
||||
$key = $dbForPlatform->createDocument('keys', $key);
|
||||
} catch (Duplicate) {
|
||||
throw new Exception(Exception::KEY_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
$dbForPlatform->purgeCachedDocument('projects', $project->getId());
|
||||
|
||||
|
|
@ -1539,11 +1162,12 @@ Http::get('/v1/projects/:projectId/keys')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('queries', [], new Keys(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Keys::ALLOWED_ATTRIBUTES), true)
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $projectId, bool $includeTotal, Response $response, Database $dbForPlatform) {
|
||||
->action(function (string $projectId, array $queries, bool $includeTotal, Response $response, Database $dbForPlatform) {
|
||||
|
||||
$project = $dbForPlatform->getDocument('projects', $projectId);
|
||||
|
||||
|
|
@ -1551,15 +1175,46 @@ Http::get('/v1/projects/:projectId/keys')
|
|||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$keys = $dbForPlatform->find('keys', [
|
||||
Query::equal('resourceType', ['projects']),
|
||||
Query::equal('resourceInternalId', [$project->getSequence()]),
|
||||
Query::limit(5000),
|
||||
]);
|
||||
try {
|
||||
$queries = Query::parseQueries($queries);
|
||||
} catch (QueryException $e) {
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
|
||||
}
|
||||
|
||||
// Backwards compatibility
|
||||
if (\count(Query::getByType($queries, [Query::TYPE_LIMIT])) === 0) {
|
||||
$queries[] = Query::limit(5000);
|
||||
}
|
||||
|
||||
$queries[] = Query::equal('resourceType', ['projects']);
|
||||
$queries[] = Query::equal('resourceInternalId', [$project->getSequence()]);
|
||||
|
||||
$cursor = Query::getCursorQueries($queries, false);
|
||||
$cursor = \reset($cursor);
|
||||
|
||||
if ($cursor !== false) {
|
||||
$validator = new Cursor();
|
||||
if (!$validator->isValid($cursor)) {
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
|
||||
}
|
||||
|
||||
$keyId = $cursor->getValue();
|
||||
$cursorDocument = $dbForPlatform->getDocument('keys', $keyId);
|
||||
|
||||
if ($cursorDocument->isEmpty()) {
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Key '{$keyId}' for the 'cursor' value not found.");
|
||||
}
|
||||
|
||||
$cursor->setValue($cursorDocument);
|
||||
}
|
||||
|
||||
$filterQueries = Query::groupByType($queries)['filters'];
|
||||
|
||||
$keys = $dbForPlatform->find('keys', $queries);
|
||||
|
||||
$response->dynamic(new Document([
|
||||
'keys' => $keys,
|
||||
'total' => $includeTotal ? count($keys) : 0,
|
||||
'total' => $includeTotal ? $dbForPlatform->count('keys', $filterQueries, APP_LIMIT_COUNT) : 0,
|
||||
]), Response::MODEL_KEY_LIST);
|
||||
});
|
||||
|
||||
|
|
@ -1580,8 +1235,8 @@ Http::get('/v1/projects/:projectId/keys/:keyId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('keyId', '', new UID(), 'Key unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('keyId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Key unique ID.', false, ['dbForPlatform'])
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $projectId, string $keyId, Response $response, Database $dbForPlatform) {
|
||||
|
|
@ -1622,8 +1277,8 @@ Http::put('/v1/projects/:projectId/keys/:keyId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('keyId', '', new UID(), 'Key unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('keyId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Key unique ID.', false, ['dbForPlatform'])
|
||||
->param('name', null, new Text(128), 'Key name. Max length: 128 chars.')
|
||||
->param('scopes', null, new Nullable(new ArrayList(new WhiteList(array_keys(Config::getParam('projectScopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE)), 'Key scopes list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.')
|
||||
->param('expire', null, new Nullable(new DatetimeValidator()), 'Expiration time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Use null for unlimited expiration.', true)
|
||||
|
|
@ -1677,8 +1332,8 @@ Http::delete('/v1/projects/:projectId/keys/:keyId')
|
|||
],
|
||||
contentType: ContentType::NONE
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('keyId', '', new UID(), 'Key unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('keyId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Key unique ID.', false, ['dbForPlatform'])
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $projectId, string $keyId, Response $response, Database $dbForPlatform) {
|
||||
|
|
@ -1725,7 +1380,7 @@ Http::post('/v1/projects/:projectId/jwts')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('scopes', [], new ArrayList(new WhiteList(array_keys(Config::getParam('projectScopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of scopes allowed for JWT key. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed.')
|
||||
->param('duration', 900, new Range(0, 3600), 'Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.', true)
|
||||
->inject('response')
|
||||
|
|
@ -1769,7 +1424,7 @@ Http::post('/v1/projects/:projectId/platforms')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param(
|
||||
'type',
|
||||
null,
|
||||
|
|
@ -1847,7 +1502,7 @@ Http::get('/v1/projects/:projectId/platforms')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
|
|
@ -1887,8 +1542,8 @@ Http::get('/v1/projects/:projectId/platforms/:platformId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('platformId', '', new UID(), 'Platform unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('platformId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Platform unique ID.', false, ['dbForPlatform'])
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $projectId, string $platformId, Response $response, Database $dbForPlatform) {
|
||||
|
|
@ -1928,8 +1583,8 @@ Http::put('/v1/projects/:projectId/platforms/:platformId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('platformId', '', new UID(), 'Platform unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('platformId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Platform unique ID.', false, ['dbForPlatform'])
|
||||
->param('name', null, new Text(128), 'Platform name. Max length: 128 chars.')
|
||||
->param('key', '', new Text(256), 'Package name for android or bundle ID for iOS. Max length: 256 chars.', true)
|
||||
->param('store', '', new Text(256), 'App store or Google Play store ID. Max length: 256 chars.', true)
|
||||
|
|
@ -1985,8 +1640,8 @@ Http::delete('/v1/projects/:projectId/platforms/:platformId')
|
|||
],
|
||||
contentType: ContentType::NONE
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('platformId', '', new UID(), 'Platform unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('platformId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Platform unique ID.', false, ['dbForPlatform'])
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $projectId, string $platformId, Response $response, Database $dbForPlatform) {
|
||||
|
|
@ -2052,7 +1707,7 @@ Http::patch('/v1/projects/:projectId/smtp')
|
|||
]
|
||||
)
|
||||
])
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('enabled', false, new Boolean(), 'Enable custom SMTP service')
|
||||
->param('senderName', '', new Text(255, 0), 'Name of the email sender', true)
|
||||
->param('senderEmail', '', new Email(), 'Email of the sender', true)
|
||||
|
|
@ -2170,7 +1825,7 @@ Http::post('/v1/projects/:projectId/smtp/tests')
|
|||
]
|
||||
)
|
||||
])
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('emails', [], new ArrayList(new Email(), 10), 'Array of emails to send test email to. Maximum of 10 emails are allowed.')
|
||||
->param('senderName', System::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server'), new Text(255, 0), 'Name of the email sender')
|
||||
->param('senderEmail', System::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM), new Email(), 'Email of the sender')
|
||||
|
|
@ -2265,7 +1920,7 @@ Http::get('/v1/projects/:projectId/templates/sms/:type/:locale')
|
|||
]
|
||||
)
|
||||
])
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type')
|
||||
->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes'])
|
||||
->inject('response')
|
||||
|
|
@ -2313,7 +1968,7 @@ Http::get('/v1/projects/:projectId/templates/email/:type/:locale')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type')
|
||||
->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes'])
|
||||
->inject('response')
|
||||
|
|
@ -2432,7 +2087,7 @@ Http::patch('/v1/projects/:projectId/templates/sms/:type/:locale')
|
|||
]
|
||||
)
|
||||
])
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type')
|
||||
->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes'])
|
||||
->param('message', '', new Text(0), 'Template message')
|
||||
|
|
@ -2479,7 +2134,7 @@ Http::patch('/v1/projects/:projectId/templates/email/:type/:locale')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type')
|
||||
->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes'])
|
||||
->param('subject', '', new Text(255), 'Email Subject')
|
||||
|
|
@ -2558,7 +2213,7 @@ Http::delete('/v1/projects/:projectId/templates/sms/:type/:locale')
|
|||
contentType: ContentType::JSON
|
||||
)
|
||||
])
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type')
|
||||
->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes'])
|
||||
->inject('response')
|
||||
|
|
@ -2609,7 +2264,7 @@ Http::delete('/v1/projects/:projectId/templates/email/:type/:locale')
|
|||
],
|
||||
contentType: ContentType::JSON
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type')
|
||||
->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes'])
|
||||
->inject('response')
|
||||
|
|
@ -2661,7 +2316,7 @@ Http::patch('/v1/projects/:projectId/auth/session-invalidation')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
||||
->param('enabled', false, new Boolean(), 'Update authentication session invalidation status. Use this endpoint to enable or disable session invalidation on password change')
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ use Utopia\Database\Validator\Query\Limit;
|
|||
use Utopia\Database\Validator\Query\Offset;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Emails\Email;
|
||||
use Utopia\Http;
|
||||
use Utopia\Http\Http;
|
||||
use Utopia\Locale\Locale;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\ArrayList;
|
||||
|
|
@ -80,9 +80,9 @@ Http::post('/v1/teams')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('teamId', '', new CustomId(), 'Team ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('teamId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('name', null, new Text(128), 'Team name. Max length: 128 chars.')
|
||||
->param('roles', ['owner'], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.', true)
|
||||
->param('roles', ['owner'], fn (Database $dbForProject) => new ArrayList(new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.', true, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -191,16 +191,10 @@ Http::get('/v1/teams')
|
|||
$queries[] = Query::search('search', $search);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries
|
||||
*/
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
/** @var Query $cursor */
|
||||
$cursor = Query::getCursorQueries($queries, false);
|
||||
$cursor = \reset($cursor);
|
||||
|
||||
if ($cursor !== false) {
|
||||
$validator = new Cursor();
|
||||
if (!$validator->isValid($cursor)) {
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
|
||||
|
|
@ -247,7 +241,7 @@ Http::get('/v1/teams/:teamId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('teamId', '', new UID(), 'Team ID.')
|
||||
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $teamId, Response $response, Database $dbForProject) {
|
||||
|
|
@ -278,7 +272,7 @@ Http::get('/v1/teams/:teamId/prefs')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('teamId', '', new UID(), 'Team ID.')
|
||||
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $teamId, Response $response, Database $dbForProject) {
|
||||
|
|
@ -320,7 +314,7 @@ Http::put('/v1/teams/:teamId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('teamId', '', new UID(), 'Team ID.')
|
||||
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
|
||||
->param('name', null, new Text(128), 'New team name. Max length: 128 chars.')
|
||||
->inject('requestTimestamp')
|
||||
->inject('response')
|
||||
|
|
@ -366,7 +360,7 @@ Http::put('/v1/teams/:teamId/prefs')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('teamId', '', new UID(), 'Team ID.')
|
||||
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
|
||||
->param('prefs', '', new Assoc(), 'Prefs key-value JSON object.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -414,7 +408,7 @@ Http::delete('/v1/teams/:teamId')
|
|||
],
|
||||
contentType: ContentType::NONE
|
||||
))
|
||||
->param('teamId', '', new UID(), 'Team ID.')
|
||||
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('getProjectDB')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -480,20 +474,20 @@ Http::post('/v1/teams/:teamId/memberships')
|
|||
]
|
||||
))
|
||||
->label('abuse-limit', 10)
|
||||
->param('teamId', '', new UID(), 'Team ID.')
|
||||
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
|
||||
->param('email', '', new EmailValidator(), 'Email of the new team member.', true)
|
||||
->param('userId', '', new UID(), 'ID of the user to be added to a team.', true)
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'ID of the user to be added to a team.', true, ['dbForProject'])
|
||||
->param('phone', '', new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
|
||||
->param('roles', [], function (Document $project) {
|
||||
->param('roles', [], function (Document $project, Database $dbForProject) {
|
||||
if ($project->getId() === 'console') {
|
||||
$roles = array_keys(Config::getParam('roles', []));
|
||||
$roles = array_filter($roles, function ($role) {
|
||||
$roles = array_values(array_filter($roles, function ($role) {
|
||||
return !in_array($role, [User::ROLE_APPS, User::ROLE_GUESTS, User::ROLE_USERS]);
|
||||
});
|
||||
}));
|
||||
return new ArrayList(new WhiteList($roles), APP_LIMIT_ARRAY_PARAMS_SIZE);
|
||||
}
|
||||
return new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE);
|
||||
}, 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.', false, ['project'])
|
||||
return new ArrayList(new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), APP_LIMIT_ARRAY_PARAMS_SIZE);
|
||||
}, 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.', false, ['project', 'dbForProject'])
|
||||
->param('url', '', fn ($redirectValidator) => $redirectValidator, 'URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. 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, ['redirectValidator']) // TODO add our own built-in confirm page
|
||||
->param('name', '', new Text(128), 'Name of the new team member. Max length: 128 chars.', true)
|
||||
->inject('response')
|
||||
|
|
@ -861,7 +855,7 @@ Http::get('/v1/teams/:teamId/memberships')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('teamId', '', new UID(), 'Team ID.')
|
||||
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
|
||||
->param('queries', [], new Memberships(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Memberships::ALLOWED_ATTRIBUTES), true)
|
||||
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
|
|
@ -889,22 +883,15 @@ Http::get('/v1/teams/:teamId/memberships')
|
|||
// Set internal queries
|
||||
$queries[] = Query::equal('teamInternalId', [$team->getSequence()]);
|
||||
|
||||
/**
|
||||
* Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries
|
||||
*/
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
/** @var Query $cursor */
|
||||
$cursor = Query::getCursorQueries($queries, false);
|
||||
$cursor = \reset($cursor);
|
||||
|
||||
if ($cursor !== false) {
|
||||
$validator = new Cursor();
|
||||
if (!$validator->isValid($cursor)) {
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
|
||||
}
|
||||
|
||||
|
||||
$membershipId = $cursor->getValue();
|
||||
$cursorDocument = $dbForProject->getDocument('memberships', $membershipId);
|
||||
|
||||
|
|
@ -1005,8 +992,8 @@ Http::get('/v1/teams/:teamId/memberships/:membershipId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('teamId', '', new UID(), 'Team ID.')
|
||||
->param('membershipId', '', new UID(), 'Membership ID.')
|
||||
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
|
||||
->param('membershipId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Membership ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -1093,18 +1080,18 @@ Http::patch('/v1/teams/:teamId/memberships/:membershipId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('teamId', '', new UID(), 'Team ID.')
|
||||
->param('membershipId', '', new UID(), 'Membership ID.')
|
||||
->param('roles', [], function (Document $project) {
|
||||
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
|
||||
->param('membershipId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Membership ID.', false, ['dbForProject'])
|
||||
->param('roles', [], function (Document $project, Database $dbForProject) {
|
||||
if ($project->getId() === 'console') {
|
||||
$roles = array_keys(Config::getParam('roles', []));
|
||||
$roles = array_filter($roles, function ($role) {
|
||||
$roles = array_values(array_filter($roles, function ($role) {
|
||||
return !in_array($role, [User::ROLE_APPS, User::ROLE_GUESTS, User::ROLE_USERS]);
|
||||
});
|
||||
}));
|
||||
return new ArrayList(new WhiteList($roles), APP_LIMIT_ARRAY_PARAMS_SIZE);
|
||||
}
|
||||
return new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE);
|
||||
}, 'An array of strings. Use this param to set the user\'s roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.', false, ['project'])
|
||||
return new ArrayList(new Key(false, $dbForProject->getAdapter()->getMaxUIDLength()), APP_LIMIT_ARRAY_PARAMS_SIZE);
|
||||
}, 'An array of strings. Use this param to set the user\'s roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.', false, ['project', 'dbForProject'])
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
|
|
@ -1204,9 +1191,9 @@ Http::patch('/v1/teams/:teamId/memberships/:membershipId/status')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('teamId', '', new UID(), 'Team ID.')
|
||||
->param('membershipId', '', new UID(), 'Membership ID.')
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
|
||||
->param('membershipId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Membership ID.', false, ['dbForProject'])
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('secret', '', new Text(256), 'Secret key.')
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
|
|
@ -1371,8 +1358,8 @@ Http::delete('/v1/teams/:teamId/memberships/:membershipId')
|
|||
],
|
||||
contentType: ContentType::NONE
|
||||
))
|
||||
->param('teamId', '', new UID(), 'Team ID.')
|
||||
->param('membershipId', '', new UID(), 'Membership ID.')
|
||||
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
|
||||
->param('membershipId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Membership ID.', false, ['dbForProject'])
|
||||
->inject('user')
|
||||
->inject('project')
|
||||
->inject('response')
|
||||
|
|
@ -1467,7 +1454,7 @@ Http::get('/v1/teams/:teamId/logs')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('teamId', '', new UID(), 'Team ID.')
|
||||
->param('teamId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Team ID.', false, ['dbForProject'])
|
||||
->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true)
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('response')
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ use Utopia\Database\Validator\Query\Limit;
|
|||
use Utopia\Database\Validator\Query\Offset;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Emails\Email;
|
||||
use Utopia\Http;
|
||||
use Utopia\Http\Http;
|
||||
use Utopia\Locale\Locale;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\ArrayList;
|
||||
|
|
@ -246,7 +246,7 @@ Http::post('/v1/users')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('email', null, new Nullable(new EmailValidator()), 'User email.', true)
|
||||
->param('phone', null, new Nullable(new Phone()), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
|
||||
->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, $project->getAttribute('auths', [])['passwordDictionary'] ?? false), 'Plain text user password. Must be at least 8 chars.', true, ['project', 'passwordsDictionary'])
|
||||
|
|
@ -283,7 +283,7 @@ Http::post('/v1/users/bcrypt')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('password', '', new Password(), 'User password hashed using Bcrypt.')
|
||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||
|
|
@ -321,7 +321,7 @@ Http::post('/v1/users/md5')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('password', '', new Password(), 'User password hashed using MD5.')
|
||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||
|
|
@ -358,7 +358,7 @@ Http::post('/v1/users/argon2')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('password', '', new Password(), 'User password hashed using Argon2.')
|
||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||
|
|
@ -395,7 +395,7 @@ Http::post('/v1/users/sha')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('password', '', new Password(), 'User password hashed using SHA.')
|
||||
->param('passwordVersion', '', new WhiteList(['sha1', 'sha224', 'sha256', 'sha384', 'sha512/224', 'sha512/256', 'sha512', 'sha3-224', 'sha3-256', 'sha3-384', 'sha3-512']), "Optional SHA version used to hash password. Allowed values are: 'sha1', 'sha224', 'sha256', 'sha384', 'sha512/224', 'sha512/256', 'sha512', 'sha3-224', 'sha3-256', 'sha3-384', 'sha3-512'", true)
|
||||
|
|
@ -436,7 +436,7 @@ Http::post('/v1/users/phpass')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or pass the string `ID.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('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or pass the string `ID.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.', false, ['dbForProject'])
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('password', '', new Password(), 'User password hashed using PHPass.')
|
||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||
|
|
@ -473,7 +473,7 @@ Http::post('/v1/users/scrypt')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('password', '', new Password(), 'User password hashed using Scrypt.')
|
||||
->param('passwordSalt', '', new Text(128), 'Optional salt used to hash password.')
|
||||
|
|
@ -521,7 +521,7 @@ Http::post('/v1/users/scrypt-modified')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('email', '', new EmailValidator(), 'User email.')
|
||||
->param('password', '', new Password(), 'User password hashed using Scrypt Modified.')
|
||||
->param('passwordSalt', '', new Text(128), 'Salt used to hash password.')
|
||||
|
|
@ -566,11 +566,11 @@ Http::post('/v1/users/:userId/targets')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('targetId', '', new CustomId(), 'Target ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('userId', '', new UID(), 'User ID.')
|
||||
->param('targetId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'Target ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('providerType', '', new WhiteList([MESSAGE_TYPE_EMAIL, MESSAGE_TYPE_SMS, MESSAGE_TYPE_PUSH]), 'The target provider type. Can be one of the following: `email`, `sms` or `push`.')
|
||||
->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)')
|
||||
->param('providerId', '', new UID(), 'Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.', true)
|
||||
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.', true, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Target name. Max length: 128 chars. For example: My Awesome App Galaxy S23.', true)
|
||||
->inject('queueForEvents')
|
||||
->inject('response')
|
||||
|
|
@ -675,16 +675,10 @@ Http::get('/v1/users')
|
|||
$queries[] = Query::search('search', $search);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries
|
||||
*/
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
/** @var Query $cursor */
|
||||
$cursor = Query::getCursorQueries($queries, false);
|
||||
$cursor = \reset($cursor);
|
||||
|
||||
if ($cursor !== false) {
|
||||
$validator = new Cursor();
|
||||
if (!$validator->isValid($cursor)) {
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
|
||||
|
|
@ -737,7 +731,7 @@ Http::get('/v1/users/:userId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $userId, Response $response, Database $dbForProject) {
|
||||
|
|
@ -768,7 +762,7 @@ Http::get('/v1/users/:userId/prefs')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $userId, Response $response, Database $dbForProject) {
|
||||
|
|
@ -801,8 +795,8 @@ Http::get('/v1/users/:userId/targets/:targetId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('targetId', '', new UID(), 'Target ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('targetId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Target ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $userId, string $targetId, Response $response, Database $dbForProject) {
|
||||
|
|
@ -839,7 +833,7 @@ Http::get('/v1/users/:userId/sessions')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -883,7 +877,7 @@ Http::get('/v1/users/:userId/memberships')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('queries', [], new Memberships(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Memberships::ALLOWED_ATTRIBUTES), true)
|
||||
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
|
|
@ -938,7 +932,7 @@ Http::get('/v1/users/:userId/logs')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true)
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('response')
|
||||
|
|
@ -1025,7 +1019,7 @@ Http::get('/v1/users/:userId/targets')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('queries', [], new Targets(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Targets::ALLOWED_ATTRIBUTES), true)
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('response')
|
||||
|
|
@ -1042,14 +1036,11 @@ Http::get('/v1/users/:userId/targets')
|
|||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
|
||||
}
|
||||
$queries[] = Query::equal('userId', [$userId]);
|
||||
/**
|
||||
* Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries
|
||||
*/
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
|
||||
$cursor = Query::getCursorQueries($queries, false);
|
||||
$cursor = \reset($cursor);
|
||||
|
||||
if ($cursor !== false) {
|
||||
$validator = new Cursor();
|
||||
if (!$validator->isValid($cursor)) {
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
|
||||
|
|
@ -1106,15 +1097,11 @@ Http::get('/v1/users/identities')
|
|||
if (!empty($search)) {
|
||||
$queries[] = Query::search('search', $search);
|
||||
}
|
||||
/**
|
||||
* Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries
|
||||
*/
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
/** @var Query $cursor */
|
||||
|
||||
$cursor = Query::getCursorQueries($queries, false);
|
||||
$cursor = \reset($cursor);
|
||||
|
||||
if ($cursor !== false) {
|
||||
$validator = new Cursor();
|
||||
if (!$validator->isValid($cursor)) {
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
|
||||
|
|
@ -1160,7 +1147,7 @@ Http::patch('/v1/users/:userId/status')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('status', null, new Boolean(true), 'User Status. To activate the user pass `true` and to block the user pass `false`.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -1201,7 +1188,7 @@ Http::put('/v1/users/:userId/labels')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('labels', [], new ArrayList(new Text(36, allowList: [...Text::NUMBERS, ...Text::ALPHABET_UPPER, ...Text::ALPHABET_LOWER]), APP_LIMIT_ARRAY_LABELS_SIZE), 'Array of user labels. Replaces the previous labels. Maximum of ' . APP_LIMIT_ARRAY_LABELS_SIZE . ' labels are allowed, each up to 36 alphanumeric characters long.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -1244,7 +1231,7 @@ Http::patch('/v1/users/:userId/verification/phone')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('phoneVerification', false, new Boolean(), 'User phone verification status.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -1286,7 +1273,7 @@ Http::patch('/v1/users/:userId/name')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('name', '', new Text(128, 0), 'User name. Max length: 128 chars.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -1329,7 +1316,7 @@ Http::patch('/v1/users/:userId/password')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, enabled: $project->getAttribute('auths', [])['passwordDictionary'] ?? false, allowEmpty: true), 'New user password. Must be at least 8 chars.', false, ['project', 'passwordsDictionary'])
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
|
|
@ -1428,7 +1415,7 @@ Http::patch('/v1/users/:userId/email')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('email', '', new EmailValidator(allowEmpty: true), 'User email.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -1539,7 +1526,7 @@ Http::patch('/v1/users/:userId/phone')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('number', '', new Phone(allowEmpty: true), 'User phone number.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -1629,7 +1616,7 @@ Http::patch('/v1/users/:userId/verification')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('emailVerification', false, new Boolean(), 'User email verification status.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -1667,7 +1654,7 @@ Http::patch('/v1/users/:userId/prefs')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('prefs', '', new Assoc(), 'Prefs key-value JSON object.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -1708,10 +1695,10 @@ Http::patch('/v1/users/:userId/targets/:targetId')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('targetId', '', new UID(), 'Target ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('targetId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Target ID.', false, ['dbForProject'])
|
||||
->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)', true)
|
||||
->param('providerId', '', new UID(), 'Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.', true)
|
||||
->param('providerId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.', true, ['dbForProject'])
|
||||
->param('name', '', new Text(128), 'Target name. Max length: 128 chars. For example: My Awesome App Galaxy S23.', true)
|
||||
->inject('queueForEvents')
|
||||
->inject('response')
|
||||
|
|
@ -1833,7 +1820,7 @@ Http::patch('/v1/users/:userId/mfa')
|
|||
]
|
||||
)
|
||||
])
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('mfa', null, new Boolean(), 'Enable or disable MFA.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -1893,7 +1880,7 @@ Http::get('/v1/users/:userId/mfa/factors')
|
|||
]
|
||||
)
|
||||
])
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $userId, Response $response, Database $dbForProject) {
|
||||
|
|
@ -1952,7 +1939,7 @@ Http::get('/v1/users/:userId/mfa/recovery-codes')
|
|||
]
|
||||
)
|
||||
])
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $userId, Response $response, Database $dbForProject) {
|
||||
|
|
@ -2017,7 +2004,7 @@ Http::patch('/v1/users/:userId/mfa/recovery-codes')
|
|||
]
|
||||
)
|
||||
])
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
|
|
@ -2090,7 +2077,7 @@ Http::put('/v1/users/:userId/mfa/recovery-codes')
|
|||
public: false,
|
||||
)
|
||||
])
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
|
|
@ -2163,7 +2150,7 @@ Http::delete('/v1/users/:userId/mfa/authenticators/:type')
|
|||
contentType: ContentType::NONE
|
||||
)
|
||||
])
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('type', null, new WhiteList([Type::TOTP]), 'Type of authenticator.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -2210,7 +2197,7 @@ Http::post('/v1/users/:userId/sessions')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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('userId', '', fn (Database $dbForProject) => new CustomId(false, $dbForProject->getAdapter()->getMaxUIDLength()), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. 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.', false, ['dbForProject'])
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
|
@ -2302,7 +2289,7 @@ Http::post('/v1/users/:userId/tokens')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('length', 6, new Range(4, 128), 'Token length in characters. The default length is 6 characters', true)
|
||||
->param('expire', TOKEN_EXPIRATION_GENERIC, new Range(60, TOKEN_EXPIRATION_LOGIN_LONG), 'Token expiration period in seconds. The default expiration is 15 minutes.', true)
|
||||
->inject('request')
|
||||
|
|
@ -2368,8 +2355,8 @@ Http::delete('/v1/users/:userId/sessions/:sessionId')
|
|||
],
|
||||
contentType: ContentType::NONE
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('sessionId', '', new UID(), 'Session ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('sessionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Session ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
|
|
@ -2419,7 +2406,7 @@ Http::delete('/v1/users/:userId/sessions')
|
|||
],
|
||||
contentType: ContentType::NONE
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
|
|
@ -2469,7 +2456,7 @@ Http::delete('/v1/users/:userId')
|
|||
],
|
||||
contentType: ContentType::NONE
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
|
|
@ -2521,8 +2508,8 @@ Http::delete('/v1/users/:userId/targets/:targetId')
|
|||
],
|
||||
contentType: ContentType::NONE
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('targetId', '', new UID(), 'Target ID.')
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('targetId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Target ID.', false, ['dbForProject'])
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForDeletes')
|
||||
->inject('response')
|
||||
|
|
@ -2579,7 +2566,7 @@ Http::delete('/v1/users/identities/:identityId')
|
|||
],
|
||||
contentType: ContentType::NONE,
|
||||
))
|
||||
->param('identityId', '', new UID(), 'Identity ID.')
|
||||
->param('identityId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Identity ID.', false, ['dbForProject'])
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
|
|
@ -2618,8 +2605,8 @@ Http::post('/v1/users/:userId/jwts')
|
|||
)
|
||||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('sessionId', '', new UID(), 'Session ID. Use the string \'recent\' to use the most recent session. Defaults to the most recent session.', true)
|
||||
->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject'])
|
||||
->param('sessionId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'Session ID. Use the string \'recent\' to use the most recent session. Defaults to the most recent session.', true, ['dbForProject'])
|
||||
->param('duration', 900, new Range(0, 3600), 'Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -8,7 +8,7 @@ use Appwrite\Auth\Key;
|
|||
use Appwrite\Event\Certificate;
|
||||
use Appwrite\Event\Delete as DeleteEvent;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Event\Func;
|
||||
use Appwrite\Event\Execution;
|
||||
use Appwrite\Event\StatsUsage;
|
||||
use Appwrite\Extend\Exception as AppwriteException;
|
||||
use Appwrite\Network\Cors;
|
||||
|
|
@ -34,8 +34,8 @@ use Appwrite\Utopia\View;
|
|||
use Executor\Executor;
|
||||
use MaxMind\Db\Reader;
|
||||
use Swoole\Http\Request as SwooleRequest;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Console;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
|
|
@ -45,7 +45,7 @@ use Utopia\Database\Query;
|
|||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Domains\Domain;
|
||||
use Utopia\DSN\DSN;
|
||||
use Utopia\Http;
|
||||
use Utopia\Http\Http;
|
||||
use Utopia\Locale\Locale;
|
||||
use Utopia\Logger\Adapter\Sentry;
|
||||
use Utopia\Logger\Log;
|
||||
|
|
@ -60,7 +60,7 @@ Config::setParam('domainVerification', false);
|
|||
Config::setParam('cookieDomain', 'localhost');
|
||||
Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE);
|
||||
|
||||
function router(Http $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Authorization $authorization, ?Key $apiKey, DeleteEvent $queueForDeletes, int $executionsRetentionCount)
|
||||
function router(Http $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Event $queueForEvents, StatsUsage $queueForStatsUsage, Execution $queueForExecutions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Authorization $authorization, ?Key $apiKey, DeleteEvent $queueForDeletes, int $executionsRetentionCount)
|
||||
{
|
||||
$host = $request->getHostname() ?? '';
|
||||
if (!empty($previewHostname)) {
|
||||
|
|
@ -630,8 +630,15 @@ function router(Http $utopia, Database $dbForPlatform, callable $getProjectDB, S
|
|||
$headerOverrides['x-appwrite-log-id'] = $execution->getId();
|
||||
}
|
||||
|
||||
// Headers that must have single values (RFC 7230)
|
||||
$singleValueHeaders = ['content-length', 'content-type'];
|
||||
|
||||
foreach ($headerOverrides as $key => $value) {
|
||||
if (\array_key_exists($key, $executionResponse['headers'])) {
|
||||
$keyLower = \strtolower($key);
|
||||
if (\in_array($keyLower, $singleValueHeaders)) {
|
||||
// Single-value headers must replace, not append
|
||||
$executionResponse['headers'][$key] = $value;
|
||||
} elseif (\array_key_exists($key, $executionResponse['headers'])) {
|
||||
if (\is_array($executionResponse['headers'][$key])) {
|
||||
$executionResponse['headers'][$key][] = $value;
|
||||
} else {
|
||||
|
|
@ -696,14 +703,11 @@ function router(Http $utopia, Database $dbForPlatform, callable $getProjectDB, S
|
|||
throw $th;
|
||||
}
|
||||
} finally {
|
||||
if ($type === 'function') {
|
||||
$queueForFunctions
|
||||
->setType(Func::TYPE_ASYNC_WRITE)
|
||||
if ($type === 'function' || $type === 'site') {
|
||||
$queueForExecutions
|
||||
->setExecution($execution)
|
||||
->setProject($project)
|
||||
->trigger();
|
||||
} elseif ($type === 'site') { // TODO: Move it to logs worker later
|
||||
$dbForProject->createDocument('executions', $execution);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -877,7 +881,7 @@ Http::init()
|
|||
->inject('geodb')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForFunctions')
|
||||
->inject('queueForExecutions')
|
||||
->inject('executor')
|
||||
->inject('platform')
|
||||
->inject('isResourceBlocked')
|
||||
|
|
@ -888,7 +892,7 @@ Http::init()
|
|||
->inject('authorization')
|
||||
->inject('queueForDeletes')
|
||||
->inject('executionsRetentionCount')
|
||||
->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Func $queueForFunctions, Executor $executor, array $platform, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization, DeleteEvent $queueForDeletes, int $executionsRetentionCount) {
|
||||
->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Execution $queueForExecutions, Executor $executor, array $platform, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization, DeleteEvent $queueForDeletes, int $executionsRetentionCount) {
|
||||
/*
|
||||
* Appwrite Router
|
||||
*/
|
||||
|
|
@ -896,7 +900,7 @@ Http::init()
|
|||
$platformHostnames = $platform['hostnames'] ?? [];
|
||||
// Only run Router when external domain
|
||||
if (!\in_array($hostname, $platformHostnames) || !empty($previewHostname)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForExecutions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) {
|
||||
$utopia->getRoute()?->label('router', true);
|
||||
}
|
||||
}
|
||||
|
|
@ -950,7 +954,15 @@ Http::init()
|
|||
$endDomain->getRegisterable() !== ''
|
||||
);
|
||||
|
||||
$isLocalHost = $request->getHostname() === 'localhost' || $request->getHostname() === 'localhost:' . $request->getPort();
|
||||
$localHosts = ['localhost','localhost:'.$request->getPort()];
|
||||
|
||||
$migrationHost = System::getEnv('_APP_MIGRATION_HOST');
|
||||
if (!empty($migrationHost)) {
|
||||
$localHosts[] = $migrationHost;
|
||||
$localHosts[] = $migrationHost.':'.$request->getPort();
|
||||
}
|
||||
|
||||
$isLocalHost = in_array($request->getHostname(), $localHosts);
|
||||
$isIpAddress = filter_var($request->getHostname(), FILTER_VALIDATE_IP) !== false;
|
||||
|
||||
$isConsoleProject = $project->getAttribute('$id', '') === 'console';
|
||||
|
|
@ -997,7 +1009,7 @@ Http::init()
|
|||
}
|
||||
|
||||
if (System::getEnv('_APP_OPTIONS_FORCE_HTTPS', 'disabled') === 'enabled') { // Force HTTPS
|
||||
if ($request->getProtocol() !== 'https' && ($swooleRequest->header['host'] ?? '') !== 'localhost') { // localhost allowed for proxy, APP_HOSTNAME_INTERNAL allowed for migrations
|
||||
if ($request->getProtocol() !== 'https' && !in_array(($swooleRequest->header['host'] ?? ''), $localHosts)) { // localhost allowed for proxy
|
||||
if ($request->getMethod() !== Request::METHOD_GET) {
|
||||
throw new AppwriteException(AppwriteException::GENERAL_PROTOCOL_UNSUPPORTED, 'Method unsupported over HTTP. Please use HTTPS instead.');
|
||||
}
|
||||
|
|
@ -1167,7 +1179,7 @@ Http::options()
|
|||
->inject('getProjectDB')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('queueForFunctions')
|
||||
->inject('queueForExecutions')
|
||||
->inject('executor')
|
||||
->inject('geodb')
|
||||
->inject('isResourceBlocked')
|
||||
|
|
@ -1180,14 +1192,14 @@ Http::options()
|
|||
->inject('authorization')
|
||||
->inject('queueForDeletes')
|
||||
->inject('executionsRetentionCount')
|
||||
->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization, DeleteEvent $queueForDeletes, int $executionsRetentionCount) {
|
||||
->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Execution $queueForExecutions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, Cors $cors, Authorization $authorization, DeleteEvent $queueForDeletes, int $executionsRetentionCount) {
|
||||
/*
|
||||
* Appwrite Router
|
||||
*/
|
||||
$platformHostnames = $platform['hostnames'] ?? [];
|
||||
// Only run Router when external domain
|
||||
if (!in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForExecutions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) {
|
||||
$utopia->getRoute()?->label('router', true);
|
||||
}
|
||||
}
|
||||
|
|
@ -1247,7 +1259,7 @@ Http::error()
|
|||
}
|
||||
|
||||
switch ($class) {
|
||||
case Utopia\Exception::class:
|
||||
case Utopia\Http\Exception::class:
|
||||
$error = new AppwriteException(AppwriteException::GENERAL_UNKNOWN, $message, $code, $error);
|
||||
switch ($code) {
|
||||
case 400:
|
||||
|
|
@ -1563,7 +1575,7 @@ Http::get('/robots.txt')
|
|||
->inject('getProjectDB')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('queueForFunctions')
|
||||
->inject('queueForExecutions')
|
||||
->inject('executor')
|
||||
->inject('geodb')
|
||||
->inject('isResourceBlocked')
|
||||
|
|
@ -1573,13 +1585,13 @@ Http::get('/robots.txt')
|
|||
->inject('authorization')
|
||||
->inject('queueForDeletes')
|
||||
->inject('executionsRetentionCount')
|
||||
->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization, DeleteEvent $queueForDeletes, int $executionsRetentionCount) {
|
||||
->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Execution $queueForExecutions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization, DeleteEvent $queueForDeletes, int $executionsRetentionCount) {
|
||||
$platformHostnames = $platform['hostnames'] ?? [];
|
||||
if (in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) {
|
||||
$template = new View(__DIR__ . '/../views/general/robots.phtml');
|
||||
$response->text($template->render(false));
|
||||
} else {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForExecutions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) {
|
||||
$utopia->getRoute()?->label('router', true);
|
||||
}
|
||||
}
|
||||
|
|
@ -1598,7 +1610,7 @@ Http::get('/humans.txt')
|
|||
->inject('getProjectDB')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('queueForFunctions')
|
||||
->inject('queueForExecutions')
|
||||
->inject('executor')
|
||||
->inject('geodb')
|
||||
->inject('isResourceBlocked')
|
||||
|
|
@ -1608,13 +1620,13 @@ Http::get('/humans.txt')
|
|||
->inject('authorization')
|
||||
->inject('queueForDeletes')
|
||||
->inject('executionsRetentionCount')
|
||||
->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization, DeleteEvent $queueForDeletes, int $executionsRetentionCount) {
|
||||
->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Execution $queueForExecutions, Executor $executor, Reader $geodb, callable $isResourceBlocked, array $platform, string $previewHostname, ?Key $apiKey, Authorization $authorization, DeleteEvent $queueForDeletes, int $executionsRetentionCount) {
|
||||
$platformHostnames = $platform['hostnames'] ?? [];
|
||||
if (in_array($request->getHostname(), $platformHostnames) || !empty($previewHostname)) {
|
||||
$template = new View(__DIR__ . '/../views/general/humans.phtml');
|
||||
$response->text($template->render(false));
|
||||
} else {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForExecutions, $executor, $geodb, $isResourceBlocked, $platform, $previewHostname, $authorization, $apiKey, $queueForDeletes, $executionsRetentionCount)) {
|
||||
$utopia->getRoute()?->label('router', true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use Utopia\Database\Helpers\ID;
|
|||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Http;
|
||||
use Utopia\Http\Http;
|
||||
use Utopia\Locale\Locale;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\Text;
|
||||
|
|
@ -31,7 +31,6 @@ Http::get('/v1/mock/tests/general/oauth2')
|
|||
->param('state', '', new Text(1024), 'OAuth2 state.')
|
||||
->inject('response')
|
||||
->action(function (string $client_id, string $redirectURI, string $scope, string $state, Response $response) {
|
||||
|
||||
$response->redirect($redirectURI . '?' . \http_build_query(['code' => 'abcdef', 'state' => $state]));
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ use Utopia\Database\Document;
|
|||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Authorization\Input;
|
||||
use Utopia\Http;
|
||||
use Utopia\Http\Http;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Telemetry\Adapter as Telemetry;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
|
@ -397,6 +397,7 @@ Http::init()
|
|||
/*
|
||||
* Abuse Check
|
||||
*/
|
||||
|
||||
$abuseKeyLabel = $route->getLabel('abuse-key', 'url:{url},ip:{ip}');
|
||||
$timeLimitArray = [];
|
||||
|
||||
|
|
@ -432,6 +433,7 @@ Http::init()
|
|||
|
||||
$abuse = new Abuse($timeLimit);
|
||||
$remaining = $timeLimit->remaining();
|
||||
|
||||
$limit = $timeLimit->limit();
|
||||
$time = $timeLimit->time() + $route->getLabel('abuse-time', 3600);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use Utopia\Config\Config;
|
|||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Http;
|
||||
use Utopia\Http\Http;
|
||||
use Utopia\System\System;
|
||||
|
||||
Http::init()
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Http;
|
||||
use Utopia\Http\Http;
|
||||
|
||||
Http::get('/versions')
|
||||
->desc('Get Version')
|
||||
|
|
|
|||
90
app/http.php
90
app/http.php
|
|
@ -14,9 +14,9 @@ use Swoole\Timer;
|
|||
use Utopia\Audit\Adapter\Database as AdapterDatabase;
|
||||
use Utopia\Audit\Adapter\SQL as AuditAdapterSQL;
|
||||
use Utopia\Audit\Audit;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Compression\Compression;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Console;
|
||||
use Utopia\Database\Adapter\Pool as DatabasePool;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
|
|
@ -26,17 +26,17 @@ use Utopia\Database\Helpers\ID;
|
|||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Http;
|
||||
use Utopia\Http\Files;
|
||||
use Utopia\Http\Http;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\Logger\Log\User;
|
||||
use Utopia\Pools\Group;
|
||||
use Utopia\Swoole\Files;
|
||||
use Utopia\System\System;
|
||||
|
||||
Files::load(__DIR__.'/../public');
|
||||
|
||||
const DOMAIN_SYNC_TIMER = 30; // 30 seconds
|
||||
|
||||
$files = null;
|
||||
|
||||
$domains = new Table(1_000_000); // 1 million rows
|
||||
$domains->column('value', Table::TYPE_INT, 1);
|
||||
$domains->create();
|
||||
|
|
@ -162,7 +162,11 @@ $http
|
|||
Constant::OPTION_TASK_WORKER_NUM => 1, // required for the task to fetch domains background
|
||||
]);
|
||||
|
||||
$http->on(Constant::EVENT_WORKER_START, function ($server, $workerId) {
|
||||
$http->on(Constant::EVENT_WORKER_START, function ($server, $workerId) use (&$files) {
|
||||
if (!$server->taskworker) {
|
||||
$files = new Files();
|
||||
$files->load(__DIR__ . '/../public');
|
||||
}
|
||||
Console::success('Worker ' . ++$workerId . ' started successfully');
|
||||
});
|
||||
|
||||
|
|
@ -181,10 +185,10 @@ $http->on(Constant::EVENT_AFTER_RELOAD, function ($server) {
|
|||
|
||||
include __DIR__ . '/controllers/general.php';
|
||||
|
||||
function createDatabase(Http $app, string $resourceKey, string $dbName, array $collections, mixed $pools, callable $extraSetup = null): void
|
||||
function createDatabase(Http $app, string $resourceKey, string $dbName, array $collections, mixed $pools, ?callable $extraSetup = null): void
|
||||
{
|
||||
$max = 10;
|
||||
$sleep = 1;
|
||||
$max = 15;
|
||||
$sleep = 2;
|
||||
$attempts = 0;
|
||||
|
||||
while (true) {
|
||||
|
|
@ -194,8 +198,8 @@ function createDatabase(Http $app, string $resourceKey, string $dbName, array $c
|
|||
/* @var $database Database */
|
||||
$database = is_callable($resource) ? $resource() : $resource;
|
||||
break; // exit loop on success
|
||||
} catch (\Exception $e) {
|
||||
Console::warning(" └── Database not ready. Retrying connection ({$attempts})...");
|
||||
} catch (\Throwable $e) {
|
||||
Console::warning(" └── Database not ready ({$dbName}). Retrying connection ({$attempts}): " . $e->getMessage());
|
||||
if ($attempts >= $max) {
|
||||
throw new \Exception(' └── Failed to connect to database: ' . $e->getMessage());
|
||||
}
|
||||
|
|
@ -205,12 +209,26 @@ function createDatabase(Http $app, string $resourceKey, string $dbName, array $c
|
|||
|
||||
Console::success("[Setup] - $dbName database init started...");
|
||||
|
||||
// Attempt to create the database
|
||||
try {
|
||||
Console::info(" └── Creating database: $dbName...");
|
||||
$database->create();
|
||||
} catch (\Exception $e) {
|
||||
Console::info(" └── Skip: metadata table already exists");
|
||||
$attempts = 0;
|
||||
while (true) {
|
||||
try {
|
||||
$attempts++;
|
||||
Console::info(" └── Creating database: $dbName...");
|
||||
$database->create();
|
||||
break; // exit loop on success
|
||||
} catch (\Exception $e) {
|
||||
if ($e instanceof DuplicateException) {
|
||||
Console::info(" └── Skip: metadata table already exists");
|
||||
break;
|
||||
}
|
||||
|
||||
Console::warning(" └── Database create failed. Retrying ({$attempts})...");
|
||||
if ($attempts >= $max) {
|
||||
throw new \Exception(' └── Failed to create database: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
\sleep($sleep);
|
||||
}
|
||||
}
|
||||
|
||||
// Process collections
|
||||
|
|
@ -394,11 +412,25 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
|
|||
->setTenant(null)
|
||||
->setNamespace(System::getEnv('_APP_DATABASE_SHARED_NAMESPACE', ''));
|
||||
|
||||
try {
|
||||
Console::success('[Setup] - Creating project database: ' . $hostname . '...');
|
||||
$dbForProject->create();
|
||||
} catch (DuplicateException) {
|
||||
Console::success('[Setup] - Skip: metadata table already exists');
|
||||
$max = 15;
|
||||
$sleep = 2;
|
||||
$attempts = 0;
|
||||
while (true) {
|
||||
try {
|
||||
$attempts++;
|
||||
Console::success('[Setup] - Creating project database: ' . $hostname . '...');
|
||||
$dbForProject->create();
|
||||
break; // exit loop on success
|
||||
} catch (DuplicateException) {
|
||||
Console::success('[Setup] - Skip: metadata table already exists');
|
||||
break;
|
||||
} catch (\Throwable $e) {
|
||||
Console::warning(" └── Project database create failed. Retrying ({$attempts})...");
|
||||
if ($attempts >= $max) {
|
||||
throw new \Exception(' └── Failed to create project database: ' . $e->getMessage());
|
||||
}
|
||||
sleep($sleep);
|
||||
}
|
||||
}
|
||||
|
||||
if ($dbForProject->getCollection(AuditAdapterSQL::COLLECTION)->isEmpty()) {
|
||||
|
|
@ -440,21 +472,21 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
|
|||
});
|
||||
});
|
||||
|
||||
$http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) use ($register) {
|
||||
$http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) use ($register, &$files) {
|
||||
Http::setResource('swooleRequest', fn () => $swooleRequest);
|
||||
Http::setResource('swooleResponse', fn () => $swooleResponse);
|
||||
|
||||
$request = new Request($swooleRequest);
|
||||
$response = new Response($swooleResponse);
|
||||
|
||||
if (Files::isFileLoaded($request->getURI())) {
|
||||
$time = (60 * 60 * 24 * 365 * 2); // 45 days cache
|
||||
if ($files instanceof Files && $files->isFileLoaded($request->getURI())) {
|
||||
$time = (60 * 60 * 24 * 45); // 45 days cache
|
||||
|
||||
$response
|
||||
->setContentType(Files::getFileMimeType($request->getURI()))
|
||||
->setContentType($files->getFileMimeType($request->getURI()))
|
||||
->addHeader('Cache-Control', 'public, max-age=' . $time)
|
||||
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time) . ' GMT') // 45 days cache
|
||||
->send(Files::getFileContents($request->getURI()));
|
||||
->send($files->getFileContents($request->getURI()));
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -585,7 +617,7 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) {
|
|||
if ($latestDocument !== null) {
|
||||
$queries[] = Query::cursorAfter($latestDocument);
|
||||
}
|
||||
if ($lastSyncUpdate != null) {
|
||||
if ($lastSyncUpdate !== null) {
|
||||
$queries[] = Query::greaterThanEqual('$updatedAt', $lastSyncUpdate);
|
||||
}
|
||||
$results = [];
|
||||
|
|
@ -593,7 +625,7 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) {
|
|||
$authorization = $app->getResource('authorization');
|
||||
$results = $authorization->skip(fn () => $dbForPlatform->find('rules', $queries));
|
||||
} catch (Throwable $th) {
|
||||
Console::error($th->getMessage());
|
||||
Console::error('rules ' . $th->getMessage());
|
||||
}
|
||||
|
||||
$sum = count($results);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ use Appwrite\Platform\Modules\Compute\Specification;
|
|||
const APP_NAME = 'Appwrite';
|
||||
const APP_DOMAIN = 'appwrite.io';
|
||||
|
||||
const APP_VIEWS_DIR = __DIR__ . '/../views';
|
||||
|
||||
// Email
|
||||
const APP_EMAIL_TEAM = 'team@localhost.test'; // Default email address
|
||||
const APP_EMAIL_SECURITY = ''; // Default security email address
|
||||
|
|
@ -369,6 +371,7 @@ const RESOURCE_TYPE_TOPICS = 'topics';
|
|||
const RESOURCE_TYPE_SUBSCRIBERS = 'subscribers';
|
||||
const RESOURCE_TYPE_MESSAGES = 'messages';
|
||||
const RESOURCE_TYPE_EXECUTIONS = 'executions';
|
||||
const RESOURCE_TYPE_VCS = 'vcs';
|
||||
|
||||
// Resource types for Tokens
|
||||
const TOKENS_RESOURCE_TYPE_FILES = 'files';
|
||||
|
|
@ -387,3 +390,6 @@ const COOKIE_NAME_PREVIEW = 'a_jwt_console';
|
|||
// Cache Reconnect
|
||||
const CACHE_RECONNECT_MAX_RETRIES = 2;
|
||||
const CACHE_RECONNECT_RETRY_DELAY = 1000;
|
||||
|
||||
// Project status
|
||||
const PROJECT_STATUS_ACTIVE = 'active';
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ Database::addFilter(
|
|||
$attributes = $database->getAuthorization()->skip(fn () => $database->find('attributes', [
|
||||
Query::equal('collectionInternalId', [$document->getSequence()]),
|
||||
Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]),
|
||||
Query::limit($database->getLimitForAttributes()),
|
||||
Query::limit($database->getLimitForAttributes() ?: APP_LIMIT_SUBQUERY),
|
||||
]));
|
||||
|
||||
foreach ($attributes as $attribute) {
|
||||
|
|
|
|||
|
|
@ -9,20 +9,23 @@ use MaxMind\Db\Reader;
|
|||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use Swoole\Database\PDOProxy;
|
||||
use Utopia\Cache\Adapter\Redis as RedisCache;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Console;
|
||||
use Utopia\Database\Adapter\MariaDB;
|
||||
use Utopia\Database\Adapter\Mongo;
|
||||
use Utopia\Database\Adapter\MySQL;
|
||||
use Utopia\Database\Adapter\Postgres;
|
||||
use Utopia\Database\Adapter\SQL;
|
||||
use Utopia\Database\PDO;
|
||||
use Utopia\Domains\Validator\PublicDomain;
|
||||
use Utopia\DSN\DSN;
|
||||
use Utopia\Http;
|
||||
use Utopia\Http\Http;
|
||||
use Utopia\Logger\Adapter\AppSignal;
|
||||
use Utopia\Logger\Adapter\LogOwl;
|
||||
use Utopia\Logger\Adapter\Raygun;
|
||||
use Utopia\Logger\Adapter\Sentry;
|
||||
use Utopia\Logger\Logger;
|
||||
use Utopia\Mongo\Client as MongoClient;
|
||||
use Utopia\Pools\Adapter\Stack as StackPool;
|
||||
use Utopia\Pools\Adapter\Swoole as SwoolePool;
|
||||
use Utopia\Pools\Group;
|
||||
|
|
@ -150,13 +153,14 @@ $register->set('pools', function () {
|
|||
$group = new Group();
|
||||
|
||||
$fallbackForDB = 'db_main=' . AppwriteURL::unparse([
|
||||
'scheme' => 'mariadb',
|
||||
'host' => System::getEnv('_APP_DB_HOST', 'mariadb'),
|
||||
'port' => System::getEnv('_APP_DB_PORT', '3306'),
|
||||
'scheme' => System::getEnv('_APP_DB_ADAPTER', 'mongodb'),
|
||||
'host' => System::getEnv('_APP_DB_HOST', 'mongodb'),
|
||||
'port' => System::getEnv('_APP_DB_PORT', '27017'),
|
||||
'user' => System::getEnv('_APP_DB_USER', ''),
|
||||
'pass' => System::getEnv('_APP_DB_PASS', ''),
|
||||
'path' => System::getEnv('_APP_DB_SCHEMA', ''),
|
||||
]);
|
||||
|
||||
$fallbackForRedis = 'redis_main=' . AppwriteURL::unparse([
|
||||
'scheme' => 'redis',
|
||||
'host' => System::getEnv('_APP_REDIS_HOST', 'redis'),
|
||||
|
|
@ -170,19 +174,19 @@ $register->set('pools', function () {
|
|||
'type' => 'database',
|
||||
'dsns' => $fallbackForDB,
|
||||
'multiple' => false,
|
||||
'schemes' => ['mariadb', 'mysql'],
|
||||
'schemes' => ['mariadb', 'mongodb', 'mysql', 'postgresql'],
|
||||
],
|
||||
'database' => [
|
||||
'type' => 'database',
|
||||
'dsns' => $fallbackForDB,
|
||||
'multiple' => true,
|
||||
'schemes' => ['mariadb', 'mysql'],
|
||||
'schemes' => ['mariadb', 'mongodb', 'mysql', 'postgresql'],
|
||||
],
|
||||
'logs' => [
|
||||
'type' => 'database',
|
||||
'dsns' => System::getEnv('_APP_CONNECTIONS_DB_LOGS', $fallbackForDB),
|
||||
'multiple' => false,
|
||||
'schemes' => ['mariadb', 'mysql'],
|
||||
'schemes' => ['mariadb', 'mongodb', 'mysql', 'postgresql'],
|
||||
],
|
||||
'publisher' => [
|
||||
'type' => 'publisher',
|
||||
|
|
@ -262,6 +266,7 @@ $register->set('pools', function () {
|
|||
*
|
||||
* Resource assignment to an adapter will happen below.
|
||||
*/
|
||||
|
||||
$resource = match ($dsnScheme) {
|
||||
'mysql',
|
||||
'mariadb' => function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) {
|
||||
|
|
@ -275,6 +280,27 @@ $register->set('pools', function () {
|
|||
]);
|
||||
});
|
||||
},
|
||||
'mongodb' => function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase, $dsn) {
|
||||
try {
|
||||
$mongo = new MongoClient($dsnDatabase, $dsnHost, (int)$dsnPort, $dsnUser, $dsnPass, false);
|
||||
@$mongo->connect();
|
||||
|
||||
return $mongo;
|
||||
} catch (\Throwable $e) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, "MongoDB connection failed: " . $e->getMessage());
|
||||
}
|
||||
},
|
||||
'postgresql' => function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) {
|
||||
return new PDOProxy(function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) {
|
||||
return new PDO("pgsql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};connect_timeout=3", $dsnUser, $dsnPass, array(
|
||||
\PDO::ATTR_TIMEOUT => 3, // Seconds
|
||||
\PDO::ATTR_PERSISTENT => false,
|
||||
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
|
||||
\PDO::ATTR_EMULATE_PREPARES => true,
|
||||
\PDO::ATTR_STRINGIFY_FETCHES => true
|
||||
));
|
||||
});
|
||||
},
|
||||
'redis' => function () use ($dsnHost, $dsnPort, $dsnPass) {
|
||||
$redis = new \Redis();
|
||||
@$redis->pconnect($dsnHost, (int)$dsnPort);
|
||||
|
|
@ -297,6 +323,8 @@ $register->set('pools', function () {
|
|||
$adapter = match ($dsn->getScheme()) {
|
||||
'mariadb' => new MariaDB($resource()),
|
||||
'mysql' => new MySQL($resource()),
|
||||
'mongodb' => new Mongo($resource()),
|
||||
'postgresql' => new Postgres($resource()),
|
||||
default => null
|
||||
};
|
||||
|
||||
|
|
@ -351,14 +379,29 @@ $register->set('db', function () {
|
|||
$dbPort = System::getEnv('_APP_DB_PORT', '');
|
||||
$dbUser = System::getEnv('_APP_DB_USER', '');
|
||||
$dbPass = System::getEnv('_APP_DB_PASS', '');
|
||||
$dbScheme = System::getEnv('_APP_DB_SCHEMA', '');
|
||||
$dbSchema = System::getEnv('_APP_DB_SCHEMA', '');
|
||||
$dbAdapter = System::getEnv('_APP_DB_ADAPTER', 'mongodb');
|
||||
$dsn = '';
|
||||
|
||||
return new PDO(
|
||||
"mysql:host={$dbHost};port={$dbPort};dbname={$dbScheme};charset=utf8mb4",
|
||||
$dbUser,
|
||||
$dbPass,
|
||||
SQL::getPDOAttributes()
|
||||
);
|
||||
switch ($dbAdapter) {
|
||||
case 'mongodb':
|
||||
try {
|
||||
$mongo = new MongoClient($dbSchema, $dbHost, (int)$dbPort, $dbUser, $dbPass, false);
|
||||
@$mongo->connect();
|
||||
return $mongo;
|
||||
} catch (\Throwable $e) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'MongoDB connection failed: ' . $e->getMessage());
|
||||
}
|
||||
case 'mysql':
|
||||
case 'mariadb':
|
||||
$dsn = "mysql:host={$dbHost};port={$dbPort};dbname={$dbSchema};charset=utf8mb4";
|
||||
return new PDO($dsn, $dbUser, $dbPass, SQL::getPDOAttributes());
|
||||
case 'postgresql':
|
||||
$dsn = "pgsql:host={$dbHost};port={$dbPort};dbname={$dbSchema};connect_timeout=3";
|
||||
return new PDO($dsn, $dbUser, $dbPass, SQL::getPDOAttributes());
|
||||
default:
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Invalid database adapter');
|
||||
}
|
||||
});
|
||||
|
||||
$register->set('smtp', function () {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use Appwrite\Event\Certificate;
|
|||
use Appwrite\Event\Database as EventDatabase;
|
||||
use Appwrite\Event\Delete;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Event\Execution;
|
||||
use Appwrite\Event\Func;
|
||||
use Appwrite\Event\Mail;
|
||||
use Appwrite\Event\Messaging;
|
||||
|
|
@ -42,8 +43,8 @@ use Utopia\Auth\Store;
|
|||
use Utopia\Cache\Adapter\Pool as CachePool;
|
||||
use Utopia\Cache\Adapter\Sharding;
|
||||
use Utopia\Cache\Cache;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Console;
|
||||
use Utopia\Database\Adapter\Pool as DatabasePool;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime as DatabaseDateTime;
|
||||
|
|
@ -51,7 +52,7 @@ use Utopia\Database\Document;
|
|||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\DSN\DSN;
|
||||
use Utopia\Http;
|
||||
use Utopia\Http\Http;
|
||||
use Utopia\Locale\Locale;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\Pools\Group;
|
||||
|
|
@ -159,6 +160,9 @@ Http::setResource('queueForAudits', function (Publisher $publisher) {
|
|||
Http::setResource('queueForFunctions', function (Publisher $publisher) {
|
||||
return new Func($publisher);
|
||||
}, ['publisher']);
|
||||
Http::setResource('queueForExecutions', function (Publisher $publisher) {
|
||||
return new Execution($publisher);
|
||||
}, ['publisher']);
|
||||
Http::setResource('eventProcessor', function () {
|
||||
return new EventProcessor();
|
||||
}, []);
|
||||
|
|
@ -198,15 +202,26 @@ Http::setResource('allowedHostnames', function (array $platform, Document $proje
|
|||
}
|
||||
|
||||
$originHostname = parse_url($request->getOrigin(), PHP_URL_HOST);
|
||||
$refererHostname = parse_url($request->getReferer(), PHP_URL_HOST);
|
||||
|
||||
$hostname = $originHostname;
|
||||
if (empty($hostname)) {
|
||||
$hostname = $refererHostname;
|
||||
}
|
||||
|
||||
/* Add request hostname for preflight requests */
|
||||
if ($request->getMethod() === 'OPTIONS') {
|
||||
$allowed[] = $originHostname;
|
||||
$allowed[] = $hostname;
|
||||
}
|
||||
|
||||
/* Allow the request origin if a dev key or rule is found */
|
||||
if ((!$rule->isEmpty() || !$devKey->isEmpty()) && !empty($originHostname)) {
|
||||
$allowed[] = $originHostname;
|
||||
/* Allow the request origin of rule */
|
||||
if (!$rule->isEmpty() && !empty($rule->getAttribute('domain', ''))) {
|
||||
$allowed[] = $rule->getAttribute('domain', '');
|
||||
}
|
||||
|
||||
/* Allow the request origin if a dev key is found */
|
||||
if (!$devKey->isEmpty() && !empty($hostname)) {
|
||||
$allowed[] = $hostname;
|
||||
}
|
||||
|
||||
return array_unique($allowed);
|
||||
|
|
@ -237,6 +252,11 @@ Http::setResource('allowedSchemes', function (Document $project) {
|
|||
*/
|
||||
Http::setResource('rule', function (Request $request, Database $dbForPlatform, Document $project, Authorization $authorization) {
|
||||
$domain = \parse_url($request->getOrigin(), PHP_URL_HOST);
|
||||
|
||||
if (empty($domain)) {
|
||||
$domain = \parse_url($request->getReferer(), PHP_URL_HOST);
|
||||
}
|
||||
|
||||
if (empty($domain)) {
|
||||
return new Document();
|
||||
}
|
||||
|
|
@ -253,7 +273,24 @@ Http::setResource('rule', function (Request $request, Database $dbForPlatform, D
|
|||
]) ?? new Document();
|
||||
});
|
||||
|
||||
if ($rule->getAttribute('projectInternalId') !== $project->getSequence()) {
|
||||
$permitsCurrentProject = $rule->getAttribute('projectInternalId', '') === $project->getSequence();
|
||||
|
||||
// Temporary implementation until custom wildcard domains are an official feature
|
||||
// Allow trusted projects; Used for Console (website) previews
|
||||
if (!$permitsCurrentProject && !$rule->isEmpty() && !empty($rule->getAttribute('projectId', ''))) {
|
||||
$trustedProjects = [];
|
||||
foreach (\explode(',', System::getEnv('_APP_CONSOLE_TRUSTED_PROJECTS', '')) as $trustedProject) {
|
||||
if (empty($trustedProject)) {
|
||||
continue;
|
||||
}
|
||||
$trustedProjects[] = $trustedProject;
|
||||
}
|
||||
if (\in_array($rule->getAttribute('projectId', ''), $trustedProjects)) {
|
||||
$permitsCurrentProject = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$permitsCurrentProject) {
|
||||
return new Document();
|
||||
}
|
||||
|
||||
|
|
@ -412,13 +449,7 @@ Http::setResource('user', function (string $mode, Document $project, Document $c
|
|||
) { // Validate user has valid login token
|
||||
$user = new User([]);
|
||||
}
|
||||
// if (APP_MODE_ADMIN === $mode) {
|
||||
// if ($user->find('teamInternalId', $project->getAttribute('teamInternalId'), 'memberships')) {
|
||||
// $authorization->setDefaultStatus(false); // Cancel security segmentation for admin users.
|
||||
// } else {
|
||||
// $user = new Document([]);
|
||||
// }
|
||||
// }
|
||||
|
||||
$authJWT = $request->getHeader('x-appwrite-jwt', '');
|
||||
if (!empty($authJWT) && !$project->isEmpty()) { // JWT authentication
|
||||
if (!$user->isEmpty()) {
|
||||
|
|
@ -487,6 +518,10 @@ Http::setResource('project', function ($dbForPlatform, $request, $console, $auth
|
|||
/** @var Utopia\Database\Document $console */
|
||||
|
||||
$projectId = $request->getParam('project', $request->getHeader('x-appwrite-project', ''));
|
||||
// Realtime channel "project" can send project=Query array
|
||||
if (!\is_string($projectId)) {
|
||||
$projectId = $request->getHeader('x-appwrite-project', '');
|
||||
}
|
||||
|
||||
if (empty($projectId) || $projectId === 'console') {
|
||||
return $console;
|
||||
|
|
@ -1280,6 +1315,8 @@ Http::setResource('team', function (Document $project, Database $dbForPlatform,
|
|||
}
|
||||
}
|
||||
|
||||
// if teamInternalId is empty, return an empty document
|
||||
|
||||
if (empty($teamInternalId)) {
|
||||
return new Document([]);
|
||||
}
|
||||
|
|
|
|||
112
app/realtime.php
112
app/realtime.php
|
|
@ -22,8 +22,8 @@ use Utopia\Auth\Store;
|
|||
use Utopia\Cache\Adapter\Pool as CachePool;
|
||||
use Utopia\Cache\Adapter\Sharding;
|
||||
use Utopia\Cache\Cache;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Console;
|
||||
use Utopia\Database\Adapter\Pool as DatabasePool;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
|
|
@ -33,7 +33,7 @@ use Utopia\Database\Helpers\ID;
|
|||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\DSN\DSN;
|
||||
use Utopia\Http;
|
||||
use Utopia\Http\Http;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\Pools\Group;
|
||||
use Utopia\Registry\Registry;
|
||||
|
|
@ -431,15 +431,20 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
|
|||
]
|
||||
];
|
||||
|
||||
$subscribers = $realtime->getSubscribers($event); // [connectionId => [subId => queries]]
|
||||
$subscribers = $realtime->getSubscribers($event);
|
||||
|
||||
// For test events, send to all connections with their matched subscription queries
|
||||
foreach ($subscribers as $connectionId => $matchedSubscriptions) {
|
||||
$groups = [];
|
||||
foreach ($subscribers as $id => $matched) {
|
||||
$key = implode(',', array_keys($matched));
|
||||
$groups[$key]['ids'][] = $id;
|
||||
$groups[$key]['subscriptions'] = array_keys($matched);
|
||||
}
|
||||
|
||||
foreach ($groups as $group) {
|
||||
$data = $event['data'];
|
||||
// Send matched subscription IDs
|
||||
$data['subscriptions'] = array_keys($matchedSubscriptions);
|
||||
$data['subscriptions'] = $group['subscriptions'];
|
||||
|
||||
$server->send([$connectionId], json_encode([
|
||||
$server->send($group['ids'], json_encode([
|
||||
'type' => 'event',
|
||||
'data' => $data
|
||||
]));
|
||||
|
|
@ -484,18 +489,18 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
|
|||
$roles = $user->getRoles($database->getAuthorization());
|
||||
$authorization = $realtime->connections[$connection]['authorization'] ?? null;
|
||||
|
||||
$subscriptionMetadata = $realtime->getSubscriptionMetadata($connection);
|
||||
$meta = $realtime->getSubscriptionMetadata($connection);
|
||||
|
||||
$realtime->unsubscribe($connection);
|
||||
|
||||
foreach ($subscriptionMetadata as $subscriptionId => $metadata) {
|
||||
$queries = Query::parseQueries($metadata['queries'] ?? []);
|
||||
foreach ($meta as $subscriptionId => $subscription) {
|
||||
$queries = Query::parseQueries($subscription['queries'] ?? []);
|
||||
$realtime->subscribe(
|
||||
$projectId,
|
||||
$connection,
|
||||
$subscriptionId,
|
||||
$roles,
|
||||
$metadata['channels'] ?? [],
|
||||
$subscription['channels'] ?? [],
|
||||
$queries
|
||||
);
|
||||
}
|
||||
|
|
@ -507,35 +512,38 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
|
|||
}
|
||||
}
|
||||
|
||||
$receivers = $realtime->getSubscribers($event); // [connectionId => [subId => queries]]
|
||||
$receivers = $realtime->getSubscribers($event);
|
||||
|
||||
if (Http::isDevelopment() && !empty($receivers)) {
|
||||
Console::log("[Debug][Worker {$workerId}] Receivers: " . count($receivers));
|
||||
Console::log("[Debug][Worker {$workerId}] Receivers Connection IDs: " . json_encode(array_keys($receivers)));
|
||||
Console::log("[Debug][Worker {$workerId}] Event Query: " . json_encode(array_values($receivers)));
|
||||
Console::log("[Debug][Worker {$workerId}] Connection IDs: " . json_encode(array_keys($receivers)));
|
||||
Console::log("[Debug][Worker {$workerId}] Matched: " . json_encode(array_values($receivers)));
|
||||
Console::log("[Debug][Worker {$workerId}] Event: " . $payload);
|
||||
}
|
||||
|
||||
$totalMessages = 0;
|
||||
|
||||
foreach ($receivers as $connectionId => $matchedSubscriptions) {
|
||||
$data = $event['data'];
|
||||
// Send matched subscription IDs
|
||||
$data['subscriptions'] = array_keys($matchedSubscriptions);
|
||||
|
||||
$server->send(
|
||||
[$connectionId],
|
||||
json_encode([
|
||||
'type' => 'event',
|
||||
'data' => $data
|
||||
])
|
||||
);
|
||||
$totalMessages++;
|
||||
// Group connections by matched subscription IDs for batch sending
|
||||
$groups = [];
|
||||
foreach ($receivers as $id => $matched) {
|
||||
$key = implode(',', array_keys($matched));
|
||||
$groups[$key]['ids'][] = $id;
|
||||
$groups[$key]['subscriptions'] = array_keys($matched);
|
||||
}
|
||||
|
||||
if ($totalMessages > 0) {
|
||||
$register->get('telemetry.messageSentCounter')->add($totalMessages);
|
||||
$stats->incr($event['project'], 'messages', $totalMessages);
|
||||
$total = 0;
|
||||
foreach ($groups as $group) {
|
||||
$data = $event['data'];
|
||||
$data['subscriptions'] = $group['subscriptions'];
|
||||
|
||||
$server->send($group['ids'], json_encode([
|
||||
'type' => 'event',
|
||||
'data' => $data
|
||||
]));
|
||||
$total += count($group['ids']);
|
||||
}
|
||||
|
||||
if ($total > 0) {
|
||||
$register->get('telemetry.messageSentCounter')->add($total);
|
||||
$stats->incr($event['project'], 'messages', $total);
|
||||
}
|
||||
});
|
||||
} catch (Throwable $th) {
|
||||
|
|
@ -624,21 +632,19 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
|||
throw new Exception(Exception::REALTIME_POLICY_VIOLATION, 'Missing channels');
|
||||
}
|
||||
|
||||
// Reconstruct subscriptions from query params using helper method
|
||||
$channelNames = array_keys($channels);
|
||||
$names = array_keys($channels);
|
||||
|
||||
try {
|
||||
$subscriptionsByIndex = Realtime::constructSubscriptions(
|
||||
$channelNames,
|
||||
$subscriptions = Realtime::constructSubscriptions(
|
||||
$names,
|
||||
fn ($channel) => $request->getQuery($channel, null)
|
||||
);
|
||||
} catch (QueryException $e) {
|
||||
throw new Exception(Exception::REALTIME_POLICY_VIOLATION, $e->getMessage());
|
||||
}
|
||||
|
||||
// Generate subscription IDs and subscribe
|
||||
$subscriptionMapping = [];
|
||||
foreach ($subscriptionsByIndex as $index => $subscription) {
|
||||
$mapping = [];
|
||||
foreach ($subscriptions as $index => $subscription) {
|
||||
$subscriptionId = ID::unique();
|
||||
|
||||
$realtime->subscribe(
|
||||
|
|
@ -647,10 +653,10 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
|||
$subscriptionId,
|
||||
$roles,
|
||||
$subscription['channels'],
|
||||
$subscription['queries'] // Query objects
|
||||
$subscription['queries']
|
||||
);
|
||||
|
||||
$subscriptionMapping[$index] = $subscriptionId;
|
||||
$mapping[$index] = $subscriptionId;
|
||||
}
|
||||
|
||||
$realtime->connections[$connection]['authorization'] = $authorization;
|
||||
|
|
@ -660,8 +666,8 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
|||
$server->send([$connection], json_encode([
|
||||
'type' => 'connected',
|
||||
'data' => [
|
||||
'channels' => $channelNames,
|
||||
'subscriptions' => $subscriptionMapping,
|
||||
'channels' => $names,
|
||||
'subscriptions' => $mapping,
|
||||
'user' => $user
|
||||
]
|
||||
]));
|
||||
|
|
@ -684,11 +690,11 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
|||
$code = 500;
|
||||
}
|
||||
|
||||
|
||||
$message = $th->getMessage();
|
||||
|
||||
// sanitize 0 && 5xx errors
|
||||
if (($code === 0 || $code >= 500) && !Http::isDevelopment()) {
|
||||
$realtimeViolation = $th instanceof AppwriteException && $th->getType() === AppwriteException::REALTIME_POLICY_VIOLATION;
|
||||
if (($code === 0 || $code >= 500) && !$realtimeViolation && !Http::isDevelopment()) {
|
||||
$message = 'Error: Server Error';
|
||||
}
|
||||
|
||||
|
|
@ -711,7 +717,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
|||
}
|
||||
});
|
||||
|
||||
$server->onMessage(function (int $connection, string $message) use ($server, $register, $realtime, $containerId) {
|
||||
$server->onMessage(function (int $connection, string $message) use ($server, $register, $realtime, $containerId, $logError) {
|
||||
try {
|
||||
$response = new Response(new SwooleResponse());
|
||||
$projectId = $realtime->connections[$connection]['projectId'] ?? null;
|
||||
|
|
@ -791,32 +797,29 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re
|
|||
}
|
||||
|
||||
$roles = $user->getRoles($database->getAuthorization());
|
||||
$channelNames = $realtime->connections[$connection]['channels'] ?? [];
|
||||
$channels = Realtime::convertChannels(array_flip($channelNames), $user->getId());
|
||||
|
||||
$authorization = $realtime->connections[$connection]['authorization'] ?? null;
|
||||
$projectId = $realtime->connections[$connection]['projectId'] ?? null;
|
||||
|
||||
$subscriptionMetadata = $realtime->getSubscriptionMetadata($connection);
|
||||
$meta = $realtime->getSubscriptionMetadata($connection);
|
||||
|
||||
$realtime->unsubscribe($connection);
|
||||
|
||||
if (!empty($projectId)) {
|
||||
foreach ($subscriptionMetadata as $subscriptionId => $metadata) {
|
||||
$queries = Query::parseQueries($metadata['queries'] ?? []);
|
||||
foreach ($meta as $subscriptionId => $subscription) {
|
||||
$queries = Query::parseQueries($subscription['queries'] ?? []);
|
||||
|
||||
$realtime->subscribe(
|
||||
$projectId,
|
||||
$connection,
|
||||
$subscriptionId,
|
||||
$roles,
|
||||
$metadata['channels'] ?? [],
|
||||
$subscription['channels'] ?? [],
|
||||
$queries
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Restore authorization after subscribe
|
||||
if ($authorization !== null) {
|
||||
$realtime->connections[$connection]['authorization'] = $authorization;
|
||||
}
|
||||
|
|
@ -837,6 +840,7 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re
|
|||
throw new Exception(Exception::REALTIME_MESSAGE_FORMAT_INVALID, 'Message type is not valid.');
|
||||
}
|
||||
} catch (Throwable $th) {
|
||||
$logError($th, "realtimeMessage");
|
||||
$code = $th->getCode();
|
||||
if (!is_int($code)) {
|
||||
$code = 500;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ $dbService = $this->getParam('database');
|
|||
$hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
||||
?>services:
|
||||
traefik:
|
||||
image: traefik:2.11
|
||||
image: traefik:3.6
|
||||
container_name: appwrite-traefik
|
||||
<<: *x-logging
|
||||
command:
|
||||
|
|
@ -75,8 +75,8 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- appwrite-sites:/storage/sites:rw
|
||||
- appwrite-builds:/storage/builds:rw
|
||||
depends_on:
|
||||
- <?= $dbService . "\n" ?>
|
||||
- redis
|
||||
- <?= $dbService . "\n" ?>
|
||||
# - clamav
|
||||
environment:
|
||||
- _APP_ENV
|
||||
|
|
@ -108,11 +108,13 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_SMTP_HOST
|
||||
- _APP_SMTP_PORT
|
||||
- _APP_SMTP_SECURE
|
||||
|
|
@ -186,7 +188,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
appwrite-console:
|
||||
<<: *x-logging
|
||||
container_name: appwrite-console
|
||||
image: <?php echo $organization; ?>/console:7.5.7
|
||||
image: <?php echo $organization; ?>/console:7.6.4
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
|
|
@ -228,8 +230,8 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
networks:
|
||||
- appwrite
|
||||
depends_on:
|
||||
- <?= $dbService . "\n" ?>
|
||||
- redis
|
||||
- <?= $dbService . "\n" ?>
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
|
|
@ -240,11 +242,13 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_USAGE_STATS
|
||||
- _APP_LOGGING_CONFIG
|
||||
|
||||
|
|
@ -267,11 +271,13 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_LOGGING_CONFIG
|
||||
|
||||
appwrite-worker-webhooks:
|
||||
|
|
@ -291,11 +297,13 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_EMAIL_SECURITY
|
||||
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
|
|
@ -328,11 +336,13 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_STORAGE_DEVICE
|
||||
- _APP_STORAGE_S3_ACCESS_KEY
|
||||
- _APP_STORAGE_S3_SECRET
|
||||
|
|
@ -384,11 +394,13 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_LOGGING_CONFIG
|
||||
|
||||
appwrite-worker-builds:
|
||||
|
|
@ -417,11 +429,13 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_VCS_GITHUB_APP_NAME
|
||||
- _APP_VCS_GITHUB_PRIVATE_KEY
|
||||
|
|
@ -489,11 +503,13 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_LOGGING_CONFIG
|
||||
|
||||
appwrite-worker-functions:
|
||||
|
|
@ -518,11 +534,13 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_FUNCTIONS_TIMEOUT
|
||||
- _APP_SITES_TIMEOUT
|
||||
- _APP_COMPUTE_BUILD_TIMEOUT
|
||||
|
|
@ -545,17 +563,20 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- appwrite
|
||||
depends_on:
|
||||
- redis
|
||||
- <?= $dbService . "\n" ?>
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_SYSTEM_EMAIL_NAME
|
||||
- _APP_SYSTEM_EMAIL_ADDRESS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
|
|
@ -581,6 +602,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- appwrite-uploads:/storage/uploads:rw
|
||||
depends_on:
|
||||
- redis
|
||||
- <?= $dbService . "\n" ?>
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
|
|
@ -589,11 +611,13 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_SMS_FROM
|
||||
- _APP_SMS_PROVIDER
|
||||
|
|
@ -647,11 +671,13 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
|
||||
|
|
@ -666,6 +692,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- appwrite
|
||||
depends_on:
|
||||
- redis
|
||||
- <?= $dbService . "\n" ?>
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
|
|
@ -681,11 +708,13 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_MAINTENANCE_INTERVAL
|
||||
- _APP_MAINTENANCE_RETENTION_EXECUTION
|
||||
- _APP_MAINTENANCE_RETENTION_CACHE
|
||||
|
|
@ -710,11 +739,13 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
|
|
@ -739,11 +770,13 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
|
|
@ -767,11 +800,13 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
|
|
@ -799,11 +834,13 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
|
||||
appwrite-task-scheduler-executions:
|
||||
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
|
||||
|
|
@ -824,11 +861,13 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
|
||||
appwrite-task-scheduler-messages:
|
||||
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
|
||||
|
|
@ -849,11 +888,13 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
|
||||
<?php if ($enableAssistant): ?>
|
||||
appwrite-assistant:
|
||||
|
|
@ -929,16 +970,13 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
|
||||
<?php if ($dbService === 'mariadb'): ?>
|
||||
mariadb:
|
||||
image: mariadb:10.11 # fix issues when upgrading using: mysql_upgrade -u root -p
|
||||
image: mariadb:10.11
|
||||
container_name: appwrite-mariadb
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- appwrite-mariadb:/var/lib/mysql:rw
|
||||
ports:
|
||||
- "3306:3306"
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=${_APP_DB_ROOT_PASS}
|
||||
- MYSQL_DATABASE=${_APP_DB_SCHEMA}
|
||||
|
|
@ -946,31 +984,100 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
|
|||
- MYSQL_PASSWORD=${_APP_DB_PASS}
|
||||
- MARIADB_AUTO_UPGRADE=1
|
||||
command: 'mysqld --innodb-flush-method=fsync'
|
||||
<?php else: ?>
|
||||
|
||||
<?php elseif ($dbService === 'mongodb'): ?>
|
||||
|
||||
mongodb:
|
||||
image: mongo:8.0.8
|
||||
image: mongo:8.2.5
|
||||
container_name: appwrite-mongodb
|
||||
<<: *x-logging
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- appwrite-mongodb:/data/db
|
||||
- appwrite-mongodb-keyfile:/data/keyfile
|
||||
ports:
|
||||
- "27017:27017"
|
||||
environment:
|
||||
- MONGO_INITDB_ROOT_USERNAME=root
|
||||
- MONGO_INITDB_ROOT_PASSWORD=${_APP_DB_ROOT_PASS}
|
||||
- MONGO_INITDB_DATABASE=${_APP_DB_SCHEMA}
|
||||
- MONGO_INITDB_USERNAME=${_APP_DB_USER}
|
||||
- MONGO_INITDB_PASSWORD=${_APP_DB_PASS}
|
||||
entrypoint:
|
||||
- /bin/bash
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
KEYFILE_PATH="/data/keyfile/mongo-keyfile"
|
||||
INIT_FLAG="/data/db/.mongodb_initialized"
|
||||
|
||||
# Generate keyfile if it doesn't exist
|
||||
if [ ! -f "$$KEYFILE_PATH" ]; then
|
||||
echo "Generating random MongoDB keyfile..."
|
||||
mkdir -p /data/keyfile
|
||||
openssl rand -base64 756 > "$$KEYFILE_PATH"
|
||||
fi
|
||||
chmod 400 "$$KEYFILE_PATH"
|
||||
chown mongodb:mongodb "$$KEYFILE_PATH" 2>/dev/null || chown 999:999 "$$KEYFILE_PATH"
|
||||
|
||||
# If not initialized, start without auth first to set up replica set and users
|
||||
if [ ! -f "$$INIT_FLAG" ]; then
|
||||
echo "First-time initialization: starting MongoDB without auth..."
|
||||
mongod --replSet rs0 --bind_ip_all --fork --logpath /var/log/mongodb/mongod.log --dbpath /data/db
|
||||
|
||||
echo "Waiting for MongoDB to start..."
|
||||
sleep 5
|
||||
|
||||
echo "Initializing replica set..."
|
||||
mongosh --eval "rs.initiate({_id: 'rs0', members: [{_id: 0, host: 'mongodb:27017'}]})"
|
||||
|
||||
echo "Waiting for replica set to initialize..."
|
||||
sleep 5
|
||||
|
||||
echo "Creating root user..."
|
||||
mongosh admin --eval "db.createUser({user: '$$MONGO_INITDB_ROOT_USERNAME', pwd: '$$MONGO_INITDB_ROOT_PASSWORD', roles: ['root']})"
|
||||
|
||||
echo "Creating application user..."
|
||||
mongosh admin --eval "db.createUser({user: '$$MONGO_INITDB_USERNAME', pwd: '$$MONGO_INITDB_PASSWORD', roles: [{role: 'readWrite', db: '$$MONGO_INITDB_DATABASE'}]})"
|
||||
|
||||
echo "Shutting down MongoDB..."
|
||||
mongod --dbpath /data/db --shutdown
|
||||
|
||||
touch "$$INIT_FLAG"
|
||||
echo "Initialization complete."
|
||||
fi
|
||||
|
||||
echo "Starting MongoDB with authentication..."
|
||||
exec mongod --replSet rs0 --bind_ip_all --auth --keyFile "$$KEYFILE_PATH"
|
||||
healthcheck:
|
||||
test: |
|
||||
mongosh -u root -p "$$MONGO_INITDB_ROOT_PASSWORD" --authenticationDatabase admin --quiet --eval "rs.status().ok" | grep -q 1
|
||||
interval: 10s
|
||||
timeout: 10s
|
||||
retries: 10
|
||||
start_period: 60s
|
||||
|
||||
<?php elseif ($dbService === 'postgresql'): ?>
|
||||
|
||||
postgresql:
|
||||
image: postgres:18
|
||||
container_name: appwrite-postgresql
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- appwrite-mongodb:/data/db:rw
|
||||
- appwrite-mongodb-config:/data/configdb:rw
|
||||
<?php if ($version === 'local' && !empty($hostPath)): ?>
|
||||
- <?php echo $hostPath; ?>/mongo-entrypoint.sh:/mongo-entrypoint.sh:ro
|
||||
<?php else: ?>
|
||||
- ./mongo-entrypoint.sh:/mongo-entrypoint.sh:ro
|
||||
<?php endif; ?>
|
||||
ports:
|
||||
- "27017:27017"
|
||||
- appwrite-postgresql:/var/lib/postgresql/data:rw
|
||||
environment:
|
||||
- MONGO_INITDB_DATABASE=${_APP_DB_SCHEMA}
|
||||
entrypoint: ["/bin/bash", "/mongo-entrypoint.sh"]
|
||||
- POSTGRES_DB=${_APP_DB_SCHEMA}
|
||||
- POSTGRES_USER=${_APP_DB_USER}
|
||||
- POSTGRES_PASSWORD=${_APP_DB_PASS}
|
||||
command: "postgres"
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
redis:
|
||||
image: redis:7.2.4-alpine
|
||||
image: redis:7.4.7-alpine
|
||||
container_name: appwrite-redis
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
|
|
@ -1004,8 +1111,11 @@ networks:
|
|||
volumes:
|
||||
<?php if ($dbService === 'mariadb'): ?>
|
||||
appwrite-mariadb:
|
||||
<?php else: ?>
|
||||
<?php elseif ($dbService === 'postgresql'): ?>
|
||||
appwrite-postgresql:
|
||||
<?php elseif ($dbService === 'mongodb'): ?>
|
||||
appwrite-mongodb:
|
||||
appwrite-mongodb-keyfile:
|
||||
appwrite-mongodb-config:
|
||||
<?php endif; ?>
|
||||
appwrite-redis:
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use Appwrite\Event\Certificate;
|
|||
use Appwrite\Event\Database as EventDatabase;
|
||||
use Appwrite\Event\Delete;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Event\Execution;
|
||||
use Appwrite\Event\Func;
|
||||
use Appwrite\Event\Mail;
|
||||
use Appwrite\Event\Messaging;
|
||||
|
|
@ -27,8 +28,8 @@ use Utopia\Audit\Audit as UtopiaAudit;
|
|||
use Utopia\Cache\Adapter\Pool as CachePool;
|
||||
use Utopia\Cache\Adapter\Sharding;
|
||||
use Utopia\Cache\Cache;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Console;
|
||||
use Utopia\Database\Adapter\Pool as DatabasePool;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
|
|
@ -358,6 +359,10 @@ Server::setResource('queueForFunctions', function (Publisher $publisher) {
|
|||
return new Func($publisher);
|
||||
}, ['publisher']);
|
||||
|
||||
Server::setResource('queueForExecutions', function (Publisher $publisher) {
|
||||
return new Execution($publisher);
|
||||
}, ['publisher']);
|
||||
|
||||
Server::setResource('queueForRealtime', function () {
|
||||
return new Realtime();
|
||||
}, []);
|
||||
|
|
|
|||
3
bin/worker-executions
Executable file
3
bin/worker-executions
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
exec php /usr/src/code/app/worker.php executions "$@"
|
||||
|
|
@ -32,6 +32,8 @@
|
|||
"Appwrite\\Tests\\": "tests/extensions"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"require": {
|
||||
"php": ">=8.3.0",
|
||||
"ext-curl": "*",
|
||||
|
|
@ -49,12 +51,13 @@
|
|||
"appwrite/php-runtimes": "0.19.*",
|
||||
"appwrite/php-clamav": "2.0.*",
|
||||
"utopia-php/abuse": "1.2.*",
|
||||
"utopia-php/analytics": "0.10.*",
|
||||
"utopia-php/analytics": "0.15.*",
|
||||
"utopia-php/audit": "2.2.*",
|
||||
"utopia-php/auth": "0.5.*",
|
||||
"utopia-php/cache": "1.0.*",
|
||||
"utopia-php/cli": "0.15.*",
|
||||
"utopia-php/cli": "0.22.*",
|
||||
"utopia-php/config": "1.*",
|
||||
"utopia-php/console": "0.1.*",
|
||||
"utopia-php/database": "5.*",
|
||||
"utopia-php/detector": "0.2.*",
|
||||
"utopia-php/domains": "1.*",
|
||||
|
|
@ -68,26 +71,24 @@
|
|||
"utopia-php/logger": "0.6.*",
|
||||
"utopia-php/messaging": "0.20.*",
|
||||
"utopia-php/migration": "1.5.*",
|
||||
"utopia-php/orchestration": "0.9.*",
|
||||
"utopia-php/platform": "0.7.*",
|
||||
"utopia-php/pools": "1.*",
|
||||
"utopia-php/preloader": "0.2.*",
|
||||
"utopia-php/queue": "0.15.*",
|
||||
"utopia-php/registry": "0.5.*",
|
||||
"utopia-php/storage": "0.18.*",
|
||||
"utopia-php/swoole": "1.*",
|
||||
"utopia-php/system": "0.9.*",
|
||||
"utopia-php/system": "0.10.*",
|
||||
"utopia-php/telemetry": "0.2.*",
|
||||
"utopia-php/vcs": "1.*",
|
||||
"utopia-php/websocket": "0.3.*",
|
||||
"utopia-php/websocket": "1.0.*",
|
||||
"matomo/device-detector": "6.4.*",
|
||||
"dragonmantank/cron-expression": "3.4.*",
|
||||
"phpmailer/phpmailer": "6.9.*",
|
||||
"chillerlan/php-qrcode": "4.4.*",
|
||||
"chillerlan/php-qrcode": "4.3.*",
|
||||
"adhocore/jwt": "1.1.*",
|
||||
"spomky-labs/otphp": "10.0.*",
|
||||
"spomky-labs/otphp": "11.*",
|
||||
"webonyx/graphql-php": "14.11.*",
|
||||
"league/csv": "9.24.*",
|
||||
"league/csv": "9.14.*",
|
||||
"enshrined/svg-sanitize": "0.22.*"
|
||||
},
|
||||
"require-dev": {
|
||||
|
|
@ -96,7 +97,7 @@
|
|||
"brianium/paratest": "7.*",
|
||||
"phpunit/phpunit": "12.*",
|
||||
"swoole/ide-helper": "6.*",
|
||||
"phpstan/phpstan": "1.8.*",
|
||||
"phpstan/phpstan": "1.12.*",
|
||||
"textalk/websocket": "1.5.*",
|
||||
"laravel/pint": "1.*",
|
||||
"phpbench/phpbench": "1.*"
|
||||
|
|
|
|||
883
composer.lock
generated
883
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -12,7 +12,7 @@ x-logging: &x-logging
|
|||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:2.11
|
||||
image: traefik:3.6
|
||||
<<: *x-logging
|
||||
container_name: appwrite-traefik
|
||||
command:
|
||||
|
|
@ -64,6 +64,7 @@ services:
|
|||
networks:
|
||||
- appwrite
|
||||
dns:
|
||||
- 127.0.0.11
|
||||
- 172.16.238.100
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
|
|
@ -98,9 +99,9 @@ services:
|
|||
- ./public:/usr/src/code/public
|
||||
- ./src:/usr/src/code/src
|
||||
- ./dev:/usr/src/code/dev
|
||||
# - ./vendor/utopia-php/framework:/usr/src/code/vendor/utopia-php/framework
|
||||
|
||||
depends_on:
|
||||
- mariadb
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
- redis
|
||||
- coredns
|
||||
# - clamav
|
||||
|
|
@ -133,6 +134,7 @@ services:
|
|||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_CONSOLE_DOMAIN
|
||||
- _APP_CONSOLE_TRUSTED_PROJECTS
|
||||
- _APP_DOMAIN_TARGET_CNAME
|
||||
- _APP_DOMAIN_TARGET_AAAA
|
||||
- _APP_DOMAIN_TARGET_A
|
||||
|
|
@ -143,11 +145,13 @@ services:
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_SMTP_HOST
|
||||
- _APP_SMTP_PORT
|
||||
- _APP_SMTP_SECURE
|
||||
|
|
@ -228,6 +232,7 @@ services:
|
|||
- _APP_FUNCTIONS_CREATION_ABUSE_LIMIT
|
||||
- _APP_CUSTOM_DOMAIN_DENY_LIST
|
||||
- _APP_TRUSTED_HEADERS
|
||||
- _APP_MIGRATION_HOST
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
|
||||
|
|
@ -281,7 +286,7 @@ services:
|
|||
- ./app:/usr/src/code/app
|
||||
- ./src:/usr/src/code/src
|
||||
depends_on:
|
||||
- mariadb
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
- redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
|
|
@ -293,11 +298,13 @@ services:
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_USAGE_STATS
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_LOGGING_CONFIG_REALTIME
|
||||
|
|
@ -316,7 +323,7 @@ services:
|
|||
- ./src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
|
|
@ -326,11 +333,13 @@ services:
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
|
||||
|
|
@ -346,7 +355,7 @@ services:
|
|||
- ./src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
- request-catcher-sms
|
||||
- request-catcher-webhook
|
||||
environment:
|
||||
|
|
@ -355,11 +364,13 @@ services:
|
|||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_EMAIL_SECURITY
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
|
|
@ -377,7 +388,7 @@ services:
|
|||
- appwrite
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
volumes:
|
||||
- appwrite-uploads:/storage/uploads:rw
|
||||
- appwrite-cache:/storage/cache:rw
|
||||
|
|
@ -396,11 +407,13 @@ services:
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_STORAGE_DEVICE
|
||||
- _APP_STORAGE_S3_ACCESS_KEY
|
||||
- _APP_STORAGE_S3_SECRET
|
||||
|
|
@ -444,7 +457,7 @@ services:
|
|||
- ./src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
|
|
@ -454,11 +467,13 @@ services:
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_WORKERS_NUM
|
||||
- _APP_QUEUE_NAME
|
||||
|
|
@ -479,7 +494,7 @@ services:
|
|||
- ./src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
|
|
@ -491,11 +506,13 @@ services:
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_VCS_GITHUB_APP_NAME
|
||||
- _APP_VCS_GITHUB_PRIVATE_KEY
|
||||
|
|
@ -510,6 +527,7 @@ services:
|
|||
- _APP_OPTIONS_ROUTER_FORCE_HTTPS
|
||||
- _APP_DOMAIN
|
||||
- _APP_CONSOLE_DOMAIN
|
||||
- _APP_CONSOLE_TRUSTED_PROJECTS
|
||||
- _APP_STORAGE_DEVICE
|
||||
- _APP_STORAGE_S3_ACCESS_KEY
|
||||
- _APP_STORAGE_S3_SECRET
|
||||
|
|
@ -550,7 +568,7 @@ services:
|
|||
- ./src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
environment:
|
||||
# Specific
|
||||
- _APP_BROWSER_HOST
|
||||
|
|
@ -565,6 +583,7 @@ services:
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
|
|
@ -606,7 +625,7 @@ services:
|
|||
- appwrite
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
volumes:
|
||||
- appwrite-config:/storage/config:rw
|
||||
- appwrite-certificates:/storage/certificates:rw
|
||||
|
|
@ -630,6 +649,38 @@ services:
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
|
||||
appwrite-worker-executions:
|
||||
entrypoint: worker-executions
|
||||
<<: *x-logging
|
||||
container_name: appwrite-worker-executions
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- ./app:/usr/src/code/app
|
||||
- ./src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
|
|
@ -649,12 +700,8 @@ services:
|
|||
- ./app:/usr/src/code/app
|
||||
- ./src:/usr/src/code/src
|
||||
depends_on:
|
||||
redis:
|
||||
condition: service_started
|
||||
mariadb:
|
||||
condition: service_started
|
||||
openruntimes-executor:
|
||||
condition: service_healthy
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
- redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
|
|
@ -666,11 +713,13 @@ services:
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_FUNCTIONS_TIMEOUT
|
||||
- _APP_SITES_TIMEOUT
|
||||
- _APP_COMPUTE_BUILD_TIMEOUT
|
||||
|
|
@ -743,11 +792,13 @@ services:
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_SMS_FROM
|
||||
- _APP_SMS_PROVIDER
|
||||
|
|
@ -791,7 +842,7 @@ services:
|
|||
- ./src:/usr/src/code/src
|
||||
- ./tests:/usr/src/code/tests
|
||||
depends_on:
|
||||
- mariadb
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
|
|
@ -808,16 +859,19 @@ services:
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
- _APP_OPTIONS_FORCE_HTTPS
|
||||
- _APP_MIGRATION_HOST
|
||||
|
||||
appwrite-task-maintenance:
|
||||
entrypoint: maintenance
|
||||
|
|
@ -830,7 +884,7 @@ services:
|
|||
- ./app:/usr/src/code/app
|
||||
- ./src:/usr/src/code/src
|
||||
depends_on:
|
||||
- mariadb
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
- redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
|
|
@ -848,11 +902,13 @@ services:
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_MAINTENANCE_INTERVAL
|
||||
- _APP_MAINTENANCE_RETENTION_EXECUTION
|
||||
- _APP_MAINTENANCE_RETENTION_CACHE
|
||||
|
|
@ -875,7 +931,7 @@ services:
|
|||
- ./app:/usr/src/code/app
|
||||
- ./src:/usr/src/code/src
|
||||
depends_on:
|
||||
- mariadb
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
- redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
|
|
@ -894,6 +950,7 @@ services:
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
|
|
@ -915,17 +972,19 @@ services:
|
|||
- ./src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
|
|
@ -947,17 +1006,19 @@ services:
|
|||
- ./src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
|
|
@ -979,17 +1040,19 @@ services:
|
|||
- ./src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_POOL_ADAPTER
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
|
|
@ -1010,7 +1073,7 @@ services:
|
|||
- ./app:/usr/src/code/app
|
||||
- ./src:/usr/src/code/src
|
||||
depends_on:
|
||||
- mariadb
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
- redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
|
|
@ -1021,11 +1084,13 @@ services:
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
|
||||
appwrite-task-scheduler-executions:
|
||||
|
|
@ -1039,7 +1104,7 @@ services:
|
|||
- ./app:/usr/src/code/app
|
||||
- ./src:/usr/src/code/src
|
||||
depends_on:
|
||||
- mariadb
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
- redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
|
|
@ -1050,11 +1115,13 @@ services:
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
|
||||
appwrite-task-scheduler-messages:
|
||||
entrypoint: schedule-messages
|
||||
|
|
@ -1067,7 +1134,7 @@ services:
|
|||
- ./app:/usr/src/code/app
|
||||
- ./src:/usr/src/code/src
|
||||
depends_on:
|
||||
- mariadb
|
||||
- ${_APP_DB_HOST:-mongodb}
|
||||
- redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
|
|
@ -1078,11 +1145,13 @@ services:
|
|||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DB_ADAPTER
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
|
||||
appwrite-assistant:
|
||||
|
|
@ -1159,6 +1228,7 @@ services:
|
|||
start_period: 5s
|
||||
|
||||
mariadb:
|
||||
profiles: ["mariadb"]
|
||||
image: mariadb:10.11 # fix issues when upgrading using: mysql_upgrade -u root -p
|
||||
container_name: appwrite-mariadb
|
||||
<<: *x-logging
|
||||
|
|
@ -1176,8 +1246,80 @@ services:
|
|||
- MARIADB_AUTO_UPGRADE=1
|
||||
command: "mysqld --innodb-flush-method=fsync"
|
||||
|
||||
mongodb:
|
||||
profiles: ["mongodb"]
|
||||
image: mongo:8.2.5
|
||||
container_name: appwrite-mongodb
|
||||
<<: *x-logging
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- appwrite-mongodb:/data/db
|
||||
- appwrite-mongodb-keyfile:/data/keyfile
|
||||
- ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
|
||||
- ./mongo-entrypoint.sh:/mongo-entrypoint.sh:ro
|
||||
ports:
|
||||
- "27017:27017"
|
||||
environment:
|
||||
- MONGO_INITDB_ROOT_USERNAME=root
|
||||
- MONGO_INITDB_ROOT_PASSWORD=${_APP_DB_ROOT_PASS}
|
||||
- MONGO_INITDB_DATABASE=${_APP_DB_SCHEMA}
|
||||
- MONGO_INITDB_USERNAME=${_APP_DB_USER}
|
||||
- MONGO_INITDB_PASSWORD=${_APP_DB_PASS}
|
||||
entrypoint: ["/bin/bash", "/mongo-entrypoint.sh"]
|
||||
healthcheck:
|
||||
test: |
|
||||
bash -c "
|
||||
if mongosh -u root -p ${_APP_DB_ROOT_PASS} --authenticationDatabase admin --quiet --eval 'rs.status().ok' 2>/dev/null | grep -q 1; then
|
||||
exit 0
|
||||
else
|
||||
mongosh -u root -p ${_APP_DB_ROOT_PASS} --authenticationDatabase admin --quiet --eval \"
|
||||
rs.initiate({_id: 'rs0', members: [{_id: 0, host: 'appwrite-mongodb:27017'}]})
|
||||
\" 2>/dev/null || exit 1
|
||||
fi
|
||||
"
|
||||
interval: 10s
|
||||
timeout: 10s
|
||||
retries: 10
|
||||
start_period: 30s
|
||||
|
||||
appwrite-mongo-express:
|
||||
profiles: ["mongodb"]
|
||||
image: mongo-express
|
||||
container_name: appwrite-mongo-express
|
||||
networks:
|
||||
- appwrite
|
||||
ports:
|
||||
- "8082:8081"
|
||||
environment:
|
||||
ME_CONFIG_MONGODB_URL: "mongodb://root:${_APP_DB_ROOT_PASS}@appwrite-mongodb:27017/?replicaSet=rs0&directConnection=true"
|
||||
ME_CONFIG_BASICAUTH_USERNAME: ${_APP_DB_USER}
|
||||
ME_CONFIG_BASICAUTH_PASSWORD: ${_APP_DB_PASS}
|
||||
depends_on:
|
||||
- mongodb
|
||||
|
||||
postgresql:
|
||||
profiles: ["postgresql"]
|
||||
build:
|
||||
context: ./tests/resources/postgresql
|
||||
args:
|
||||
POSTGRES_VERSION: 17
|
||||
container_name: appwrite-postgresql
|
||||
<<: *x-logging
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- appwrite-postgresql:/var/lib/postgresql/data:rw
|
||||
ports:
|
||||
- "5432:5432"
|
||||
environment:
|
||||
- POSTGRES_DB=${_APP_DB_SCHEMA}
|
||||
- POSTGRES_USER=${_APP_DB_USER}
|
||||
- POSTGRES_PASSWORD=${_APP_DB_PASS}
|
||||
command: "postgres"
|
||||
|
||||
redis:
|
||||
image: redis:7.2.4-alpine
|
||||
image: redis:7.4.7-alpine
|
||||
<<: *x-logging
|
||||
container_name: appwrite-redis
|
||||
command: >
|
||||
|
|
@ -1403,6 +1545,9 @@ configs:
|
|||
|
||||
volumes:
|
||||
appwrite-mariadb:
|
||||
appwrite-mongodb:
|
||||
appwrite-mongodb-keyfile:
|
||||
appwrite-postgresql:
|
||||
appwrite-redis:
|
||||
appwrite-cache:
|
||||
appwrite-uploads:
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Teams;
|
||||
import io.appwrite.enums.Roles;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
|
|
@ -12,7 +11,7 @@ Teams teams = new Teams(client);
|
|||
|
||||
teams.createMembership(
|
||||
"<TEAM_ID>", // teamId
|
||||
Roles.ADMIN, // roles
|
||||
List.of(), // roles
|
||||
"email@example.com", // email (optional)
|
||||
"<USER_ID>", // userId (optional)
|
||||
"+12065550100", // phone (optional)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Teams;
|
||||
import io.appwrite.enums.Roles;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
|
|
@ -13,7 +12,7 @@ Teams teams = new Teams(client);
|
|||
teams.updateMembership(
|
||||
"<TEAM_ID>", // teamId
|
||||
"<MEMBERSHIP_ID>", // membershipId
|
||||
Roles.ADMIN, // roles
|
||||
List.of(), // roles
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
import io.appwrite.Client
|
||||
import io.appwrite.coroutines.CoroutineCallback
|
||||
import io.appwrite.services.Teams
|
||||
import io.appwrite.enums.Roles
|
||||
|
||||
val client = Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
|
|
@ -12,7 +11,7 @@ val teams = Teams(client)
|
|||
|
||||
val result = teams.createMembership(
|
||||
teamId = "<TEAM_ID>",
|
||||
roles = roles.ADMIN,
|
||||
roles = listOf(),
|
||||
email = "email@example.com", // (optional)
|
||||
userId = "<USER_ID>", // (optional)
|
||||
phone = "+12065550100", // (optional)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
import io.appwrite.Client
|
||||
import io.appwrite.coroutines.CoroutineCallback
|
||||
import io.appwrite.services.Teams
|
||||
import io.appwrite.enums.Roles
|
||||
|
||||
val client = Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
|
|
@ -13,5 +12,5 @@ val teams = Teams(client)
|
|||
val result = teams.updateMembership(
|
||||
teamId = "<TEAM_ID>",
|
||||
membershipId = "<MEMBERSHIP_ID>",
|
||||
roles = roles.ADMIN,
|
||||
roles = listOf(),
|
||||
)```
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
```swift
|
||||
import Appwrite
|
||||
import AppwriteEnums
|
||||
|
||||
let client = Client()
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
|
|
@ -10,7 +9,7 @@ let teams = Teams(client)
|
|||
|
||||
let membership = try await teams.createMembership(
|
||||
teamId: "<TEAM_ID>",
|
||||
roles: [.admin],
|
||||
roles: [],
|
||||
email: "email@example.com", // optional
|
||||
userId: "<USER_ID>", // optional
|
||||
phone: "+12065550100", // optional
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
```swift
|
||||
import Appwrite
|
||||
import AppwriteEnums
|
||||
|
||||
let client = Client()
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
|
|
@ -11,7 +10,7 @@ let teams = Teams(client)
|
|||
let membership = try await teams.updateMembership(
|
||||
teamId: "<TEAM_ID>",
|
||||
membershipId: "<MEMBERSHIP_ID>",
|
||||
roles: [.admin]
|
||||
roles: []
|
||||
)
|
||||
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
```dart
|
||||
import 'package:appwrite/appwrite.dart';
|
||||
import 'package:appwrite/enums.dart' as enums;
|
||||
|
||||
Client client = Client()
|
||||
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
|
@ -10,7 +9,7 @@ Teams teams = Teams(client);
|
|||
|
||||
Membership result = await teams.createMembership(
|
||||
teamId: '<TEAM_ID>',
|
||||
roles: [enums.Roles.admin],
|
||||
roles: [],
|
||||
email: 'email@example.com', // optional
|
||||
userId: '<USER_ID>', // optional
|
||||
phone: '+12065550100', // optional
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
```dart
|
||||
import 'package:appwrite/appwrite.dart';
|
||||
import 'package:appwrite/enums.dart' as enums;
|
||||
|
||||
Client client = Client()
|
||||
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
|
@ -11,6 +10,6 @@ Teams teams = Teams(client);
|
|||
Membership result = await teams.updateMembership(
|
||||
teamId: '<TEAM_ID>',
|
||||
membershipId: '<MEMBERSHIP_ID>',
|
||||
roles: [enums.Roles.admin],
|
||||
roles: [],
|
||||
);
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
```javascript
|
||||
import { Client, Teams, Roles } from "react-native-appwrite";
|
||||
import { Client, Teams } from "react-native-appwrite";
|
||||
|
||||
const client = new Client()
|
||||
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
|
@ -9,7 +9,7 @@ const teams = new Teams(client);
|
|||
|
||||
const result = await teams.createMembership({
|
||||
teamId: '<TEAM_ID>',
|
||||
roles: [Roles.Admin],
|
||||
roles: [],
|
||||
email: 'email@example.com', // optional
|
||||
userId: '<USER_ID>', // optional
|
||||
phone: '+12065550100', // optional
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
```javascript
|
||||
import { Client, Teams, Roles } from "react-native-appwrite";
|
||||
import { Client, Teams } from "react-native-appwrite";
|
||||
|
||||
const client = new Client()
|
||||
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
|
@ -10,7 +10,7 @@ const teams = new Teams(client);
|
|||
const result = await teams.updateMembership({
|
||||
teamId: '<TEAM_ID>',
|
||||
membershipId: '<MEMBERSHIP_ID>',
|
||||
roles: [Roles.Admin]
|
||||
roles: []
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
```javascript
|
||||
import { Client, Teams, Roles } from "appwrite";
|
||||
import { Client, Teams } from "appwrite";
|
||||
|
||||
const client = new Client()
|
||||
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
|
@ -9,7 +9,7 @@ const teams = new Teams(client);
|
|||
|
||||
const result = await teams.createMembership({
|
||||
teamId: '<TEAM_ID>',
|
||||
roles: [Roles.Admin],
|
||||
roles: [],
|
||||
email: 'email@example.com', // optional
|
||||
userId: '<USER_ID>', // optional
|
||||
phone: '+12065550100', // optional
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
```javascript
|
||||
import { Client, Teams, Roles } from "appwrite";
|
||||
import { Client, Teams } from "appwrite";
|
||||
|
||||
const client = new Client()
|
||||
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
|
@ -10,7 +10,7 @@ const teams = new Teams(client);
|
|||
const result = await teams.updateMembership({
|
||||
teamId: '<TEAM_ID>',
|
||||
membershipId: '<MEMBERSHIP_ID>',
|
||||
roles: [Roles.Admin]
|
||||
roles: []
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ const result = await projects.createKey({
|
|||
projectId: '<PROJECT_ID>',
|
||||
name: '<NAME>',
|
||||
scopes: [Scopes.SessionsWrite],
|
||||
keyId: '<KEY_ID>', // optional
|
||||
expire: '' // optional
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ const projects = new Projects(client);
|
|||
|
||||
const result = await projects.listKeys({
|
||||
projectId: '<PROJECT_ID>',
|
||||
queries: [], // optional
|
||||
total: false // optional
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
```javascript
|
||||
import { Client, Teams, Roles } from "@appwrite.io/console";
|
||||
import { Client, Teams } from "@appwrite.io/console";
|
||||
|
||||
const client = new Client()
|
||||
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
|
@ -9,7 +9,7 @@ const teams = new Teams(client);
|
|||
|
||||
const result = await teams.createMembership({
|
||||
teamId: '<TEAM_ID>',
|
||||
roles: [Roles.Admin],
|
||||
roles: [],
|
||||
email: 'email@example.com', // optional
|
||||
userId: '<USER_ID>', // optional
|
||||
phone: '+12065550100', // optional
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
```javascript
|
||||
import { Client, Teams, Roles } from "@appwrite.io/console";
|
||||
import { Client, Teams } from "@appwrite.io/console";
|
||||
|
||||
const client = new Client()
|
||||
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
|
@ -10,7 +10,7 @@ const teams = new Teams(client);
|
|||
const result = await teams.updateMembership({
|
||||
teamId: '<TEAM_ID>',
|
||||
membershipId: '<MEMBERSHIP_ID>',
|
||||
roles: [Roles.Admin]
|
||||
roles: []
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
```dart
|
||||
import 'package:dart_appwrite/dart_appwrite.dart';
|
||||
import 'package:dart_appwrite/enums.dart' as enums;
|
||||
|
||||
Client client = Client()
|
||||
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
|
@ -11,7 +10,7 @@ Teams teams = Teams(client);
|
|||
|
||||
Membership result = await teams.createMembership(
|
||||
teamId: '<TEAM_ID>',
|
||||
roles: [enums.Roles.admin],
|
||||
roles: [],
|
||||
email: 'email@example.com', // (optional)
|
||||
userId: '<USER_ID>', // (optional)
|
||||
phone: '+12065550100', // (optional)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
```dart
|
||||
import 'package:dart_appwrite/dart_appwrite.dart';
|
||||
import 'package:dart_appwrite/enums.dart' as enums;
|
||||
|
||||
Client client = Client()
|
||||
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
|
@ -12,6 +11,6 @@ Teams teams = Teams(client);
|
|||
Membership result = await teams.updateMembership(
|
||||
teamId: '<TEAM_ID>',
|
||||
membershipId: '<MEMBERSHIP_ID>',
|
||||
roles: [enums.Roles.admin],
|
||||
roles: [],
|
||||
);
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
```csharp
|
||||
using Appwrite;
|
||||
using Appwrite.Enums;
|
||||
using Appwrite.Models;
|
||||
using Appwrite.Services;
|
||||
|
||||
|
|
@ -13,7 +12,7 @@ Teams teams = new Teams(client);
|
|||
|
||||
Membership result = await teams.CreateMembership(
|
||||
teamId: "<TEAM_ID>",
|
||||
roles: new List<Roles> { Roles.Admin },
|
||||
roles: new List<string>(),
|
||||
email: "email@example.com", // optional
|
||||
userId: "<USER_ID>", // optional
|
||||
phone: "+12065550100", // optional
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
```csharp
|
||||
using Appwrite;
|
||||
using Appwrite.Enums;
|
||||
using Appwrite.Models;
|
||||
using Appwrite.Services;
|
||||
|
||||
|
|
@ -14,5 +13,5 @@ Teams teams = new Teams(client);
|
|||
Membership result = await teams.UpdateMembership(
|
||||
teamId: "<TEAM_ID>",
|
||||
membershipId: "<MEMBERSHIP_ID>",
|
||||
roles: new List<Roles> { Roles.Admin }
|
||||
roles: new List<string>()
|
||||
);```
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ mutation {
|
|||
lengths
|
||||
orders
|
||||
}
|
||||
bytesMax
|
||||
bytesUsed
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ mutation {
|
|||
lengths
|
||||
orders
|
||||
}
|
||||
bytesMax
|
||||
bytesUsed
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ mutation {
|
|||
lengths
|
||||
orders
|
||||
}
|
||||
bytesMax
|
||||
bytesUsed
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ mutation {
|
|||
lengths
|
||||
orders
|
||||
}
|
||||
bytesMax
|
||||
bytesUsed
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Teams;
|
||||
import io.appwrite.enums.Roles;
|
||||
|
||||
Client client = new Client()
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
|
|
@ -13,7 +12,7 @@ Teams teams = new Teams(client);
|
|||
|
||||
teams.createMembership(
|
||||
"<TEAM_ID>", // teamId
|
||||
List.of(Roles.ADMIN), // roles
|
||||
List.of(), // roles
|
||||
"email@example.com", // email (optional)
|
||||
"<USER_ID>", // userId (optional)
|
||||
"+12065550100", // phone (optional)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Teams;
|
||||
import io.appwrite.enums.Roles;
|
||||
|
||||
Client client = new Client()
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
|
|
@ -14,7 +13,7 @@ Teams teams = new Teams(client);
|
|||
teams.updateMembership(
|
||||
"<TEAM_ID>", // teamId
|
||||
"<MEMBERSHIP_ID>", // membershipId
|
||||
List.of(Roles.ADMIN), // roles
|
||||
List.of(), // roles
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
import io.appwrite.Client
|
||||
import io.appwrite.coroutines.CoroutineCallback
|
||||
import io.appwrite.services.Teams
|
||||
import io.appwrite.enums.Roles
|
||||
|
||||
val client = Client()
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
|
|
@ -13,7 +12,7 @@ val teams = Teams(client)
|
|||
|
||||
val response = teams.createMembership(
|
||||
teamId = "<TEAM_ID>",
|
||||
roles = listOf(Roles.ADMIN),
|
||||
roles = listOf(),
|
||||
email = "email@example.com", // optional
|
||||
userId = "<USER_ID>", // optional
|
||||
phone = "+12065550100", // optional
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
import io.appwrite.Client
|
||||
import io.appwrite.coroutines.CoroutineCallback
|
||||
import io.appwrite.services.Teams
|
||||
import io.appwrite.enums.Roles
|
||||
|
||||
val client = Client()
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
|
|
@ -14,6 +13,6 @@ val teams = Teams(client)
|
|||
val response = teams.updateMembership(
|
||||
teamId = "<TEAM_ID>",
|
||||
membershipId = "<MEMBERSHIP_ID>",
|
||||
roles = listOf(Roles.ADMIN)
|
||||
roles = listOf()
|
||||
)
|
||||
```
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const teams = new sdk.Teams(client);
|
|||
|
||||
const result = await teams.createMembership({
|
||||
teamId: '<TEAM_ID>',
|
||||
roles: [sdk.Roles.Admin],
|
||||
roles: [],
|
||||
email: 'email@example.com', // optional
|
||||
userId: '<USER_ID>', // optional
|
||||
phone: '+12065550100', // optional
|
||||
|
|
|
|||
|
|
@ -11,6 +11,6 @@ const teams = new sdk.Teams(client);
|
|||
const result = await teams.updateMembership({
|
||||
teamId: '<TEAM_ID>',
|
||||
membershipId: '<MEMBERSHIP_ID>',
|
||||
roles: [sdk.Roles.Admin]
|
||||
roles: []
|
||||
});
|
||||
```
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Teams;
|
||||
use Appwrite\Enums\Roles;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
|
@ -14,7 +13,7 @@ $teams = new Teams($client);
|
|||
|
||||
$result = $teams->createMembership(
|
||||
teamId: '<TEAM_ID>',
|
||||
roles: [Roles::ADMIN()],
|
||||
roles: [],
|
||||
email: 'email@example.com', // optional
|
||||
userId: '<USER_ID>', // optional
|
||||
phone: '+12065550100', // optional
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Teams;
|
||||
use Appwrite\Enums\Roles;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
|
@ -15,5 +14,5 @@ $teams = new Teams($client);
|
|||
$result = $teams->updateMembership(
|
||||
teamId: '<TEAM_ID>',
|
||||
membershipId: '<MEMBERSHIP_ID>',
|
||||
roles: [Roles::ADMIN()]
|
||||
roles: []
|
||||
);```
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
```python
|
||||
from appwrite.client import Client
|
||||
from appwrite.services.teams import Teams
|
||||
from appwrite.enums import Roles
|
||||
|
||||
client = Client()
|
||||
client.set_endpoint('https://<REGION>.cloud.appwrite.io/v1') # Your API Endpoint
|
||||
|
|
@ -12,7 +11,7 @@ teams = Teams(client)
|
|||
|
||||
result = teams.create_membership(
|
||||
team_id = '<TEAM_ID>',
|
||||
roles = [Roles.ADMIN],
|
||||
roles = [],
|
||||
email = 'email@example.com', # optional
|
||||
user_id = '<USER_ID>', # optional
|
||||
phone = '+12065550100', # optional
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
```python
|
||||
from appwrite.client import Client
|
||||
from appwrite.services.teams import Teams
|
||||
from appwrite.enums import Roles
|
||||
|
||||
client = Client()
|
||||
client.set_endpoint('https://<REGION>.cloud.appwrite.io/v1') # Your API Endpoint
|
||||
|
|
@ -13,6 +12,6 @@ teams = Teams(client)
|
|||
result = teams.update_membership(
|
||||
team_id = '<TEAM_ID>',
|
||||
membership_id = '<MEMBERSHIP_ID>',
|
||||
roles = [Roles.ADMIN]
|
||||
roles = []
|
||||
)
|
||||
```
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
require 'appwrite'
|
||||
|
||||
include Appwrite
|
||||
include Appwrite::Enums
|
||||
|
||||
client = Client.new
|
||||
.set_endpoint('https://<REGION>.cloud.appwrite.io/v1') # Your API Endpoint
|
||||
|
|
@ -13,7 +12,7 @@ teams = Teams.new(client)
|
|||
|
||||
result = teams.create_membership(
|
||||
team_id: '<TEAM_ID>',
|
||||
roles: [Roles::ADMIN],
|
||||
roles: [],
|
||||
email: 'email@example.com', # optional
|
||||
user_id: '<USER_ID>', # optional
|
||||
phone: '+12065550100', # optional
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
require 'appwrite'
|
||||
|
||||
include Appwrite
|
||||
include Appwrite::Enums
|
||||
|
||||
client = Client.new
|
||||
.set_endpoint('https://<REGION>.cloud.appwrite.io/v1') # Your API Endpoint
|
||||
|
|
@ -14,6 +13,6 @@ teams = Teams.new(client)
|
|||
result = teams.update_membership(
|
||||
team_id: '<TEAM_ID>',
|
||||
membership_id: '<MEMBERSHIP_ID>',
|
||||
roles: [Roles::ADMIN]
|
||||
roles: []
|
||||
)
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
```swift
|
||||
import Appwrite
|
||||
import AppwriteEnums
|
||||
|
||||
let client = Client()
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
|
|
@ -11,7 +10,7 @@ let teams = Teams(client)
|
|||
|
||||
let membership = try await teams.createMembership(
|
||||
teamId: "<TEAM_ID>",
|
||||
roles: [.admin],
|
||||
roles: [],
|
||||
email: "email@example.com", // optional
|
||||
userId: "<USER_ID>", // optional
|
||||
phone: "+12065550100", // optional
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
```swift
|
||||
import Appwrite
|
||||
import AppwriteEnums
|
||||
|
||||
let client = Client()
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
|
|
@ -12,7 +11,7 @@ let teams = Teams(client)
|
|||
let membership = try await teams.updateMembership(
|
||||
teamId: "<TEAM_ID>",
|
||||
membershipId: "<MEMBERSHIP_ID>",
|
||||
roles: [.admin]
|
||||
roles: []
|
||||
)
|
||||
|
||||
```
|
||||
|
|
|
|||
12
docs/sdks/agent-skills/CHANGELOG.md
Normal file
12
docs/sdks/agent-skills/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# Changelog
|
||||
|
||||
## 0.1.0
|
||||
|
||||
Initial release compatible with Appwrite server 1.8.x. Follows the [Agent Skills Open Standard](https://agentskills.io/home).
|
||||
|
||||
- Added agent skills for 9 languages: TypeScript, Python, PHP, Go, Kotlin, Swift, Ruby, .NET, and Dart
|
||||
- Coverage for Account, Users, TablesDB, Storage, Teams, Functions, and Realtime services
|
||||
- Query builder with filtering, sorting, pagination, and field selection
|
||||
- Permission and Role helpers for access control
|
||||
- SSR authentication patterns for major frameworks
|
||||
- Consistent error handling via `AppwriteException` across all languages
|
||||
96
docs/sdks/agent-skills/GETTING_STARTED.md
Normal file
96
docs/sdks/agent-skills/GETTING_STARTED.md
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
## Getting Started
|
||||
|
||||
Agent Skills to help developers using AI coding agents with Appwrite. Agent Skills are folders of instructions, scripts, and resources that agents like Claude Code, Cursor, GitHub Copilot, and others can discover and use to work more accurately and efficiently.
|
||||
|
||||
These skills follow the Agent Skills Open Standard: https://agentskills.io/home
|
||||
|
||||
### Install the skills
|
||||
|
||||
Install directly with the Skills CLI:
|
||||
|
||||
```bash
|
||||
npx skills add chiragagg5k/appwrite-agent-skills
|
||||
```
|
||||
|
||||
This installs the packaged `appwrite-*` skills into your local skills directory.
|
||||
|
||||
### Available language skills
|
||||
|
||||
- `appwrite-typescript`
|
||||
- `appwrite-dart`
|
||||
- `appwrite-kotlin`
|
||||
- `appwrite-swift`
|
||||
- `appwrite-php`
|
||||
- `appwrite-python`
|
||||
- `appwrite-ruby`
|
||||
- `appwrite-go`
|
||||
- `appwrite-dotnet`
|
||||
|
||||
### Usage
|
||||
|
||||
Skills are automatically available once installed. The agent will use them when relevant tasks are detected.
|
||||
|
||||
### Prompt examples
|
||||
|
||||
Use these as copy-paste prompt starters.
|
||||
|
||||
#### TypeScript (server-side)
|
||||
|
||||
```text
|
||||
Use the appwrite-typescript skill.
|
||||
Create a Node.js script that uses Users service to create a user, then adds an initial profile row in TablesDB.
|
||||
Use env vars for endpoint, project ID, and API key.
|
||||
Include error handling and a small retry for transient failures.
|
||||
```
|
||||
|
||||
#### TypeScript (web client)
|
||||
|
||||
```text
|
||||
Use the appwrite-typescript skill.
|
||||
Build a browser login flow with Account service:
|
||||
- email/password signup
|
||||
- email/password session login
|
||||
- fetch current user
|
||||
- logout current session
|
||||
Return production-ready TypeScript code.
|
||||
```
|
||||
|
||||
#### Python
|
||||
|
||||
```text
|
||||
Use the appwrite-python skill.
|
||||
Write a script that uploads a local file to Storage, then prints the file ID and a preview URL.
|
||||
Use InputFile.from_path and catch Appwrite exceptions.
|
||||
```
|
||||
|
||||
#### PHP
|
||||
|
||||
```text
|
||||
Use the appwrite-php skill.
|
||||
Create a service class that lists rows from TablesDB with Query.equal and Query.limit, and maps them to DTOs.
|
||||
Prefer dependency injection for the Appwrite client.
|
||||
```
|
||||
|
||||
#### Go
|
||||
|
||||
```text
|
||||
Use the appwrite-go skill.
|
||||
Implement a CLI command that creates a document-style row, then reads it back and prints JSON output.
|
||||
Use context timeouts and structured error messages.
|
||||
```
|
||||
|
||||
#### Kotlin
|
||||
|
||||
```text
|
||||
Use the appwrite-kotlin skill.
|
||||
Generate Android repository code to paginate rows using cursor queries and expose a suspend function API.
|
||||
Keep UI concerns out of the data layer.
|
||||
```
|
||||
|
||||
#### Migration prompt (Databases -> TablesDB)
|
||||
|
||||
```text
|
||||
Use the appwrite-typescript skill.
|
||||
Migrate this existing Databases-based code to TablesDB APIs.
|
||||
Keep behavior identical and list each API mapping you changed.
|
||||
```
|
||||
|
|
@ -1,5 +1,11 @@
|
|||
# Change Log
|
||||
|
||||
## 12.1.0
|
||||
|
||||
* Add `queries` parameter to Realtime subscriptions for filtering events
|
||||
* Add `subscriptions` field to `RealtimeCallback` and `RealtimeResponseEvent` types
|
||||
* Fix `Roles` enum removed from Teams service; `roles` parameter now accepts `List<String>`
|
||||
|
||||
## 12.0.0
|
||||
|
||||
* Add array-based enum parameters (e.g., `permissions: List<BrowserPermission>`).
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue