mirror of
https://github.com/appwrite/appwrite
synced 2026-05-23 00:49:02 +00:00
commit
9873daa3ad
5065 changed files with 294564 additions and 9254 deletions
11
.coderabbit.yaml
Normal file
11
.coderabbit.yaml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
reviews:
|
||||
path_filters:
|
||||
- "!app/config/specs/**"
|
||||
- "!docs/examples/**"
|
||||
- "!docs/references/**"
|
||||
- "!docs/sdks/**"
|
||||
auto_review:
|
||||
base_branches:
|
||||
- main
|
||||
- 1.6.x
|
||||
- 1.7.x
|
||||
27
.env
27
.env
|
|
@ -19,11 +19,14 @@ _APP_CUSTOM_DOMAIN_DENY_LIST=
|
|||
_APP_OPTIONS_ABUSE=disabled
|
||||
_APP_OPTIONS_ROUTER_PROTECTION=disabled
|
||||
_APP_OPTIONS_FORCE_HTTPS=disabled
|
||||
_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS=disabled
|
||||
_APP_OPTIONS_ROUTER_FORCE_HTTPS=disabled
|
||||
_APP_OPENSSL_KEY_V1=your-secret-key
|
||||
_APP_DOMAIN=traefik
|
||||
_APP_DOMAIN_FUNCTIONS=functions.localhost
|
||||
_APP_DOMAIN_TARGET=localhost
|
||||
_APP_DOMAIN_SITES=sites.localhost
|
||||
_APP_DOMAIN_TARGET_CNAME=test.appwrite.io
|
||||
_APP_DOMAIN_TARGET_A=127.0.0.1
|
||||
_APP_DOMAIN_TARGET_AAAA=::1
|
||||
_APP_RULES_FORMAT=md5
|
||||
_APP_REDIS_HOST=redis
|
||||
_APP_REDIS_PORT=6379
|
||||
|
|
@ -70,17 +73,19 @@ _APP_SMS_FROM=+123456789
|
|||
_APP_SMS_PROJECTS_DENY_LIST=
|
||||
_APP_STORAGE_LIMIT=30000000
|
||||
_APP_STORAGE_PREVIEW_LIMIT=20000000
|
||||
_APP_FUNCTIONS_SIZE_LIMIT=30000000
|
||||
_APP_COMPUTE_SIZE_LIMIT=30000000
|
||||
_APP_FUNCTIONS_TIMEOUT=900
|
||||
_APP_FUNCTIONS_BUILD_TIMEOUT=900
|
||||
_APP_FUNCTIONS_CPUS=8
|
||||
_APP_FUNCTIONS_MEMORY=8192
|
||||
_APP_FUNCTIONS_INACTIVE_THRESHOLD=600
|
||||
_APP_FUNCTIONS_MAINTENANCE_INTERVAL=600
|
||||
_APP_FUNCTIONS_RUNTIMES_NETWORK=runtimes
|
||||
_APP_SITES_TIMEOUT=30
|
||||
_APP_COMPUTE_BUILD_TIMEOUT=900
|
||||
_APP_COMPUTE_CPUS=8
|
||||
_APP_COMPUTE_MEMORY=8192
|
||||
_APP_COMPUTE_INACTIVE_THRESHOLD=600
|
||||
_APP_COMPUTE_MAINTENANCE_INTERVAL=600
|
||||
_APP_COMPUTE_RUNTIMES_NETWORK=runtimes
|
||||
_APP_EXECUTOR_SECRET=your-secret-key
|
||||
_APP_EXECUTOR_HOST=http://proxy/v1
|
||||
_APP_EXECUTOR_HOST=http://exc1/v1
|
||||
_APP_FUNCTIONS_RUNTIMES=php-8.0,node-18.0,python-3.9,ruby-3.1
|
||||
_APP_SITES_RUNTIMES=static-1,node-22,flutter-3.29
|
||||
_APP_MAINTENANCE_INTERVAL=86400
|
||||
_APP_MAINTENANCE_START_TIME=12:00
|
||||
_APP_MAINTENANCE_RETENTION_CACHE=2592000
|
||||
|
|
@ -89,7 +94,7 @@ _APP_MAINTENANCE_RETENTION_ABUSE=86400
|
|||
_APP_MAINTENANCE_RETENTION_AUDIT=1209600
|
||||
_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE=15778800
|
||||
_APP_USAGE_AGGREGATION_INTERVAL=30
|
||||
_APP_STATS_RESOURCES_INTERVAL=3600
|
||||
_APP_STATS_RESOURCES_INTERVAL=30
|
||||
_APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000
|
||||
_APP_MAINTENANCE_RETENTION_SCHEDULES=86400
|
||||
_APP_USAGE_STATS=enabled
|
||||
|
|
|
|||
120
.github/workflows/benchmark.yml
vendored
Normal file
120
.github/workflows/benchmark.yml
vendored
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
name: Benchmark
|
||||
concurrency:
|
||||
group: '${{ github.workflow }}-${{ github.ref }}'
|
||||
cancel-in-progress: true
|
||||
env:
|
||||
IMAGE: appwrite-dev
|
||||
CACHE_KEY: 'appwrite-dev-${{ github.event.pull_request.head.sha }}'
|
||||
'on':
|
||||
- pull_request
|
||||
jobs:
|
||||
setup:
|
||||
name: Setup & Build Appwrite Image
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Build Appwrite
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: false
|
||||
tags: '${{ env.IMAGE }}'
|
||||
load: true
|
||||
cache-from: type=gha
|
||||
cache-to: 'type=gha,mode=max'
|
||||
outputs: 'type=docker,dest=/tmp/${{ env.IMAGE }}.tar'
|
||||
build-args: |
|
||||
DEBUG=false
|
||||
TESTING=true
|
||||
VERSION=dev
|
||||
- name: Cache Docker Image
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: '${{ env.CACHE_KEY }}'
|
||||
path: '/tmp/${{ env.IMAGE }}.tar'
|
||||
benchmarking:
|
||||
name: Benchmark
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: '${{ env.CACHE_KEY }}'
|
||||
path: '/tmp/${{ env.IMAGE }}.tar'
|
||||
fail-on-cache-miss: true
|
||||
- name: Load and Start Appwrite
|
||||
run: |
|
||||
sed -i 's/traefik/localhost/g' .env
|
||||
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||
docker compose up -d
|
||||
sleep 10
|
||||
- name: Install Oha
|
||||
run: |
|
||||
echo "deb [signed-by=/usr/share/keyrings/azlux-archive-keyring.gpg] http://packages.azlux.fr/debian/ stable main" | sudo tee /etc/apt/sources.list.d/azlux.list
|
||||
sudo wget -O /usr/share/keyrings/azlux-archive-keyring.gpg https://azlux.fr/repo.gpg
|
||||
sudo apt update
|
||||
sudo apt install oha
|
||||
- name: Benchmark PR
|
||||
run: 'oha -z 180s http://localhost/v1/health/version -j > benchmark.json'
|
||||
- name: Cleaning
|
||||
run: docker compose down -v
|
||||
- name: Installing latest version
|
||||
run: |
|
||||
rm docker-compose.yml
|
||||
rm .env
|
||||
curl https://appwrite.io/install/compose -o docker-compose.yml
|
||||
curl https://appwrite.io/install/env -o .env
|
||||
sed -i 's/_APP_OPTIONS_ABUSE=enabled/_APP_OPTIONS_ABUSE=disabled/g' .env
|
||||
docker compose up -d
|
||||
sleep 10
|
||||
- name: Benchmark Latest
|
||||
run: oha -z 180s http://localhost/v1/health/version -j > benchmark-latest.json
|
||||
- name: Prepare comment
|
||||
run: |
|
||||
echo '## :sparkles: Benchmark results' > benchmark.txt
|
||||
echo ' ' >> benchmark.txt
|
||||
echo "- Requests per second: $(jq -r '.summary.requestsPerSec|tonumber?|floor|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark.json)" >> benchmark.txt
|
||||
echo "- Requests with 200 status code: $(jq -r '.statusCodeDistribution."200"|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark.json)" >> benchmark.txt
|
||||
echo "- P99 latency: $(jq -r '.latencyPercentiles.p99' benchmark.json )" >> benchmark.txt
|
||||
echo " " >> benchmark.txt
|
||||
echo " " >> benchmark.txt
|
||||
echo "## :zap: Benchmark Comparison" >> benchmark.txt
|
||||
echo " " >> benchmark.txt
|
||||
echo "| Metric | This PR | Latest version | " >> benchmark.txt
|
||||
echo "| --- | --- | --- | " >> benchmark.txt
|
||||
echo "| RPS | $(jq -r '.summary.requestsPerSec|tonumber?|floor|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark.json) | $(jq -r '.summary.requestsPerSec|tonumber|floor|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark-latest.json) | " >> benchmark.txt
|
||||
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
|
||||
if: '${{ !cancelled() }}'
|
||||
with:
|
||||
name: benchmark.json
|
||||
path: benchmark.json
|
||||
retention-days: 7
|
||||
- name: Find Comment
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
uses: peter-evans/find-comment@v3
|
||||
id: fc
|
||||
with:
|
||||
issue-number: '${{ github.event.pull_request.number }}'
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: Benchmark results
|
||||
- name: Comment on PR
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
uses: peter-evans/create-or-update-comment@v4
|
||||
with:
|
||||
comment-id: '${{ steps.fc.outputs.comment-id }}'
|
||||
issue-number: '${{ github.event.pull_request.number }}'
|
||||
body-path: benchmark.txt
|
||||
edit-mode: replace
|
||||
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@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- 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@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
|
|
|
|||
2
.github/workflows/linter.yml
vendored
2
.github/workflows/linter.yml
vendored
|
|
@ -12,7 +12,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
|
|
|
|||
2
.github/workflows/publish.yml
vendored
2
.github/workflows/publish.yml
vendored
|
|
@ -12,7 +12,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
submodules: recursive
|
||||
|
|
|
|||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
|
|
@ -11,7 +11,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
|
|
|
|||
16
.github/workflows/static-analysis.yml
vendored
Normal file
16
.github/workflows/static-analysis.yml
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
name: "Static code analysis"
|
||||
|
||||
on: [pull_request]
|
||||
jobs:
|
||||
lint:
|
||||
name: CodeQL
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run CodeQL
|
||||
run: |
|
||||
docker run --rm -v $PWD:/app composer:2.6 sh -c \
|
||||
"composer install --profile --ignore-platform-reqs && composer check"
|
||||
169
.github/workflows/tests.yml
vendored
169
.github/workflows/tests.yml
vendored
|
|
@ -90,6 +90,9 @@ jobs:
|
|||
docker compose up -d
|
||||
sleep 10
|
||||
|
||||
- name: Logs
|
||||
run: docker compose logs appwrite
|
||||
|
||||
- name: Doctor
|
||||
run: docker compose exec -T appwrite doctor
|
||||
|
||||
|
|
@ -119,6 +122,14 @@ jobs:
|
|||
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||
docker compose up -d
|
||||
sleep 10
|
||||
|
||||
- name: Wait for Open Runtimes
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
while ! docker compose logs openruntimes-executor | grep -q "Executor is ready."; do
|
||||
echo "Waiting for Executor to come online"
|
||||
sleep 1
|
||||
done
|
||||
|
||||
- name: Run General Tests
|
||||
run: docker compose exec -T appwrite test /usr/src/code/tests/e2e/General --debug
|
||||
|
|
@ -142,7 +153,10 @@ jobs:
|
|||
Locale,
|
||||
Projects,
|
||||
Realtime,
|
||||
Sites,
|
||||
Proxy,
|
||||
Storage,
|
||||
Tokens,
|
||||
Teams,
|
||||
Users,
|
||||
Webhooks,
|
||||
|
|
@ -167,6 +181,14 @@ jobs:
|
|||
docker compose up -d
|
||||
sleep 30
|
||||
|
||||
- name: Wait for Open Runtimes
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
while ! docker compose logs openruntimes-executor | grep -q "Executor is ready."; do
|
||||
echo "Waiting for Executor to come online"
|
||||
sleep 1
|
||||
done
|
||||
|
||||
- name: Run ${{ matrix.service }} tests with Project table mode
|
||||
run: |
|
||||
echo "Using project tables"
|
||||
|
|
@ -176,7 +198,7 @@ jobs:
|
|||
docker compose exec -T \
|
||||
-e _APP_DATABASE_SHARED_TABLES \
|
||||
-e _APP_DATABASE_SHARED_TABLES_V1 \
|
||||
appwrite test /usr/src/code/tests/e2e/Services/${{ matrix.service }} --debug
|
||||
appwrite test /usr/src/code/tests/e2e/Services/${{ matrix.service }} --debug --exclude=devKeys
|
||||
|
||||
e2e_shared_mode_test:
|
||||
name: E2E Shared Mode Service Test
|
||||
|
|
@ -199,13 +221,16 @@ jobs:
|
|||
Locale,
|
||||
Projects,
|
||||
Realtime,
|
||||
Sites,
|
||||
Proxy,
|
||||
Storage,
|
||||
Teams,
|
||||
Users,
|
||||
Webhooks,
|
||||
VCS,
|
||||
Messaging,
|
||||
Migrations
|
||||
Migrations,
|
||||
Tokens
|
||||
]
|
||||
tables-mode: [
|
||||
'Shared V1',
|
||||
|
|
@ -229,6 +254,14 @@ jobs:
|
|||
docker compose up -d
|
||||
sleep 30
|
||||
|
||||
- name: Wait for Open Runtimes
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
while ! docker compose logs openruntimes-executor | grep -q "Executor is ready."; do
|
||||
echo "Waiting for Executor to come online"
|
||||
sleep 1
|
||||
done
|
||||
|
||||
- name: Run ${{ matrix.service }} tests with ${{ matrix.tables-mode }} table mode
|
||||
run: |
|
||||
if [ "${{ matrix.tables-mode }}" == "Shared V1" ]; then
|
||||
|
|
@ -240,90 +273,90 @@ jobs:
|
|||
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 \
|
||||
appwrite test /usr/src/code/tests/e2e/Services/${{ matrix.service }} --debug
|
||||
appwrite test /usr/src/code/tests/e2e/Services/${{ matrix.service }} --debug --exclude=devKeys
|
||||
|
||||
benchmarking:
|
||||
name: Benchmark
|
||||
e2e_dev_keys:
|
||||
name: E2E Service Test (Dev Keys)
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
permissions:
|
||||
pull-requests: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: ${{ env.CACHE_KEY }}
|
||||
path: /tmp/${{ env.IMAGE }}.tar
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: Load and Start Appwrite
|
||||
run: |
|
||||
sed -i 's/traefik/localhost/g' .env
|
||||
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||
sed -i 's/_APP_OPTIONS_ABUSE=disabled/_APP_OPTIONS_ABUSE=enabled/' .env
|
||||
docker compose up -d
|
||||
sleep 10
|
||||
- name: Install Oha
|
||||
sleep 30
|
||||
|
||||
- name: Run Projects tests with dev keys in dedicated table mode
|
||||
run: |
|
||||
echo "deb [signed-by=/usr/share/keyrings/azlux-archive-keyring.gpg] http://packages.azlux.fr/debian/ stable main" | sudo tee /etc/apt/sources.list.d/azlux.list
|
||||
sudo wget -O /usr/share/keyrings/azlux-archive-keyring.gpg https://azlux.fr/repo.gpg
|
||||
sudo apt update
|
||||
sudo apt install oha
|
||||
- name: Benchmark PR
|
||||
run: oha -z 180s http://localhost/v1/health/version -j > benchmark.json
|
||||
- name: Cleaning
|
||||
run: docker compose down -v
|
||||
- name: Installing latest version
|
||||
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 \
|
||||
appwrite test /usr/src/code/tests/e2e/Services/Projects --debug --group=devKeys
|
||||
|
||||
e2e_dev_keys_shared_mode:
|
||||
name: E2E Shared Mode Service Test (Dev Keys)
|
||||
runs-on: ubuntu-latest
|
||||
needs: [ setup, check_database_changes ]
|
||||
if: needs.check_database_changes.outputs.database_changed == 'true'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
tables-mode: [
|
||||
'Shared V1',
|
||||
'Shared V2',
|
||||
]
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Load Cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: ${{ env.CACHE_KEY }}
|
||||
path: /tmp/${{ env.IMAGE }}.tar
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: Load and Start Appwrite
|
||||
run: |
|
||||
rm docker-compose.yml
|
||||
rm .env
|
||||
curl https://appwrite.io/install/compose -o docker-compose.yml
|
||||
curl https://appwrite.io/install/env -o .env
|
||||
sed -i 's/_APP_OPTIONS_ABUSE=enabled/_APP_OPTIONS_ABUSE=disabled/g' .env
|
||||
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||
sed -i 's/_APP_OPTIONS_ABUSE=disabled/_APP_OPTIONS_ABUSE=enabled/' .env
|
||||
docker compose up -d
|
||||
sleep 10
|
||||
- name: Benchmark Latest
|
||||
run: oha -z 180s http://localhost/v1/health/version -j > benchmark-latest.json
|
||||
- name: Prepare comment
|
||||
sleep 30
|
||||
|
||||
- name: Run Projects tests with dev keys in ${{ matrix.tables-mode }} table mode
|
||||
run: |
|
||||
echo '## :sparkles: Benchmark results' > benchmark.txt
|
||||
echo ' ' >> benchmark.txt
|
||||
echo "- Requests per second: $(jq -r '.summary.requestsPerSec|tonumber?|floor|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark.json)" >> benchmark.txt
|
||||
echo "- Requests with 200 status code: $(jq -r '.statusCodeDistribution."200"|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark.json)" >> benchmark.txt
|
||||
echo "- P99 latency: $(jq -r '.latencyPercentiles.p99' benchmark.json )" >> benchmark.txt
|
||||
echo " " >> benchmark.txt
|
||||
echo " " >> benchmark.txt
|
||||
echo "## :zap: Benchmark Comparison" >> benchmark.txt
|
||||
echo " " >> benchmark.txt
|
||||
echo "| Metric | This PR | Latest version | " >> benchmark.txt
|
||||
echo "| --- | --- | --- | " >> benchmark.txt
|
||||
echo "| RPS | $(jq -r '.summary.requestsPerSec|tonumber?|floor|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark.json) | $(jq -r '.summary.requestsPerSec|tonumber|floor|tostring|[while(length>0;.[:-3])|.[-3:]]|reverse|join(",")' benchmark-latest.json) | " >> benchmark.txt
|
||||
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
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
name: benchmark.json
|
||||
path: benchmark.json
|
||||
retention-days: 7
|
||||
- name: Find Comment
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
uses: peter-evans/find-comment@v3
|
||||
id: fc
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: Benchmark results
|
||||
- name: Comment on PR
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
uses: peter-evans/create-or-update-comment@v4
|
||||
with:
|
||||
comment-id: ${{ steps.fc.outputs.comment-id }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
body-path: benchmark.txt
|
||||
edit-mode: replace
|
||||
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 \
|
||||
appwrite test /usr/src/code/tests/e2e/Services/Projects --debug --group=devKeys
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -3,6 +3,7 @@
|
|||
/node_modules/
|
||||
/tests/resources/storage/
|
||||
/tests/resources/functions/**/code.tar.gz
|
||||
/tests/resources/sites/**/code.tar.gz
|
||||
/app/sdks/*
|
||||
/.idea/
|
||||
!/.idea/workspace.xml
|
||||
|
|
|
|||
|
|
@ -163,6 +163,28 @@ Other containes should be named the same as their service, for example `redis` s
|
|||
- [Encryption](https://medium.com/searchencrypt/what-is-encryption-how-does-it-work-e8f20e340537#:~:text=Encryption%20is%20a%20process%20that,%2C%20or%20decrypt%2C%20the%20information.)
|
||||
- [Hashing](https://searchsqlserver.techtarget.com/definition/hashing#:~:text=Hashing%20is%20the%20transformation%20of,it%20using%20the%20original%20value.)
|
||||
|
||||
## Modules
|
||||
|
||||
As Appwrite grows, we noticed approach of having all service endpoints in `app/controllers/api/[service].php` is not maintainable. Not only it creates massive files, it also doesnt contain all product's features such as workers or tasks. While there might still be some occurances of those controller files, we avoid it in all new development, and gradually migrate existing controllers to **HTTP modules**.
|
||||
|
||||
### HTTP Endpoints
|
||||
|
||||
Every endpoint file follows below structure, making it consistent with HTTP REST endpoint path:
|
||||
|
||||
```
|
||||
src/Appwrite/Platform/Modules/[service]/Http/[resource]/[action].php
|
||||
```
|
||||
|
||||
Tips and tricks:
|
||||
|
||||
1. If endpoint doesn't have resource, use service name as resource name too
|
||||
> Example: `Modules/Sites/Http/Sites/Get.php`
|
||||
|
||||
2. If there are multiple resources, use then all in folder structure
|
||||
> Example: `Modules/Sites/Http/Deployments/Builds/Create.php`
|
||||
|
||||
3. Action can only be `Get`, `Create`, `Update`, `Delete` or `XList`
|
||||
|
||||
## Architecture
|
||||
|
||||
Appwrite's current structure is a combination of both [Monolithic](https://en.wikipedia.org/wiki/Monolithic_application) and [Microservice](https://en.wikipedia.org/wiki/Microservices) architectures.
|
||||
|
|
|
|||
|
|
@ -44,12 +44,14 @@ COPY ./dev /usr/src/code/dev
|
|||
|
||||
# Set Volumes
|
||||
RUN mkdir -p /storage/uploads && \
|
||||
mkdir -p /storage/imports && \
|
||||
mkdir -p /storage/cache && \
|
||||
mkdir -p /storage/config && \
|
||||
mkdir -p /storage/certificates && \
|
||||
mkdir -p /storage/functions && \
|
||||
mkdir -p /storage/debug && \
|
||||
chown -Rf www-data.www-data /storage/uploads && chmod -Rf 0755 /storage/uploads && \
|
||||
chown -Rf www-data.www-data /storage/imports && chmod -Rf 0755 /storage/imports && \
|
||||
chown -Rf www-data.www-data /storage/cache && chmod -Rf 0755 /storage/cache && \
|
||||
chown -Rf www-data.www-data /storage/config && chmod -Rf 0755 /storage/config && \
|
||||
chown -Rf www-data.www-data /storage/certificates && chmod -Rf 0755 /storage/certificates && \
|
||||
|
|
@ -68,6 +70,7 @@ RUN chmod +x /usr/local/bin/doctor && \
|
|||
chmod +x /usr/local/bin/sdks && \
|
||||
chmod +x /usr/local/bin/specs && \
|
||||
chmod +x /usr/local/bin/ssl && \
|
||||
chmod +x /usr/local/bin/screenshot && \
|
||||
chmod +x /usr/local/bin/test && \
|
||||
chmod +x /usr/local/bin/upgrade && \
|
||||
chmod +x /usr/local/bin/vars && \
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ docker run -it --rm \
|
|||
--volume /var/run/docker.sock:/var/run/docker.sock \
|
||||
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
|
||||
--entrypoint="install" \
|
||||
appwrite/appwrite:1.6.2
|
||||
appwrite/appwrite:1.7.0
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
|
@ -84,7 +84,7 @@ docker run -it --rm ^
|
|||
--volume //var/run/docker.sock:/var/run/docker.sock ^
|
||||
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
|
||||
--entrypoint="install" ^
|
||||
appwrite/appwrite:1.6.2
|
||||
appwrite/appwrite:1.7.0
|
||||
```
|
||||
|
||||
#### PowerShell
|
||||
|
|
@ -94,7 +94,7 @@ docker run -it --rm `
|
|||
--volume /var/run/docker.sock:/var/run/docker.sock `
|
||||
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw `
|
||||
--entrypoint="install" `
|
||||
appwrite/appwrite:1.6.2
|
||||
appwrite/appwrite:1.7.0
|
||||
```
|
||||
|
||||
运行后,可以在浏览器上访问 http://localhost 找到 Appwrite 控制台。在非 Linux 的本机主机上完成安装后,服务器可能需要几分钟才能启动。
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ docker run -it --rm \
|
|||
--volume /var/run/docker.sock:/var/run/docker.sock \
|
||||
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
|
||||
--entrypoint="install" \
|
||||
appwrite/appwrite:1.6.2
|
||||
appwrite/appwrite:1.7.0
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
|
@ -90,7 +90,7 @@ docker run -it --rm ^
|
|||
--volume //var/run/docker.sock:/var/run/docker.sock ^
|
||||
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
|
||||
--entrypoint="install" ^
|
||||
appwrite/appwrite:1.6.2
|
||||
appwrite/appwrite:1.7.0
|
||||
```
|
||||
|
||||
#### PowerShell
|
||||
|
|
@ -100,7 +100,7 @@ docker run -it --rm `
|
|||
--volume /var/run/docker.sock:/var/run/docker.sock `
|
||||
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw `
|
||||
--entrypoint="install" `
|
||||
appwrite/appwrite:1.6.2
|
||||
appwrite/appwrite:1.7.0
|
||||
```
|
||||
|
||||
Once the Docker installation is complete, go to http://localhost to access the Appwrite console from your browser. Please note that on non-Linux native hosts, the server might take a few minutes to start after completing the installation.
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ use Utopia\Telemetry\Adapter\None as NoTelemetry;
|
|||
|
||||
use function Swoole\Coroutine\run;
|
||||
|
||||
// Overwriting runtimes to be architecture agnostic for CLI
|
||||
Config::setParam('runtimes', (new Runtimes('v4'))->getAll(supported: false));
|
||||
// overwriting runtimes to be architecture agnostic for CLI
|
||||
Config::setParam('runtimes', (new Runtimes('v5'))->getAll(supported: false));
|
||||
|
||||
// require controllers after overwriting runtimes
|
||||
require_once __DIR__ . '/controllers/general.php';
|
||||
|
|
|
|||
|
|
@ -1101,6 +1101,28 @@ return [
|
|||
'array' => false,
|
||||
'filters' => ['json', 'encrypt'],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('scopes'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => true,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('expire'),
|
||||
'type' => Database::VAR_DATETIME,
|
||||
'format' => '',
|
||||
'size' => 0,
|
||||
'required' => false,
|
||||
'signed' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => ['datetime'],
|
||||
],
|
||||
],
|
||||
'indexes' => [
|
||||
[
|
||||
|
|
@ -1417,6 +1439,13 @@ return [
|
|||
'lengths' => [],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('_key_roles'),
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['roles'],
|
||||
'lengths' => [128],
|
||||
'orders' => [],
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ return [
|
|||
'$id' => ID::custom('templates'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 1000000, // TODO make sure size fits
|
||||
'size' => 1_000_000, // TODO make sure size fits
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => [],
|
||||
|
|
@ -287,6 +287,17 @@ return [
|
|||
'array' => false,
|
||||
'filters' => ['subQueryKeys'],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('devKeys'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 16384,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => ['subQueryDevKeys'],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('search'),
|
||||
'type' => Database::VAR_STRING,
|
||||
|
|
@ -717,6 +728,107 @@ return [
|
|||
],
|
||||
],
|
||||
|
||||
'devKeys' => [
|
||||
'$collection' => ID::custom(Database::METADATA),
|
||||
'$id' => ID::custom('devKeys'),
|
||||
'name' => 'Dev keys',
|
||||
'attributes' => [
|
||||
[
|
||||
'$id' => ID::custom('projectInternalId'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('projectId'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => true,
|
||||
'default' => 0,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('name'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('secret'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 512, // var_dump of \bin2hex(\random_bytes(128)) => string(256) doubling for encryption
|
||||
'signed' => true,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => ['encrypt'],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('expire'),
|
||||
'type' => Database::VAR_DATETIME,
|
||||
'format' => '',
|
||||
'size' => 0,
|
||||
'signed' => false,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => ['datetime'],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('accessedAt'),
|
||||
'type' => Database::VAR_DATETIME,
|
||||
'format' => '',
|
||||
'size' => 0,
|
||||
'signed' => false,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => ['datetime'],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('sdks'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => true,
|
||||
'filters' => [],
|
||||
],
|
||||
],
|
||||
'indexes' => [
|
||||
[
|
||||
'$id' => ID::custom('_key_project'),
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['projectInternalId'],
|
||||
'lengths' => [Database::LENGTH_KEY],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => '_key_accessedAt',
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['accessedAt'],
|
||||
'lengths' => [],
|
||||
'orders' => [],
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
'webhooks' => [
|
||||
'$collection' => ID::custom(Database::METADATA),
|
||||
'$id' => ID::custom('webhooks'),
|
||||
|
|
@ -1041,21 +1153,10 @@ return [
|
|||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('resourceType'),
|
||||
'$id' => ID::custom('type'), // 'api', 'redirect', 'deployment' (site or function)
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 100,
|
||||
'signed' => true,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('resourceInternalId'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'size' => 32,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
|
|
@ -1063,13 +1164,101 @@ return [
|
|||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('resourceId'),
|
||||
'$id' => ID::custom('trigger'), // 'manual', 'deployment', '' (empty)
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 32,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => '',
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('redirectUrl'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 2048,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => '',
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('redirectStatusCode'),
|
||||
'type' => Database::VAR_INTEGER,
|
||||
'format' => '',
|
||||
'size' => 0,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('deploymentResourceType'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 32,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => '',
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('deploymentId'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'default' => '',
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('deploymentInternalId'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => '',
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('deploymentResourceId'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => '',
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('deploymentResourceInternalId'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => '',
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('deploymentVcsProviderBranch'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => '',
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
|
|
@ -1095,6 +1284,17 @@ return [
|
|||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('search'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 16384,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('owner'),
|
||||
'type' => Database::VAR_STRING,
|
||||
|
|
@ -1119,6 +1319,13 @@ return [
|
|||
],
|
||||
],
|
||||
'indexes' => [
|
||||
[
|
||||
'$id' => ID::custom('_key_search'),
|
||||
'type' => Database::INDEX_FULLTEXT,
|
||||
'attributes' => ['search'],
|
||||
'lengths' => [],
|
||||
'orders' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('_key_domain'),
|
||||
'type' => Database::INDEX_UNIQUE,
|
||||
|
|
@ -1141,24 +1348,59 @@ return [
|
|||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => '_key_resourceInternalId',
|
||||
'$id' => '_key_type',
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['resourceInternalId'],
|
||||
'attributes' => ['type'],
|
||||
'lengths' => [32],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => '_key_trigger',
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['trigger'],
|
||||
'lengths' => [32],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => '_key_deploymentResourceType',
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['deploymentResourceType'],
|
||||
'lengths' => [32],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => '_key_deploymentResourceId',
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['deploymentResourceId'],
|
||||
'lengths' => [Database::LENGTH_KEY],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => '_key_resourceId',
|
||||
'$id' => '_key_deploymentResourceInternalId',
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['resourceId'],
|
||||
'attributes' => ['deploymentResourceInternalId'],
|
||||
'lengths' => [Database::LENGTH_KEY],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => '_key_resourceType',
|
||||
'$id' => '_key_deploymentId',
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['resourceType'],
|
||||
'lengths' => [],
|
||||
'attributes' => ['deploymentId'],
|
||||
'lengths' => [Database::LENGTH_KEY],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => '_key_deploymentInternalId',
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['deploymentInternalId'],
|
||||
'lengths' => [Database::LENGTH_KEY],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => '_key_deploymentVcsProviderBranch',
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['deploymentVcsProviderBranch'],
|
||||
'lengths' => [Database::LENGTH_KEY],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
|
|
@ -1178,7 +1420,7 @@ return [
|
|||
[
|
||||
'$id' => ID::custom('_key_piid_riid_rt'),
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['projectInternalId', 'resourceInternalId', 'resourceType'],
|
||||
'attributes' => ['projectInternalId', 'deploymentInternalId', 'deploymentResourceType'],
|
||||
'lengths' => [],
|
||||
'orders' => [],
|
||||
],
|
||||
|
|
@ -1648,5 +1890,5 @@ return [
|
|||
'name' => 'vcsCommentLocks',
|
||||
'attributes' => [],
|
||||
'indexes' => []
|
||||
]
|
||||
],
|
||||
];
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -375,6 +375,13 @@ return [
|
|||
'code' => 409,
|
||||
],
|
||||
|
||||
/** Console */
|
||||
Exception::RESOURCE_ALREADY_EXISTS => [
|
||||
'name' => Exception::RESOURCE_ALREADY_EXISTS,
|
||||
'description' => 'Resource with the requested ID already exists. Please choose a different ID and try again.',
|
||||
'code' => 409,
|
||||
],
|
||||
|
||||
/** Membership */
|
||||
Exception::MEMBERSHIP_NOT_FOUND => [
|
||||
'name' => Exception::MEMBERSHIP_NOT_FOUND,
|
||||
|
|
@ -481,6 +488,23 @@ return [
|
|||
'code' => 403,
|
||||
],
|
||||
|
||||
/** Tokens */
|
||||
Exception::TOKEN_NOT_FOUND => [
|
||||
'name' => Exception::TOKEN_NOT_FOUND,
|
||||
'description' => 'The requested file token could not be found.',
|
||||
'code' => 404,
|
||||
],
|
||||
Exception::TOKEN_EXPIRED => [
|
||||
'name' => Exception::TOKEN_EXPIRED,
|
||||
'description' => 'The requested file token has expired.',
|
||||
'code' => 401,
|
||||
],
|
||||
Exception::TOKEN_RESOURCE_TYPE_INVALID => [
|
||||
'name' => Exception::TOKEN_RESOURCE_TYPE_INVALID,
|
||||
'description' => 'The resource type for the token is invalid.',
|
||||
'code' => 400,
|
||||
],
|
||||
|
||||
/** VCS */
|
||||
Exception::INSTALLATION_NOT_FOUND => [
|
||||
'name' => Exception::INSTALLATION_NOT_FOUND,
|
||||
|
|
@ -520,7 +544,7 @@ return [
|
|||
'code' => 404,
|
||||
],
|
||||
Exception::FUNCTION_ENTRYPOINT_MISSING => [
|
||||
'name' => Exception::FUNCTION_RUNTIME_UNSUPPORTED,
|
||||
'name' => Exception::FUNCTION_ENTRYPOINT_MISSING,
|
||||
'description' => 'Entrypoint for your Appwrite Function is missing. Please specify it when making deployment or update the entrypoint under your function\'s "Settings" > "Configuration" > "Entrypoint".',
|
||||
'code' => 404,
|
||||
],
|
||||
|
|
@ -534,6 +558,28 @@ return [
|
|||
'description' => 'Function Template with the requested ID could not be found.',
|
||||
'code' => 404,
|
||||
],
|
||||
Exception::FUNCTION_RUNTIME_NOT_DETECTED => [
|
||||
'name' => Exception::FUNCTION_RUNTIME_NOT_DETECTED,
|
||||
'description' => 'Function runtime could not be detected.',
|
||||
'code' => 400,
|
||||
],
|
||||
Exception::FUNCTION_EXECUTE_PERMISSION_MISSING => [
|
||||
'name' => Exception::FUNCTION_EXECUTE_PERMISSION_MISSING,
|
||||
'description' => 'To execute function using domain, execute permissions must include "any" or "guests".',
|
||||
'code' => 401,
|
||||
],
|
||||
|
||||
/** Sites */
|
||||
Exception::SITE_NOT_FOUND => [
|
||||
'name' => Exception::SITE_NOT_FOUND,
|
||||
'description' => 'Site with the requested ID could not be found.',
|
||||
'code' => 404,
|
||||
],
|
||||
Exception::SITE_TEMPLATE_NOT_FOUND => [
|
||||
'name' => Exception::SITE_TEMPLATE_NOT_FOUND,
|
||||
'description' => 'Site Template with the requested ID could not be found.',
|
||||
'code' => 404,
|
||||
],
|
||||
|
||||
/** Builds */
|
||||
Exception::BUILD_NOT_FOUND => [
|
||||
|
|
@ -556,6 +602,16 @@ return [
|
|||
'description' => 'Build with the requested ID is already completed and cannot be canceled.',
|
||||
'code' => 400,
|
||||
],
|
||||
Exception::BUILD_CANCELED => [
|
||||
'name' => Exception::BUILD_CANCELED,
|
||||
'description' => 'Build with the requested ID has been canceled.',
|
||||
'code' => 400,
|
||||
],
|
||||
Exception::BUILD_FAILED => [
|
||||
'name' => Exception::BUILD_FAILED,
|
||||
'description' => 'Build with the requested ID failed. Please check the logs for more information.',
|
||||
'code' => 400,
|
||||
],
|
||||
|
||||
/** Deployments */
|
||||
Exception::DEPLOYMENT_NOT_FOUND => [
|
||||
|
|
@ -577,6 +633,13 @@ return [
|
|||
'code' => 400,
|
||||
],
|
||||
|
||||
/** Logs */
|
||||
Exception::LOG_NOT_FOUND => [
|
||||
'name' => Exception::LOG_NOT_FOUND,
|
||||
'description' => 'Log with the requested ID could not be found.',
|
||||
'code' => 404,
|
||||
],
|
||||
|
||||
/** Databases */
|
||||
Exception::DATABASE_NOT_FOUND => [
|
||||
'name' => Exception::DATABASE_NOT_FOUND,
|
||||
|
|
@ -806,7 +869,7 @@ return [
|
|||
Exception::RULE_VERIFICATION_FAILED => [
|
||||
'name' => Exception::RULE_VERIFICATION_FAILED,
|
||||
'description' => 'Domain verification failed. Please check if your DNS records are correct and try again.',
|
||||
'code' => 401,
|
||||
'code' => 400,
|
||||
'publish' => true
|
||||
],
|
||||
Exception::PROJECT_SMTP_CONFIG_INVALID => [
|
||||
|
|
@ -849,6 +912,11 @@ return [
|
|||
'description' => 'Variable with the same ID already exists in this project. Try again with a different ID.',
|
||||
'code' => 409,
|
||||
],
|
||||
Exception::VARIABLE_CANNOT_UNSET_SECRET => [
|
||||
'name' => Exception::VARIABLE_CANNOT_UNSET_SECRET,
|
||||
'description' => 'Secret variables cannot be marked as non-secret. Please re-create the variable if this is your intention.',
|
||||
'code' => 400,
|
||||
],
|
||||
Exception::GRAPHQL_NO_QUERY => [
|
||||
'name' => Exception::GRAPHQL_NO_QUERY,
|
||||
'description' => 'Param "query" is not optional.',
|
||||
|
|
|
|||
|
|
@ -217,6 +217,34 @@ return [
|
|||
],
|
||||
]
|
||||
],
|
||||
'sites' => [
|
||||
'$model' => Response::MODEL_SITE,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any sites event.',
|
||||
'deployments' => [
|
||||
'$model' => Response::MODEL_DEPLOYMENT,
|
||||
'$resource' => true,
|
||||
'$description' => 'This event triggers on any deployments event.',
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a deployment is created.',
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when a deployment is deleted.'
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a deployment is updated.'
|
||||
],
|
||||
],
|
||||
'create' => [
|
||||
'$description' => 'This event triggers when a site is created.'
|
||||
],
|
||||
'delete' => [
|
||||
'$description' => 'This event triggers when a site is deleted.',
|
||||
],
|
||||
'update' => [
|
||||
'$description' => 'This event triggers when a site is updated.',
|
||||
]
|
||||
],
|
||||
'functions' => [
|
||||
'$model' => Response::MODEL_FUNCTION,
|
||||
'$resource' => true,
|
||||
|
|
|
|||
312
app/config/frameworks.php
Normal file
312
app/config/frameworks.php
Normal file
|
|
@ -0,0 +1,312 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* List of Appwrite Sites supported frameworks
|
||||
*/
|
||||
|
||||
use Utopia\Config\Config;
|
||||
|
||||
$templateRuntimes = Config::getParam('template-runtimes');
|
||||
|
||||
function getVersions(array $versions, string $prefix)
|
||||
{
|
||||
return array_map(function ($version) use ($prefix) {
|
||||
return $prefix . '-' . $version;
|
||||
}, $versions);
|
||||
}
|
||||
|
||||
return [
|
||||
'analog' => [
|
||||
'key' => 'analog',
|
||||
'name' => 'Analog',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
|
||||
'bundleCommand' => 'bash /usr/local/server/helpers/analog/bundle.sh',
|
||||
'envCommand' => 'source /usr/local/server/helpers/analog/env.sh',
|
||||
'adapters' => [
|
||||
'ssr' => [
|
||||
'key' => 'ssr',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist/analog',
|
||||
'startCommand' => 'bash helpers/analog/server.sh',
|
||||
],
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist/analog/public',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
'fallbackFile' => 'index.html'
|
||||
]
|
||||
]
|
||||
],
|
||||
'angular' => [
|
||||
'key' => 'angular',
|
||||
'name' => 'Angular',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
|
||||
'bundleCommand' => 'bash /usr/local/server/helpers/angular/bundle.sh',
|
||||
'envCommand' => 'source /usr/local/server/helpers/angular/env.sh',
|
||||
'adapters' => [
|
||||
'ssr' => [
|
||||
'key' => 'ssr',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist/angular',
|
||||
'startCommand' => 'bash helpers/angular/server.sh',
|
||||
],
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist/angular/browser',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
'fallbackFile' => 'index.csr.html'
|
||||
]
|
||||
]
|
||||
],
|
||||
'nextjs' => [
|
||||
'key' => 'nextjs',
|
||||
'name' => 'Next.js',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
|
||||
'bundleCommand' => 'bash /usr/local/server/helpers/next-js/bundle.sh',
|
||||
'envCommand' => 'source /usr/local/server/helpers/next-js/env.sh',
|
||||
'adapters' => [
|
||||
'ssr' => [
|
||||
'key' => 'ssr',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './.next',
|
||||
'startCommand' => 'bash helpers/next-js/server.sh',
|
||||
],
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './out',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
]
|
||||
]
|
||||
],
|
||||
'react' => [
|
||||
'key' => 'react',
|
||||
'name' => 'React',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
|
||||
'adapters' => [
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
'fallbackFile' => 'index.html'
|
||||
]
|
||||
]
|
||||
],
|
||||
'nuxt' => [
|
||||
'key' => 'nuxt',
|
||||
'name' => 'Nuxt',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
|
||||
'bundleCommand' => 'bash /usr/local/server/helpers/nuxt/bundle.sh',
|
||||
'envCommand' => 'source /usr/local/server/helpers/nuxt/env.sh',
|
||||
'adapters' => [
|
||||
'ssr' => [
|
||||
'key' => 'ssr',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './.output',
|
||||
'startCommand' => 'bash helpers/nuxt/server.sh',
|
||||
],
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run generate',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './output/public',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
]
|
||||
]
|
||||
],
|
||||
'vue' => [
|
||||
'key' => 'vue',
|
||||
'name' => 'Vue.js',
|
||||
'screenshotSleep' => 5000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
|
||||
'adapters' => [
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
'fallbackFile' => 'index.html'
|
||||
]
|
||||
]
|
||||
],
|
||||
'sveltekit' => [
|
||||
'key' => 'sveltekit',
|
||||
'name' => 'SvelteKit',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
|
||||
'bundleCommand' => 'bash /usr/local/server/helpers/sveltekit/bundle.sh',
|
||||
'envCommand' => 'source /usr/local/server/helpers/sveltekit/env.sh',
|
||||
'adapters' => [
|
||||
'ssr' => [
|
||||
'key' => 'ssr',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './build',
|
||||
'startCommand' => 'bash helpers/sveltekit/server.sh',
|
||||
],
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './build',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
]
|
||||
]
|
||||
],
|
||||
'astro' => [
|
||||
'key' => 'astro',
|
||||
'name' => 'Astro',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
|
||||
'bundleCommand' => 'bash /usr/local/server/helpers/astro/bundle.sh',
|
||||
'envCommand' => 'source /usr/local/server/helpers/astro/env.sh',
|
||||
'adapters' => [
|
||||
'ssr' => [
|
||||
'key' => 'ssr',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist',
|
||||
'startCommand' => 'bash helpers/astro/server.sh',
|
||||
],
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
]
|
||||
]
|
||||
],
|
||||
'remix' => [
|
||||
'key' => 'remix',
|
||||
'name' => 'Remix',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
|
||||
'bundleCommand' => 'bash /usr/local/server/helpers/remix/bundle.sh',
|
||||
'envCommand' => 'source /usr/local/server/helpers/remix/env.sh',
|
||||
'adapters' => [
|
||||
'ssr' => [
|
||||
'key' => 'ssr',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './build',
|
||||
'startCommand' => 'bash helpers/remix/server.sh',
|
||||
],
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './build/client',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
]
|
||||
]
|
||||
],
|
||||
'lynx' => [
|
||||
'key' => 'lynx',
|
||||
'name' => 'Lynx',
|
||||
'screenshotSleep' => 5000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
|
||||
'adapters' => [
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
'fallbackFile' => 'index.html'
|
||||
]
|
||||
]
|
||||
],
|
||||
'flutter' => [
|
||||
'key' => 'flutter',
|
||||
'name' => 'Flutter',
|
||||
'screenshotSleep' => 5000,
|
||||
'buildRuntime' => 'flutter-3.29',
|
||||
'runtimes' => getVersions($templateRuntimes['FLUTTER']['versions'], 'flutter'),
|
||||
'adapters' => [
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'flutter build web --release -t lib/main.dart',
|
||||
'installCommand' => 'flutter pub get',
|
||||
'outputDirectory' => './build/web',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
],
|
||||
],
|
||||
],
|
||||
'react-native' => [
|
||||
'key' => 'react-native',
|
||||
'name' => 'React Native',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
|
||||
'adapters' => [
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
'fallbackFile' => 'index.html'
|
||||
]
|
||||
]
|
||||
],
|
||||
'vite' => [
|
||||
'key' => 'vite',
|
||||
'name' => 'Vite',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
|
||||
'adapters' => [
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => 'npm run build',
|
||||
'installCommand' => 'npm install',
|
||||
'outputDirectory' => './dist',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
],
|
||||
]
|
||||
],
|
||||
'other' => [
|
||||
'key' => 'other',
|
||||
'name' => 'Other',
|
||||
'screenshotSleep' => 3000,
|
||||
'buildRuntime' => 'node-22',
|
||||
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
|
||||
'adapters' => [
|
||||
'static' => [
|
||||
'key' => 'static',
|
||||
'buildCommand' => '',
|
||||
'installCommand' => '',
|
||||
'outputDirectory' => './',
|
||||
'startCommand' => 'bash helpers/server.sh',
|
||||
],
|
||||
]
|
||||
],
|
||||
];
|
||||
|
|
@ -79,7 +79,7 @@
|
|||
<style>
|
||||
a.button {
|
||||
display: inline-block;
|
||||
background: #fd366e;
|
||||
background: {{accentColor}};
|
||||
color: #ffffff;
|
||||
border-radius: 8px;
|
||||
height: 48px;
|
||||
|
|
@ -88,7 +88,7 @@
|
|||
cursor: pointer;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
border-color: #fd366e;
|
||||
border-color: {{accentColor}};
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
margin-right: 24px;
|
||||
|
|
@ -126,7 +126,7 @@
|
|||
<td>
|
||||
<img
|
||||
height="32px"
|
||||
src="https://cloud.appwrite.io/images/mails/logo.png"
|
||||
src="{{logoUrl}}"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -164,7 +164,7 @@
|
|||
<tr>
|
||||
<td style="padding-left: 4px; padding-right: 4px">
|
||||
<a
|
||||
href="https://twitter.com/appwrite"
|
||||
href="{{twitterUrl}}"
|
||||
class="social-icon"
|
||||
title="Twitter"
|
||||
>
|
||||
|
|
@ -173,7 +173,7 @@
|
|||
</td>
|
||||
<td style="padding-left: 4px; padding-right: 4px">
|
||||
<a
|
||||
href="https://appwrite.io/discord"
|
||||
href="{{discordUrl}}"
|
||||
class="social-icon"
|
||||
>
|
||||
<img src="https://cloud.appwrite.io/images/mails/discord.png" height="24" width="24" />
|
||||
|
|
@ -181,7 +181,7 @@
|
|||
</td>
|
||||
<td style="padding-left: 4px; padding-right: 4px">
|
||||
<a
|
||||
href="https://github.com/appwrite/appwrite"
|
||||
href="{{githubUrl}}"
|
||||
class="social-icon"
|
||||
>
|
||||
<img src="https://cloud.appwrite.io/images/mails/github.png" height="24" width="24" />
|
||||
|
|
@ -191,11 +191,11 @@
|
|||
</table>
|
||||
<table style="width: auto; margin: 0 auto; margin-top: 60px">
|
||||
<tr>
|
||||
<td><a href="https://appwrite.io/terms">Terms</a></td>
|
||||
<td><a href="{{termsUrl}}">Terms</a></td>
|
||||
<td style="color: #e8e9f0">
|
||||
<div style="margin: 0 8px">|</div>
|
||||
</td>
|
||||
<td><a href="https://appwrite.io/privacy">Privacy</a></td>
|
||||
<td><a href="{{privacyUrl}}">Privacy</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p style="text-align: center" align="center">
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Amazon',
|
||||
],
|
||||
'apple' => [
|
||||
'name' => 'Apple',
|
||||
|
|
@ -21,6 +22,7 @@ return [
|
|||
'form' => 'apple.phtml', // Preparation for adding ability to customized OAuth UI forms, currently handled hardcoded.
|
||||
'beta' => true,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Apple',
|
||||
],
|
||||
'auth0' => [
|
||||
'name' => 'Auth0',
|
||||
|
|
@ -31,6 +33,7 @@ return [
|
|||
'form' => 'auth0.phtml',
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Auth0',
|
||||
],
|
||||
'authentik' => [
|
||||
'name' => 'Authentik',
|
||||
|
|
@ -41,6 +44,7 @@ return [
|
|||
'form' => 'authentik.phtml',
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Authentik',
|
||||
],
|
||||
'autodesk' => [
|
||||
'name' => 'Autodesk',
|
||||
|
|
@ -51,6 +55,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Autodesk',
|
||||
],
|
||||
'bitbucket' => [
|
||||
'name' => 'BitBucket',
|
||||
|
|
@ -61,6 +66,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Bitbucket',
|
||||
],
|
||||
'bitly' => [
|
||||
'name' => 'Bitly',
|
||||
|
|
@ -70,7 +76,8 @@ return [
|
|||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Bitly',
|
||||
],
|
||||
'box' => [
|
||||
'name' => 'Box',
|
||||
|
|
@ -80,7 +87,8 @@ return [
|
|||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Box',
|
||||
],
|
||||
'dailymotion' => [
|
||||
'name' => 'Dailymotion',
|
||||
|
|
@ -90,7 +98,8 @@ return [
|
|||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Dailymotion',
|
||||
],
|
||||
'discord' => [
|
||||
'name' => 'Discord',
|
||||
|
|
@ -101,6 +110,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Discord',
|
||||
],
|
||||
'disqus' => [
|
||||
'name' => 'Disqus',
|
||||
|
|
@ -111,6 +121,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Disqus',
|
||||
],
|
||||
'dropbox' => [
|
||||
'name' => 'Dropbox',
|
||||
|
|
@ -121,6 +132,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Dropbox',
|
||||
],
|
||||
'etsy' => [
|
||||
'name' => 'Etsy',
|
||||
|
|
@ -131,6 +143,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Etsy',
|
||||
],
|
||||
'facebook' => [
|
||||
'name' => 'Facebook',
|
||||
|
|
@ -141,6 +154,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Facebook',
|
||||
],
|
||||
'figma' => [
|
||||
'name' => 'Figma',
|
||||
|
|
@ -151,6 +165,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Figma',
|
||||
],
|
||||
'github' => [
|
||||
'name' => 'GitHub',
|
||||
|
|
@ -161,6 +176,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Github',
|
||||
],
|
||||
'gitlab' => [
|
||||
'name' => 'GitLab',
|
||||
|
|
@ -171,6 +187,7 @@ return [
|
|||
'form' => 'gitlab.phtml',
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Gitlab',
|
||||
],
|
||||
'google' => [
|
||||
'name' => 'Google',
|
||||
|
|
@ -181,6 +198,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Google',
|
||||
],
|
||||
'linkedin' => [
|
||||
'name' => 'LinkedIn',
|
||||
|
|
@ -191,6 +209,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Linkedin',
|
||||
],
|
||||
'microsoft' => [
|
||||
'name' => 'Microsoft',
|
||||
|
|
@ -201,6 +220,7 @@ return [
|
|||
'form' => 'microsoft.phtml',
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Microsoft',
|
||||
],
|
||||
'notion' => [
|
||||
'name' => 'Notion',
|
||||
|
|
@ -211,6 +231,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Notion',
|
||||
],
|
||||
'oidc' => [
|
||||
'name' => 'OpenID Connect',
|
||||
|
|
@ -221,6 +242,7 @@ return [
|
|||
'form' => 'oidc.phtml',
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Oidc',
|
||||
],
|
||||
'okta' => [
|
||||
'name' => 'Okta',
|
||||
|
|
@ -231,6 +253,7 @@ return [
|
|||
'form' => 'okta.phtml',
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Okta',
|
||||
],
|
||||
'paypal' => [
|
||||
'name' => 'PayPal',
|
||||
|
|
@ -240,7 +263,8 @@ return [
|
|||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Paypal',
|
||||
],
|
||||
'paypalSandbox' => [
|
||||
'name' => 'PayPal Sandbox',
|
||||
|
|
@ -250,7 +274,8 @@ return [
|
|||
'sandbox' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Paypal',
|
||||
],
|
||||
'podio' => [
|
||||
'name' => 'Podio',
|
||||
|
|
@ -261,6 +286,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Podio',
|
||||
],
|
||||
'salesforce' => [
|
||||
'name' => 'Salesforce',
|
||||
|
|
@ -271,6 +297,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Salesforce',
|
||||
],
|
||||
'slack' => [
|
||||
'name' => 'Slack',
|
||||
|
|
@ -281,6 +308,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Slack',
|
||||
],
|
||||
'spotify' => [
|
||||
'name' => 'Spotify',
|
||||
|
|
@ -291,6 +319,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Spotify',
|
||||
],
|
||||
'stripe' => [
|
||||
'name' => 'Stripe',
|
||||
|
|
@ -300,7 +329,8 @@ return [
|
|||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Stripe',
|
||||
],
|
||||
'tradeshift' => [
|
||||
'name' => 'Tradeshift',
|
||||
|
|
@ -311,6 +341,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Tradeshift',
|
||||
],
|
||||
'tradeshiftBox' => [
|
||||
'name' => 'Tradeshift Sandbox',
|
||||
|
|
@ -321,6 +352,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Tradeshift',
|
||||
],
|
||||
'twitch' => [
|
||||
'name' => 'Twitch',
|
||||
|
|
@ -331,6 +363,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Twitch',
|
||||
],
|
||||
'wordpress' => [
|
||||
'name' => 'WordPress',
|
||||
|
|
@ -340,7 +373,8 @@ return [
|
|||
'sandbox' => false,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Wordpress',
|
||||
],
|
||||
'yahoo' => [
|
||||
'name' => 'Yahoo',
|
||||
|
|
@ -351,6 +385,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Yahoo',
|
||||
],
|
||||
'yammer' => [
|
||||
'name' => 'Yammer',
|
||||
|
|
@ -361,6 +396,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Yammer',
|
||||
],
|
||||
'yandex' => [
|
||||
'name' => 'Yandex',
|
||||
|
|
@ -371,6 +407,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Yandex',
|
||||
],
|
||||
'zoho' => [
|
||||
'name' => 'Zoho',
|
||||
|
|
@ -381,6 +418,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Zoho',
|
||||
],
|
||||
'zoom' => [
|
||||
'name' => 'Zoom',
|
||||
|
|
@ -391,6 +429,7 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Zoom',
|
||||
],
|
||||
// 'instagram' => [
|
||||
// 'name' => 'Instagram',
|
||||
|
|
@ -399,6 +438,7 @@ return [
|
|||
// 'enabled' => false,
|
||||
// 'beta' => false,
|
||||
// 'mock' => false,
|
||||
// 'class' => 'Appwrite\\Auth\\OAuth2\\Instagram',
|
||||
// ],
|
||||
// 'twitter' => [
|
||||
// 'name' => 'twitter',
|
||||
|
|
@ -407,6 +447,7 @@ return [
|
|||
// 'enabled' => false,
|
||||
// 'beta' => false,
|
||||
// 'mock' => false,
|
||||
// 'class' => 'Appwrite\\Auth\\OAuth2\\Twitter',
|
||||
// ],
|
||||
|
||||
// Keep Last
|
||||
|
|
@ -419,5 +460,6 @@ return [
|
|||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => true,
|
||||
'class' => 'Appwrite\\Auth\\OAuth2\\Mock',
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ return [
|
|||
[
|
||||
'key' => 'web',
|
||||
'name' => 'Web',
|
||||
'version' => '17.0.2',
|
||||
'version' => '18.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-web',
|
||||
'package' => 'https://www.npmjs.com/package/appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -59,7 +59,7 @@ return [
|
|||
[
|
||||
'key' => 'flutter',
|
||||
'name' => 'Flutter',
|
||||
'version' => '15.0.2',
|
||||
'version' => '16.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-flutter',
|
||||
'package' => 'https://pub.dev/packages/appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -77,7 +77,7 @@ return [
|
|||
[
|
||||
'key' => 'apple',
|
||||
'name' => 'Apple',
|
||||
'version' => '9.0.1',
|
||||
'version' => '10.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-apple',
|
||||
'package' => 'https://github.com/appwrite/sdk-for-apple',
|
||||
'enabled' => true,
|
||||
|
|
@ -112,7 +112,7 @@ return [
|
|||
[
|
||||
'key' => 'android',
|
||||
'name' => 'Android',
|
||||
'version' => '7.0.1',
|
||||
'version' => '8.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-android',
|
||||
'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-android',
|
||||
'enabled' => true,
|
||||
|
|
@ -134,7 +134,7 @@ return [
|
|||
[
|
||||
'key' => 'react-native',
|
||||
'name' => 'React Native',
|
||||
'version' => '0.7.4',
|
||||
'version' => '0.9.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-react-native',
|
||||
'package' => 'https://npmjs.com/package/react-native-appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -199,7 +199,7 @@ return [
|
|||
[
|
||||
'key' => 'web',
|
||||
'name' => 'Console',
|
||||
'version' => '1.2.1',
|
||||
'version' => '1.3.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-console',
|
||||
'package' => '',
|
||||
'enabled' => true,
|
||||
|
|
@ -245,7 +245,7 @@ return [
|
|||
[
|
||||
'key' => 'nodejs',
|
||||
'name' => 'Node.js',
|
||||
'version' => '16.1.0-rc.1',
|
||||
'version' => '17.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-node',
|
||||
'package' => 'https://www.npmjs.com/package/node-appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -263,7 +263,7 @@ return [
|
|||
[
|
||||
'key' => 'deno',
|
||||
'name' => 'Deno',
|
||||
'version' => '14.1.0-rc.1',
|
||||
'version' => '15.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-deno',
|
||||
'package' => 'https://deno.land/x/appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -281,7 +281,7 @@ return [
|
|||
[
|
||||
'key' => 'php',
|
||||
'name' => 'PHP',
|
||||
'version' => '14.1.0-rc.1',
|
||||
'version' => '15.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-php',
|
||||
'package' => 'https://packagist.org/packages/appwrite/appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -299,7 +299,7 @@ return [
|
|||
[
|
||||
'key' => 'python',
|
||||
'name' => 'Python',
|
||||
'version' => '10.1.0-rc.1',
|
||||
'version' => '11.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-python',
|
||||
'package' => 'https://pypi.org/project/appwrite/',
|
||||
'enabled' => true,
|
||||
|
|
@ -317,7 +317,7 @@ return [
|
|||
[
|
||||
'key' => 'ruby',
|
||||
'name' => 'Ruby',
|
||||
'version' => '15.1.0-rc.1',
|
||||
'version' => '16.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-ruby',
|
||||
'package' => 'https://rubygems.org/gems/appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -335,7 +335,7 @@ return [
|
|||
[
|
||||
'key' => 'go',
|
||||
'name' => 'Go',
|
||||
'version' => '0.6.0-rc.1',
|
||||
'version' => '0.8.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-go',
|
||||
'package' => 'https://github.com/appwrite/sdk-for-go',
|
||||
'enabled' => true,
|
||||
|
|
@ -353,7 +353,7 @@ return [
|
|||
[
|
||||
'key' => 'dotnet',
|
||||
'name' => '.NET',
|
||||
'version' => '0.13.0-rc.1',
|
||||
'version' => '0.15.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-dotnet',
|
||||
'package' => 'https://www.nuget.org/packages/Appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -371,7 +371,7 @@ return [
|
|||
[
|
||||
'key' => 'dart',
|
||||
'name' => 'Dart',
|
||||
'version' => '15.1.0-rc.1',
|
||||
'version' => '16.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-dart',
|
||||
'package' => 'https://pub.dev/packages/dart_appwrite',
|
||||
'enabled' => true,
|
||||
|
|
@ -389,7 +389,7 @@ return [
|
|||
[
|
||||
'key' => 'kotlin',
|
||||
'name' => 'Kotlin',
|
||||
'version' => '8.1.0-rc.1',
|
||||
'version' => '9.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-kotlin',
|
||||
'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-kotlin',
|
||||
'enabled' => true,
|
||||
|
|
@ -411,7 +411,7 @@ return [
|
|||
[
|
||||
'key' => 'swift',
|
||||
'name' => 'Swift',
|
||||
'version' => '9.1.0-rc.1',
|
||||
'version' => '10.0.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-swift',
|
||||
'package' => 'https://github.com/appwrite/sdk-for-swift',
|
||||
'enabled' => true,
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ $member = [
|
|||
'subscribers.write',
|
||||
'subscribers.read',
|
||||
'assistant.read',
|
||||
'rules.read'
|
||||
];
|
||||
|
||||
$admins = [
|
||||
|
|
@ -58,6 +59,10 @@ $admins = [
|
|||
'health.read',
|
||||
'functions.read',
|
||||
'functions.write',
|
||||
'sites.read',
|
||||
'sites.write',
|
||||
'log.read',
|
||||
'log.write',
|
||||
'execution.read',
|
||||
'execution.write',
|
||||
'rules.read',
|
||||
|
|
@ -76,6 +81,8 @@ $admins = [
|
|||
'topics.read',
|
||||
'subscribers.write',
|
||||
'subscribers.read',
|
||||
'tokens.read',
|
||||
'tokens.write',
|
||||
];
|
||||
|
||||
return [
|
||||
|
|
|
|||
|
|
@ -6,4 +6,4 @@
|
|||
|
||||
use Appwrite\Runtimes\Runtimes;
|
||||
|
||||
return (new Runtimes('v4'))->getAll();
|
||||
return (new Runtimes('v5'))->getAll();
|
||||
|
|
|
|||
|
|
@ -64,6 +64,18 @@ return [ // List of publicly visible scopes
|
|||
'functions.write' => [
|
||||
'description' => 'Access to create, update, and delete your project\'s functions and code deployments',
|
||||
],
|
||||
'sites.read' => [
|
||||
'description' => 'Access to read your project\'s sites and deployments',
|
||||
],
|
||||
'sites.write' => [
|
||||
'description' => 'Access to create, update, and delete your project\'s sites and deployments',
|
||||
],
|
||||
'log.read' => [
|
||||
'description' => 'Access to read your site\'s logs',
|
||||
],
|
||||
'log.write' => [
|
||||
'description' => 'Access to update, and delete your site\'s logs',
|
||||
],
|
||||
'execution.read' => [
|
||||
'description' => 'Access to read your project\'s execution logs',
|
||||
],
|
||||
|
|
@ -130,4 +142,10 @@ return [ // List of publicly visible scopes
|
|||
'assistant.read' => [
|
||||
'description' => 'Access to read the Assistant service',
|
||||
],
|
||||
'tokens.read' => [
|
||||
'description' => 'Access to read your project\'s tokens',
|
||||
],
|
||||
'tokens.write' => [
|
||||
'description' => 'Access to create, update, and delete your project\'s tokens',
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -170,12 +170,25 @@ return [
|
|||
'optional' => false,
|
||||
'icon' => '',
|
||||
],
|
||||
'sites' => [
|
||||
'key' => 'sites',
|
||||
'name' => 'Sites',
|
||||
'subtitle' => 'The Sites Service allows you view, create and manage your web applications.',
|
||||
'description' => '/docs/services/sites.md',
|
||||
'controller' => '', // Uses modules
|
||||
'sdk' => true,
|
||||
'docs' => true,
|
||||
'docsUrl' => 'https://appwrite.io/docs/sites',
|
||||
'tests' => false,
|
||||
'optional' => true,
|
||||
'icon' => '/images/services/sites.png',
|
||||
],
|
||||
'functions' => [
|
||||
'key' => 'functions',
|
||||
'name' => 'Functions',
|
||||
'subtitle' => 'The Functions Service allows you view, create and manage your Cloud Functions.',
|
||||
'description' => '/docs/services/functions.md',
|
||||
'controller' => 'api/functions.php',
|
||||
'controller' => '', // Uses modules
|
||||
'sdk' => true,
|
||||
'docs' => true,
|
||||
'docsUrl' => 'https://appwrite.io/docs/functions',
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use Appwrite\Functions\Specification;
|
||||
use Appwrite\Platform\Modules\Compute\Specification;
|
||||
|
||||
return [
|
||||
Specification::S_05VCPU_512MB => [
|
||||
9762
app/config/specs/open-api3-1.7.x-client.json
Normal file
9762
app/config/specs/open-api3-1.7.x-client.json
Normal file
File diff suppressed because it is too large
Load diff
43665
app/config/specs/open-api3-1.7.x-console.json
Normal file
43665
app/config/specs/open-api3-1.7.x-console.json
Normal file
File diff suppressed because it is too large
Load diff
30205
app/config/specs/open-api3-1.7.x-server.json
Normal file
30205
app/config/specs/open-api3-1.7.x-server.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"version": "1.6.2",
|
||||
"version": "1.7.0",
|
||||
"title": "Appwrite",
|
||||
"description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)",
|
||||
"termsOfService": "https:\/\/appwrite.io\/policy\/terms",
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"group": "account",
|
||||
"weight": 9,
|
||||
"weight": 10,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -96,7 +96,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "create",
|
||||
"group": "account",
|
||||
"weight": 8,
|
||||
"weight": 9,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -181,7 +181,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateEmail",
|
||||
"group": "account",
|
||||
"weight": 34,
|
||||
"weight": 35,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -257,7 +257,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listIdentities",
|
||||
"group": "identities",
|
||||
"weight": 57,
|
||||
"weight": 58,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -316,7 +316,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteIdentity",
|
||||
"group": "identities",
|
||||
"weight": 58,
|
||||
"weight": 59,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -379,7 +379,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createJWT",
|
||||
"group": "tokens",
|
||||
"weight": 29,
|
||||
"weight": 30,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -428,7 +428,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listLogs",
|
||||
"group": "logs",
|
||||
"weight": 31,
|
||||
"weight": 32,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -494,7 +494,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMFA",
|
||||
"group": "mfa",
|
||||
"weight": 44,
|
||||
"weight": 45,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -564,7 +564,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 46,
|
||||
"weight": 47,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -630,7 +630,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 47,
|
||||
"weight": 48,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -708,7 +708,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 51,
|
||||
"weight": 52,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -776,7 +776,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 52,
|
||||
"weight": 53,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -850,7 +850,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 53,
|
||||
"weight": 54,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -926,7 +926,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listMfaFactors",
|
||||
"group": "mfa",
|
||||
"weight": 45,
|
||||
"weight": 46,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -977,7 +977,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 50,
|
||||
"weight": 51,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1026,7 +1026,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 48,
|
||||
"weight": 49,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1075,7 +1075,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 49,
|
||||
"weight": 50,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1126,7 +1126,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateName",
|
||||
"group": "account",
|
||||
"weight": 32,
|
||||
"weight": 33,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1196,7 +1196,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updatePassword",
|
||||
"group": "account",
|
||||
"weight": 33,
|
||||
"weight": 34,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1271,7 +1271,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updatePhone",
|
||||
"group": "account",
|
||||
"weight": 35,
|
||||
"weight": 36,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1347,7 +1347,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getPrefs",
|
||||
"group": "account",
|
||||
"weight": 30,
|
||||
"weight": 31,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1396,7 +1396,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updatePrefs",
|
||||
"group": "account",
|
||||
"weight": 36,
|
||||
"weight": 37,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1466,7 +1466,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createRecovery",
|
||||
"group": "recovery",
|
||||
"weight": 38,
|
||||
"weight": 39,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1543,7 +1543,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateRecovery",
|
||||
"group": "recovery",
|
||||
"weight": 39,
|
||||
"weight": 40,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1625,7 +1625,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listSessions",
|
||||
"group": "sessions",
|
||||
"weight": 11,
|
||||
"weight": 12,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1667,7 +1667,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteSessions",
|
||||
"group": "sessions",
|
||||
"weight": 12,
|
||||
"weight": 13,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1718,7 +1718,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createAnonymousSession",
|
||||
"group": "sessions",
|
||||
"weight": 17,
|
||||
"weight": 18,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1767,7 +1767,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createEmailPasswordSession",
|
||||
"group": "sessions",
|
||||
"weight": 16,
|
||||
"weight": 17,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1841,7 +1841,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMagicURLSession",
|
||||
"group": "sessions",
|
||||
"weight": 26,
|
||||
"weight": 27,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": true,
|
||||
|
|
@ -1908,7 +1908,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createOAuth2Session",
|
||||
"group": "sessions",
|
||||
"weight": 19,
|
||||
"weight": 20,
|
||||
"cookies": false,
|
||||
"type": "webAuth",
|
||||
"deprecated": false,
|
||||
|
|
@ -2050,7 +2050,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updatePhoneSession",
|
||||
"group": "sessions",
|
||||
"weight": 27,
|
||||
"weight": 28,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": true,
|
||||
|
|
@ -2124,7 +2124,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createSession",
|
||||
"group": "sessions",
|
||||
"weight": 18,
|
||||
"weight": 19,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2198,7 +2198,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getSession",
|
||||
"group": "sessions",
|
||||
"weight": 13,
|
||||
"weight": 14,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2259,7 +2259,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateSession",
|
||||
"group": "sessions",
|
||||
"weight": 15,
|
||||
"weight": 16,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2313,7 +2313,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteSession",
|
||||
"group": "sessions",
|
||||
"weight": 14,
|
||||
"weight": 15,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2376,7 +2376,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateStatus",
|
||||
"group": "account",
|
||||
"weight": 37,
|
||||
"weight": 38,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2427,7 +2427,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createPushTarget",
|
||||
"group": "pushTargets",
|
||||
"weight": 54,
|
||||
"weight": 55,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2506,7 +2506,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updatePushTarget",
|
||||
"group": "pushTargets",
|
||||
"weight": 55,
|
||||
"weight": 56,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2577,7 +2577,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deletePushTarget",
|
||||
"group": "pushTargets",
|
||||
"weight": 56,
|
||||
"weight": 57,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2638,7 +2638,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createEmailToken",
|
||||
"group": "tokens",
|
||||
"weight": 25,
|
||||
"weight": 26,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2720,7 +2720,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMagicURLToken",
|
||||
"group": "tokens",
|
||||
"weight": 24,
|
||||
"weight": 25,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2800,7 +2800,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createOAuth2Token",
|
||||
"group": "tokens",
|
||||
"weight": 23,
|
||||
"weight": 24,
|
||||
"cookies": false,
|
||||
"type": "webAuth",
|
||||
"deprecated": false,
|
||||
|
|
@ -2942,7 +2942,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createPhoneToken",
|
||||
"group": "tokens",
|
||||
"weight": 28,
|
||||
"weight": 29,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -3019,7 +3019,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createVerification",
|
||||
"group": "verification",
|
||||
"weight": 40,
|
||||
"weight": 41,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -3087,7 +3087,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateVerification",
|
||||
"group": "verification",
|
||||
"weight": 41,
|
||||
"weight": 42,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -3163,7 +3163,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createPhoneVerification",
|
||||
"group": "verification",
|
||||
"weight": 42,
|
||||
"weight": 43,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -3215,7 +3215,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updatePhoneVerification",
|
||||
"group": "verification",
|
||||
"weight": 43,
|
||||
"weight": 44,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -3284,7 +3284,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getBrowser",
|
||||
"group": null,
|
||||
"weight": 60,
|
||||
"weight": 61,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -3381,13 +3381,13 @@
|
|||
},
|
||||
{
|
||||
"name": "quality",
|
||||
"description": "Image quality. Pass an integer between 0 to 100. Defaults to 100.",
|
||||
"description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"x-example": 0,
|
||||
"default": 100
|
||||
"x-example": -1,
|
||||
"default": -1
|
||||
},
|
||||
"in": "query"
|
||||
}
|
||||
|
|
@ -3410,7 +3410,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getCreditCard",
|
||||
"group": null,
|
||||
"weight": 59,
|
||||
"weight": 60,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -3513,13 +3513,13 @@
|
|||
},
|
||||
{
|
||||
"name": "quality",
|
||||
"description": "Image quality. Pass an integer between 0 to 100. Defaults to 100.",
|
||||
"description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"x-example": 0,
|
||||
"default": 100
|
||||
"x-example": -1,
|
||||
"default": -1
|
||||
},
|
||||
"in": "query"
|
||||
}
|
||||
|
|
@ -3542,7 +3542,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFavicon",
|
||||
"group": null,
|
||||
"weight": 63,
|
||||
"weight": 64,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -3600,7 +3600,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFlag",
|
||||
"group": null,
|
||||
"weight": 61,
|
||||
"weight": 62,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -4059,13 +4059,13 @@
|
|||
},
|
||||
{
|
||||
"name": "quality",
|
||||
"description": "Image quality. Pass an integer between 0 to 100. Defaults to 100.",
|
||||
"description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"x-example": 0,
|
||||
"default": 100
|
||||
"x-example": -1,
|
||||
"default": -1
|
||||
},
|
||||
"in": "query"
|
||||
}
|
||||
|
|
@ -4088,7 +4088,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getImage",
|
||||
"group": null,
|
||||
"weight": 62,
|
||||
"weight": 63,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -4170,7 +4170,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getInitials",
|
||||
"group": null,
|
||||
"weight": 65,
|
||||
"weight": 66,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -4262,7 +4262,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getQR",
|
||||
"group": null,
|
||||
"weight": 64,
|
||||
"weight": 65,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -4361,7 +4361,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listDocuments",
|
||||
"group": "documents",
|
||||
"weight": 109,
|
||||
"weight": 110,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -4446,7 +4446,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createDocument",
|
||||
"group": "documents",
|
||||
"weight": 108,
|
||||
"weight": 109,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -4465,6 +4465,11 @@
|
|||
"methods": [
|
||||
{
|
||||
"name": "createDocument",
|
||||
"auth": {
|
||||
"Session": [],
|
||||
"Key": [],
|
||||
"JWT": []
|
||||
},
|
||||
"parameters": [
|
||||
"databaseId",
|
||||
"collectionId",
|
||||
|
|
@ -4582,7 +4587,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getDocument",
|
||||
"group": "documents",
|
||||
"weight": 110,
|
||||
"weight": 111,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -4677,7 +4682,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateDocument",
|
||||
"group": "documents",
|
||||
"weight": 112,
|
||||
"weight": 113,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -4776,7 +4781,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteDocument",
|
||||
"group": "documents",
|
||||
"weight": 115,
|
||||
"weight": 116,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -4860,12 +4865,12 @@
|
|||
"x-appwrite": {
|
||||
"method": "listExecutions",
|
||||
"group": "executions",
|
||||
"weight": 308,
|
||||
"weight": 391,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "functions\/list-executions.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/list-executions.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the current user function execution logs. You can use the query params to filter your results.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
|
|
@ -4910,17 +4915,6 @@
|
|||
"default": []
|
||||
},
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"name": "search",
|
||||
"description": "Search term to filter your list results. Max length: 256 chars.",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<SEARCH>",
|
||||
"default": ""
|
||||
},
|
||||
"in": "query"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -4946,12 +4940,12 @@
|
|||
"x-appwrite": {
|
||||
"method": "createExecution",
|
||||
"group": "executions",
|
||||
"weight": 307,
|
||||
"weight": 389,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "functions\/create-execution.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/create-execution.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterTrigger a function execution. The returned object will return you the current execution status. You can ping the `Get Execution` endpoint to get updates on the current execution status. Once this endpoint is called, your function execution process will start asynchronously.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
|
|
@ -5061,12 +5055,12 @@
|
|||
"x-appwrite": {
|
||||
"method": "getExecution",
|
||||
"group": "executions",
|
||||
"weight": 309,
|
||||
"weight": 390,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "functions\/get-execution.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/get-execution.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function execution log by its unique ID.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
|
|
@ -5135,7 +5129,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "query",
|
||||
"group": "graphql",
|
||||
"weight": 333,
|
||||
"weight": 305,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"deprecated": false,
|
||||
|
|
@ -5187,7 +5181,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "mutation",
|
||||
"group": "graphql",
|
||||
"weight": 332,
|
||||
"weight": 304,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"deprecated": false,
|
||||
|
|
@ -5239,7 +5233,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"group": null,
|
||||
"weight": 120,
|
||||
"weight": 121,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5291,7 +5285,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listCodes",
|
||||
"group": null,
|
||||
"weight": 121,
|
||||
"weight": 122,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5343,7 +5337,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listContinents",
|
||||
"group": null,
|
||||
"weight": 125,
|
||||
"weight": 126,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5395,7 +5389,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listCountries",
|
||||
"group": null,
|
||||
"weight": 122,
|
||||
"weight": 123,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5447,7 +5441,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listCountriesEU",
|
||||
"group": null,
|
||||
"weight": 123,
|
||||
"weight": 124,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5499,7 +5493,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listCountriesPhones",
|
||||
"group": null,
|
||||
"weight": 124,
|
||||
"weight": 125,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5551,7 +5545,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listCurrencies",
|
||||
"group": null,
|
||||
"weight": 126,
|
||||
"weight": 127,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5603,7 +5597,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listLanguages",
|
||||
"group": null,
|
||||
"weight": 127,
|
||||
"weight": 128,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5655,7 +5649,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 378,
|
||||
"weight": 351,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5738,7 +5732,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 382,
|
||||
"weight": 355,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5813,7 +5807,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listFiles",
|
||||
"group": "files",
|
||||
"weight": 210,
|
||||
"weight": 211,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5899,7 +5893,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createFile",
|
||||
"group": "files",
|
||||
"weight": 209,
|
||||
"weight": 210,
|
||||
"cookies": false,
|
||||
"type": "upload",
|
||||
"deprecated": false,
|
||||
|
|
@ -5997,7 +5991,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFile",
|
||||
"group": "files",
|
||||
"weight": 211,
|
||||
"weight": 212,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -6069,7 +6063,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateFile",
|
||||
"group": "files",
|
||||
"weight": 216,
|
||||
"weight": 217,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -6158,7 +6152,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteFile",
|
||||
"group": "files",
|
||||
"weight": 217,
|
||||
"weight": 218,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -6225,7 +6219,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFileDownload",
|
||||
"group": "files",
|
||||
"weight": 213,
|
||||
"weight": 214,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -6272,6 +6266,17 @@
|
|||
"x-example": "<FILE_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"name": "token",
|
||||
"description": "File token for accessing this file.",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN>",
|
||||
"default": ""
|
||||
},
|
||||
"in": "query"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -6292,7 +6297,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFilePreview",
|
||||
"group": "files",
|
||||
"weight": 212,
|
||||
"weight": 213,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -6390,13 +6395,13 @@
|
|||
},
|
||||
{
|
||||
"name": "quality",
|
||||
"description": "Preview image quality. Pass an integer between 0 to 100. Defaults to 100.",
|
||||
"description": "Preview image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"x-example": 0,
|
||||
"default": 100
|
||||
"x-example": -1,
|
||||
"default": -1
|
||||
},
|
||||
"in": "query"
|
||||
},
|
||||
|
|
@ -6478,7 +6483,6 @@
|
|||
"enum": [
|
||||
"jpg",
|
||||
"jpeg",
|
||||
"gif",
|
||||
"png",
|
||||
"webp",
|
||||
"heic",
|
||||
|
|
@ -6489,6 +6493,17 @@
|
|||
"default": ""
|
||||
},
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"name": "token",
|
||||
"description": "File token for accessing this file.",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN>",
|
||||
"default": ""
|
||||
},
|
||||
"in": "query"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -6509,7 +6524,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFileView",
|
||||
"group": "files",
|
||||
"weight": 214,
|
||||
"weight": 215,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -6556,6 +6571,17 @@
|
|||
"x-example": "<FILE_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"name": "token",
|
||||
"description": "File token for accessing this file.",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN>",
|
||||
"default": ""
|
||||
},
|
||||
"in": "query"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -6583,7 +6609,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "list",
|
||||
"group": "teams",
|
||||
"weight": 221,
|
||||
"weight": 222,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -6659,7 +6685,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "create",
|
||||
"group": "teams",
|
||||
"weight": 220,
|
||||
"weight": 221,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -6744,7 +6770,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"group": "teams",
|
||||
"weight": 222,
|
||||
"weight": 223,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -6806,7 +6832,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateName",
|
||||
"group": "teams",
|
||||
"weight": 224,
|
||||
"weight": 225,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -6880,7 +6906,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "delete",
|
||||
"group": "teams",
|
||||
"weight": 226,
|
||||
"weight": 227,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -6944,7 +6970,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listMemberships",
|
||||
"group": "memberships",
|
||||
"weight": 228,
|
||||
"weight": 229,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -6984,7 +7010,7 @@
|
|||
},
|
||||
{
|
||||
"name": "queries",
|
||||
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm",
|
||||
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "array",
|
||||
|
|
@ -7030,7 +7056,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMembership",
|
||||
"group": "memberships",
|
||||
"weight": 227,
|
||||
"weight": 228,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -7141,7 +7167,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getMembership",
|
||||
"group": "memberships",
|
||||
"weight": 229,
|
||||
"weight": 230,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -7213,7 +7239,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMembership",
|
||||
"group": "memberships",
|
||||
"weight": 230,
|
||||
"weight": 231,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -7300,7 +7326,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteMembership",
|
||||
"group": "memberships",
|
||||
"weight": 232,
|
||||
"weight": 233,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -7374,7 +7400,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMembershipStatus",
|
||||
"group": "memberships",
|
||||
"weight": 231,
|
||||
"weight": 232,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -7472,7 +7498,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getPrefs",
|
||||
"group": "teams",
|
||||
"weight": 223,
|
||||
"weight": 224,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -7533,7 +7559,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updatePrefs",
|
||||
"group": "teams",
|
||||
"weight": 225,
|
||||
"weight": 226,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -7634,6 +7660,10 @@
|
|||
"name": "users",
|
||||
"description": "The Users service allows you to manage your project users."
|
||||
},
|
||||
{
|
||||
"name": "sites",
|
||||
"description": "The Sites Service allows you view, create and manage your web applications."
|
||||
},
|
||||
{
|
||||
"name": "functions",
|
||||
"description": "The Functions Service allows you view, create and manage your Cloud Functions."
|
||||
|
|
@ -9257,7 +9287,7 @@
|
|||
},
|
||||
"duration": {
|
||||
"type": "number",
|
||||
"description": "Function execution duration in seconds.",
|
||||
"description": "Resource(function\/site) execution duration in seconds.",
|
||||
"x-example": 0.4,
|
||||
"format": "double"
|
||||
},
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
9836
app/config/specs/swagger2-1.7.x-client.json
Normal file
9836
app/config/specs/swagger2-1.7.x-client.json
Normal file
File diff suppressed because it is too large
Load diff
43962
app/config/specs/swagger2-1.7.x-console.json
Normal file
43962
app/config/specs/swagger2-1.7.x-console.json
Normal file
File diff suppressed because it is too large
Load diff
30468
app/config/specs/swagger2-1.7.x-server.json
Normal file
30468
app/config/specs/swagger2-1.7.x-server.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"version": "1.6.2",
|
||||
"version": "1.7.0",
|
||||
"title": "Appwrite",
|
||||
"description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)",
|
||||
"termsOfService": "https:\/\/appwrite.io\/policy\/terms",
|
||||
|
|
@ -87,7 +87,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"group": "account",
|
||||
"weight": 9,
|
||||
"weight": 10,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -138,7 +138,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "create",
|
||||
"group": "account",
|
||||
"weight": 8,
|
||||
"weight": 9,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -229,7 +229,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateEmail",
|
||||
"group": "account",
|
||||
"weight": 34,
|
||||
"weight": 35,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -307,7 +307,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listIdentities",
|
||||
"group": "identities",
|
||||
"weight": 57,
|
||||
"weight": 58,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -369,7 +369,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteIdentity",
|
||||
"group": "identities",
|
||||
"weight": 58,
|
||||
"weight": 59,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -432,7 +432,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createJWT",
|
||||
"group": "tokens",
|
||||
"weight": 29,
|
||||
"weight": 30,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -481,7 +481,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listLogs",
|
||||
"group": "logs",
|
||||
"weight": 31,
|
||||
"weight": 32,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -548,7 +548,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMFA",
|
||||
"group": "mfa",
|
||||
"weight": 44,
|
||||
"weight": 45,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -621,7 +621,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 46,
|
||||
"weight": 47,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -687,7 +687,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 47,
|
||||
"weight": 48,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -766,7 +766,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteMfaAuthenticator",
|
||||
"group": "mfa",
|
||||
"weight": 51,
|
||||
"weight": 52,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -834,7 +834,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 52,
|
||||
"weight": 53,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -911,7 +911,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMfaChallenge",
|
||||
"group": "mfa",
|
||||
"weight": 53,
|
||||
"weight": 54,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -989,7 +989,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listMfaFactors",
|
||||
"group": "mfa",
|
||||
"weight": 45,
|
||||
"weight": 46,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1040,7 +1040,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 50,
|
||||
"weight": 51,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1091,7 +1091,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 48,
|
||||
"weight": 49,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1142,7 +1142,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMfaRecoveryCodes",
|
||||
"group": "mfa",
|
||||
"weight": 49,
|
||||
"weight": 50,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1195,7 +1195,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateName",
|
||||
"group": "account",
|
||||
"weight": 32,
|
||||
"weight": 33,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1268,7 +1268,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updatePassword",
|
||||
"group": "account",
|
||||
"weight": 33,
|
||||
"weight": 34,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1347,7 +1347,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updatePhone",
|
||||
"group": "account",
|
||||
"weight": 35,
|
||||
"weight": 36,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1425,7 +1425,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getPrefs",
|
||||
"group": "account",
|
||||
"weight": 30,
|
||||
"weight": 31,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1476,7 +1476,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updatePrefs",
|
||||
"group": "account",
|
||||
"weight": 36,
|
||||
"weight": 37,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1549,7 +1549,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createRecovery",
|
||||
"group": "recovery",
|
||||
"weight": 38,
|
||||
"weight": 39,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1630,7 +1630,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateRecovery",
|
||||
"group": "recovery",
|
||||
"weight": 39,
|
||||
"weight": 40,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1715,7 +1715,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listSessions",
|
||||
"group": "sessions",
|
||||
"weight": 11,
|
||||
"weight": 12,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1761,7 +1761,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteSessions",
|
||||
"group": "sessions",
|
||||
"weight": 12,
|
||||
"weight": 13,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1814,7 +1814,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createAnonymousSession",
|
||||
"group": "sessions",
|
||||
"weight": 17,
|
||||
"weight": 18,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1865,7 +1865,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createEmailPasswordSession",
|
||||
"group": "sessions",
|
||||
"weight": 16,
|
||||
"weight": 17,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -1943,7 +1943,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMagicURLSession",
|
||||
"group": "sessions",
|
||||
"weight": 26,
|
||||
"weight": 27,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": true,
|
||||
|
|
@ -2016,7 +2016,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createOAuth2Session",
|
||||
"group": "sessions",
|
||||
"weight": 19,
|
||||
"weight": 20,
|
||||
"cookies": false,
|
||||
"type": "webAuth",
|
||||
"deprecated": false,
|
||||
|
|
@ -2153,7 +2153,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updatePhoneSession",
|
||||
"group": "sessions",
|
||||
"weight": 27,
|
||||
"weight": 28,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": true,
|
||||
|
|
@ -2231,7 +2231,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createSession",
|
||||
"group": "sessions",
|
||||
"weight": 18,
|
||||
"weight": 19,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2307,7 +2307,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getSession",
|
||||
"group": "sessions",
|
||||
"weight": 13,
|
||||
"weight": 14,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2368,7 +2368,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateSession",
|
||||
"group": "sessions",
|
||||
"weight": 15,
|
||||
"weight": 16,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2424,7 +2424,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteSession",
|
||||
"group": "sessions",
|
||||
"weight": 14,
|
||||
"weight": 15,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2487,7 +2487,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateStatus",
|
||||
"group": "account",
|
||||
"weight": 37,
|
||||
"weight": 38,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2540,7 +2540,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createPushTarget",
|
||||
"group": "pushTargets",
|
||||
"weight": 54,
|
||||
"weight": 55,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2624,7 +2624,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updatePushTarget",
|
||||
"group": "pushTargets",
|
||||
"weight": 55,
|
||||
"weight": 56,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2696,7 +2696,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deletePushTarget",
|
||||
"group": "pushTargets",
|
||||
"weight": 56,
|
||||
"weight": 57,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2757,7 +2757,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createEmailToken",
|
||||
"group": "tokens",
|
||||
"weight": 25,
|
||||
"weight": 26,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2844,7 +2844,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMagicURLToken",
|
||||
"group": "tokens",
|
||||
"weight": 24,
|
||||
"weight": 25,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -2932,7 +2932,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createOAuth2Token",
|
||||
"group": "tokens",
|
||||
"weight": 23,
|
||||
"weight": 24,
|
||||
"cookies": false,
|
||||
"type": "webAuth",
|
||||
"deprecated": false,
|
||||
|
|
@ -3069,7 +3069,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createPhoneToken",
|
||||
"group": "tokens",
|
||||
"weight": 28,
|
||||
"weight": 29,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -3150,7 +3150,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createVerification",
|
||||
"group": "verification",
|
||||
"weight": 40,
|
||||
"weight": 41,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -3221,7 +3221,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateVerification",
|
||||
"group": "verification",
|
||||
"weight": 41,
|
||||
"weight": 42,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -3301,7 +3301,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createPhoneVerification",
|
||||
"group": "verification",
|
||||
"weight": 42,
|
||||
"weight": 43,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -3355,7 +3355,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updatePhoneVerification",
|
||||
"group": "verification",
|
||||
"weight": 43,
|
||||
"weight": 44,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -3433,7 +3433,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getBrowser",
|
||||
"group": null,
|
||||
"weight": 60,
|
||||
"weight": 61,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -3524,12 +3524,12 @@
|
|||
},
|
||||
{
|
||||
"name": "quality",
|
||||
"description": "Image quality. Pass an integer between 0 to 100. Defaults to 100.",
|
||||
"description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.",
|
||||
"required": false,
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"x-example": 0,
|
||||
"default": 100,
|
||||
"x-example": -1,
|
||||
"default": -1,
|
||||
"in": "query"
|
||||
}
|
||||
]
|
||||
|
|
@ -3558,7 +3558,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getCreditCard",
|
||||
"group": null,
|
||||
"weight": 59,
|
||||
"weight": 60,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -3655,12 +3655,12 @@
|
|||
},
|
||||
{
|
||||
"name": "quality",
|
||||
"description": "Image quality. Pass an integer between 0 to 100. Defaults to 100.",
|
||||
"description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.",
|
||||
"required": false,
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"x-example": 0,
|
||||
"default": 100,
|
||||
"x-example": -1,
|
||||
"default": -1,
|
||||
"in": "query"
|
||||
}
|
||||
]
|
||||
|
|
@ -3689,7 +3689,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFavicon",
|
||||
"group": null,
|
||||
"weight": 63,
|
||||
"weight": 64,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -3752,7 +3752,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFlag",
|
||||
"group": null,
|
||||
"weight": 61,
|
||||
"weight": 62,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -4205,12 +4205,12 @@
|
|||
},
|
||||
{
|
||||
"name": "quality",
|
||||
"description": "Image quality. Pass an integer between 0 to 100. Defaults to 100.",
|
||||
"description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.",
|
||||
"required": false,
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"x-example": 0,
|
||||
"default": 100,
|
||||
"x-example": -1,
|
||||
"default": -1,
|
||||
"in": "query"
|
||||
}
|
||||
]
|
||||
|
|
@ -4239,7 +4239,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getImage",
|
||||
"group": null,
|
||||
"weight": 62,
|
||||
"weight": 63,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -4322,7 +4322,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getInitials",
|
||||
"group": null,
|
||||
"weight": 65,
|
||||
"weight": 66,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -4413,7 +4413,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getQR",
|
||||
"group": null,
|
||||
"weight": 64,
|
||||
"weight": 65,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -4504,7 +4504,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listDocuments",
|
||||
"group": "documents",
|
||||
"weight": 109,
|
||||
"weight": 110,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -4586,7 +4586,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createDocument",
|
||||
"group": "documents",
|
||||
"weight": 108,
|
||||
"weight": 109,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -4605,6 +4605,11 @@
|
|||
"methods": [
|
||||
{
|
||||
"name": "createDocument",
|
||||
"auth": {
|
||||
"Session": [],
|
||||
"Key": [],
|
||||
"JWT": []
|
||||
},
|
||||
"parameters": [
|
||||
"databaseId",
|
||||
"collectionId",
|
||||
|
|
@ -4720,7 +4725,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getDocument",
|
||||
"group": "documents",
|
||||
"weight": 110,
|
||||
"weight": 111,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -4810,7 +4815,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateDocument",
|
||||
"group": "documents",
|
||||
"weight": 112,
|
||||
"weight": 113,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -4907,7 +4912,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteDocument",
|
||||
"group": "documents",
|
||||
"weight": 115,
|
||||
"weight": 116,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -4985,12 +4990,12 @@
|
|||
"x-appwrite": {
|
||||
"method": "listExecutions",
|
||||
"group": "executions",
|
||||
"weight": 308,
|
||||
"weight": 391,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "functions\/list-executions.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/list-executions.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the current user function execution logs. You can use the query params to filter your results.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
|
|
@ -5032,15 +5037,6 @@
|
|||
},
|
||||
"default": [],
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"name": "search",
|
||||
"description": "Search term to filter your list results. Max length: 256 chars.",
|
||||
"required": false,
|
||||
"type": "string",
|
||||
"x-example": "<SEARCH>",
|
||||
"default": "",
|
||||
"in": "query"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -5068,12 +5064,12 @@
|
|||
"x-appwrite": {
|
||||
"method": "createExecution",
|
||||
"group": "executions",
|
||||
"weight": 307,
|
||||
"weight": 389,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "functions\/create-execution.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/create-execution.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterTrigger a function execution. The returned object will return you the current execution status. You can ping the `Get Execution` endpoint to get updates on the current execution status. Once this endpoint is called, your function execution process will start asynchronously.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
|
|
@ -5185,12 +5181,12 @@
|
|||
"x-appwrite": {
|
||||
"method": "getExecution",
|
||||
"group": "executions",
|
||||
"weight": 309,
|
||||
"weight": 390,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "functions\/get-execution.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/get-execution.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function execution log by its unique ID.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
|
|
@ -5257,7 +5253,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "query",
|
||||
"group": "graphql",
|
||||
"weight": 333,
|
||||
"weight": 305,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"deprecated": false,
|
||||
|
|
@ -5331,7 +5327,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "mutation",
|
||||
"group": "graphql",
|
||||
"weight": 332,
|
||||
"weight": 304,
|
||||
"cookies": false,
|
||||
"type": "graphql",
|
||||
"deprecated": false,
|
||||
|
|
@ -5403,7 +5399,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"group": null,
|
||||
"weight": 120,
|
||||
"weight": 121,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5455,7 +5451,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listCodes",
|
||||
"group": null,
|
||||
"weight": 121,
|
||||
"weight": 122,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5507,7 +5503,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listContinents",
|
||||
"group": null,
|
||||
"weight": 125,
|
||||
"weight": 126,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5559,7 +5555,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listCountries",
|
||||
"group": null,
|
||||
"weight": 122,
|
||||
"weight": 123,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5611,7 +5607,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listCountriesEU",
|
||||
"group": null,
|
||||
"weight": 123,
|
||||
"weight": 124,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5663,7 +5659,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listCountriesPhones",
|
||||
"group": null,
|
||||
"weight": 124,
|
||||
"weight": 125,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5715,7 +5711,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listCurrencies",
|
||||
"group": null,
|
||||
"weight": 126,
|
||||
"weight": 127,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5767,7 +5763,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listLanguages",
|
||||
"group": null,
|
||||
"weight": 127,
|
||||
"weight": 128,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5821,7 +5817,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 378,
|
||||
"weight": 351,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5906,7 +5902,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteSubscriber",
|
||||
"group": "subscribers",
|
||||
"weight": 382,
|
||||
"weight": 355,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -5977,7 +5973,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listFiles",
|
||||
"group": "files",
|
||||
"weight": 210,
|
||||
"weight": 211,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -6060,7 +6056,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createFile",
|
||||
"group": "files",
|
||||
"weight": 209,
|
||||
"weight": 210,
|
||||
"cookies": false,
|
||||
"type": "upload",
|
||||
"deprecated": false,
|
||||
|
|
@ -6150,7 +6146,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFile",
|
||||
"group": "files",
|
||||
"weight": 211,
|
||||
"weight": 212,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -6220,7 +6216,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateFile",
|
||||
"group": "files",
|
||||
"weight": 216,
|
||||
"weight": 217,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -6309,7 +6305,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteFile",
|
||||
"group": "files",
|
||||
"weight": 217,
|
||||
"weight": 218,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -6379,7 +6375,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFileDownload",
|
||||
"group": "files",
|
||||
"weight": 213,
|
||||
"weight": 214,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -6422,6 +6418,15 @@
|
|||
"type": "string",
|
||||
"x-example": "<FILE_ID>",
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"name": "token",
|
||||
"description": "File token for accessing this file.",
|
||||
"required": false,
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN>",
|
||||
"default": "",
|
||||
"in": "query"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -6449,7 +6454,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFilePreview",
|
||||
"group": "files",
|
||||
"weight": 212,
|
||||
"weight": 213,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -6537,12 +6542,12 @@
|
|||
},
|
||||
{
|
||||
"name": "quality",
|
||||
"description": "Preview image quality. Pass an integer between 0 to 100. Defaults to 100.",
|
||||
"description": "Preview image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.",
|
||||
"required": false,
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"x-example": 0,
|
||||
"default": 100,
|
||||
"x-example": -1,
|
||||
"default": -1,
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
|
|
@ -6610,7 +6615,6 @@
|
|||
"enum": [
|
||||
"jpg",
|
||||
"jpeg",
|
||||
"gif",
|
||||
"png",
|
||||
"webp",
|
||||
"heic",
|
||||
|
|
@ -6620,6 +6624,15 @@
|
|||
"x-enum-keys": [],
|
||||
"default": "",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"name": "token",
|
||||
"description": "File token for accessing this file.",
|
||||
"required": false,
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN>",
|
||||
"default": "",
|
||||
"in": "query"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -6647,7 +6660,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getFileView",
|
||||
"group": "files",
|
||||
"weight": 214,
|
||||
"weight": 215,
|
||||
"cookies": false,
|
||||
"type": "location",
|
||||
"deprecated": false,
|
||||
|
|
@ -6690,6 +6703,15 @@
|
|||
"type": "string",
|
||||
"x-example": "<FILE_ID>",
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"name": "token",
|
||||
"description": "File token for accessing this file.",
|
||||
"required": false,
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN>",
|
||||
"default": "",
|
||||
"in": "query"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -6717,7 +6739,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "list",
|
||||
"group": "teams",
|
||||
"weight": 221,
|
||||
"weight": 222,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -6792,7 +6814,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "create",
|
||||
"group": "teams",
|
||||
"weight": 220,
|
||||
"weight": 221,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -6882,7 +6904,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"group": "teams",
|
||||
"weight": 222,
|
||||
"weight": 223,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -6944,7 +6966,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateName",
|
||||
"group": "teams",
|
||||
"weight": 224,
|
||||
"weight": 225,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -7019,7 +7041,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "delete",
|
||||
"group": "teams",
|
||||
"weight": 226,
|
||||
"weight": 227,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -7081,7 +7103,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "listMemberships",
|
||||
"group": "memberships",
|
||||
"weight": 228,
|
||||
"weight": 229,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -7119,7 +7141,7 @@
|
|||
},
|
||||
{
|
||||
"name": "queries",
|
||||
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm",
|
||||
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles",
|
||||
"required": false,
|
||||
"type": "array",
|
||||
"collectionFormat": "multi",
|
||||
|
|
@ -7164,7 +7186,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "createMembership",
|
||||
"group": "memberships",
|
||||
"weight": 227,
|
||||
"weight": 228,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -7277,7 +7299,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getMembership",
|
||||
"group": "memberships",
|
||||
"weight": 229,
|
||||
"weight": 230,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -7347,7 +7369,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMembership",
|
||||
"group": "memberships",
|
||||
"weight": 230,
|
||||
"weight": 231,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -7433,7 +7455,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "deleteMembership",
|
||||
"group": "memberships",
|
||||
"weight": 232,
|
||||
"weight": 233,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -7505,7 +7527,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updateMembershipStatus",
|
||||
"group": "memberships",
|
||||
"weight": 231,
|
||||
"weight": 232,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -7599,7 +7621,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "getPrefs",
|
||||
"group": "teams",
|
||||
"weight": 223,
|
||||
"weight": 224,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -7660,7 +7682,7 @@
|
|||
"x-appwrite": {
|
||||
"method": "updatePrefs",
|
||||
"group": "teams",
|
||||
"weight": 225,
|
||||
"weight": 226,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
|
|
@ -7758,6 +7780,10 @@
|
|||
"name": "users",
|
||||
"description": "The Users service allows you to manage your project users."
|
||||
},
|
||||
{
|
||||
"name": "sites",
|
||||
"description": "The Sites Service allows you view, create and manage your web applications."
|
||||
},
|
||||
{
|
||||
"name": "functions",
|
||||
"description": "The Functions Service allows you view, create and manage your Cloud Functions."
|
||||
|
|
@ -9367,7 +9393,7 @@
|
|||
},
|
||||
"duration": {
|
||||
"type": "number",
|
||||
"description": "Function execution duration in seconds.",
|
||||
"description": "Resource(function\/site) execution duration in seconds.",
|
||||
"x-example": 0.4,
|
||||
"format": "double"
|
||||
},
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
43
app/config/template-runtimes.php
Normal file
43
app/config/template-runtimes.php
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
// TODO: Remove, replace with runtimes.php directly
|
||||
// Used in function templates and site frameworks
|
||||
|
||||
return [
|
||||
'NODE' => [
|
||||
'name' => 'node',
|
||||
'versions' => ['22', '21.0', '20.0', '19.0', '18.0', '16.0', '14.5']
|
||||
],
|
||||
'PYTHON' => [
|
||||
'name' => 'python',
|
||||
'versions' => ['3.12', '3.11', '3.10', '3.9', '3.8']
|
||||
],
|
||||
'DART' => [
|
||||
'name' => 'dart',
|
||||
'versions' => ['3.5', '3.3', '3.1', '3.0', '2.19', '2.18', '2.17', '2.16']
|
||||
],
|
||||
'GO' => [
|
||||
'name' => 'go',
|
||||
'versions' => ['1.23']
|
||||
],
|
||||
'PHP' => [
|
||||
'name' => 'php',
|
||||
'versions' => ['8.3', '8.2', '8.1', '8.0']
|
||||
],
|
||||
'DENO' => [
|
||||
'name' => 'deno',
|
||||
'versions' => ['2.0', '1.46', '1.40', '1.35', '1.24', '1.21']
|
||||
],
|
||||
'BUN' => [
|
||||
'name' => 'bun',
|
||||
'versions' => ['1.1', '1.0']
|
||||
],
|
||||
'RUBY' => [
|
||||
'name' => 'ruby',
|
||||
'versions' => ['3.3', '3.2', '3.1', '3.0']
|
||||
],
|
||||
'FLUTTER' => [
|
||||
'name' => 'flutter',
|
||||
'versions' => ['3.24']
|
||||
],
|
||||
];
|
||||
|
|
@ -1,39 +1,8 @@
|
|||
<?php
|
||||
|
||||
const TEMPLATE_RUNTIMES = [
|
||||
'NODE' => [
|
||||
'name' => 'node',
|
||||
'versions' => ['22', '21.0', '20.0', '19.0', '18.0', '16.0', '14.5']
|
||||
],
|
||||
'PYTHON' => [
|
||||
'name' => 'python',
|
||||
'versions' => ['3.12', '3.11', '3.10', '3.9', '3.8']
|
||||
],
|
||||
'DART' => [
|
||||
'name' => 'dart',
|
||||
'versions' => ['3.5', '3.3', '3.1', '3.0', '2.19', '2.18', '2.17', '2.16']
|
||||
],
|
||||
'GO' => [
|
||||
'name' => 'go',
|
||||
'versions' => ['1.23']
|
||||
],
|
||||
'PHP' => [
|
||||
'name' => 'php',
|
||||
'versions' => ['8.3', '8.2', '8.1', '8.0']
|
||||
],
|
||||
'DENO' => [
|
||||
'name' => 'deno',
|
||||
'versions' => ['2.0', '1.46', '1.40', '1.35', '1.24', '1.21']
|
||||
],
|
||||
'BUN' => [
|
||||
'name' => 'bun',
|
||||
'versions' => ['1.1', '1.0']
|
||||
],
|
||||
'RUBY' => [
|
||||
'name' => 'ruby',
|
||||
'versions' => ['3.3', '3.2', '3.1', '3.0']
|
||||
],
|
||||
];
|
||||
use Utopia\Config\Config;
|
||||
|
||||
$templateRuntimes = Config::getParam('template-runtimes');
|
||||
|
||||
function getRuntimes($runtime, $commands, $entrypoint, $providerRootDirectory, $versionsDenyList = [])
|
||||
{
|
||||
|
|
@ -54,6 +23,7 @@ return [
|
|||
'icon' => 'icon-lightning-bolt',
|
||||
'id' => 'starter',
|
||||
'name' => 'Starter function',
|
||||
'score' => 5,
|
||||
'tagline' =>
|
||||
'A simple function to get started. Edit this function to explore endless possibilities with Appwrite Functions.',
|
||||
'permissions' => ['any'],
|
||||
|
|
@ -62,24 +32,24 @@ return [
|
|||
'timeout' => 15,
|
||||
'useCases' => ['starter'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(TEMPLATE_RUNTIMES['NODE'], 'npm install', 'src/main.js', 'node/starter'),
|
||||
...getRuntimes($templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/starter'),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['PYTHON'],
|
||||
$templateRuntimes['PYTHON'],
|
||||
'pip install -r requirements.txt',
|
||||
'src/main.py',
|
||||
'python/starter'
|
||||
),
|
||||
...getRuntimes(TEMPLATE_RUNTIMES['DART'], 'dart pub get', 'lib/main.dart', 'dart/starter'),
|
||||
...getRuntimes(TEMPLATE_RUNTIMES['GO'], '', 'main.go', 'go/starter'),
|
||||
...getRuntimes($templateRuntimes['DART'], 'dart pub get', 'lib/main.dart', 'dart/starter'),
|
||||
...getRuntimes($templateRuntimes['GO'], '', 'main.go', 'go/starter'),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['PHP'],
|
||||
$templateRuntimes['PHP'],
|
||||
'composer install',
|
||||
'src/index.php',
|
||||
'php/starter'
|
||||
),
|
||||
...getRuntimes(TEMPLATE_RUNTIMES['DENO'], 'deno cache src/main.ts', 'src/main.ts', 'deno/starter'),
|
||||
...getRuntimes(TEMPLATE_RUNTIMES['BUN'], 'bun install', 'src/main.ts', 'bun/starter'),
|
||||
...getRuntimes(TEMPLATE_RUNTIMES['RUBY'], 'bundle install', 'lib/main.rb', 'ruby/starter'),
|
||||
...getRuntimes($templateRuntimes['DENO'], 'deno cache src/main.ts', 'src/main.ts', 'deno/starter'),
|
||||
...getRuntimes($templateRuntimes['BUN'], 'bun install', 'src/main.ts', 'bun/starter'),
|
||||
...getRuntimes($templateRuntimes['RUBY'], 'bundle install', 'lib/main.rb', 'ruby/starter'),
|
||||
],
|
||||
'instructions' => 'For documentation and instructions check out <a target="_blank" rel="noopener noreferrer" class="link" href="https://github.com/appwrite/templates/tree/main/node/starter">file</a>.',
|
||||
'vcsProvider' => 'github',
|
||||
|
|
@ -93,6 +63,7 @@ return [
|
|||
'icon' => 'icon-upstash',
|
||||
'id' => 'query-upstash-vector',
|
||||
'name' => 'Query Upstash Vector',
|
||||
'score' => 4,
|
||||
'tagline' => 'Vector database that stores text embeddings and context retrieval for LLMs',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -101,7 +72,7 @@ return [
|
|||
'useCases' => ['databases'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/query-upstash-vector'
|
||||
|
|
@ -137,6 +108,7 @@ return [
|
|||
'icon' => 'icon-redis',
|
||||
'id' => 'query-redis-labs',
|
||||
'name' => 'Query Redis Labs',
|
||||
'score' => 4,
|
||||
'tagline' => 'Key-value database with advanced caching capabilities.',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -145,7 +117,7 @@ return [
|
|||
'useCases' => ['databases'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/query-redis-labs'
|
||||
|
|
@ -180,6 +152,7 @@ return [
|
|||
'icon' => 'icon-neo4j',
|
||||
'id' => 'query-neo4j-auradb',
|
||||
'name' => 'Query Neo4j AuraDB',
|
||||
'score' => 4,
|
||||
'tagline' => 'Graph database with focus on relations between data.',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -188,7 +161,7 @@ return [
|
|||
'useCases' => ['databases'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/query-neo4j-auradb'
|
||||
|
|
@ -231,6 +204,7 @@ return [
|
|||
'icon' => 'icon-mongodb',
|
||||
'id' => 'query-mongo-atlas',
|
||||
'name' => 'Query MongoDB Atlas',
|
||||
'score' => 4,
|
||||
'tagline' =>
|
||||
'Realtime NoSQL document database with geospecial, graph, search, and vector suport.',
|
||||
'permissions' => ['any'],
|
||||
|
|
@ -240,7 +214,7 @@ return [
|
|||
'useCases' => ['databases'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/query-mongo-atlas'
|
||||
|
|
@ -268,6 +242,7 @@ return [
|
|||
'icon' => 'icon-neon',
|
||||
'id' => 'query-neon-postgres',
|
||||
'name' => 'Query Neon Postgres',
|
||||
'score' => 4,
|
||||
'tagline' =>
|
||||
'Reliable SQL database with replication, point-in-time recovery, and pgvector support.',
|
||||
'permissions' => ['any'],
|
||||
|
|
@ -277,7 +252,7 @@ return [
|
|||
'useCases' => ['databases'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/query-neon-postgres'
|
||||
|
|
@ -336,6 +311,7 @@ return [
|
|||
'icon' => 'icon-open-ai',
|
||||
'id' => 'prompt-chatgpt',
|
||||
'name' => 'Prompt ChatGPT',
|
||||
'score' => 7,
|
||||
'tagline' => 'Ask questions and let OpenAI GPT-3.5-turbo answer.',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -344,25 +320,25 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/prompt-chatgpt'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['PYTHON'],
|
||||
$templateRuntimes['PYTHON'],
|
||||
'pip install -r requirements.txt',
|
||||
'src/main.py',
|
||||
'python/prompt_chatgpt'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['PHP'],
|
||||
$templateRuntimes['PHP'],
|
||||
'composer install',
|
||||
'src/index.php',
|
||||
'php/prompt-chatgpt'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['DART'],
|
||||
$templateRuntimes['DART'],
|
||||
'dart pub get',
|
||||
'lib/main.dart',
|
||||
'dart/prompt_chatgpt'
|
||||
|
|
@ -397,6 +373,7 @@ return [
|
|||
'icon' => 'icon-discord',
|
||||
'id' => 'discord-command-bot',
|
||||
'name' => 'Discord Command Bot',
|
||||
'score' => 6,
|
||||
'tagline' => 'Simple command using Discord Interactions.',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -405,19 +382,19 @@ return [
|
|||
'useCases' => ['messaging'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install && npm run setup',
|
||||
'src/main.js',
|
||||
'node/discord-command-bot'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['PYTHON'],
|
||||
$templateRuntimes['PYTHON'],
|
||||
'pip install -r requirements.txt && python src/setup.py',
|
||||
'src/main.py',
|
||||
'python/discord_command_bot'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['GO'],
|
||||
$templateRuntimes['GO'],
|
||||
'',
|
||||
'main.go',
|
||||
'go/discord-command-bot'
|
||||
|
|
@ -460,6 +437,7 @@ return [
|
|||
'icon' => 'icon-perspective-api',
|
||||
'id' => 'analyze-with-perspectiveapi',
|
||||
'name' => 'Analyze with PerspectiveAPI',
|
||||
'score' => 5,
|
||||
'tagline' => 'Automate moderation by getting toxicity of messages.',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -468,7 +446,7 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/analyze-with-perspectiveapi'
|
||||
|
|
@ -495,6 +473,7 @@ return [
|
|||
'icon' => 'icon-pangea',
|
||||
'id' => 'censor-with-redact',
|
||||
'name' => 'Censor with Redact',
|
||||
'score' => 5,
|
||||
'tagline' =>
|
||||
'Censor sensitive information from a provided text string using Redact API by Pangea.',
|
||||
'permissions' => ['any'],
|
||||
|
|
@ -504,19 +483,19 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/censor-with-redact'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['PYTHON'],
|
||||
$templateRuntimes['PYTHON'],
|
||||
'pip install -r requirements.txt',
|
||||
'src/main.py',
|
||||
'python/censor_with_redact'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['DART'],
|
||||
$templateRuntimes['DART'],
|
||||
'dart pub get',
|
||||
'lib/main.dart',
|
||||
'dart/censor_with_redact'
|
||||
|
|
@ -543,6 +522,7 @@ return [
|
|||
'icon' => 'icon-document',
|
||||
'id' => 'generate-pdf',
|
||||
'name' => 'Generate PDF',
|
||||
'score' => 7,
|
||||
'tagline' => 'Document containing sample invoice in PDF format.',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -550,7 +530,7 @@ return [
|
|||
'timeout' => 15,
|
||||
'useCases' => ['utilities'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(TEMPLATE_RUNTIMES['NODE'], 'npm install', 'src/main.js', 'node/generate-pdf')
|
||||
...getRuntimes($templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/generate-pdf')
|
||||
],
|
||||
'instructions' => 'For documentation and instructions check out <a target="_blank" rel="noopener noreferrer" class="link" href="https://github.com/appwrite/templates/tree/main/node/generate-pdf">file</a>.',
|
||||
'vcsProvider' => 'github',
|
||||
|
|
@ -564,6 +544,7 @@ return [
|
|||
'icon' => 'icon-github',
|
||||
'id' => 'github-issue-bot',
|
||||
'name' => 'GitHub issue bot',
|
||||
'score' => 4,
|
||||
'tagline' =>
|
||||
'Automate the process of responding to newly opened issues in a GitHub repository.',
|
||||
'permissions' => ['any'],
|
||||
|
|
@ -573,7 +554,7 @@ return [
|
|||
'useCases' => ['dev-tools'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/github-issue-bot'
|
||||
|
|
@ -608,6 +589,7 @@ return [
|
|||
'icon' => 'icon-bookmark',
|
||||
'id' => 'url-shortener',
|
||||
'name' => 'URL shortener',
|
||||
'score' => 3,
|
||||
'tagline' => 'Generate URL with short ID and redirect to the original URL when visited.',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -616,7 +598,7 @@ return [
|
|||
'useCases' => ['utilities'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/url-shortener'
|
||||
|
|
@ -659,6 +641,7 @@ return [
|
|||
'icon' => 'icon-algolia',
|
||||
'id' => 'sync-with-algolia',
|
||||
'name' => 'Sync with Algolia',
|
||||
'score' => 4,
|
||||
'tagline' => 'Intuitive search bar for any data in Appwrite Databases.',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -667,19 +650,19 @@ return [
|
|||
'useCases' => ['databases'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/sync-with-algolia'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['PYTHON'],
|
||||
$templateRuntimes['PYTHON'],
|
||||
'pip install -r requirements.txt',
|
||||
'src/main.py',
|
||||
'python/sync_with_algolia'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['PHP'],
|
||||
$templateRuntimes['PHP'],
|
||||
'composer install',
|
||||
'src/index.php',
|
||||
'php/sync-with-algolia'
|
||||
|
|
@ -740,6 +723,7 @@ return [
|
|||
'icon' => 'icon-meilisearch',
|
||||
'id' => 'sync-with-meilisearch',
|
||||
'name' => 'Sync with Meilisearch',
|
||||
'score' => 4,
|
||||
'tagline' => 'Intuitive search bar for any data in Appwrite Databases.',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -748,31 +732,31 @@ return [
|
|||
'useCases' => ['databases'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/sync-with-meilisearch'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['PYTHON'],
|
||||
$templateRuntimes['PYTHON'],
|
||||
'pip install -r requirements.txt',
|
||||
'src/main.py',
|
||||
'python/sync-with-meilisearch'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['PHP'],
|
||||
$templateRuntimes['PHP'],
|
||||
'composer install',
|
||||
'src/index.php',
|
||||
'php/sync-with-meilisearch'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['BUN'],
|
||||
$templateRuntimes['BUN'],
|
||||
'bun install',
|
||||
'src/main.ts',
|
||||
'bun/sync-with-meilisearch'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['RUBY'],
|
||||
$templateRuntimes['RUBY'],
|
||||
'bundle install',
|
||||
'lib/main.rb',
|
||||
'ruby/sync-with-meilisearch'
|
||||
|
|
@ -833,6 +817,7 @@ return [
|
|||
'icon' => 'icon-vonage',
|
||||
'id' => 'whatsapp-with-vonage',
|
||||
'name' => 'WhatsApp with Vonage',
|
||||
'score' => 6,
|
||||
'tagline' => 'Simple bot to answer WhatsApp messages.',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -841,37 +826,37 @@ return [
|
|||
'useCases' => ['messaging'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/whatsapp-with-vonage'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['PYTHON'],
|
||||
$templateRuntimes['PYTHON'],
|
||||
'pip install -r requirements.txt',
|
||||
'src/main.py',
|
||||
'python/whatsapp_with_vonage'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['DART'],
|
||||
$templateRuntimes['DART'],
|
||||
'dart pub get',
|
||||
'lib/main.dart',
|
||||
'dart/whatsapp-with-vonage'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['PHP'],
|
||||
$templateRuntimes['PHP'],
|
||||
'composer install',
|
||||
'src/index.php',
|
||||
'php/whatsapp-with-vonage'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['BUN'],
|
||||
$templateRuntimes['BUN'],
|
||||
'bun install',
|
||||
'src/main.ts',
|
||||
'bun/whatsapp-with-vonage'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['RUBY'],
|
||||
$templateRuntimes['RUBY'],
|
||||
'bundle install',
|
||||
'lib/main.rb',
|
||||
'ruby/whatsapp-with-vonage'
|
||||
|
|
@ -919,6 +904,7 @@ return [
|
|||
'icon' => 'icon-bell',
|
||||
'id' => 'push-notification-with-fcm',
|
||||
'name' => 'Push notification with FCM',
|
||||
'score' => 4,
|
||||
'tagline' => 'Send push notifications to your users using Firebase Cloud Messaging (FCM).',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -927,7 +913,7 @@ return [
|
|||
'useCases' => ['messaging'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/push-notification-with-fcm'
|
||||
|
|
@ -975,6 +961,7 @@ return [
|
|||
'icon' => 'icon-mail',
|
||||
'id' => 'email-contact-form',
|
||||
'name' => 'Email contact form',
|
||||
'score' => 7,
|
||||
'tagline' => 'Sends an email with the contents of a HTML form.',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -983,19 +970,19 @@ return [
|
|||
'useCases' => ['utilities'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/email-contact-form'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['PYTHON'],
|
||||
$templateRuntimes['PYTHON'],
|
||||
'pip install -r requirements.txt',
|
||||
'src/main.py',
|
||||
'python/email_contact_form'
|
||||
),
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['PHP'],
|
||||
$templateRuntimes['PHP'],
|
||||
'composer install',
|
||||
'src/index.php',
|
||||
'php/email-contact-form'
|
||||
|
|
@ -1058,6 +1045,7 @@ return [
|
|||
'icon' => 'icon-stripe',
|
||||
'id' => 'subscriptions-with-stripe',
|
||||
'name' => 'Subscriptions with Stripe',
|
||||
'score' => 6,
|
||||
'tagline' => 'Receive recurring card payments and grant subscribers extra permissions.',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -1066,7 +1054,7 @@ return [
|
|||
'useCases' => ['utilities'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/subscriptions-with-stripe'
|
||||
|
|
@ -1099,6 +1087,7 @@ return [
|
|||
'icon' => 'icon-stripe',
|
||||
'id' => 'payments-with-stripe',
|
||||
'name' => 'Payments with Stripe',
|
||||
'score' => 8,
|
||||
'tagline' => 'Receive card payments and store paid orders.',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -1107,7 +1096,7 @@ return [
|
|||
'useCases' => ['utilities'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/payments-with-stripe'
|
||||
|
|
@ -1156,6 +1145,7 @@ return [
|
|||
'icon' => 'icon-chat',
|
||||
'id' => 'text-generation-with-huggingface',
|
||||
'name' => 'Text generation',
|
||||
'score' => 5,
|
||||
'tagline' => 'Generate text using the Hugging Face inference API.',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -1164,7 +1154,7 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/text-generation-with-huggingface'
|
||||
|
|
@ -1190,6 +1180,7 @@ return [
|
|||
'icon' => 'icon-translate',
|
||||
'id' => 'language-translation-with-huggingface',
|
||||
'name' => 'Language translation',
|
||||
'score' => 5,
|
||||
'tagline' => 'Translate text using the Hugging Face inference API.',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -1198,7 +1189,7 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/language-translation-with-huggingface'
|
||||
|
|
@ -1224,6 +1215,7 @@ return [
|
|||
'icon' => 'icon-eye',
|
||||
'id' => 'image-classification-with-huggingface',
|
||||
'name' => 'Image classification',
|
||||
'score' => 5,
|
||||
'tagline' => 'Classify images using the Hugging Face inference API.',
|
||||
'permissions' => ['any'],
|
||||
'events' => ['buckets.*.files.*.create'],
|
||||
|
|
@ -1232,7 +1224,7 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install && npm run setup',
|
||||
'src/main.js',
|
||||
'node/image-classification-with-huggingface'
|
||||
|
|
@ -1282,6 +1274,7 @@ return [
|
|||
'icon' => 'icon-eye',
|
||||
'id' => 'object-detection-with-huggingface',
|
||||
'name' => 'Object detection',
|
||||
'score' => 5,
|
||||
'tagline' => 'Detect objects in images using the Hugging Face inference API.',
|
||||
'permissions' => ['any'],
|
||||
'events' => ['buckets.*.files.*.create'],
|
||||
|
|
@ -1290,7 +1283,7 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install && npm run setup',
|
||||
'src/main.js',
|
||||
'node/object-detection-with-huggingface'
|
||||
|
|
@ -1340,6 +1333,7 @@ return [
|
|||
'icon' => 'icon-text',
|
||||
'id' => 'speech-recognition-with-huggingface',
|
||||
'name' => 'Speech recognition',
|
||||
'score' => 5,
|
||||
'tagline' => 'Transcribe audio to text using the Hugging Face inference API.',
|
||||
'permissions' => ['any'],
|
||||
'events' => ['buckets.*.files.*.create'],
|
||||
|
|
@ -1348,7 +1342,7 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install && npm run setup',
|
||||
'src/main.js',
|
||||
'node/speech-recognition-with-huggingface'
|
||||
|
|
@ -1398,6 +1392,7 @@ return [
|
|||
'icon' => 'icon-chat',
|
||||
'id' => 'text-to-speech-with-huggingface',
|
||||
'name' => 'Text to speech',
|
||||
'score' => 5,
|
||||
'tagline' => 'Convert text to speech using the Hugging Face inference API.',
|
||||
'permissions' => ['any'],
|
||||
'events' => ['databases.*.collections.*.documents.*.create'],
|
||||
|
|
@ -1406,7 +1401,7 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install && npm run setup',
|
||||
'src/main.js',
|
||||
'node/text-to-speech-with-huggingface'
|
||||
|
|
@ -1456,6 +1451,7 @@ return [
|
|||
'icon' => 'icon-chip',
|
||||
'id' => 'generate-with-replicate',
|
||||
'name' => 'Generate with Replicate',
|
||||
'score' => 5,
|
||||
'tagline' => "Generate text, audio and images using Replicate's API.",
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -1464,7 +1460,7 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/generate-with-replicate'
|
||||
|
|
@ -1491,6 +1487,7 @@ return [
|
|||
'icon' => 'icon-chip',
|
||||
'id' => 'generate-with-together-ai',
|
||||
'name' => 'Generate with Together AI',
|
||||
'score' => 5,
|
||||
'tagline' => "Generate text and images using Together AI's API.",
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -1499,7 +1496,7 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/generate-with-together-ai'
|
||||
|
|
@ -1533,6 +1530,7 @@ return [
|
|||
'icon' => 'icon-chip',
|
||||
'id' => 'chat-with-perplexity-ai',
|
||||
'name' => 'Chat with Perplexity AI',
|
||||
'score' => 5,
|
||||
'tagline' => 'Create a chatbot using the Perplexity AI API.',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -1541,7 +1539,7 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/chat-with-perplexity-ai'
|
||||
|
|
@ -1574,6 +1572,7 @@ return [
|
|||
'icon' => 'icon-chip',
|
||||
'id' => 'generate-with-replicate',
|
||||
'name' => 'Generate with Replicate',
|
||||
'score' => 5,
|
||||
'tagline' => "Generate text, audio and images using Replicate's API.",
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -1582,7 +1581,7 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/generate-with-replicate'
|
||||
|
|
@ -1609,6 +1608,7 @@ return [
|
|||
'icon' => 'icon-document-search',
|
||||
'id' => 'sync-with-pinecone',
|
||||
'name' => 'Sync with Pinecone',
|
||||
'score' => 4,
|
||||
'tagline' => "Sync your Appwrite database with Pinecone's vector database.",
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -1617,7 +1617,7 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/sync-with-pinecone'
|
||||
|
|
@ -1672,6 +1672,7 @@ return [
|
|||
'icon' => 'icon-chip',
|
||||
'id' => 'rag-with-langchain',
|
||||
'name' => 'RAG with LangChain',
|
||||
'score' => 6,
|
||||
'tagline' => 'Generate text using a LangChain RAG model',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -1680,7 +1681,7 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/rag-with-langchain'
|
||||
|
|
@ -1735,6 +1736,7 @@ return [
|
|||
'icon' => 'icon-chat',
|
||||
'id' => 'speak-with-elevenlabs',
|
||||
'name' => 'Speak with ElevenLabs',
|
||||
'score' => 5,
|
||||
'tagline' => 'Convert text to speech using the ElevenLabs API.',
|
||||
'permissions' => ['any'],
|
||||
'cron' => '',
|
||||
|
|
@ -1743,7 +1745,7 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/speak-with-elevenlabs'
|
||||
|
|
@ -1790,6 +1792,7 @@ return [
|
|||
'icon' => 'icon-chip',
|
||||
'id' => 'speak-with-lmnt',
|
||||
'name' => 'Speak with LMNT',
|
||||
'score' => 5,
|
||||
'tagline' => 'Convert text to speech using the LMNT API.',
|
||||
'permissions' => ['any'],
|
||||
'cron' => '',
|
||||
|
|
@ -1798,7 +1801,7 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/speak-with-lmnt'
|
||||
|
|
@ -1831,6 +1834,7 @@ return [
|
|||
'icon' => 'icon-chip',
|
||||
'id' => 'chat-with-anyscale',
|
||||
'name' => 'Chat with AnyScale',
|
||||
'score' => 5,
|
||||
'tagline' => 'Create a chatbot using the AnyScale API.',
|
||||
'permissions' => ['any'],
|
||||
'cron' => '',
|
||||
|
|
@ -1839,7 +1843,7 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/chat-with-anyscale'
|
||||
|
|
@ -1872,6 +1876,7 @@ return [
|
|||
'icon' => 'icon-music-note',
|
||||
'id' => 'music-generation-with-huggingface',
|
||||
'name' => 'Music generation',
|
||||
'score' => 4,
|
||||
'tagline' => 'Generate music from a text prompt using the Hugging Face inference API.',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -1880,7 +1885,7 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install && npm run setup',
|
||||
'src/main.js',
|
||||
'node/music-generation-with-huggingface'
|
||||
|
|
@ -1914,6 +1919,7 @@ return [
|
|||
'icon' => 'icon-chip',
|
||||
'id' => 'generate-with-fal-ai',
|
||||
'name' => 'Generate with fal.ai',
|
||||
'score' => 5,
|
||||
'tagline' => "Generate images using fal.ai's API.",
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -1922,7 +1928,7 @@ return [
|
|||
'useCases' => ['ai'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/generate-with-fal-ai'
|
||||
|
|
@ -1949,6 +1955,7 @@ return [
|
|||
'icon' => 'icon-currency-dollar',
|
||||
'id' => 'subscriptions-with-lemon-squeezy',
|
||||
'name' => 'Subscriptions with Lemon Squeezy',
|
||||
'score' => 6,
|
||||
'tagline' => 'Receive recurring card payments and grant subscribers extra permissions.',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -1957,7 +1964,7 @@ return [
|
|||
'useCases' => ['utilities'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/subscriptions-with-lemon-squeezy'
|
||||
|
|
@ -2004,6 +2011,7 @@ return [
|
|||
'icon' => 'icon-currency-dollar',
|
||||
'id' => 'payments-with-lemon-squeezy',
|
||||
'name' => 'Payments with Lemon Squeezy',
|
||||
'score' => 6,
|
||||
'tagline' => 'Receive card payments and store paid orders.',
|
||||
'permissions' => ['any'],
|
||||
'events' => [],
|
||||
|
|
@ -2012,7 +2020,7 @@ return [
|
|||
'useCases' => ['utilities'],
|
||||
'runtimes' => [
|
||||
...getRuntimes(
|
||||
TEMPLATE_RUNTIMES['NODE'],
|
||||
$templateRuntimes['NODE'],
|
||||
'npm install',
|
||||
'src/main.js',
|
||||
'node/payments-with-lemon-squeezy'
|
||||
1354
app/config/templates/site.php
Normal file
1354
app/config/templates/site.php
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -45,7 +45,16 @@ return [
|
|||
],
|
||||
[
|
||||
'name' => '_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS',
|
||||
'description' => 'Allows you to force HTTPS connection to function domains. This feature redirects any HTTP call to HTTPS and adds the \'Strict-Transport-Security\' header to all HTTP responses. By default, set to \'enabled\'. To disable, set to \'disabled\'. This feature will work only when your ports are set to default 80 and 443.',
|
||||
'description' => 'Deprecated since 1.7.0. Allows you to force HTTPS connection to function domains. This feature redirects any HTTP call to HTTPS and adds the \'Strict-Transport-Security\' header to all HTTP responses. By default, set to \'enabled\'. To disable, set to \'disabled\'. This feature will work only when your ports are set to default 80 and 443.',
|
||||
'introduction' => '',
|
||||
'default' => 'disabled',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_OPTIONS_ROUTER_FORCE_HTTPS',
|
||||
'description' => 'Allows you to force HTTPS connection to function and site domains. This feature redirects any HTTP call to HTTPS and adds the \'Strict-Transport-Security\' header to all HTTP responses. By default, set to \'enabled\'. To disable, set to \'disabled\'. This feature will work only when your ports are set to default 80 and 443.',
|
||||
'introduction' => '',
|
||||
'default' => 'disabled',
|
||||
'required' => false,
|
||||
|
|
@ -99,13 +108,40 @@ return [
|
|||
],
|
||||
[
|
||||
'name' => '_APP_DOMAIN_TARGET',
|
||||
'description' => 'A DNS A record hostname to serve as a CNAME target for your Appwrite custom domains. You can use the same value as used for the Appwrite \'_APP_DOMAIN\' variable. The default value is \'localhost\'.',
|
||||
'description' => 'Deprecated since 1.7.0. A DNS A record hostname to serve as a CNAME target for your Appwrite custom domains. You can use the same value as used for the Appwrite \'_APP_DOMAIN\' variable. The default value is \'localhost\'.',
|
||||
'introduction' => '',
|
||||
'default' => 'localhost',
|
||||
'required' => true,
|
||||
'question' => 'Enter a DNS A record hostname to serve as a CNAME for your custom domains.' . PHP_EOL . 'You can use the same value as used for the Appwrite hostname.',
|
||||
'filter' => 'domainTarget'
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DOMAIN_TARGET_CNAME',
|
||||
'description' => 'A domain that can be used as DNS CNAME record to point to instance of Appwrite server.',
|
||||
'introduction' => '',
|
||||
'default' => 'localhost',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DOMAIN_TARGET_AAAA',
|
||||
'description' => 'An IPv6 that can be used as DNS AAAA record to point to instance of Appwrite server.',
|
||||
'introduction' => '',
|
||||
'default' => '::1',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DOMAIN_TARGET_A',
|
||||
'description' => 'An IPV4 that can be used as DNS A record to point to instance of Appwrite server.',
|
||||
'introduction' => '',
|
||||
'default' => '127.0.0.1',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_CONSOLE_WHITELIST_ROOT',
|
||||
'description' => 'This option allows you to disable the creation of new users on the Appwrite console. When enabled only 1 user will be able to use the registration form. New users can be added by inviting them to your project. By default this option is enabled.',
|
||||
|
|
@ -755,13 +791,22 @@ return [
|
|||
'variables' => [
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_SIZE_LIMIT',
|
||||
'description' => 'The maximum size of a function in bytes. The default value is 30MB.',
|
||||
'description' => 'Deprecated since 1.7.0. The maximum size of a function in bytes. The default value is 30MB.',
|
||||
'introduction' => '0.13.0',
|
||||
'default' => '30000000',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_COMPUTE_SIZE_LIMIT',
|
||||
'description' => 'The maximum size of a function and site deployments in bytes. The default value is 30MB.',
|
||||
'introduction' => '1.7.0',
|
||||
'default' => '30000000',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_BUILD_SIZE_LIMIT',
|
||||
'description' => 'The maximum size of a built deployment in bytes. The default value is 2,000,000,000 (2GB), and the maximum value is 4,294,967,295 (4.2GB).',
|
||||
|
|
@ -782,13 +827,22 @@ return [
|
|||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_BUILD_TIMEOUT',
|
||||
'description' => 'The maximum number of seconds allowed as a timeout value when building a new function. The default value is 900 seconds.',
|
||||
'description' => 'Deprecated since 1.7.0. The maximum number of seconds allowed as a timeout value when building a new function. The default value is 900 seconds.',
|
||||
'introduction' => '0.13.0',
|
||||
'default' => '900',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_COMPUTE_BUILD_TIMEOUT',
|
||||
'description' => 'The maximum number of seconds allowed as a timeout value when building a new function or site. The default value is 900 seconds.',
|
||||
'introduction' => '1.7.0',
|
||||
'default' => '900',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_CONTAINERS',
|
||||
'description' => 'Deprecated since 1.2.0. Runtimes now timeout by inactivity using \'_APP_FUNCTIONS_INACTIVE_THRESHOLD\'.',
|
||||
|
|
@ -800,22 +854,40 @@ return [
|
|||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_CPUS',
|
||||
'description' => 'The maximum number of CPU core a single cloud function is allowed to use. Please note that setting a value higher than available cores will result in a function error, which might result in an error. The default value is empty. When it\'s empty or 0, CPU limit will be disabled.',
|
||||
'description' => 'Deprecated since 1.7.0. The maximum number of CPU core a single cloud function is allowed to use. Please note that setting a value higher than available cores will result in a function error, which might result in an error. The default value is empty. When it\'s empty or 0, CPU limit will be disabled',
|
||||
'introduction' => '0.7.0',
|
||||
'default' => '0',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_COMPUTE_CPUS',
|
||||
'description' => 'The maximum number of CPU core a single cloud function or a site is allowed to use. Please note that setting a value higher than available cores might result in an error. The default value is empty. When it\'s empty, CPU limit will be disabled.',
|
||||
'introduction' => '1.7.0',
|
||||
'default' => '0',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_MEMORY',
|
||||
'description' => 'The maximum amount of memory a single cloud function is allowed to use in megabytes. The default value is empty. When it\'s empty or 0, memory limit will be disabled.',
|
||||
'description' => 'Deprecated since 1.7.0. The maximum amount of memory a single cloud function is allowed to use in megabytes. The default value is empty. When it\'s empty or 0, memory limit will be disabled.',
|
||||
'introduction' => '0.7.0',
|
||||
'default' => '0',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_COMPUTE_MEMORY',
|
||||
'description' => 'The maximum amount of memory a single function or site is allowed to use in megabytes. The default value is empty. When it\'s empty, memory limit will be disabled.',
|
||||
'introduction' => '1.7.0',
|
||||
'default' => '0',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_MEMORY_SWAP',
|
||||
'description' => 'Deprecated since 1.2.0. High use of swap memory is not recommended to preserve harddrive health.',
|
||||
|
|
@ -873,13 +945,22 @@ return [
|
|||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_INACTIVE_THRESHOLD',
|
||||
'description' => 'The minimum time a function must be inactive before it can be shut down and cleaned up. This feature is intended to clean up unused containers. Containers may remain active for longer than the interval before being shut down, as Appwrite only cleans up unused containers every hour. If no value is provided, the default is 60 seconds.',
|
||||
'description' => 'Deprecated since 1.7.0. The minimum time a function must be inactive before it can be shut down and cleaned up. This feature is intended to clean up unused containers. Containers may remain active for longer than the interval before being shut down, as Appwrite only cleans up unused containers every hour. If no value is provided, the default is 60 seconds.',
|
||||
'introduction' => '0.13.0',
|
||||
'default' => '60',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_COMPUTE_INACTIVE_THRESHOLD',
|
||||
'description' => 'The minimum time a function or site must be inactive before it can be shut down and cleaned up. This feature is intended to clean up unused containers. Containers may remain active for longer than the interval before being shut down, as Appwrite only cleans up unused containers every hour. If no value is provided, the default is 60 seconds.',
|
||||
'introduction' => '1.7.0',
|
||||
'default' => '60',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => 'DOCKERHUB_PULL_USERNAME',
|
||||
'description' => 'Deprecated with 1.2.0, use \'_APP_DOCKER_HUB_USERNAME\' instead.',
|
||||
|
|
@ -918,13 +999,22 @@ return [
|
|||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_RUNTIMES_NETWORK',
|
||||
'description' => 'The docker network used for communication between the executor and runtimes.',
|
||||
'description' => 'Deprecated since 1.7.0. The docker network used for communication between the executor and runtimes.',
|
||||
'introduction' => '1.2.0',
|
||||
'default' => 'runtimes',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_COMPUTE_RUNTIMES_NETWORK',
|
||||
'description' => 'The docker network used for communication between the executor and runtimes for sites and functions.',
|
||||
'introduction' => '1.7.0',
|
||||
'default' => 'runtimes',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DOCKER_HUB_USERNAME',
|
||||
'description' => 'The username for hub.docker.com. This variable is used to pull images from hub.docker.com.',
|
||||
|
|
@ -945,7 +1035,7 @@ return [
|
|||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_MAINTENANCE_INTERVAL',
|
||||
'description' => 'Interval value containing the number of seconds that the executor should wait before checking for inactive runtimes. The default value is 3600 seconds (1 hour).',
|
||||
'description' => 'Deprecated since 1.7.0. Interval value containing the number of seconds that the executor should wait before checking for inactive runtimes. The default value is 3600 seconds (1 hour).',
|
||||
'introduction' => '1.4.0',
|
||||
'default' => '3600',
|
||||
'required' => false,
|
||||
|
|
@ -953,8 +1043,42 @@ return [
|
|||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_COMPUTE_MAINTENANCE_INTERVAL',
|
||||
'description' => 'Interval value containing the number of seconds that the executor should wait before checking for inactive runtimes of functions and sites. The default value is 3600 seconds (1 hour).',
|
||||
'introduction' => '1.7.0',
|
||||
'default' => '3600',
|
||||
'required' => false,
|
||||
'overwrite' => true,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'category' => 'Sites',
|
||||
'description' => '',
|
||||
'variables' => [
|
||||
[
|
||||
'name' => '_APP_SITES_TIMEOUT',
|
||||
'description' => 'The maximum number of seconds allowed as a timeout value when creating a new site. The default value is 900 seconds. This is the global limit, timeout for individual functions are configured in the sites\'s settings or in appwrite.json.',
|
||||
'introduction' => '1.7.0',
|
||||
'default' => '900',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_SITES_RUNTIMES',
|
||||
'description' => "This option allows you to enable or disable runtime environments for Sites. Disable unused runtimes to save disk space.\n\nTo enable cloud site runtimes, pass a list of enabled environments separated by a comma.\n\nCurrently, supported environments are: " . \implode(', ', \array_keys(Config::getParam('runtimes'))),
|
||||
'introduction' => '1.7.0',
|
||||
'default' => 'static-1,node-22,flutter-3.29',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
'category' => 'VCS (Version Control System)',
|
||||
'description' => '',
|
||||
|
|
|
|||
|
|
@ -1182,8 +1182,8 @@ App::get('/v1/account/sessions/oauth2/:provider')
|
|||
->label('abuse-limit', 50)
|
||||
->label('abuse-key', 'ip:{ip}')
|
||||
->param('provider', '', new WhiteList(\array_keys(Config::getParam('oAuthProviders')), true), 'OAuth2 Provider. Currently, supported providers are: ' . \implode(', ', \array_keys(\array_filter(Config::getParam('oAuthProviders'), fn ($node) => (!$node['mock'])))) . '.')
|
||||
->param('success', '', fn ($clients) => new Host($clients), 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients'])
|
||||
->param('failure', '', fn ($clients) => new Host($clients), 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients'])
|
||||
->param('success', '', fn ($clients, $devKey) => $devKey->isEmpty() ? new Host($clients) : new URL(), 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients', 'devKey'])
|
||||
->param('failure', '', fn ($clients, $devKey) => $devKey->isEmpty() ? new Host($clients) : new URL(), 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients', 'devKey'])
|
||||
->param('scopes', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true)
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
|
|
@ -1210,8 +1210,8 @@ App::get('/v1/account/sessions/oauth2/:provider')
|
|||
throw new Exception(Exception::PROJECT_PROVIDER_DISABLED, 'This provider is disabled. Please configure the provider app ID and app secret key from your ' . APP_NAME . ' console to continue.');
|
||||
}
|
||||
|
||||
$className = 'Appwrite\\Auth\\OAuth2\\' . \ucfirst($provider);
|
||||
|
||||
$oAuthProviders = Config::getParam('oAuthProviders');
|
||||
$className = $oAuthProviders[$provider]['class'];
|
||||
if (!\class_exists($className)) {
|
||||
throw new Exception(Exception::PROJECT_PROVIDER_UNSUPPORTED);
|
||||
}
|
||||
|
|
@ -1779,8 +1779,8 @@ App::get('/v1/account/tokens/oauth2/:provider')
|
|||
->label('abuse-limit', 50)
|
||||
->label('abuse-key', 'ip:{ip}')
|
||||
->param('provider', '', new WhiteList(\array_keys(Config::getParam('oAuthProviders')), true), 'OAuth2 Provider. Currently, supported providers are: ' . \implode(', ', \array_keys(\array_filter(Config::getParam('oAuthProviders'), fn ($node) => (!$node['mock'])))) . '.')
|
||||
->param('success', '', fn ($clients) => new Host($clients), 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients'])
|
||||
->param('failure', '', fn ($clients) => new Host($clients), 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients'])
|
||||
->param('success', '', fn ($clients, $devKey) => $devKey->isEmpty() ? new Host($clients) : new URL(), 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients', 'devKey'])
|
||||
->param('failure', '', fn ($clients, $devKey) => $devKey->isEmpty() ? new Host($clients) : new URL(), 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project\'s platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients', 'devKey'])
|
||||
->param('scopes', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true)
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
|
|
@ -1860,7 +1860,7 @@ App::post('/v1/account/tokens/magic-url')
|
|||
->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.')
|
||||
->param('email', '', new Email(), 'User email.')
|
||||
->param('url', '', fn ($clients) => new Host($clients), 'URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients'])
|
||||
->param('url', '', fn ($clients, $devKey) => $devKey->isEmpty() ? new Host($clients) : new URL(), 'URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients', 'devKey'])
|
||||
->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')
|
||||
->inject('response')
|
||||
|
|
@ -3146,7 +3146,7 @@ App::post('/v1/account/recovery')
|
|||
->label('abuse-limit', 10)
|
||||
->label('abuse-key', ['url:{url},email:{param-email}', 'url:{url},ip:{ip}'])
|
||||
->param('email', '', new Email(), 'User email.')
|
||||
->param('url', '', fn ($clients) => new Host($clients), 'URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients'])
|
||||
->param('url', '', fn ($clients, $devKey) => $devKey->isEmpty() ? new Host($clients) : new URL(), 'URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients', 'devKey'])
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
|
|
@ -3412,7 +3412,7 @@ App::post('/v1/account/verification')
|
|||
))
|
||||
->label('abuse-limit', 10)
|
||||
->label('abuse-key', 'url:{url},userId:{userId}')
|
||||
->param('url', '', fn ($clients) => new Host($clients), 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add built-in confirm page
|
||||
->param('url', '', fn ($clients, $devKey) => $devKey->isEmpty() ? new Host($clients) : new URL(), 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients', 'devKey']) // TODO add built-in confirm page
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
|
|
|
|||
|
|
@ -502,6 +502,7 @@ App::get('/v1/avatars/qr')
|
|||
'addQuietzone' => true,
|
||||
'quietzoneSize' => $margin,
|
||||
'outputType' => QRCode::OUTPUT_IMAGICK,
|
||||
'scale' => 15,
|
||||
]);
|
||||
|
||||
$qrcode = new QRCode($options);
|
||||
|
|
@ -516,7 +517,7 @@ App::get('/v1/avatars/qr')
|
|||
$response
|
||||
->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days
|
||||
->setContentType('image/png')
|
||||
->send($image->output('png', 9));
|
||||
->send($image->output('png', 90));
|
||||
});
|
||||
|
||||
App::get('/v1/avatars/initials')
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ use Appwrite\SDK\Response as SDKResponse;
|
|||
use Appwrite\Utopia\Response;
|
||||
use Utopia\App;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Domains\Domain;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\IP;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
App::init()
|
||||
|
|
@ -41,10 +43,21 @@ App::get('/v1/console/variables')
|
|||
))
|
||||
->inject('response')
|
||||
->action(function (Response $response) {
|
||||
$isDomainEnabled = !empty(System::getEnv('_APP_DOMAIN', ''))
|
||||
&& !empty(System::getEnv('_APP_DOMAIN_TARGET', ''))
|
||||
&& System::getEnv('_APP_DOMAIN', '') !== 'localhost'
|
||||
&& System::getEnv('_APP_DOMAIN_TARGET', '') !== 'localhost';
|
||||
$validator = new Domain(System::getEnv('_APP_DOMAIN'));
|
||||
$isDomainValid = !empty(System::getEnv('_APP_DOMAIN', '')) && $validator->isKnown() && !$validator->isTest();
|
||||
|
||||
$validator = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME'));
|
||||
$isCNAMEValid = !empty(System::getEnv('_APP_DOMAIN_TARGET_CNAME', '')) && $validator->isKnown() && !$validator->isTest();
|
||||
|
||||
$validator = new IP(IP::V4);
|
||||
$isAValid = !empty(System::getEnv('_APP_DOMAIN_TARGET_A', '')) && ($validator->isValid(System::getEnv('_APP_DOMAIN_TARGET_A')));
|
||||
|
||||
$validator = new IP(IP::V6);
|
||||
$isAAAAValid = !empty(System::getEnv('_APP_DOMAIN_TARGET_AAAA', '')) && $validator->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA'));
|
||||
|
||||
$isDomainEnabled = $isDomainValid && (
|
||||
$isAAAAValid || $isAValid || $isCNAMEValid
|
||||
);
|
||||
|
||||
$isVcsEnabled = !empty(System::getEnv('_APP_VCS_GITHUB_APP_NAME', ''))
|
||||
&& !empty(System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY', ''))
|
||||
|
|
@ -55,13 +68,19 @@ App::get('/v1/console/variables')
|
|||
$isAssistantEnabled = !empty(System::getEnv('_APP_ASSISTANT_OPENAI_API_KEY', ''));
|
||||
|
||||
$variables = new Document([
|
||||
'_APP_DOMAIN_TARGET' => System::getEnv('_APP_DOMAIN_TARGET'),
|
||||
'_APP_DOMAIN_TARGET_CNAME' => System::getEnv('_APP_DOMAIN_TARGET_CNAME'),
|
||||
'_APP_DOMAIN_TARGET_AAAA' => System::getEnv('_APP_DOMAIN_TARGET_AAAA'),
|
||||
'_APP_DOMAIN_TARGET_A' => System::getEnv('_APP_DOMAIN_TARGET_A'),
|
||||
'_APP_STORAGE_LIMIT' => +System::getEnv('_APP_STORAGE_LIMIT'),
|
||||
'_APP_FUNCTIONS_SIZE_LIMIT' => +System::getEnv('_APP_FUNCTIONS_SIZE_LIMIT'),
|
||||
'_APP_COMPUTE_SIZE_LIMIT' => +System::getEnv('_APP_COMPUTE_SIZE_LIMIT'),
|
||||
'_APP_USAGE_STATS' => System::getEnv('_APP_USAGE_STATS'),
|
||||
'_APP_VCS_ENABLED' => $isVcsEnabled,
|
||||
'_APP_DOMAIN_ENABLED' => $isDomainEnabled,
|
||||
'_APP_ASSISTANT_ENABLED' => $isAssistantEnabled
|
||||
'_APP_ASSISTANT_ENABLED' => $isAssistantEnabled,
|
||||
'_APP_DOMAIN_SITES' => System::getEnv('_APP_DOMAIN_SITES'),
|
||||
'_APP_DOMAIN_FUNCTIONS' => System::getEnv('_APP_DOMAIN_FUNCTIONS'),
|
||||
'_APP_OPTIONS_FORCE_HTTPS' => System::getEnv('_APP_OPTIONS_FORCE_HTTPS'),
|
||||
'_APP_DOMAINS_NAMESERVERS' => System::getEnv('_APP_DOMAINS_NAMESERVERS'),
|
||||
]);
|
||||
|
||||
$response->dynamic($variables, Response::MODEL_CONSOLE_VARIABLES);
|
||||
|
|
|
|||
|
|
@ -3219,25 +3219,25 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
|
|||
new Parameter('permissions', optional: true),
|
||||
]
|
||||
),
|
||||
// new Method(
|
||||
// namespace: 'databases',
|
||||
// group: 'documents',
|
||||
// name: 'createDocuments',
|
||||
// description: '/docs/references/databases/create-documents.md',
|
||||
// auth: [AuthType::KEY],
|
||||
// responses: [
|
||||
// new SDKResponse(
|
||||
// code: Response::STATUS_CODE_CREATED,
|
||||
// model: Response::MODEL_DOCUMENT_LIST,
|
||||
// )
|
||||
// ],
|
||||
// contentType: ContentType::JSON,
|
||||
// parameters: [
|
||||
// new Parameter('databaseId', optional: false),
|
||||
// new Parameter('collectionId', optional: false),
|
||||
// new Parameter('documents', optional: false),
|
||||
// ]
|
||||
// )
|
||||
new Method(
|
||||
namespace: 'databases',
|
||||
group: 'documents',
|
||||
name: 'createDocuments',
|
||||
description: '/docs/references/databases/create-documents.md',
|
||||
auth: [AuthType::KEY],
|
||||
responses: [
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_CREATED,
|
||||
model: Response::MODEL_DOCUMENT_LIST,
|
||||
)
|
||||
],
|
||||
contentType: ContentType::JSON,
|
||||
parameters: [
|
||||
new Parameter('databaseId', optional: false),
|
||||
new Parameter('collectionId', optional: false),
|
||||
new Parameter('documents', optional: false),
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
->param('databaseId', '', new UID(), 'Database ID.')
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -845,9 +845,10 @@ App::get('/v1/health/storage')
|
|||
->inject('response')
|
||||
->inject('deviceForFiles')
|
||||
->inject('deviceForFunctions')
|
||||
->inject('deviceForSites')
|
||||
->inject('deviceForBuilds')
|
||||
->action(function (Response $response, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds) {
|
||||
$devices = [$deviceForFiles, $deviceForFunctions, $deviceForBuilds];
|
||||
->action(function (Response $response, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForSites, Device $deviceForBuilds) {
|
||||
$devices = [$deviceForFiles, $deviceForFunctions, $deviceForSites, $deviceForBuilds];
|
||||
$checkStart = \microtime(true);
|
||||
|
||||
foreach ($devices as $device) {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
<?php
|
||||
|
||||
use Appwrite\Auth\Auth;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Event\Migration;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\OpenSSL\OpenSSL;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Database\Validator\CompoundUID;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Migrations;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\App;
|
||||
|
|
@ -16,12 +19,21 @@ use Utopia\Database\Exception\Order as OrderException;
|
|||
use Utopia\Database\Exception\Query as QueryException;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Query\Cursor;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Migration\Resource;
|
||||
use Utopia\Migration\Sources\Appwrite;
|
||||
use Utopia\Migration\Sources\CSV;
|
||||
use Utopia\Migration\Sources\Firebase;
|
||||
use Utopia\Migration\Sources\NHost;
|
||||
use Utopia\Migration\Sources\Supabase;
|
||||
use Utopia\Migration\Transfer;
|
||||
use Utopia\Storage\Compression\Algorithms\GZIP;
|
||||
use Utopia\Storage\Compression\Algorithms\Zstd;
|
||||
use Utopia\Storage\Compression\Compression;
|
||||
use Utopia\Storage\Device;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\ArrayList;
|
||||
use Utopia\Validator\Integer;
|
||||
use Utopia\Validator\Text;
|
||||
|
|
@ -91,7 +103,6 @@ App::post('/v1/migrations/appwrite')
|
|||
->dynamic($migration, Response::MODEL_MIGRATION);
|
||||
});
|
||||
|
||||
|
||||
App::post('/v1/migrations/firebase')
|
||||
->groups(['api', 'migrations'])
|
||||
->desc('Create Firebase migration')
|
||||
|
|
@ -295,6 +306,131 @@ App::post('/v1/migrations/nhost')
|
|||
->dynamic($migration, Response::MODEL_MIGRATION);
|
||||
});
|
||||
|
||||
App::post('/v1/migrations/csv')
|
||||
->groups(['api', 'migrations'])
|
||||
->desc('Import documents from a CSV')
|
||||
->label('scope', 'migrations.write')
|
||||
->label('event', 'migrations.[migrationId].create')
|
||||
->label('audits.event', 'migration.create')
|
||||
->label('sdk', new Method(
|
||||
namespace: 'migrations',
|
||||
group: null,
|
||||
name: 'createCsvMigration',
|
||||
description: '/docs/references/migrations/migration-csv.md',
|
||||
auth: [AuthType::ADMIN],
|
||||
responses: [
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_ACCEPTED,
|
||||
model: Response::MODEL_MIGRATION,
|
||||
)
|
||||
]
|
||||
))
|
||||
->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('resourceId', null, new CompoundUID(), 'Composite ID in the format {databaseId:collectionId}, identifying a collection within a database.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('project')
|
||||
->inject('deviceForFiles')
|
||||
->inject('deviceForImports')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForMigrations')
|
||||
->action(function (string $bucketId, string $fileId, string $resourceId, Response $response, Database $dbForProject, Document $project, Device $deviceForFiles, Device $deviceForImports, Event $queueForEvents, Migration $queueForMigrations) {
|
||||
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
|
||||
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
|
||||
|
||||
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
if ($bucket->isEmpty() || (!$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
|
||||
if ($file->isEmpty()) {
|
||||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$path = $file->getAttribute('path', '');
|
||||
if (!$deviceForFiles->exists($path)) {
|
||||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in ' . $path);
|
||||
}
|
||||
|
||||
// no encryption, compression on files above 20MB.
|
||||
$hasEncryption = !empty($file->getAttribute('openSSLCipher'));
|
||||
$compression = $file->getAttribute('algorithm', Compression::NONE);
|
||||
$hasCompression = $compression !== Compression::NONE;
|
||||
|
||||
$migrationId = ID::unique();
|
||||
$newPath = $deviceForImports->getPath('/' . $migrationId . '_' . $fileId . '.csv');
|
||||
|
||||
if ($hasEncryption || $hasCompression) {
|
||||
$source = $deviceForFiles->read($path);
|
||||
|
||||
// 1. decrypt
|
||||
if ($hasEncryption) {
|
||||
$source = OpenSSL::decrypt(
|
||||
$source,
|
||||
$file->getAttribute('openSSLCipher'),
|
||||
System::getEnv('_APP_OPENSSL_KEY_V' . $file->getAttribute('openSSLVersion')),
|
||||
0,
|
||||
hex2bin($file->getAttribute('openSSLIV')),
|
||||
hex2bin($file->getAttribute('openSSLTag'))
|
||||
);
|
||||
}
|
||||
|
||||
// 2. decompress
|
||||
if ($hasCompression) {
|
||||
switch ($compression) {
|
||||
case Compression::ZSTD:
|
||||
$source = (new Zstd())->decompress($source);
|
||||
break;
|
||||
case Compression::GZIP:
|
||||
$source = (new GZIP())->decompress($source);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// manual write after decryption and/or decompression
|
||||
if (! $deviceForImports->write($newPath, $source, 'text/csv')) {
|
||||
throw new \Exception("Unable to copy file");
|
||||
}
|
||||
} elseif (! $deviceForFiles->transfer($path, $newPath, $deviceForImports)) {
|
||||
throw new \Exception("Unable to copy file");
|
||||
}
|
||||
|
||||
$fileSize = $deviceForImports->getFileSize($newPath);
|
||||
$resources = Transfer::extractServices([Transfer::GROUP_DATABASES]);
|
||||
|
||||
$migration = $dbForProject->createDocument('migrations', new Document([
|
||||
'$id' => $migrationId,
|
||||
'status' => 'pending',
|
||||
'stage' => 'init',
|
||||
'source' => CSV::getName(),
|
||||
'destination' => Appwrite::getName(),
|
||||
'resources' => $resources,
|
||||
'resourceId' => $resourceId,
|
||||
'resourceType' => Resource::TYPE_DATABASE,
|
||||
'statusCounters' => [],
|
||||
'resourceData' => [],
|
||||
'errors' => [],
|
||||
'options' => [
|
||||
'path' => $newPath,
|
||||
'size' => $fileSize,
|
||||
],
|
||||
]));
|
||||
|
||||
$queueForEvents->setParam('migrationId', $migration->getId());
|
||||
|
||||
$queueForMigrations
|
||||
->setMigration($migration)
|
||||
->setProject($project)
|
||||
->trigger();
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_ACCEPTED)
|
||||
->dynamic($migration, Response::MODEL_MIGRATION);
|
||||
});
|
||||
|
||||
App::get('/v1/migrations')
|
||||
->groups(['api', 'migrations'])
|
||||
->desc('List migrations')
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use Utopia\Database\Query;
|
|||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Datetime as DateTimeValidator;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
|
|
@ -149,7 +150,7 @@ App::get('/v1/project/usage')
|
|||
$executionsBreakdown = array_map(function ($function) use ($dbForProject) {
|
||||
$id = $function->getId();
|
||||
$name = $function->getAttribute('name');
|
||||
$metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS);
|
||||
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS);
|
||||
$value = $dbForProject->findOne('stats', [
|
||||
Query::equal('metric', [$metric]),
|
||||
Query::equal('period', ['inf'])
|
||||
|
|
@ -165,7 +166,7 @@ App::get('/v1/project/usage')
|
|||
$executionsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) {
|
||||
$id = $function->getId();
|
||||
$name = $function->getAttribute('name');
|
||||
$metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS);
|
||||
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS);
|
||||
$value = $dbForProject->findOne('stats', [
|
||||
Query::equal('metric', [$metric]),
|
||||
Query::equal('period', ['inf'])
|
||||
|
|
@ -181,7 +182,7 @@ App::get('/v1/project/usage')
|
|||
$buildsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) {
|
||||
$id = $function->getId();
|
||||
$name = $function->getAttribute('name');
|
||||
$metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS);
|
||||
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS);
|
||||
$value = $dbForProject->findOne('stats', [
|
||||
Query::equal('metric', [$metric]),
|
||||
Query::equal('period', ['inf'])
|
||||
|
|
@ -230,13 +231,13 @@ App::get('/v1/project/usage')
|
|||
$functionsStorageBreakdown = array_map(function ($function) use ($dbForProject) {
|
||||
$id = $function->getId();
|
||||
$name = $function->getAttribute('name');
|
||||
$deploymentMetric = str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $function->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE);
|
||||
$deploymentMetric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE);
|
||||
$deploymentValue = $dbForProject->findOne('stats', [
|
||||
Query::equal('metric', [$deploymentMetric]),
|
||||
Query::equal('period', ['inf'])
|
||||
]);
|
||||
|
||||
$buildMetric = str_replace(['{functionInternalId}'], [$function->getInternalId()], METRIC_FUNCTION_ID_BUILDS_STORAGE);
|
||||
$buildMetric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE);
|
||||
$buildValue = $dbForProject->findOne('stats', [
|
||||
Query::equal('metric', [$buildMetric]),
|
||||
Query::equal('period', ['inf'])
|
||||
|
|
@ -254,7 +255,7 @@ App::get('/v1/project/usage')
|
|||
$executionsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) {
|
||||
$id = $function->getId();
|
||||
$name = $function->getAttribute('name');
|
||||
$metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS);
|
||||
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS);
|
||||
$value = $dbForProject->findOne('stats', [
|
||||
Query::equal('metric', [$metric]),
|
||||
Query::equal('period', ['inf'])
|
||||
|
|
@ -270,7 +271,7 @@ App::get('/v1/project/usage')
|
|||
$buildsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) {
|
||||
$id = $function->getId();
|
||||
$name = $function->getAttribute('name');
|
||||
$metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS);
|
||||
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS);
|
||||
$value = $dbForProject->findOne('stats', [
|
||||
Query::equal('metric', [$metric]),
|
||||
Query::equal('period', ['inf'])
|
||||
|
|
@ -401,11 +402,12 @@ App::post('/v1/project/variables')
|
|||
))
|
||||
->param('key', null, new Text(Database::LENGTH_KEY), 'Variable key. Max length: ' . Database::LENGTH_KEY . ' chars.', false)
|
||||
->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', false)
|
||||
->param('secret', true, new Boolean(), 'Secret variables can be updated or deleted, but only projects can read them during build and runtime.', true)
|
||||
->inject('project')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $key, string $value, Document $project, Response $response, Database $dbForProject, Database $dbForPlatform) {
|
||||
->action(function (string $key, string $value, bool $secret, Document $project, Response $response, Database $dbForProject, Database $dbForPlatform) {
|
||||
$variableId = ID::unique();
|
||||
|
||||
$variable = new Document([
|
||||
|
|
@ -420,6 +422,7 @@ App::post('/v1/project/variables')
|
|||
'resourceType' => 'project',
|
||||
'key' => $key,
|
||||
'value' => $value,
|
||||
'secret' => $secret,
|
||||
'search' => implode(' ', [$variableId, $key, 'project']),
|
||||
]);
|
||||
|
||||
|
|
@ -523,19 +526,25 @@ App::put('/v1/project/variables/:variableId')
|
|||
->param('variableId', '', new UID(), 'Variable unique ID.', false)
|
||||
->param('key', null, new Text(255), 'Variable key. Max length: 255 chars.', false)
|
||||
->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', true)
|
||||
->param('secret', null, new Boolean(), 'Secret variables can be updated or deleted, but only projects can read them during build and runtime.', true)
|
||||
->inject('project')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $variableId, string $key, ?string $value, Document $project, Response $response, Database $dbForProject, Database $dbForPlatform) {
|
||||
->action(function (string $variableId, string $key, ?string $value, ?bool $secret, Document $project, Response $response, Database $dbForProject, Database $dbForPlatform) {
|
||||
$variable = $dbForProject->getDocument('variables', $variableId);
|
||||
if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceType') !== 'project') {
|
||||
throw new Exception(Exception::VARIABLE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($variable->getAttribute('secret') === true && $secret === false) {
|
||||
throw new Exception(Exception::VARIABLE_CANNOT_UNSET_SECRET);
|
||||
}
|
||||
|
||||
$variable
|
||||
->setAttribute('key', $key)
|
||||
->setAttribute('value', $value ?? $variable->getAttribute('value'))
|
||||
->setAttribute('secret', $secret ?? $variable->getAttribute('secret'))
|
||||
->setAttribute('search', implode(' ', [$variableId, $key, 'project']));
|
||||
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -2139,7 +2139,8 @@ App::post('/v1/projects/:projectId/smtp/tests')
|
|||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->inject('queueForMails')
|
||||
->action(function (string $projectId, array $emails, string $senderName, string $senderEmail, string $replyTo, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForPlatform, Mail $queueForMails) {
|
||||
->inject('plan')
|
||||
->action(function (string $projectId, array $emails, string $senderName, string $senderEmail, string $replyTo, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForPlatform, Mail $queueForMails, array $plan) {
|
||||
$project = $dbForPlatform->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
|
|
@ -2152,7 +2153,14 @@ App::post('/v1/projects/:projectId/smtp/tests')
|
|||
$template = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-smtp-test.tpl');
|
||||
$template
|
||||
->setParam('{{from}}', "{$senderName} ({$senderEmail})")
|
||||
->setParam('{{replyTo}}', "{$senderName} ({$replyToEmail})");
|
||||
->setParam('{{replyTo}}', "{$senderName} ({$replyToEmail})")
|
||||
->setParam('{{logoUrl}}', $plan['logoUrl'] ?? APP_EMAIL_LOGO_URL)
|
||||
->setParam('{{accentColor}}', $plan['accentColor'] ?? APP_EMAIL_ACCENT_COLOR)
|
||||
->setParam('{{twitterUrl}}', $plan['twitterUrl'] ?? APP_SOCIAL_TWITTER)
|
||||
->setParam('{{discordUrl}}', $plan['discordUrl'] ?? APP_SOCIAL_DISCORD)
|
||||
->setParam('{{githubUrl}}', $plan['githubUrl'] ?? APP_SOCIAL_GITHUB_APPWRITE)
|
||||
->setParam('{{termsUrl}}', $plan['termsUrl'] ?? APP_EMAIL_TERMS_URL)
|
||||
->setParam('{{privacyUrl}}', $plan['privacyUrl'] ?? APP_EMAIL_PRIVACY_URL);
|
||||
|
||||
foreach ($emails as $email) {
|
||||
$queueForMails
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use Appwrite\Event\Certificate;
|
|||
use Appwrite\Event\Delete;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Network\Validator\CNAME;
|
||||
use Appwrite\Network\Validator\DNS;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
|
|
@ -15,169 +15,15 @@ use Utopia\App;
|
|||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Query as QueryException;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Query\Cursor;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Domains\Domain;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\Domain as ValidatorDomain;
|
||||
use Utopia\Validator\AnyOf;
|
||||
use Utopia\Validator\IP;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
App::post('/v1/proxy/rules')
|
||||
->groups(['api', 'proxy'])
|
||||
->desc('Create rule')
|
||||
->label('scope', 'rules.write')
|
||||
->label('event', 'rules.[ruleId].create')
|
||||
->label('audits.event', 'rule.create')
|
||||
->label('audits.resource', 'rule/{response.$id}')
|
||||
->label('sdk', new Method(
|
||||
namespace: 'proxy',
|
||||
group: null,
|
||||
name: 'createRule',
|
||||
description: '/docs/references/proxy/create-rule.md',
|
||||
auth: [AuthType::ADMIN],
|
||||
responses: [
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_CREATED,
|
||||
model: Response::MODEL_PROXY_RULE,
|
||||
)
|
||||
]
|
||||
))
|
||||
->param('domain', null, new ValidatorDomain(), 'Domain name.')
|
||||
->param('resourceType', null, new WhiteList(['api', 'function']), 'Action definition for the rule. Possible values are "api", "function"')
|
||||
->param('resourceId', '', new UID(), 'ID of resource for the action type. If resourceType is "api", leave empty. If resourceType is "function", provide ID of the function.', true)
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
->inject('queueForCertificates')
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForPlatform')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $domain, string $resourceType, string $resourceId, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject) {
|
||||
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
if ($domain === $mainDomain) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'You cannot assign your main domain to specific resource. Please use subdomain or a different domain.');
|
||||
}
|
||||
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS');
|
||||
$denyListDomains = System::getEnv('_APP_CUSTOM_DOMAIN_DENY_LIST');
|
||||
|
||||
if (!empty($denyListDomains)) {
|
||||
$functionsDomain .= ',' . $denyListDomains;
|
||||
}
|
||||
|
||||
$deniedDomains = array_map('trim', explode(',', $functionsDomain));
|
||||
|
||||
foreach ($deniedDomains as $deniedDomain) {
|
||||
if (str_ends_with($domain, $deniedDomain)) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'You cannot assign your functions domain or its subdomain to a specific resource. Please use a different domain.');
|
||||
}
|
||||
}
|
||||
|
||||
if ($domain === 'localhost' || $domain === APP_HOSTNAME_INTERNAL) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please pick another one.');
|
||||
}
|
||||
|
||||
// TODO: @christyjacob remove once we migrate the rules in 1.7.x
|
||||
if (System::getEnv('_APP_RULES_FORMAT') === 'md5') {
|
||||
$document = $dbForPlatform->getDocument('rules', md5($domain));
|
||||
} else {
|
||||
$document = $dbForPlatform->findOne('rules', [
|
||||
Query::equal('domain', [$domain]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
if (!$document->isEmpty()) {
|
||||
if ($document->getAttribute('projectId') === $project->getId()) {
|
||||
$resourceType = $document->getAttribute('resourceType');
|
||||
$resourceId = $document->getAttribute('resourceId');
|
||||
$message = "Domain already assigned to '{$resourceType}' service";
|
||||
if (!empty($resourceId)) {
|
||||
$message .= " with ID '{$resourceId}'";
|
||||
}
|
||||
|
||||
$message .= '.';
|
||||
} else {
|
||||
$message = 'Domain already assigned to different project.';
|
||||
}
|
||||
|
||||
throw new Exception(Exception::RULE_ALREADY_EXISTS, $message);
|
||||
}
|
||||
|
||||
$resourceInternalId = '';
|
||||
|
||||
if ($resourceType == 'function') {
|
||||
if (empty($resourceId)) {
|
||||
throw new Exception(Exception::FUNCTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$function = $dbForProject->getDocument('functions', $resourceId);
|
||||
|
||||
if ($function->isEmpty()) {
|
||||
throw new Exception(Exception::RULE_RESOURCE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$resourceInternalId = $function->getInternalId();
|
||||
}
|
||||
|
||||
try {
|
||||
$domain = new Domain($domain);
|
||||
} catch (\Throwable) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.');
|
||||
}
|
||||
|
||||
// TODO: @christyjacob remove once we migrate the rules in 1.7.x
|
||||
$ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain->get()) : ID::unique();
|
||||
|
||||
$rule = new Document([
|
||||
'$id' => $ruleId,
|
||||
'projectId' => $project->getId(),
|
||||
'projectInternalId' => $project->getInternalId(),
|
||||
'domain' => $domain->get(),
|
||||
'resourceType' => $resourceType,
|
||||
'resourceId' => $resourceId,
|
||||
'resourceInternalId' => $resourceInternalId,
|
||||
'certificateId' => '',
|
||||
'owner' => '',
|
||||
'region' => $project->getAttribute('region')
|
||||
]);
|
||||
|
||||
$status = 'created';
|
||||
$functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS');
|
||||
if (!empty($functionsDomain) && \str_ends_with($domain->get(), $functionsDomain)) {
|
||||
$status = 'verified';
|
||||
}
|
||||
|
||||
if ($status === 'created') {
|
||||
$target = new Domain(System::getEnv('_APP_DOMAIN_TARGET', ''));
|
||||
$validator = new CNAME($target->get()); // Verify Domain with DNS records
|
||||
|
||||
if ($validator->isValid($domain->get())) {
|
||||
$status = 'verifying';
|
||||
|
||||
$queueForCertificates
|
||||
->setDomain(new Document([
|
||||
'domain' => $rule->getAttribute('domain')
|
||||
]))
|
||||
->trigger();
|
||||
}
|
||||
}
|
||||
|
||||
$rule->setAttribute('status', $status);
|
||||
$rule = $dbForPlatform->createDocument('rules', $rule);
|
||||
|
||||
$queueForEvents->setParam('ruleId', $rule->getId());
|
||||
|
||||
$rule->setAttribute('logs', '');
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->dynamic($rule, Response::MODEL_PROXY_RULE);
|
||||
});
|
||||
|
||||
App::get('/v1/proxy/rules')
|
||||
->groups(['api', 'proxy'])
|
||||
|
|
@ -368,17 +214,27 @@ App::patch('/v1/proxy/rules/:ruleId/verification')
|
|||
throw new Exception(Exception::RULE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$target = new Domain(System::getEnv('_APP_DOMAIN_TARGET', ''));
|
||||
$validators = [];
|
||||
$targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
|
||||
if (!$targetCNAME->isKnown() || $targetCNAME->isTest()) {
|
||||
$validators[] = new DNS($targetCNAME->get(), DNS::RECORD_CNAME);
|
||||
}
|
||||
if ((new IP(IP::V4))->isValid(System::getEnv('_APP_DOMAIN_TARGET_A', ''))) {
|
||||
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), DNS::RECORD_A);
|
||||
}
|
||||
if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) {
|
||||
$validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), DNS::RECORD_AAAA);
|
||||
}
|
||||
|
||||
if (!$target->isKnown() || $target->isTest()) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Domain target must be configured as environment variable.');
|
||||
if (empty($validators)) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'At least one of domain targets environment variable must be configured.');
|
||||
}
|
||||
|
||||
if ($rule->getAttribute('verification') === true) {
|
||||
return $response->dynamic($rule, Response::MODEL_PROXY_RULE);
|
||||
}
|
||||
|
||||
$validator = new CNAME($target->get()); // Verify Domain with DNS records
|
||||
$validator = new AnyOf($validators, AnyOf::TYPE_STRING);
|
||||
$domain = new Domain($rule->getAttribute('domain', ''));
|
||||
|
||||
$validationStart = \microtime(true);
|
||||
|
|
@ -386,7 +242,14 @@ App::patch('/v1/proxy/rules/:ruleId/verification')
|
|||
$log->addExtra('dnsTiming', \strval(\microtime(true) - $validationStart));
|
||||
$log->addTag('dnsDomain', $domain->get());
|
||||
|
||||
$error = $validator->getLogs();
|
||||
$errors = [];
|
||||
foreach ($validators as $validator) {
|
||||
if (!empty($validator->getLogs())) {
|
||||
$errors[] = $validator->getLogs();
|
||||
}
|
||||
}
|
||||
|
||||
$error = \implode("\n", $errors);
|
||||
$log->addExtra('dnsResponse', \is_array($error) ? \json_encode($error) : \strval($error));
|
||||
|
||||
throw new Exception(Exception::RULE_VERIFICATION_FAILED);
|
||||
|
|
|
|||
|
|
@ -951,11 +951,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
|
|||
->param('rotation', 0, new Range(-360, 360), 'Preview image rotation in degrees. Pass an integer between -360 and 360.', true)
|
||||
->param('background', '', new HexColor(), 'Preview image background color. Only works with transparent images (png). Use a valid HEX color, no # is needed for prefix.', true)
|
||||
->param('output', '', new WhiteList(\array_keys(Config::getParam('storage-outputs')), true), 'Output format type (jpeg, jpg, png, gif and webp).', true)
|
||||
// NOTE: this is only for the sdk generator and is not used in the action below and is utilised in `resources.php` for `resourceToken`.
|
||||
->param('token', '', new Text(512), 'File token for accessing this file.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('resourceToken')
|
||||
->inject('deviceForFiles')
|
||||
->inject('deviceForLocal')
|
||||
->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, Response $response, Database $dbForProject, Device $deviceForFiles, Device $deviceForLocal) {
|
||||
->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, ?string $token, Response $response, Database $dbForProject, Document $resourceToken, Device $deviceForFiles, Device $deviceForLocal) {
|
||||
|
||||
if (!\extension_loaded('imagick')) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing');
|
||||
|
|
@ -970,19 +973,24 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
|
|||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
$isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getInternalId();
|
||||
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
|
||||
$validator = new Authorization(Database::PERMISSION_READ);
|
||||
$valid = $validator->isValid($bucket->getRead());
|
||||
if (!$fileSecurity && !$valid) {
|
||||
if (!$fileSecurity && !$valid && !$isToken) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
if ($fileSecurity && !$valid) {
|
||||
if ($fileSecurity && !$valid && !$isToken) {
|
||||
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
|
||||
} else {
|
||||
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
|
||||
}
|
||||
|
||||
if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getInternalId()) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
if ($file->isEmpty()) {
|
||||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
|
@ -1123,12 +1131,15 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download')
|
|||
))
|
||||
->param('bucketId', '', new UID(), 'Storage bucket 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.')
|
||||
// NOTE: this is only for the sdk generator and is not used in the action below and is utilised in `resources.php` for `resourceToken`.
|
||||
->param('token', '', new Text(512), 'File token for accessing this file.', true)
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('mode')
|
||||
->inject('resourceToken')
|
||||
->inject('deviceForFiles')
|
||||
->action(function (string $bucketId, string $fileId, Request $request, Response $response, Database $dbForProject, string $mode, Device $deviceForFiles) {
|
||||
->action(function (string $bucketId, string $fileId, ?string $token, Request $request, Response $response, Database $dbForProject, string $mode, Document $resourceToken, Device $deviceForFiles) {
|
||||
|
||||
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
|
|
@ -1139,10 +1150,11 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download')
|
|||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
$isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getInternalId();
|
||||
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
|
||||
$validator = new Authorization(Database::PERMISSION_READ);
|
||||
$valid = $validator->isValid($bucket->getRead());
|
||||
if (!$fileSecurity && !$valid) {
|
||||
if (!$fileSecurity && !$valid && !$isToken) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
|
|
@ -1152,6 +1164,10 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download')
|
|||
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
|
||||
}
|
||||
|
||||
if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getInternalId()) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
if ($file->isEmpty()) {
|
||||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
|
@ -1272,12 +1288,15 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view')
|
|||
))
|
||||
->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.')
|
||||
// NOTE: this is only for the sdk generator and is not used in the action below and is utilised in `resources.php` for `resourceToken`.
|
||||
->param('token', '', new Text(512), 'File token for accessing this file.', true)
|
||||
->inject('response')
|
||||
->inject('request')
|
||||
->inject('dbForProject')
|
||||
->inject('mode')
|
||||
->inject('resourceToken')
|
||||
->inject('deviceForFiles')
|
||||
->action(function (string $bucketId, string $fileId, Response $response, Request $request, Database $dbForProject, string $mode, Device $deviceForFiles) {
|
||||
->action(function (string $bucketId, string $fileId, ?string $token, Response $response, Request $request, Database $dbForProject, string $mode, Document $resourceToken, Device $deviceForFiles) {
|
||||
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
|
||||
|
|
@ -1287,10 +1306,11 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view')
|
|||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
$isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getInternalId();
|
||||
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
|
||||
$validator = new Authorization(Database::PERMISSION_READ);
|
||||
$valid = $validator->isValid($bucket->getRead());
|
||||
if (!$fileSecurity && !$valid) {
|
||||
if (!$fileSecurity && !$valid && !$isToken) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
|
|
@ -1300,6 +1320,10 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view')
|
|||
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
|
||||
}
|
||||
|
||||
if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getInternalId()) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
if ($file->isEmpty()) {
|
||||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
|
@ -1783,6 +1807,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId')
|
|||
$response->noContent();
|
||||
});
|
||||
|
||||
/** Storage usage */
|
||||
App::get('/v1/storage/usage')
|
||||
->desc('Get storage usage stats')
|
||||
->groups(['api', 'storage'])
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ use Utopia\Validator\ArrayList;
|
|||
use Utopia\Validator\Assoc;
|
||||
use Utopia\Validator\Host;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\URL;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
App::post('/v1/teams')
|
||||
|
|
@ -465,7 +466,7 @@ App::post('/v1/teams/:teamId/memberships')
|
|||
}
|
||||
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'])
|
||||
->param('url', '', fn ($clients) => new Host($clients), '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, ['clients']) // TODO add our own built-in confirm page
|
||||
->param('url', '', fn ($clients, $devKey) => $devKey->isEmpty() ? new Host($clients) : new URL(), '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, ['clients', 'devKey']) // TODO add our own built-in confirm page
|
||||
->param('name', '', new Text(128), 'Name of the new team member. Max length: 128 chars.', true)
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ use Appwrite\SDK\Method;
|
|||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Identities;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Memberships;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Targets;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Users;
|
||||
use Appwrite\Utopia\Request;
|
||||
|
|
@ -822,9 +823,11 @@ App::get('/v1/users/:userId/memberships')
|
|||
]
|
||||
))
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->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)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $userId, Response $response, Database $dbForProject) {
|
||||
->action(function (string $userId, array $queries, string $search, Response $response, Database $dbForProject) {
|
||||
|
||||
$user = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
|
|
@ -832,6 +835,19 @@ App::get('/v1/users/:userId/memberships')
|
|||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
try {
|
||||
$queries = Query::parseQueries($queries);
|
||||
} catch (QueryException $e) {
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
|
||||
}
|
||||
|
||||
if (!empty($search)) {
|
||||
$queries[] = Query::search('search', $search);
|
||||
}
|
||||
|
||||
// Set internal queries
|
||||
$queries[] = Query::equal('userInternalId', [$user->getInternalId()]);
|
||||
|
||||
$memberships = array_map(function ($membership) use ($dbForProject, $user) {
|
||||
$team = $dbForProject->getDocument('teams', $membership->getAttribute('teamId'));
|
||||
|
||||
|
|
@ -841,7 +857,7 @@ App::get('/v1/users/:userId/memberships')
|
|||
->setAttribute('userEmail', $user->getAttribute('email'));
|
||||
|
||||
return $membership;
|
||||
}, $user->getAttribute('memberships', []));
|
||||
}, $dbForProject->find('memberships', $queries));
|
||||
|
||||
$response->dynamic(new Document([
|
||||
'memberships' => $memberships,
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@ use Appwrite\Utopia\Request;
|
|||
use Appwrite\Utopia\Response;
|
||||
use Appwrite\Vcs\Comment;
|
||||
use Utopia\App;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Duplicate;
|
||||
use Utopia\Database\Exception\Order as OrderException;
|
||||
use Utopia\Database\Exception\Query as QueryException;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
|
|
@ -27,22 +27,35 @@ use Utopia\Database\Helpers\Role;
|
|||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Query\Cursor;
|
||||
use Utopia\Detector\Adapter\Bun;
|
||||
use Utopia\Detector\Adapter\CPP;
|
||||
use Utopia\Detector\Adapter\Dart;
|
||||
use Utopia\Detector\Adapter\Deno;
|
||||
use Utopia\Detector\Adapter\Dotnet;
|
||||
use Utopia\Detector\Adapter\Java;
|
||||
use Utopia\Detector\Adapter\JavaScript;
|
||||
use Utopia\Detector\Adapter\PHP;
|
||||
use Utopia\Detector\Adapter\Python;
|
||||
use Utopia\Detector\Adapter\Ruby;
|
||||
use Utopia\Detector\Adapter\Swift;
|
||||
use Utopia\Detector\Detector;
|
||||
use Utopia\Detector\Detection\Framework\Astro;
|
||||
use Utopia\Detector\Detection\Framework\Flutter;
|
||||
use Utopia\Detector\Detection\Framework\NextJs;
|
||||
use Utopia\Detector\Detection\Framework\Nuxt;
|
||||
use Utopia\Detector\Detection\Framework\Remix;
|
||||
use Utopia\Detector\Detection\Framework\SvelteKit;
|
||||
use Utopia\Detector\Detection\Packager\NPM;
|
||||
use Utopia\Detector\Detection\Packager\PNPM;
|
||||
use Utopia\Detector\Detection\Packager\Yarn;
|
||||
use Utopia\Detector\Detection\Runtime\Bun;
|
||||
use Utopia\Detector\Detection\Runtime\CPP;
|
||||
use Utopia\Detector\Detection\Runtime\Dart;
|
||||
use Utopia\Detector\Detection\Runtime\Deno;
|
||||
use Utopia\Detector\Detection\Runtime\Dotnet;
|
||||
use Utopia\Detector\Detection\Runtime\Java;
|
||||
use Utopia\Detector\Detection\Runtime\Node;
|
||||
use Utopia\Detector\Detection\Runtime\PHP;
|
||||
use Utopia\Detector\Detection\Runtime\Python;
|
||||
use Utopia\Detector\Detection\Runtime\Ruby;
|
||||
use Utopia\Detector\Detection\Runtime\Swift;
|
||||
use Utopia\Detector\Detector\Framework;
|
||||
use Utopia\Detector\Detector\Packager;
|
||||
use Utopia\Detector\Detector\Runtime;
|
||||
use Utopia\Detector\Detector\Strategy;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Host;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\VCS\Adapter\Git\GitHub;
|
||||
use Utopia\VCS\Exception\RepositoryNotFound;
|
||||
|
||||
|
|
@ -50,29 +63,30 @@ use function Swoole\Coroutine\batch;
|
|||
|
||||
$createGitDeployments = function (GitHub $github, string $providerInstallationId, array $repositories, string $providerBranch, string $providerBranchUrl, string $providerRepositoryName, string $providerRepositoryUrl, string $providerRepositoryOwner, string $providerCommitHash, string $providerCommitAuthor, string $providerCommitAuthorUrl, string $providerCommitMessage, string $providerCommitUrl, string $providerPullRequestId, bool $external, Database $dbForPlatform, Build $queueForBuilds, callable $getProjectDB, Request $request) {
|
||||
$errors = [];
|
||||
foreach ($repositories as $resource) {
|
||||
foreach ($repositories as $repository) {
|
||||
try {
|
||||
$resourceType = $resource->getAttribute('resourceType');
|
||||
$resourceType = $repository->getAttribute('resourceType');
|
||||
|
||||
if ($resourceType !== "function") {
|
||||
if ($resourceType !== "function" && $resourceType !== "site") {
|
||||
continue;
|
||||
}
|
||||
|
||||
$projectId = $resource->getAttribute('projectId');
|
||||
$projectId = $repository->getAttribute('projectId');
|
||||
$project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId));
|
||||
$dbForProject = $getProjectDB($project);
|
||||
|
||||
$functionId = $resource->getAttribute('resourceId');
|
||||
$function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId));
|
||||
$functionInternalId = $function->getInternalId();
|
||||
$resourceCollection = $resourceType === "function" ? 'functions' : 'sites';
|
||||
$resourceId = $repository->getAttribute('resourceId');
|
||||
$resource = Authorization::skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId));
|
||||
$resourceInternalId = $resource->getInternalId();
|
||||
|
||||
$deploymentId = ID::unique();
|
||||
$repositoryId = $resource->getId();
|
||||
$repositoryInternalId = $resource->getInternalId();
|
||||
$providerRepositoryId = $resource->getAttribute('providerRepositoryId');
|
||||
$installationId = $resource->getAttribute('installationId');
|
||||
$installationInternalId = $resource->getAttribute('installationInternalId');
|
||||
$productionBranch = $function->getAttribute('providerBranch');
|
||||
$repositoryId = $repository->getId();
|
||||
$repositoryInternalId = $repository->getInternalId();
|
||||
$providerRepositoryId = $repository->getAttribute('providerRepositoryId');
|
||||
$installationId = $repository->getAttribute('installationId');
|
||||
$installationInternalId = $repository->getAttribute('installationInternalId');
|
||||
$productionBranch = $resource->getAttribute('providerBranch');
|
||||
$activate = false;
|
||||
|
||||
if ($providerBranch == $productionBranch && $external === false) {
|
||||
|
|
@ -96,7 +110,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
|||
$isAuthorized = !$external;
|
||||
|
||||
if (!$isAuthorized && !empty($providerPullRequestId)) {
|
||||
if (\in_array($providerPullRequestId, $resource->getAttribute('providerPullRequestIds', []))) {
|
||||
if (\in_array($providerPullRequestId, $repository->getAttribute('providerPullRequestIds', []))) {
|
||||
$isAuthorized = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -109,7 +123,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
|||
|
||||
$latestCommentId = '';
|
||||
|
||||
if (!empty($providerPullRequestId) && $function->getAttribute('providerSilentMode', false) === false) {
|
||||
if (!empty($providerPullRequestId) && $resource->getAttribute('providerSilentMode', false) === false) {
|
||||
$latestComment = Authorization::skip(fn () => $dbForPlatform->findOne('vcsComments', [
|
||||
Query::equal('providerRepositoryId', [$providerRepositoryId]),
|
||||
Query::equal('providerPullRequestId', [$providerPullRequestId]),
|
||||
|
|
@ -118,14 +132,15 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
|||
|
||||
if (!$latestComment->isEmpty()) {
|
||||
$latestCommentId = $latestComment->getAttribute('providerCommentId', '');
|
||||
|
||||
$comment = new Comment();
|
||||
$comment->parseComment($github->getComment($owner, $repositoryName, $latestCommentId));
|
||||
$comment->addBuild($project, $function, $commentStatus, $deploymentId, $action);
|
||||
$comment->addBuild($project, $resource, $resourceType, $commentStatus, $deploymentId, $action, '');
|
||||
|
||||
$latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment()));
|
||||
} else {
|
||||
$comment = new Comment();
|
||||
$comment->addBuild($project, $function, $commentStatus, $deploymentId, $action);
|
||||
$comment->addBuild($project, $resource, $resourceType, $commentStatus, $deploymentId, $action, '');
|
||||
$latestCommentId = \strval($github->createComment($owner, $repositoryName, $providerPullRequestId, $comment->generateComment()));
|
||||
|
||||
if (!empty($latestCommentId)) {
|
||||
|
|
@ -162,19 +177,19 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
|||
$latestCommentId = $comment->getAttribute('providerCommentId', '');
|
||||
$comment = new Comment();
|
||||
$comment->parseComment($github->getComment($owner, $repositoryName, $latestCommentId));
|
||||
$comment->addBuild($project, $function, $commentStatus, $deploymentId, $action);
|
||||
$comment->addBuild($project, $resource, $resourceType, $commentStatus, $deploymentId, $action, '');
|
||||
|
||||
$latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment()));
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isAuthorized) {
|
||||
$functionName = $function->getAttribute('name');
|
||||
$resourceName = $resource->getAttribute('name');
|
||||
$projectName = $project->getAttribute('name');
|
||||
$name = "{$functionName} ({$projectName})";
|
||||
$name = "{$resourceName} ({$projectName})";
|
||||
$message = 'Authorization required for external contributor.';
|
||||
|
||||
$providerRepositoryId = $resource->getAttribute('providerRepositoryId');
|
||||
$providerRepositoryId = $repository->getAttribute('providerRepositoryId');
|
||||
try {
|
||||
$repositoryName = $github->getRepositoryName($providerRepositoryId) ?? '';
|
||||
if (empty($repositoryName)) {
|
||||
|
|
@ -194,18 +209,32 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
|||
$providerRepositoryOwner = $pullRequestResponse['head']['repo']['name'];
|
||||
}
|
||||
|
||||
$deployment = $dbForProject->createDocument('deployments', new Document([
|
||||
$commands = [];
|
||||
if (!empty($resource->getAttribute('installCommand', ''))) {
|
||||
$commands[] = $resource->getAttribute('installCommand', '');
|
||||
}
|
||||
if (!empty($resource->getAttribute('buildCommand', ''))) {
|
||||
$commands[] = $resource->getAttribute('buildCommand', '');
|
||||
}
|
||||
if (!empty($resource->getAttribute('commands', ''))) {
|
||||
$commands[] = $resource->getAttribute('commands', '');
|
||||
}
|
||||
|
||||
$deployment = Authorization::skip(fn () => $dbForProject->createDocument('deployments', new Document([
|
||||
'$id' => $deploymentId,
|
||||
'$permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
Permission::delete(Role::any()),
|
||||
],
|
||||
'resourceId' => $functionId,
|
||||
'resourceInternalId' => $functionInternalId,
|
||||
'resourceType' => 'functions',
|
||||
'entrypoint' => $function->getAttribute('entrypoint'),
|
||||
'commands' => $function->getAttribute('commands'),
|
||||
'resourceId' => $resourceId,
|
||||
'resourceInternalId' => $resourceInternalId,
|
||||
'resourceType' => $resourceCollection,
|
||||
'entrypoint' => $resource->getAttribute('entrypoint', ''),
|
||||
'buildCommands' => \implode(' && ', $commands),
|
||||
'buildOutput' => $resource->getAttribute('outputDirectory', ''),
|
||||
'adapter' => $resource->getAttribute('adapter', ''),
|
||||
'fallbackFile' => $resource->getAttribute('fallbackFile', ''),
|
||||
'type' => 'vcs',
|
||||
'installationId' => $installationId,
|
||||
'installationInternalId' => $installationInternalId,
|
||||
|
|
@ -219,21 +248,120 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
|||
'providerCommitHash' => $providerCommitHash,
|
||||
'providerCommitAuthorUrl' => $providerCommitAuthorUrl,
|
||||
'providerCommitAuthor' => $providerCommitAuthor,
|
||||
'providerCommitMessage' => $providerCommitMessage,
|
||||
'providerCommitMessage' => mb_strimwidth($providerCommitMessage, 0, 255, '...'),
|
||||
'providerCommitUrl' => $providerCommitUrl,
|
||||
'providerCommentId' => \strval($latestCommentId),
|
||||
'providerBranch' => $providerBranch,
|
||||
'search' => implode(' ', [$deploymentId, $function->getAttribute('entrypoint')]),
|
||||
'search' => implode(' ', [$deploymentId, $resource->getAttribute('entrypoint', '')]),
|
||||
'activate' => $activate,
|
||||
]));
|
||||
])));
|
||||
|
||||
if (!empty($providerCommitHash) && $function->getAttribute('providerSilentMode', false) === false) {
|
||||
$functionName = $function->getAttribute('name');
|
||||
$resource = $resource
|
||||
->setAttribute('latestDeploymentId', $deployment->getId())
|
||||
->setAttribute('latestDeploymentInternalId', $deployment->getInternalId())
|
||||
->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt())
|
||||
->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
|
||||
Authorization::skip(fn () => $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource));
|
||||
|
||||
if ($resource->getCollection() === 'sites') {
|
||||
$projectId = $project->getId();
|
||||
|
||||
// Deployment preview
|
||||
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
|
||||
$domain = ID::unique() . "." . $sitesDomain;
|
||||
$ruleId = md5($domain);
|
||||
Authorization::skip(
|
||||
fn () => $dbForPlatform->createDocument('rules', new Document([
|
||||
'$id' => $ruleId,
|
||||
'projectId' => $project->getId(),
|
||||
'projectInternalId' => $project->getInternalId(),
|
||||
'domain' => $domain,
|
||||
'type' => 'deployment',
|
||||
'trigger' => 'deployment',
|
||||
'deploymentId' => $deployment->getId(),
|
||||
'deploymentInternalId' => $deployment->getInternalId(),
|
||||
'deploymentResourceType' => 'site',
|
||||
'deploymentResourceId' => $resourceId,
|
||||
'deploymentResourceInternalId' => $resourceInternalId,
|
||||
'deploymentVcsProviderBranch' => $providerBranch,
|
||||
'status' => 'verified',
|
||||
'certificateId' => '',
|
||||
'search' => implode(' ', [$ruleId, $domain]),
|
||||
'owner' => 'Appwrite',
|
||||
'region' => $project->getAttribute('region')
|
||||
]))
|
||||
);
|
||||
|
||||
// VCS branch preview
|
||||
if (!empty($providerBranch)) {
|
||||
$domain = "branch-{$providerBranch}-{$resource->getId()}-{$project->getId()}.{$sitesDomain}";
|
||||
$ruleId = md5($domain);
|
||||
try {
|
||||
Authorization::skip(
|
||||
fn () => $dbForPlatform->createDocument('rules', new Document([
|
||||
'$id' => $ruleId,
|
||||
'projectId' => $project->getId(),
|
||||
'projectInternalId' => $project->getInternalId(),
|
||||
'domain' => $domain,
|
||||
'type' => 'deployment',
|
||||
'trigger' => 'deployment',
|
||||
'deploymentId' => $deployment->getId(),
|
||||
'deploymentInternalId' => $deployment->getInternalId(),
|
||||
'deploymentResourceType' => 'site',
|
||||
'deploymentResourceId' => $resourceId,
|
||||
'deploymentResourceInternalId' => $resourceInternalId,
|
||||
'deploymentVcsProviderBranch' => $providerBranch,
|
||||
'status' => 'verified',
|
||||
'certificateId' => '',
|
||||
'search' => implode(' ', [$ruleId, $domain]),
|
||||
'owner' => 'Appwrite',
|
||||
'region' => $project->getAttribute('region')
|
||||
]))
|
||||
);
|
||||
} catch (Duplicate $err) {
|
||||
// Ignore, rule already exists; will be updated by builds worker
|
||||
}
|
||||
}
|
||||
|
||||
// VCS commit preview
|
||||
if (!empty($providerCommitHash)) {
|
||||
$domain = "commit-{$providerCommitHash}-{$resource->getId()}-{$project->getId()}.{$sitesDomain}";
|
||||
$ruleId = md5($domain);
|
||||
try {
|
||||
Authorization::skip(
|
||||
fn () => $dbForPlatform->createDocument('rules', new Document([
|
||||
'$id' => $ruleId,
|
||||
'projectId' => $project->getId(),
|
||||
'projectInternalId' => $project->getInternalId(),
|
||||
'domain' => $domain,
|
||||
'type' => 'deployment',
|
||||
'trigger' => 'deployment',
|
||||
'deploymentId' => $deployment->getId(),
|
||||
'deploymentInternalId' => $deployment->getInternalId(),
|
||||
'deploymentResourceType' => 'site',
|
||||
'deploymentResourceId' => $resourceId,
|
||||
'deploymentResourceInternalId' => $resourceInternalId,
|
||||
'deploymentVcsProviderBranch' => $providerBranch,
|
||||
'status' => 'verified',
|
||||
'certificateId' => '',
|
||||
'search' => implode(' ', [$ruleId, $domain]),
|
||||
'owner' => 'Appwrite',
|
||||
'region' => $project->getAttribute('region')
|
||||
]))
|
||||
);
|
||||
} catch (Duplicate $err) {
|
||||
// Ignore, rule already exists; will be updated by builds worker
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($providerCommitHash) && $resource->getAttribute('providerSilentMode', false) === false) {
|
||||
$resourceName = $resource->getAttribute('name');
|
||||
$projectName = $project->getAttribute('name');
|
||||
$name = "{$functionName} ({$projectName})";
|
||||
$name = "{$resourceName} ({$projectName})";
|
||||
$message = 'Starting...';
|
||||
|
||||
$providerRepositoryId = $resource->getAttribute('providerRepositoryId');
|
||||
$providerRepositoryId = $repository->getAttribute('providerRepositoryId');
|
||||
try {
|
||||
$repositoryName = $github->getRepositoryName($providerRepositoryId) ?? '';
|
||||
if (empty($repositoryName)) {
|
||||
|
|
@ -244,17 +372,17 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
|||
}
|
||||
$owner = $github->getOwnerName($providerInstallationId);
|
||||
|
||||
$providerTargetUrl = $request->getProtocol() . '://' . $request->getHostname() . "/console/project-$projectId/functions/function-$functionId";
|
||||
$providerTargetUrl = $request->getProtocol() . '://' . $request->getHostname() . "/console/project-$projectId/$resourceCollection/$resourceType-$resourceId";
|
||||
$github->updateCommitStatus($repositoryName, $providerCommitHash, $owner, 'pending', $message, $providerTargetUrl, $name);
|
||||
}
|
||||
|
||||
$queueForBuilds
|
||||
->setType(BUILD_TYPE_DEPLOYMENT)
|
||||
->setResource($function)
|
||||
->setResource($resource)
|
||||
->setDeployment($deployment)
|
||||
->setProject($project); // set the project because it won't be set for git deployments
|
||||
|
||||
$queueForBuilds->trigger(); // must trigger here so that we create a build for each function
|
||||
$queueForBuilds->trigger(); // must trigger here so that we create a build for each function/site
|
||||
|
||||
//TODO: Add event?
|
||||
} catch (Throwable $e) {
|
||||
|
|
@ -519,8 +647,9 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro
|
|||
]), Response::MODEL_VCS_CONTENT_LIST);
|
||||
});
|
||||
|
||||
App::post('/v1/vcs/github/installations/:installationId/providerRepositories/:providerRepositoryId/detection')
|
||||
->desc('Create runtime settings detection')
|
||||
App::post('/v1/vcs/github/installations/:installationId/detections')
|
||||
->alias('/v1/vcs/github/installations/:installationId/providerRepositories/:providerRepositoryId/detection')
|
||||
->desc('Create repository detection')
|
||||
->groups(['api', 'vcs'])
|
||||
->label('scope', 'vcs.write')
|
||||
->label('sdk', new Method(
|
||||
|
|
@ -532,18 +661,22 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories/:pr
|
|||
responses: [
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_OK,
|
||||
model: Response::MODEL_DETECTION,
|
||||
model: Response::MODEL_DETECTION_RUNTIME,
|
||||
),
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_OK,
|
||||
model: Response::MODEL_DETECTION_FRAMEWORK,
|
||||
)
|
||||
]
|
||||
))
|
||||
->param('installationId', '', new Text(256), 'Installation Id')
|
||||
->param('providerRepositoryId', '', new Text(256), 'Repository Id')
|
||||
->param('type', '', new WhiteList(['runtime', 'framework']), 'Detector type. Must be one of the following: runtime, framework')
|
||||
->param('providerRootDirectory', '', new Text(256, 0), 'Path to Root Directory', true)
|
||||
->inject('gitHub')
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $installationId, string $providerRepositoryId, string $providerRootDirectory, GitHub $github, Response $response, Document $project, Database $dbForPlatform) {
|
||||
->action(function (string $installationId, string $providerRepositoryId, string $type, string $providerRootDirectory, GitHub $github, Response $response, Database $dbForPlatform) {
|
||||
$installation = $dbForPlatform->getDocument('installations', $installationId);
|
||||
|
||||
if ($installation->isEmpty()) {
|
||||
|
|
@ -569,32 +702,108 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories/:pr
|
|||
$files = \array_column($files, 'name');
|
||||
$languages = $github->listRepositoryLanguages($owner, $repositoryName);
|
||||
|
||||
$detectorFactory = new Detector($files, $languages);
|
||||
$detector = new Packager($files);
|
||||
$detector
|
||||
->addOption(new Yarn())
|
||||
->addOption(new PNPM())
|
||||
->addOption(new NPM());
|
||||
$detection = $detector->detect();
|
||||
|
||||
$detectorFactory
|
||||
->addDetector(new JavaScript())
|
||||
->addDetector(new Bun())
|
||||
->addDetector(new PHP())
|
||||
->addDetector(new Python())
|
||||
->addDetector(new Dart())
|
||||
->addDetector(new Swift())
|
||||
->addDetector(new Ruby())
|
||||
->addDetector(new Java())
|
||||
->addDetector(new CPP())
|
||||
->addDetector(new Deno())
|
||||
->addDetector(new Dotnet());
|
||||
$packager = !\is_null($detection) ? $detection->getName() : 'npm';
|
||||
|
||||
$runtime = $detectorFactory->detect();
|
||||
if ($type === 'framework') {
|
||||
$output = new Document([
|
||||
'framework' => '',
|
||||
'installCommand' => '',
|
||||
'buildCommand' => '',
|
||||
'outputDirectory' => '',
|
||||
]);
|
||||
|
||||
$runtimes = Config::getParam('runtimes');
|
||||
$runtimeDetail = \array_reverse(\array_filter(\array_keys($runtimes), function ($key) use ($runtime, $runtimes) {
|
||||
return $runtimes[$key]['key'] === $runtime;
|
||||
}))[0] ?? '';
|
||||
$detector = new Framework($files, $packager);
|
||||
$detector
|
||||
->addOption(new Flutter())
|
||||
->addOption(new Nuxt())
|
||||
->addOption(new Astro())
|
||||
->addOption(new SvelteKit())
|
||||
->addOption(new NextJs())
|
||||
->addOption(new Remix());
|
||||
|
||||
$detection = [];
|
||||
$detection['runtime'] = $runtimeDetail;
|
||||
$framework = $detector->detect();
|
||||
|
||||
$response->dynamic(new Document($detection), Response::MODEL_DETECTION);
|
||||
if (!\is_null($framework)) {
|
||||
$output->setAttribute('installCommand', $framework->getInstallCommand());
|
||||
$output->setAttribute('buildCommand', $framework->getBuildCommand());
|
||||
$output->setAttribute('outputDirectory', $framework->getOutputDirectory());
|
||||
$framework = $framework->getName();
|
||||
} else {
|
||||
$framework = 'other';
|
||||
$output->setAttribute('installCommand', '');
|
||||
$output->setAttribute('buildCommand', '');
|
||||
$output->setAttribute('outputDirectory', '');
|
||||
}
|
||||
|
||||
$frameworks = Config::getParam('frameworks');
|
||||
if (!\in_array($framework, \array_keys($frameworks), true)) {
|
||||
$framework = 'other';
|
||||
}
|
||||
$output->setAttribute('framework', $framework);
|
||||
} else {
|
||||
$output = new Document([
|
||||
'runtime' => '',
|
||||
'commands' => '',
|
||||
'entrypoint' => '',
|
||||
]);
|
||||
|
||||
$strategies = [
|
||||
new Strategy(Strategy::FILEMATCH),
|
||||
new Strategy(Strategy::LANGUAGES),
|
||||
new Strategy(Strategy::EXTENSION),
|
||||
];
|
||||
|
||||
foreach ($strategies as $strategy) {
|
||||
$detector = new Runtime($strategy === Strategy::LANGUAGES ? $languages : $files, $strategy, $packager);
|
||||
$detector
|
||||
->addOption(new Node())
|
||||
->addOption(new Bun())
|
||||
->addOption(new Deno())
|
||||
->addOption(new PHP())
|
||||
->addOption(new Python())
|
||||
->addOption(new Dart())
|
||||
->addOption(new Swift())
|
||||
->addOption(new Ruby())
|
||||
->addOption(new Java())
|
||||
->addOption(new CPP())
|
||||
->addOption(new Dotnet());
|
||||
|
||||
$runtime = $detector->detect();
|
||||
|
||||
if (!\is_null($runtime)) {
|
||||
$output->setAttribute('commands', $runtime->getCommands());
|
||||
$output->setAttribute('entrypoint', $runtime->getEntrypoint());
|
||||
$runtime = $runtime->getName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($runtime)) {
|
||||
$runtimes = Config::getParam('runtimes');
|
||||
$runtimeWithVersion = '';
|
||||
foreach ($runtimes as $runtimeKey => $runtimeConfig) {
|
||||
if ($runtimeConfig['key'] === $runtime) {
|
||||
$runtimeWithVersion = $runtimeKey;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($runtimeWithVersion)) {
|
||||
throw new Exception(Exception::FUNCTION_RUNTIME_NOT_DETECTED);
|
||||
}
|
||||
|
||||
$output->setAttribute('runtime', $runtimeWithVersion);
|
||||
} else {
|
||||
throw new Exception(Exception::FUNCTION_RUNTIME_NOT_DETECTED);
|
||||
}
|
||||
}
|
||||
$response->dynamic($output, $type === 'framework' ? Response::MODEL_DETECTION_FRAMEWORK : Response::MODEL_DETECTION_RUNTIME);
|
||||
});
|
||||
|
||||
App::get('/v1/vcs/github/installations/:installationId/providerRepositories')
|
||||
|
|
@ -610,17 +819,21 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories')
|
|||
responses: [
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_OK,
|
||||
model: Response::MODEL_PROVIDER_REPOSITORY_LIST,
|
||||
model: Response::MODEL_PROVIDER_REPOSITORY_RUNTIME_LIST,
|
||||
),
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_OK,
|
||||
model: Response::MODEL_PROVIDER_REPOSITORY_FRAMEWORK_LIST,
|
||||
)
|
||||
]
|
||||
))
|
||||
->param('installationId', '', new Text(256), 'Installation Id')
|
||||
->param('type', '', new WhiteList(['runtime', 'framework']), 'Detector type. Must be one of the following: runtime, framework')
|
||||
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
|
||||
->inject('gitHub')
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $installationId, string $search, GitHub $github, Response $response, Document $project, Database $dbForPlatform) {
|
||||
->action(function (string $installationId, string $type, string $search, GitHub $github, Response $response, Database $dbForPlatform) {
|
||||
if (empty($search)) {
|
||||
$search = "";
|
||||
}
|
||||
|
|
@ -650,39 +863,86 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories')
|
|||
return $repo;
|
||||
}, $repos);
|
||||
|
||||
$repos = batch(\array_map(function ($repo) use ($github) {
|
||||
return function () use ($repo, $github) {
|
||||
try {
|
||||
$files = $github->listRepositoryContents($repo['organization'], $repo['name'], '');
|
||||
$files = \array_column($files, 'name');
|
||||
$repos = batch(\array_map(function ($repo) use ($type, $github) {
|
||||
return function () use ($repo, $type, $github) {
|
||||
$files = $github->listRepositoryContents($repo['organization'], $repo['name'], '');
|
||||
$files = \array_column($files, 'name');
|
||||
|
||||
$detector = new Packager($files);
|
||||
$detector
|
||||
->addOption(new Yarn())
|
||||
->addOption(new PNPM())
|
||||
->addOption(new NPM());
|
||||
$detection = $detector->detect();
|
||||
|
||||
$packager = !\is_null($detection) ? $detection->getName() : 'npm';
|
||||
|
||||
if ($type === 'framework') {
|
||||
$frameworkDetector = new Framework($files, $packager);
|
||||
$frameworkDetector
|
||||
->addOption(new Flutter())
|
||||
->addOption(new Nuxt())
|
||||
->addOption(new Astro())
|
||||
->addOption(new SvelteKit())
|
||||
->addOption(new NextJs())
|
||||
->addOption(new Remix());
|
||||
|
||||
$detectedFramework = $frameworkDetector->detect();
|
||||
|
||||
if (!\is_null($detectedFramework)) {
|
||||
$framework = $detectedFramework->getName();
|
||||
} else {
|
||||
$framework = 'other';
|
||||
}
|
||||
|
||||
$frameworks = Config::getParam('frameworks');
|
||||
if (!\in_array($framework, \array_keys($frameworks), true)) {
|
||||
$framework = 'other';
|
||||
}
|
||||
$repo['framework'] = $framework;
|
||||
} else {
|
||||
$languages = $github->listRepositoryLanguages($repo['organization'], $repo['name']);
|
||||
|
||||
$detectorFactory = new Detector($files, $languages);
|
||||
$strategies = [
|
||||
new Strategy(Strategy::FILEMATCH),
|
||||
new Strategy(Strategy::LANGUAGES),
|
||||
new Strategy(Strategy::EXTENSION),
|
||||
];
|
||||
|
||||
$detectorFactory
|
||||
->addDetector(new JavaScript())
|
||||
->addDetector(new Bun())
|
||||
->addDetector(new PHP())
|
||||
->addDetector(new Python())
|
||||
->addDetector(new Dart())
|
||||
->addDetector(new Swift())
|
||||
->addDetector(new Ruby())
|
||||
->addDetector(new Java())
|
||||
->addDetector(new CPP())
|
||||
->addDetector(new Deno())
|
||||
->addDetector(new Dotnet());
|
||||
foreach ($strategies as $strategy) {
|
||||
$detector = new Runtime($strategy === Strategy::LANGUAGES ? $languages : $files, $strategy, $packager);
|
||||
$detector
|
||||
->addOption(new Node())
|
||||
->addOption(new Bun())
|
||||
->addOption(new Deno())
|
||||
->addOption(new PHP())
|
||||
->addOption(new Python())
|
||||
->addOption(new Dart())
|
||||
->addOption(new Swift())
|
||||
->addOption(new Ruby())
|
||||
->addOption(new Java())
|
||||
->addOption(new CPP())
|
||||
->addOption(new Dotnet());
|
||||
|
||||
$runtime = $detectorFactory->detect();
|
||||
$runtime = $detector->detect();
|
||||
|
||||
$runtimes = Config::getParam('runtimes');
|
||||
$runtimeDetail = \array_reverse(\array_filter(\array_keys($runtimes), function ($key) use ($runtime, $runtimes) {
|
||||
return $runtimes[$key]['key'] === $runtime;
|
||||
}))[0] ?? '';
|
||||
if (!\is_null($runtime)) {
|
||||
$runtime = $runtime->getName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$repo['runtime'] = $runtimeDetail;
|
||||
} catch (Throwable $error) {
|
||||
$repo['runtime'] = "";
|
||||
Console::warning("Runtime not detected for " . $repo['organization'] . "/" . $repo['name']);
|
||||
if (!empty($runtime)) {
|
||||
$runtimes = Config::getParam('runtimes');
|
||||
$runtimeWithVersion = '';
|
||||
foreach ($runtimes as $runtimeKey => $runtimeConfig) {
|
||||
if ($runtimeConfig['key'] === $runtime) {
|
||||
$runtimeWithVersion = $runtimeKey;
|
||||
}
|
||||
}
|
||||
|
||||
$repo['runtime'] = $runtimeWithVersion ?? '';
|
||||
}
|
||||
}
|
||||
return $repo;
|
||||
};
|
||||
|
|
@ -693,9 +953,9 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories')
|
|||
}, $repos);
|
||||
|
||||
$response->dynamic(new Document([
|
||||
'providerRepositories' => $repos,
|
||||
$type === 'framework' ? 'frameworkProviderRepositories' : 'runtimeProviderRepositories' => $repos,
|
||||
'total' => \count($repos),
|
||||
]), Response::MODEL_PROVIDER_REPOSITORY_LIST);
|
||||
]), ($type === 'framework') ? Response::MODEL_PROVIDER_REPOSITORY_FRAMEWORK_LIST : Response::MODEL_PROVIDER_REPOSITORY_RUNTIME_LIST);
|
||||
});
|
||||
|
||||
App::post('/v1/vcs/github/installations/:installationId/providerRepositories')
|
||||
|
|
@ -965,7 +1225,7 @@ App::post('/v1/vcs/github/events')
|
|||
|
||||
$github->initializeVariables($providerInstallationId, $privateKey, $githubAppId);
|
||||
|
||||
//find functionId from functions table
|
||||
//find resourceId from relevant resources table
|
||||
$repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [
|
||||
Query::equal('providerRepositoryId', [$providerRepositoryId]),
|
||||
Query::limit(100),
|
||||
|
|
@ -977,7 +1237,7 @@ App::post('/v1/vcs/github/events')
|
|||
}
|
||||
} elseif ($event == $github::EVENT_INSTALLATION) {
|
||||
if ($parsedPayload["action"] == "deleted") {
|
||||
// TODO: Use worker for this job instead (update function as well)
|
||||
// TODO: Use worker for this job instead (update function/site as well)
|
||||
$providerInstallationId = $parsedPayload["installationId"];
|
||||
|
||||
$installations = $dbForPlatform->find('installations', [
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -169,6 +169,15 @@ $usageDatabaseListener = function (string $event, Document $document, StatsUsage
|
|||
$queueForStatsUsage
|
||||
->addMetric(METRIC_FUNCTIONS, $value); // per project
|
||||
|
||||
if ($event === Database::EVENT_DOCUMENT_DELETE) {
|
||||
$queueForStatsUsage
|
||||
->addReduce($document);
|
||||
}
|
||||
break;
|
||||
case $document->getCollection() === 'sites':
|
||||
$queueForStatsUsage
|
||||
->addMetric(METRIC_SITES, $value); // per project
|
||||
|
||||
if ($event === Database::EVENT_DOCUMENT_DELETE) {
|
||||
$queueForStatsUsage
|
||||
->addReduce($document);
|
||||
|
|
@ -178,8 +187,10 @@ $usageDatabaseListener = function (string $event, Document $document, StatsUsage
|
|||
$queueForStatsUsage
|
||||
->addMetric(METRIC_DEPLOYMENTS, $value) // per project
|
||||
->addMetric(METRIC_DEPLOYMENTS_STORAGE, $document->getAttribute('size') * $value) // per project
|
||||
->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_FUNCTION_ID_DEPLOYMENTS), $value) // per function
|
||||
->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE), $document->getAttribute('size') * $value);
|
||||
->addMetric(str_replace(['{resourceType}'], [$document->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_DEPLOYMENTS), $value) // per function
|
||||
->addMetric(str_replace(['{resourceType}'], [$document->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_DEPLOYMENTS_STORAGE), $document->getAttribute('size') * $value)
|
||||
->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), $value) // per function
|
||||
->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), $document->getAttribute('size') * $value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -254,7 +265,7 @@ App::init()
|
|||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$accessedAt = $dbKey->getAttribute('accessedAt', '');
|
||||
$accessedAt = $dbKey->getAttribute('accessedAt', 0);
|
||||
|
||||
if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_KEY_ACCESS)) > $accessedAt) {
|
||||
$dbKey->setAttribute('accessedAt', DateTime::now());
|
||||
|
|
@ -265,7 +276,7 @@ App::init()
|
|||
$sdkValidator = new WhiteList($servers, true);
|
||||
$sdk = $request->getHeader('x-sdk-name', 'UNKNOWN');
|
||||
|
||||
if ($sdkValidator->isValid($sdk)) {
|
||||
if ($sdk !== 'UNKNOWN' && $sdkValidator->isValid($sdk)) {
|
||||
$sdks = $dbKey->getAttribute('sdks', []);
|
||||
|
||||
if (!in_array($sdk, $sdks)) {
|
||||
|
|
@ -314,7 +325,7 @@ App::init()
|
|||
|
||||
// Update project last activity
|
||||
if (!$project->isEmpty() && $project->getId() !== 'console') {
|
||||
$accessedAt = $project->getAttribute('accessedAt', '');
|
||||
$accessedAt = $project->getAttribute('accessedAt', 0);
|
||||
if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) {
|
||||
$project->setAttribute('accessedAt', DateTime::now());
|
||||
Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project));
|
||||
|
|
@ -323,7 +334,7 @@ App::init()
|
|||
|
||||
// Update user last activity
|
||||
if (!empty($user->getId())) {
|
||||
$accessedAt = $user->getAttribute('accessedAt', '');
|
||||
$accessedAt = $user->getAttribute('accessedAt', 0);
|
||||
if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_USER_ACCESS)) > $accessedAt) {
|
||||
$user->setAttribute('accessedAt', DateTime::now());
|
||||
|
||||
|
|
@ -404,10 +415,12 @@ App::init()
|
|||
->inject('queueForStatsUsage')
|
||||
->inject('dbForProject')
|
||||
->inject('timelimit')
|
||||
->inject('resourceToken')
|
||||
->inject('mode')
|
||||
->inject('apiKey')
|
||||
->inject('plan')
|
||||
->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Database $dbForProject, callable $timelimit, string $mode, ?Key $apiKey, array $plan) use ($usageDatabaseListener, $eventDatabaseListener) {
|
||||
->inject('devKey')
|
||||
->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey) use ($usageDatabaseListener, $eventDatabaseListener) {
|
||||
|
||||
$route = $utopia->getRoute();
|
||||
|
||||
|
|
@ -474,6 +487,7 @@ App::init()
|
|||
$enabled // Abuse is enabled
|
||||
&& !$isAppUser // User is not API key
|
||||
&& !$isPrivilegedUser // User is not an admin
|
||||
&& $devKey->isEmpty() // request doesn't not contain development key
|
||||
&& $abuse->check() // Route is rate-limited
|
||||
) {
|
||||
throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED);
|
||||
|
|
@ -560,6 +574,10 @@ App::init()
|
|||
$bucketId = $parts[1] ?? null;
|
||||
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
$isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getInternalId();
|
||||
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
|
||||
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
|
||||
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAppUser && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
|
@ -567,20 +585,23 @@ App::init()
|
|||
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
|
||||
$validator = new Authorization(Database::PERMISSION_READ);
|
||||
$valid = $validator->isValid($bucket->getRead());
|
||||
|
||||
if (!$fileSecurity && !$valid) {
|
||||
if (!$fileSecurity && !$valid && !$isToken) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$parts = explode('/', $cacheLog->getAttribute('resource'));
|
||||
$fileId = $parts[1] ?? null;
|
||||
|
||||
if ($fileSecurity && !$valid) {
|
||||
if ($fileSecurity && !$valid && !$isToken) {
|
||||
$file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId);
|
||||
} else {
|
||||
$file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId));
|
||||
}
|
||||
|
||||
if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getInternalId()) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
if ($file->isEmpty()) {
|
||||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
|
@ -806,7 +827,7 @@ App::shutdown()
|
|||
$key = $request->cacheIdentifier();
|
||||
$signature = md5($data['payload']);
|
||||
$cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key));
|
||||
$accessedAt = $cacheLog->getAttribute('accessedAt', '');
|
||||
$accessedAt = $cacheLog->getAttribute('accessedAt', 0);
|
||||
$now = DateTime::now();
|
||||
if ($cacheLog->isEmpty()) {
|
||||
Authorization::skip(fn () => $dbForProject->createDocument('cache', new Document([
|
||||
|
|
|
|||
57
app/http.php
57
app/http.php
|
|
@ -13,6 +13,7 @@ use Swoole\Table;
|
|||
use Utopia\App;
|
||||
use Utopia\Audit\Audit;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Compression\Compression;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
|
|
@ -28,6 +29,8 @@ use Utopia\Pools\Group;
|
|||
use Utopia\Swoole\Files;
|
||||
use Utopia\System\System;
|
||||
|
||||
Files::load(__DIR__.'/../public');
|
||||
|
||||
const DOMAIN_SYNC_TIMER = 30; // 30 seconds
|
||||
|
||||
$domains = new Table(1_000_000); // 1 million rows
|
||||
|
|
@ -255,8 +258,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
|
|||
$audit->setup();
|
||||
}
|
||||
|
||||
if ($dbForPlatform->getDocument('buckets', 'default')->isEmpty() &&
|
||||
!$dbForPlatform->exists($dbForPlatform->getDatabase(), 'bucket_1')) {
|
||||
if ($dbForPlatform->getDocument('buckets', 'default')->isEmpty()) {
|
||||
Console::info(" └── Creating default bucket...");
|
||||
$dbForPlatform->createDocument('buckets', new Document([
|
||||
'$id' => ID::custom('default'),
|
||||
|
|
@ -308,6 +310,54 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
|
|||
|
||||
$dbForPlatform->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes);
|
||||
}
|
||||
|
||||
if (Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) {
|
||||
Console::info(" └── Creating screenshots bucket...");
|
||||
Authorization::skip(fn () => $dbForPlatform->createDocument('buckets', new Document([
|
||||
'$id' => ID::custom('screenshots'),
|
||||
'$collection' => ID::custom('buckets'),
|
||||
'name' => 'Screenshots',
|
||||
'maximumFileSize' => 20000000, // ~20MB
|
||||
'allowedFileExtensions' => [ 'png' ],
|
||||
'enabled' => true,
|
||||
'compression' => Compression::GZIP,
|
||||
'encryption' => false,
|
||||
'antivirus' => false,
|
||||
'fileSecurity' => true,
|
||||
'$permissions' => [],
|
||||
'search' => 'buckets Screenshots',
|
||||
])));
|
||||
|
||||
$bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots'));
|
||||
|
||||
Console::info(" └── Creating files collection for screenshots bucket...");
|
||||
$files = $collections['buckets']['files'] ?? [];
|
||||
if (empty($files)) {
|
||||
throw new Exception('Files collection is not configured.');
|
||||
}
|
||||
|
||||
$attributes = array_map(fn ($attr) => new Document([
|
||||
'$id' => ID::custom($attr['$id']),
|
||||
'type' => $attr['type'],
|
||||
'size' => $attr['size'],
|
||||
'required' => $attr['required'],
|
||||
'signed' => $attr['signed'],
|
||||
'array' => $attr['array'],
|
||||
'filters' => $attr['filters'],
|
||||
'default' => $attr['default'] ?? null,
|
||||
'format' => $attr['format'] ?? ''
|
||||
]), $files['attributes']);
|
||||
|
||||
$indexes = array_map(fn ($index) => new Document([
|
||||
'$id' => ID::custom($index['$id']),
|
||||
'type' => $index['type'],
|
||||
'attributes' => $index['attributes'],
|
||||
'lengths' => $index['lengths'],
|
||||
'orders' => $index['orders'],
|
||||
]), $files['indexes']);
|
||||
|
||||
Authorization::skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes));
|
||||
}
|
||||
});
|
||||
|
||||
$projectCollections = $collections['projects'];
|
||||
|
|
@ -520,7 +570,6 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) {
|
|||
if ($lastSyncUpdate != null) {
|
||||
$queries[] = Query::greaterThanEqual('$updatedAt', $lastSyncUpdate);
|
||||
}
|
||||
$queries[] = Query::equal('resourceType', ['function']);
|
||||
$results = [];
|
||||
try {
|
||||
$results = Authorization::skip(fn () => $dbForPlatform->find('rules', $queries));
|
||||
|
|
@ -531,7 +580,7 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) {
|
|||
$sum = count($results);
|
||||
foreach ($results as $document) {
|
||||
$domain = $document->getAttribute('domain');
|
||||
if (str_ends_with($domain, System::getEnv('_APP_DOMAIN_FUNCTIONS'))) {
|
||||
if (str_ends_with($domain, System::getEnv('_APP_DOMAIN_FUNCTIONS')) || str_ends_with($domain, System::getEnv('_APP_DOMAIN_SITES'))) {
|
||||
continue;
|
||||
}
|
||||
$domains->set(md5($domain), ['value' => 1]);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use Utopia\Config\Config;
|
||||
|
||||
Config::load('template-runtimes', __DIR__ . '/../config/template-runtimes.php');
|
||||
Config::load('events', __DIR__ . '/../config/events.php');
|
||||
Config::load('auth', __DIR__ . '/../config/auth.php');
|
||||
Config::load('apis', __DIR__ . '/../config/apis.php'); // List of APIs
|
||||
|
|
@ -10,6 +11,7 @@ Config::load('oAuthProviders', __DIR__ . '/../config/oAuthProviders.php');
|
|||
Config::load('platforms', __DIR__ . '/../config/platforms.php');
|
||||
Config::load('console', __DIR__ . '/../config/console.php');
|
||||
Config::load('collections', __DIR__ . '/../config/collections.php');
|
||||
Config::load('frameworks', __DIR__ . '/../config/frameworks.php');
|
||||
Config::load('runtimes', __DIR__ . '/../config/runtimes.php');
|
||||
Config::load('runtimes-v2', __DIR__ . '/../config/runtimes-v2.php');
|
||||
Config::load('usage', __DIR__ . '/../config/usage.php');
|
||||
|
|
@ -33,5 +35,6 @@ Config::load('storage-logos', __DIR__ . '/../config/storage/logos.php');
|
|||
Config::load('storage-mimes', __DIR__ . '/../config/storage/mimes.php');
|
||||
Config::load('storage-inputs', __DIR__ . '/../config/storage/inputs.php');
|
||||
Config::load('storage-outputs', __DIR__ . '/../config/storage/outputs.php');
|
||||
Config::load('runtime-specifications', __DIR__ . '/../config/runtimes/specifications.php');
|
||||
Config::load('function-templates', __DIR__ . '/../config/function-templates.php');
|
||||
Config::load('specifications', __DIR__ . '/../config/specifications.php');
|
||||
Config::load('templates-function', __DIR__ . '/../config/templates/function.php');
|
||||
Config::load('templates-site', __DIR__ . '/../config/templates/site.php');
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
<?php
|
||||
|
||||
use Appwrite\Functions\Specification;
|
||||
use Appwrite\Platform\Modules\Compute\Specification;
|
||||
|
||||
const APP_NAME = 'Appwrite';
|
||||
const APP_DOMAIN = 'appwrite.io';
|
||||
const APP_EMAIL_TEAM = 'team@localhost.test'; // Default email address
|
||||
const APP_EMAIL_SECURITY = ''; // Default security email address
|
||||
const APP_EMAIL_LOGO_URL = 'https://cloud.appwrite.io/images/mails/logo.png';
|
||||
const APP_EMAIL_ACCENT_COLOR = '#fd366e';
|
||||
const APP_EMAIL_TERMS_URL = 'https://appwrite.io/terms';
|
||||
const APP_EMAIL_PRIVACY_URL = 'https://appwrite.io/privacy';
|
||||
const APP_USERAGENT = APP_NAME . '-Server v%s. Please report abuse at %s';
|
||||
const APP_MODE_DEFAULT = 'default';
|
||||
const APP_MODE_ADMIN = 'admin';
|
||||
|
|
@ -30,10 +34,11 @@ const APP_LIMIT_DATABASE_BATCH = 100; // Default maximum batch size for database
|
|||
const APP_KEY_ACCESS = 24 * 60 * 60; // 24 hours
|
||||
const APP_USER_ACCESS = 24 * 60 * 60; // 24 hours
|
||||
const APP_PROJECT_ACCESS = 24 * 60 * 60; // 24 hours
|
||||
const APP_RESOURCE_TOKEN_ACCESS = 24 * 60 * 60; // 24 hours
|
||||
const APP_FILE_ACCESS = 24 * 60 * 60; // 24 hours
|
||||
const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours
|
||||
const APP_CACHE_BUSTER = 4318;
|
||||
const APP_VERSION_STABLE = '1.6.2';
|
||||
const APP_CACHE_BUSTER = 4319;
|
||||
const APP_VERSION_STABLE = '1.7.0';
|
||||
const APP_DATABASE_ATTRIBUTE_EMAIL = 'email';
|
||||
const APP_DATABASE_ATTRIBUTE_ENUM = 'enum';
|
||||
const APP_DATABASE_ATTRIBUTE_IP = 'ip';
|
||||
|
|
@ -47,9 +52,11 @@ const APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER = 300 * 1000; // 5 minutes
|
|||
const APP_DATABASE_TIMEOUT_MILLISECONDS_TASK = 300 * 1000; // 5 minutes
|
||||
const APP_DATABASE_QUERY_MAX_VALUES = 500;
|
||||
const APP_STORAGE_UPLOADS = '/storage/uploads';
|
||||
const APP_STORAGE_SITES = '/storage/sites';
|
||||
const APP_STORAGE_FUNCTIONS = '/storage/functions';
|
||||
const APP_STORAGE_BUILDS = '/storage/builds';
|
||||
const APP_STORAGE_CACHE = '/storage/cache';
|
||||
const APP_STORAGE_IMPORTS = '/storage/imports'; // Temporary storage for csv imports
|
||||
const APP_STORAGE_CERTIFICATES = '/storage/certificates';
|
||||
const APP_STORAGE_CONFIG = '/storage/config';
|
||||
const APP_STORAGE_READ_BUFFER = 20 * (1000 * 1000); //20MB other names `APP_STORAGE_MEMORY_LIMIT`, `APP_STORAGE_MEMORY_BUFFER`, `APP_STORAGE_READ_LIMIT`, `APP_STORAGE_BUFFER_LIMIT`
|
||||
|
|
@ -59,15 +66,16 @@ const APP_SOCIAL_FACEBOOK = 'https://www.facebook.com/appwrite.io';
|
|||
const APP_SOCIAL_LINKEDIN = 'https://www.linkedin.com/company/appwrite';
|
||||
const APP_SOCIAL_INSTAGRAM = 'https://www.instagram.com/appwrite.io';
|
||||
const APP_SOCIAL_GITHUB = 'https://github.com/appwrite';
|
||||
const APP_SOCIAL_GITHUB_APPWRITE = 'https://github.com/appwrite/appwrite';
|
||||
const APP_SOCIAL_DISCORD = 'https://appwrite.io/discord';
|
||||
const APP_SOCIAL_DISCORD_CHANNEL = '564160730845151244';
|
||||
const APP_SOCIAL_DEV = 'https://dev.to/appwrite';
|
||||
const APP_SOCIAL_STACKSHARE = 'https://stackshare.io/appwrite';
|
||||
const APP_SOCIAL_YOUTUBE = 'https://www.youtube.com/c/appwrite?sub_confirmation=1';
|
||||
const APP_HOSTNAME_INTERNAL = 'appwrite';
|
||||
const APP_FUNCTION_SPECIFICATION_DEFAULT = Specification::S_1VCPU_512MB;
|
||||
const APP_FUNCTION_CPUS_DEFAULT = 0.5;
|
||||
const APP_FUNCTION_MEMORY_DEFAULT = 512;
|
||||
const APP_COMPUTE_CPUS_DEFAULT = 0.5;
|
||||
const APP_COMPUTE_MEMORY_DEFAULT = 512;
|
||||
const APP_COMPUTE_SPECIFICATION_DEFAULT = Specification::S_1VCPU_512MB;
|
||||
const APP_PLATFORM_SERVER = 'server';
|
||||
const APP_PLATFORM_CLIENT = 'client';
|
||||
const APP_PLATFORM_CONSOLE = 'console';
|
||||
|
|
@ -93,6 +101,7 @@ const DELETE_TYPE_DATABASES = 'databases';
|
|||
const DELETE_TYPE_DOCUMENT = 'document';
|
||||
const DELETE_TYPE_COLLECTIONS = 'collections';
|
||||
const DELETE_TYPE_PROJECTS = 'projects';
|
||||
const DELETE_TYPE_SITES = 'sites';
|
||||
const DELETE_TYPE_FUNCTIONS = 'functions';
|
||||
const DELETE_TYPE_DEPLOYMENTS = 'deployments';
|
||||
const DELETE_TYPE_USERS = 'users';
|
||||
|
|
@ -182,6 +191,7 @@ const METRIC_FILES_IMAGES_TRANSFORMED = 'files.imagesTransformed';
|
|||
const METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED = '{bucketInternalId}.files.imagesTransformed';
|
||||
const METRIC_BUCKET_ID_FILES = '{bucketInternalId}.files';
|
||||
const METRIC_BUCKET_ID_FILES_STORAGE = '{bucketInternalId}.files.storage';
|
||||
const METRIC_SITES = 'sites';
|
||||
const METRIC_FUNCTIONS = 'functions';
|
||||
const METRIC_DEPLOYMENTS = 'deployments';
|
||||
const METRIC_DEPLOYMENTS_STORAGE = 'deployments.storage';
|
||||
|
|
@ -193,22 +203,35 @@ const METRIC_BUILDS_COMPUTE = 'builds.compute';
|
|||
const METRIC_BUILDS_COMPUTE_SUCCESS = 'builds.compute.success';
|
||||
const METRIC_BUILDS_COMPUTE_FAILED = 'builds.compute.failed';
|
||||
const METRIC_BUILDS_MB_SECONDS = 'builds.mbSeconds';
|
||||
const METRIC_FUNCTION_ID_BUILDS = '{functionInternalId}.builds';
|
||||
const METRIC_FUNCTION_ID_BUILDS_SUCCESS = '{functionInternalId}.builds.success';
|
||||
const METRIC_FUNCTION_ID_BUILDS_FAILED = '{functionInternalId}.builds.failed';
|
||||
const METRIC_FUNCTION_ID_BUILDS_STORAGE = '{functionInternalId}.builds.storage';
|
||||
const METRIC_FUNCTION_ID_BUILDS_COMPUTE = '{functionInternalId}.builds.compute';
|
||||
const METRIC_FUNCTION_ID_BUILDS_COMPUTE_SUCCESS = '{functionInternalId}.builds.compute.success';
|
||||
const METRIC_FUNCTION_ID_BUILDS_COMPUTE_FAILED = '{functionInternalId}.builds.compute.failed';
|
||||
const METRIC_FUNCTION_ID_DEPLOYMENTS = '{resourceType}.{resourceInternalId}.deployments';
|
||||
const METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE = '{resourceType}.{resourceInternalId}.deployments.storage';
|
||||
const METRIC_FUNCTION_ID_BUILDS_MB_SECONDS = '{functionInternalId}.builds.mbSeconds';
|
||||
const METRIC_EXECUTIONS = 'executions';
|
||||
const METRIC_EXECUTIONS_COMPUTE = 'executions.compute';
|
||||
const METRIC_EXECUTIONS_MB_SECONDS = 'executions.mbSeconds';
|
||||
const METRIC_FUNCTION_ID_EXECUTIONS = '{functionInternalId}.executions';
|
||||
const METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE = '{functionInternalId}.executions.compute';
|
||||
const METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS = '{functionInternalId}.executions.mbSeconds';
|
||||
const METRIC_RESOURCE_TYPE_ID_EXECUTIONS = '{resourceType}.{resourceInternalId}.executions';
|
||||
const METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE = '{resourceType}.{resourceInternalId}.executions.compute';
|
||||
const METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS = '{resourceType}.{resourceInternalId}.executions.mbSeconds';
|
||||
const METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS = '{resourceType}.{resourceInternalId}.builds.success';
|
||||
const METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED = '{resourceType}.{resourceInternalId}.builds.failed';
|
||||
const METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE = '{resourceType}.{resourceInternalId}.builds.compute';
|
||||
const METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_SUCCESS = '{resourceType}.{resourceInternalId}.builds.compute.success';
|
||||
const METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_FAILED = '{resourceType}.{resourceInternalId}.builds.compute.failed';
|
||||
const METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS = '{resourceType}.{resourceInternalId}.builds.mbSeconds';
|
||||
const METRIC_RESOURCE_TYPE_ID_BUILDS = '{resourceType}.{resourceInternalId}.builds';
|
||||
const METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE = '{resourceType}.{resourceInternalId}.builds.storage';
|
||||
const METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS = '{resourceType}.{resourceInternalId}.deployments';
|
||||
const METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE = '{resourceType}.{resourceInternalId}.deployments.storage';
|
||||
const METRIC_RESOURCE_TYPE_EXECUTIONS = '{resourceType}.executions';
|
||||
const METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE = '{resourceType}.executions.compute';
|
||||
const METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS = '{resourceType}.executions.mbSeconds';
|
||||
const METRIC_RESOURCE_TYPE_BUILDS_SUCCESS = '{resourceType}.builds.success';
|
||||
const METRIC_RESOURCE_TYPE_BUILDS_FAILED = '{resourceType}.builds.failed';
|
||||
const METRIC_RESOURCE_TYPE_BUILDS_COMPUTE = '{resourceType}.builds.compute';
|
||||
const METRIC_RESOURCE_TYPE_BUILDS_COMPUTE_SUCCESS = '{resourceType}.builds.compute.success';
|
||||
const METRIC_RESOURCE_TYPE_BUILDS_COMPUTE_FAILED = '{resourceType}.builds.compute.failed';
|
||||
const METRIC_RESOURCE_TYPE_BUILDS_MB_SECONDS = '{resourceType}.builds.mbSeconds';
|
||||
const METRIC_RESOURCE_TYPE_BUILDS = '{resourceType}.builds';
|
||||
const METRIC_RESOURCE_TYPE_BUILDS_STORAGE = '{resourceType}.builds.storage';
|
||||
const METRIC_RESOURCE_TYPE_DEPLOYMENTS = '{resourceType}.deployments';
|
||||
const METRIC_RESOURCE_TYPE_DEPLOYMENTS_STORAGE = '{resourceType}.deployments.storage';
|
||||
const METRIC_NETWORK_REQUESTS = 'network.requests';
|
||||
const METRIC_NETWORK_INBOUND = 'network.inbound';
|
||||
const METRIC_NETWORK_OUTBOUND = 'network.outbound';
|
||||
|
|
@ -223,18 +246,28 @@ const METRIC_TARGETS = 'targets';
|
|||
const METRIC_PROVIDER_TYPE_TARGETS = '{providerType}.targets';
|
||||
const METRIC_KEYS = 'keys';
|
||||
const METRIC_DOMAINS = 'domains';
|
||||
const METRIC_RESOURCE_TYPE_ID_BUILDS = '{resourceType}.{resourceInternalId}.builds';
|
||||
const METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE = '{resourceType}.{resourceInternalId}.builds.storage';
|
||||
const METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS = '{resourceType}.{resourceInternalId}.deployments';
|
||||
const METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE = '{resourceType}.{resourceInternalId}.deployments.storage';
|
||||
const METRIC_SITES_REQUESTS = 'sites.requests';
|
||||
const METRIC_SITES_INBOUND = 'sites.inbound';
|
||||
const METRIC_SITES_OUTBOUND = 'sites.outbound';
|
||||
const METRIC_SITES_ID_REQUESTS = 'sites.{siteInternalId}.requests';
|
||||
const METRIC_SITES_ID_INBOUND = 'sites.{siteInternalId}.inbound';
|
||||
const METRIC_SITES_ID_OUTBOUND = 'sites.{siteInternalId}.outbound';
|
||||
|
||||
// Resource types
|
||||
|
||||
const RESOURCE_TYPE_PROJECTS = 'projects';
|
||||
const RESOURCE_TYPE_FUNCTIONS = 'functions';
|
||||
const RESOURCE_TYPE_SITES = 'sites';
|
||||
const RESOURCE_TYPE_DATABASES = 'databases';
|
||||
const RESOURCE_TYPE_BUCKETS = 'buckets';
|
||||
const RESOURCE_TYPE_PROVIDERS = 'providers';
|
||||
const RESOURCE_TYPE_TOPICS = 'topics';
|
||||
const RESOURCE_TYPE_SUBSCRIBERS = 'subscribers';
|
||||
const RESOURCE_TYPE_MESSAGES = 'messages';
|
||||
|
||||
// Resource types for Tokens
|
||||
|
||||
const TOKENS_RESOURCE_TYPE_FILES = 'files';
|
||||
const TOKENS_RESOURCE_TYPE_SITES = 'sites';
|
||||
const TOKENS_RESOURCE_TYPE_FUNCTIONS = 'functions';
|
||||
const TOKENS_RESOURCE_TYPE_DATABASES = 'databases';
|
||||
|
|
|
|||
|
|
@ -133,6 +133,20 @@ Database::addFilter(
|
|||
}
|
||||
);
|
||||
|
||||
Database::addFilter(
|
||||
'subQueryDevKeys',
|
||||
function (mixed $value) {
|
||||
return;
|
||||
},
|
||||
function (mixed $value, Document $document, Database $database) {
|
||||
return $database
|
||||
->find('devKeys', [
|
||||
Query::equal('projectInternalId', [$document->getInternalId()]),
|
||||
Query::limit(APP_LIMIT_SUBQUERY),
|
||||
]);
|
||||
}
|
||||
);
|
||||
|
||||
Database::addFilter(
|
||||
'subQueryWebhooks',
|
||||
function (mixed $value) {
|
||||
|
|
@ -225,7 +239,7 @@ Database::addFilter(
|
|||
return $database
|
||||
->find('variables', [
|
||||
Query::equal('resourceInternalId', [$document->getInternalId()]),
|
||||
Query::equal('resourceType', ['function']),
|
||||
Query::equal('resourceType', ['function', 'site']),
|
||||
Query::limit(APP_LIMIT_SUBQUERY),
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ use Utopia\Cache\Cache;
|
|||
use Utopia\CLI\Console;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime as DatabaseDateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
|
|
@ -51,6 +52,7 @@ use Utopia\System\System;
|
|||
use Utopia\Telemetry\Adapter as Telemetry;
|
||||
use Utopia\Telemetry\Adapter\None as NoTelemetry;
|
||||
use Utopia\Validator\Hostname;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\VCS\Adapter\Git\GitHub as VcsGitHub;
|
||||
|
||||
// Runtime Execution
|
||||
|
|
@ -468,7 +470,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) {
|
|||
|
||||
App::setResource('telemetry', fn () => new NoTelemetry());
|
||||
|
||||
App::setResource('cache', function (Group $pools, Telemetry $telemetry) {
|
||||
App::setResource('cache', function (Group $pools) {
|
||||
$list = Config::getParam('pools-cache', []);
|
||||
$adapters = [];
|
||||
|
||||
|
|
@ -479,12 +481,8 @@ App::setResource('cache', function (Group $pools, Telemetry $telemetry) {
|
|||
->getResource();
|
||||
}
|
||||
|
||||
$cache = new Cache(new Sharding($adapters));
|
||||
|
||||
$cache->setTelemetry($telemetry);
|
||||
|
||||
return $cache;
|
||||
}, ['pools', 'telemetry']);
|
||||
return new Cache(new Sharding($adapters));
|
||||
}, ['pools']);
|
||||
|
||||
App::setResource('redis', function () {
|
||||
$host = System::getEnv('_APP_REDIS_HOST', 'localhost');
|
||||
|
|
@ -507,18 +505,22 @@ App::setResource('timelimit', function (\Redis $redis) {
|
|||
};
|
||||
}, ['redis']);
|
||||
|
||||
App::setResource('deviceForLocal', function () {
|
||||
App::setResource('deviceForLocal', function (Telemetry $telemetry) {
|
||||
return new Local();
|
||||
});
|
||||
}, ['telemetry']);
|
||||
|
||||
App::setResource('deviceForFiles', function ($project) {
|
||||
return getDevice(APP_STORAGE_UPLOADS . '/app-' . $project->getId());
|
||||
}, ['project']);
|
||||
|
||||
App::setResource('deviceForSites', function ($project) {
|
||||
return getDevice(APP_STORAGE_SITES . '/app-' . $project->getId());
|
||||
}, ['project']);
|
||||
App::setResource('deviceForImports', function ($project) {
|
||||
return getDevice(APP_STORAGE_IMPORTS . '/app-' . $project->getId());
|
||||
}, ['project']);
|
||||
App::setResource('deviceForFunctions', function ($project) {
|
||||
return getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId());
|
||||
}, ['project']);
|
||||
|
||||
App::setResource('deviceForBuilds', function ($project) {
|
||||
return getDevice(APP_STORAGE_BUILDS . '/app-' . $project->getId());
|
||||
}, ['project']);
|
||||
|
|
@ -788,6 +790,49 @@ App::setResource('smsRates', function () {
|
|||
return [];
|
||||
});
|
||||
|
||||
App::setResource('devKey', function (Request $request, Document $project, array $servers, Database $dbForPlatform) {
|
||||
$devKey = $request->getHeader('x-appwrite-dev-key', $request->getParam('devKey', ''));
|
||||
|
||||
// Check if given key match project's development keys
|
||||
$key = $project->find('secret', $devKey, 'devKeys');
|
||||
if (!$key) {
|
||||
return new Document([]);
|
||||
}
|
||||
|
||||
// check expiration
|
||||
$expire = $key->getAttribute('expire');
|
||||
if (!empty($expire) && $expire < DatabaseDateTime::formatTz(DatabaseDateTime::now())) {
|
||||
return new Document([]);
|
||||
}
|
||||
|
||||
// update access time
|
||||
$accessedAt = $key->getAttribute('accessedAt', 0);
|
||||
if (empty($accessedAt) || DatabaseDateTime::formatTz(DatabaseDateTime::addSeconds(new \DateTime(), -APP_KEY_ACCESS)) > $accessedAt) {
|
||||
$key->setAttribute('accessedAt', DatabaseDateTime::now());
|
||||
Authorization::skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key));
|
||||
$dbForPlatform->purgeCachedDocument('projects', $project->getId());
|
||||
}
|
||||
|
||||
// add sdk to key
|
||||
$sdkValidator = new WhiteList($servers, true);
|
||||
$sdk = \strtolower($request->getHeader('x-sdk-name', 'UNKNOWN'));
|
||||
|
||||
if ($sdk !== 'UNKNOWN' && $sdkValidator->isValid($sdk)) {
|
||||
$sdks = $key->getAttribute('sdks', []);
|
||||
|
||||
if (!in_array($sdk, $sdks)) {
|
||||
$sdks[] = $sdk;
|
||||
$key->setAttribute('sdks', $sdks);
|
||||
|
||||
/** Update access time as well */
|
||||
$key->setAttribute('accessedAt', DatabaseDateTime::now());
|
||||
$key = Authorization::skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key));
|
||||
$dbForPlatform->purgeCachedDocument('projects', $project->getId());
|
||||
}
|
||||
}
|
||||
return $key;
|
||||
}, ['request', 'project', 'servers', 'dbForPlatform']);
|
||||
|
||||
App::setResource('team', function (Document $project, Database $dbForPlatform, App $utopia, Request $request) {
|
||||
$teamInternalId = '';
|
||||
if ($project->getId() !== 'console') {
|
||||
|
|
@ -821,16 +866,24 @@ App::setResource(
|
|||
fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false
|
||||
);
|
||||
|
||||
App::setResource('previewHostname', function (Request $request) {
|
||||
App::setResource('previewHostname', function (Request $request, ?Key $apiKey) {
|
||||
$allowed = false;
|
||||
|
||||
if (App::isDevelopment()) {
|
||||
$host = $request->getQuery('appwrite-hostname') ?? '';
|
||||
$allowed = true;
|
||||
} elseif (!\is_null($apiKey) && $apiKey->getHostnameOverride() === true) {
|
||||
$allowed = true;
|
||||
}
|
||||
|
||||
if ($allowed) {
|
||||
$host = $request->getQuery('appwrite-hostname', $request->getHeader('x-appwrite-hostname', '')) ?? '';
|
||||
if (!empty($host)) {
|
||||
return $host;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}, ['request']);
|
||||
}, ['request', 'apiKey']);
|
||||
|
||||
App::setResource('apiKey', function (Request $request, Document $project): ?Key {
|
||||
$key = $request->getHeader('x-appwrite-key');
|
||||
|
|
@ -843,3 +896,66 @@ App::setResource('apiKey', function (Request $request, Document $project): ?Key
|
|||
}, ['request', 'project']);
|
||||
|
||||
App::setResource('executor', fn () => new Executor(fn (string $projectId, string $deploymentId) => System::getEnv('_APP_EXECUTOR_HOST')));
|
||||
|
||||
App::setResource('resourceToken', function ($project, $dbForProject, $request) {
|
||||
$tokenJWT = $request->getParam('token');
|
||||
|
||||
if (!empty($tokenJWT) && !$project->isEmpty()) { // JWT authentication
|
||||
$jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 900, 10); // Instantiate with key, algo, maxAge and leeway.
|
||||
|
||||
try {
|
||||
$payload = $jwt->decode($tokenJWT);
|
||||
} catch (JWTException $error) {
|
||||
return new Document([]);
|
||||
}
|
||||
|
||||
$tokenId = $payload['tokenId'] ?? '';
|
||||
if (empty($tokenId)) {
|
||||
return new Document([]);
|
||||
}
|
||||
|
||||
$token = Authorization::skip(fn () => $dbForProject->getDocument('resourceTokens', $tokenId));
|
||||
|
||||
if ($token->isEmpty()) {
|
||||
return new Document([]);
|
||||
}
|
||||
|
||||
$expiry = $token->getAttribute('expire');
|
||||
|
||||
if ($expiry !== null) {
|
||||
$now = new \DateTime();
|
||||
$expiryDate = new \DateTime($expiry);
|
||||
|
||||
if ($expiryDate < $now) {
|
||||
return new Document([]);
|
||||
}
|
||||
}
|
||||
|
||||
return match ($token->getAttribute('resourceType')) {
|
||||
TOKENS_RESOURCE_TYPE_FILES => (function () use ($token, $dbForProject) {
|
||||
$internalIds = explode(':', $token->getAttribute('resourceInternalId'));
|
||||
$ids = explode(':', $token->getAttribute('resourceId'));
|
||||
|
||||
if (count($internalIds) !== 2 || count($ids) !== 2) {
|
||||
return new Document([]);
|
||||
}
|
||||
|
||||
$accessedAt = $token->getAttribute('accessedAt', 0);
|
||||
if (empty($accessedAt) || DatabaseDateTime::formatTz(DatabaseDateTime::addSeconds(new \DateTime(), - APP_RESOURCE_TOKEN_ACCESS)) > $accessedAt) {
|
||||
$token->setAttribute('accessedAt', DatabaseDateTime::now());
|
||||
Authorization::skip(fn () => $dbForProject->updateDocument('resourceTokens', $token->getId(), $token));
|
||||
}
|
||||
|
||||
return new Document([
|
||||
'bucketId' => $ids[0],
|
||||
'fileId' => $ids[1],
|
||||
'bucketInternalId' => $internalIds[0],
|
||||
'fileInternalId' => $internalIds[1],
|
||||
]);
|
||||
})(),
|
||||
|
||||
default => throw new Exception(Exception::TOKEN_RESOURCE_TYPE_INVALID),
|
||||
};
|
||||
}
|
||||
return new Document([]);
|
||||
}, ['project', 'dbForProject', 'request']);
|
||||
|
|
|
|||
187
app/views/general/404.phtml
Normal file
187
app/views/general/404.phtml
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>404 Not Found</title>
|
||||
|
||||
<style>
|
||||
@import url(https://fonts.bunny.net/css?family=fira-code:400|inter:400);
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.main {
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
width: 100vw;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
span {
|
||||
padding: var(--space-1, 2px) var(--space-3, 6px);
|
||||
border-radius: var(--border-radius-XS, 6px);
|
||||
background: var(--color-overlay-on-neutral, rgba(0, 0, 0, 0.06));
|
||||
color: var(--color-fgColor-neutral-secondary, #56565C);
|
||||
text-align: center;
|
||||
font-family: var(--font-family-sansSerif, Inter), sans-serif;
|
||||
font-size: var(--font-size-S, 14px);
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 140%;
|
||||
letter-spacing: -0.063px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: var(--color-fgColor-neutral-primary, #2D2D31);
|
||||
text-align: center;
|
||||
font-family: var(--font-family-sansSerif, Inter), sans-serif;
|
||||
font-size: var(--font-size-XXXL, 32px);
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 140%;
|
||||
letter-spacing: -0.144px;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: var(--border-radius-S, 8px);
|
||||
font-family: var(--font-family-sansSerif, Inter), sans-serif;
|
||||
font-size: var(--font-size-S, 14px);
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 140%;
|
||||
letter-spacing: -0.063px;
|
||||
padding: var(--space-3, 6px) var(--space-5, 10px);
|
||||
cursor: pointer;
|
||||
border: var(--border-width-S, 1px) solid var(--color-border-neutral-strong, #D8D8DB);
|
||||
background: var(--color-bgColor-neutral-primary, #FFF);
|
||||
color: var(--color-fgColor-neutral-secondary, #56565C);
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.brand {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
bottom: 32px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.brand p {
|
||||
font-family: var(--font-family-monospace, "Fira Code"), monospace;
|
||||
font-size: var(--font-size-XS, 12px);
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 130%;
|
||||
letter-spacing: 0.96px;
|
||||
text-transform: uppercase;
|
||||
color: var(--color-fgColor-neutral-secondary, #56565C);
|
||||
}
|
||||
|
||||
.brand svg {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.logo-dark {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #1D1D21;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: var(--color-fgColor-neutral-primary, #EDEDF0);
|
||||
}
|
||||
|
||||
button {
|
||||
border: var(--border-width-S, 1px) solid var(--color-border-neutral-strong, #414146);
|
||||
background: var(--color-bgColor-neutral-primary, #1D1D21);
|
||||
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
|
||||
}
|
||||
|
||||
.brand p {
|
||||
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
|
||||
}
|
||||
|
||||
span {
|
||||
background: var(--color-overlay-on-neutral, rgba(255, 255, 255, 0.20));
|
||||
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
|
||||
}
|
||||
|
||||
.logo-light {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.logo-dark {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="main">
|
||||
<div class="content">
|
||||
<div class="center"><span>Page not found</span></div>
|
||||
<h1>The page you’re looking for doesn’t exist.</h1>
|
||||
<div class="center"><a href="/"><button>Go to homepage</button></a></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="brand">
|
||||
<p>Powered by</p>
|
||||
<svg class="logo-dark" width="110" height="20" viewBox="0 0 110 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M31.8649 16.2461C33.6492 16.2461 34.5511 15.3184 34.9433 14.6867H35.1197C35.1981 15.3578 35.6687 15.9895 36.5903 15.9895H38.3353V14.0156H37.8843C37.5706 14.0156 37.4138 13.838 37.4138 13.5617V5.64661H35.1001V6.90986H34.9236C34.4727 6.27823 33.5315 5.39001 31.8061 5.39001C29.0611 5.39001 27.022 7.67965 27.022 10.818C27.022 13.9564 29.1003 16.2461 31.8649 16.2461ZM32.2767 13.9959C30.6493 13.9959 29.3748 12.7919 29.3748 10.8378C29.3748 8.92316 30.6101 7.62044 32.2571 7.62044C33.8256 7.62044 35.1393 8.78499 35.1393 10.8378C35.1393 12.5945 34.0217 13.9959 32.2767 13.9959Z" fill="#EDEDF0" />
|
||||
<path d="M39.7013 20H42.0149V14.6867H42.1914C42.6227 15.3184 43.5443 16.2461 45.3677 16.2461C48.1127 16.2461 50.1127 13.9169 50.1127 10.818C50.1127 7.69939 47.9755 5.39001 45.2109 5.39001C43.4462 5.39001 42.5835 6.35719 42.1718 6.89012H41.9953V5.64661H39.7013V20ZM44.8776 14.0551C43.2894 14.0551 41.9757 12.8708 41.9757 10.818C41.9757 9.06133 43.0933 7.58096 44.8383 7.58096C46.4657 7.58096 47.7402 8.86395 47.7402 10.818C47.7402 12.7326 46.5049 14.0551 44.8776 14.0551Z" fill="#EDEDF0" />
|
||||
<path d="M51.3065 20H53.6202V14.6867H53.7966C54.228 15.3184 55.1495 16.2461 56.973 16.2461C59.718 16.2461 61.5273 13.9169 61.5273 10.818C61.5273 7.69939 59.5807 5.39001 56.8161 5.39001C55.0515 5.39001 54.1888 6.35719 53.777 6.89012H53.6005V5.64661H51.3065V20ZM56.4828 14.0551C54.8946 14.0551 53.5809 12.8708 53.5809 10.818C53.5809 9.06133 54.6985 7.58096 56.4436 7.58096C58.071 7.58096 59.3454 8.86395 59.3454 10.818C59.3454 12.7326 58.1102 14.0551 56.4828 14.0551Z" fill="#EDEDF0" />
|
||||
<path d="M64.5857 16.2296H67.8601L69.7227 8.11721H69.8404L71.7031 16.2296H74.9579L77.5642 5.88678H75.2323L73.3697 14.0189H73.1932L71.3305 5.88678H68.2522L66.3699 14.0189H66.1935L64.3504 5.88678H61.8799L64.5857 16.2296Z" fill="#EDEDF0" />
|
||||
<path d="M78.7363 16.2296H81.0499V11.1174C81.0499 9.16334 81.9519 7.9593 83.6381 7.9593H84.6576V5.63019H83.893C82.5793 5.63019 81.5793 6.53815 81.1872 7.40663H81.0303V5.88678H78.7363V16.2296Z" fill="#EDEDF0" />
|
||||
<path d="M96.1391 16.2296H97.943V14.1571H96.1587C95.4529 14.1571 95.1588 13.8413 95.1588 13.111V7.93956H98.0606V5.88678H95.1588V2.98526H92.9628V5.88678H91.0413V7.93956H92.8255V13.1307C92.8255 15.3217 94.1392 16.2296 96.1391 16.2296Z" fill="#EDEDF0" />
|
||||
<path d="M104.15 16.2461C106.287 16.2461 108.17 15.1802 108.836 13.0287L106.719 12.5155C106.346 13.6603 105.268 14.2525 104.13 14.2525C102.444 14.2525 101.327 13.1472 101.307 11.4102H109.091V10.7588C109.091 7.67965 107.189 5.39001 104.052 5.39001C101.287 5.39001 98.915 7.58096 98.915 10.8378C98.915 13.9959 101.013 16.2461 104.15 16.2461ZM101.327 9.71269C101.464 8.46918 102.581 7.42305 104.052 7.42305C105.464 7.42305 106.621 8.31128 106.738 9.71269H101.327Z" fill="#EDEDF0" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M90.0125 16.2296H87.6989V7.93956H85.895V5.88678H90.0125V16.2296Z" fill="#EDEDF0" />
|
||||
<path d="M88.6834 4.45145C89.5265 4.45145 90.154 3.81983 90.154 2.99082C90.154 2.18155 89.5265 1.54993 88.6834 1.54993C87.8403 1.54993 87.2129 2.18155 87.2129 2.99082C87.2129 3.81983 87.8403 4.45145 88.6834 4.45145Z" fill="#EDEDF0" />
|
||||
<path d="M20.2007 13.6935V18.258H8.88588C5.5894 18.258 2.71111 16.4222 1.17116 13.6935C0.947288 13.2968 0.751353 12.8806 0.586995 12.4486C0.26435 11.6021 0.0615332 10.6938 0 9.74603V8.51195C0.0133592 8.30074 0.03441 8.09119 0.0619381 7.88413C0.118209 7.45921 0.203222 7.04343 0.314953 6.63926C1.37195 2.80758 4.8089 0 8.88588 0C12.9629 0 16.3994 2.80758 17.4564 6.63926H12.6184C11.8241 5.39025 10.4493 4.5645 8.88588 4.5645C7.32245 4.5645 5.94767 5.39025 5.15341 6.63926C4.91132 7.01895 4.72349 7.43764 4.60042 7.88413C4.49112 8.27999 4.43282 8.69744 4.43282 9.12899C4.43282 10.4373 4.96962 11.6166 5.83027 12.4486C6.62778 13.2209 7.70299 13.6935 8.88588 13.6935H20.2007Z" fill="#FD366E" />
|
||||
<path d="M20.2006 7.88412V12.4486H11.9414C12.8021 11.6166 13.3389 10.4373 13.3389 9.12899C13.3389 8.69744 13.2806 8.27999 13.1713 7.88412H20.2006Z" fill="#FD366E" />
|
||||
</svg>
|
||||
<svg class="logo-light" width="110" height="20" viewBox="0 0 110 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M31.8648 16.2461C33.649 16.2461 34.5509 15.3184 34.9431 14.6867H35.1195C35.198 15.3578 35.6685 15.9895 36.5901 15.9895H38.3351V14.0156H37.8841C37.5704 14.0156 37.4136 13.838 37.4136 13.5617V5.64661H35.0999V6.90986H34.9235C34.4725 6.27823 33.5314 5.39001 31.8059 5.39001C29.0609 5.39001 27.0218 7.67965 27.0218 10.818C27.0218 13.9564 29.1001 16.2461 31.8648 16.2461ZM32.2765 13.9959C30.6491 13.9959 29.3746 12.7919 29.3746 10.8378C29.3746 8.92316 30.6099 7.62044 32.2569 7.62044C33.8255 7.62044 35.1391 8.78499 35.1391 10.8378C35.1391 12.5945 34.0215 13.9959 32.2765 13.9959Z" fill="#2D2D31" />
|
||||
<path d="M39.7011 20H42.0147V14.6867H42.1912C42.6226 15.3184 43.5441 16.2461 45.3676 16.2461C48.1126 16.2461 50.1125 13.9169 50.1125 10.818C50.1125 7.69939 47.9753 5.39001 45.2107 5.39001C43.4461 5.39001 42.5833 6.35719 42.1716 6.89012H41.9951V5.64661H39.7011V20ZM44.8774 14.0551C43.2892 14.0551 41.9755 12.8708 41.9755 10.818C41.9755 9.06133 43.0931 7.58096 44.8382 7.58096C46.4656 7.58096 47.74 8.86395 47.74 10.818C47.74 12.7326 46.5048 14.0551 44.8774 14.0551Z" fill="#2D2D31" />
|
||||
<path d="M51.3063 20H53.62V14.6867H53.7964C54.2278 15.3184 55.1493 16.2461 56.9728 16.2461C59.7178 16.2461 61.5271 13.9169 61.5271 10.818C61.5271 7.69939 59.5805 5.39001 56.8159 5.39001C55.0513 5.39001 54.1886 6.35719 53.7768 6.89012H53.6004V5.64661H51.3063V20ZM56.4826 14.0551C54.8944 14.0551 53.5808 12.8708 53.5808 10.818C53.5808 9.06133 54.6984 7.58096 56.4434 7.58096C58.0708 7.58096 59.3453 8.86395 59.3453 10.818C59.3453 12.7326 58.11 14.0551 56.4826 14.0551Z" fill="#2D2D31" />
|
||||
<path d="M64.5855 16.2296H67.8599L69.7226 8.11721H69.8402L71.7029 16.2296H74.9577L77.564 5.88678H75.2322L73.3695 14.0189H73.193L71.3303 5.88678H68.252L66.3697 14.0189H66.1933L64.3502 5.88678H61.8797L64.5855 16.2296Z" fill="#2D2D31" />
|
||||
<path d="M78.7361 16.2296H81.0498V11.1174C81.0498 9.16334 81.9517 7.9593 83.6379 7.9593H84.6575V5.63019H83.8928C82.5791 5.63019 81.5791 6.53815 81.187 7.40663H81.0301V5.88678H78.7361V16.2296Z" fill="#2D2D31" />
|
||||
<path d="M96.1389 16.2296H97.9428V14.1571H96.1585C95.4527 14.1571 95.1586 13.8413 95.1586 13.111V7.93956H98.0604V5.88678H95.1586V2.98526H92.9626V5.88678H91.0411V7.93956H92.8253V13.1307C92.8253 15.3217 94.139 16.2296 96.1389 16.2296Z" fill="#2D2D31" />
|
||||
<path d="M104.15 16.2461C106.287 16.2461 108.169 15.1802 108.836 13.0287L106.718 12.5155C106.346 13.6603 105.268 14.2525 104.13 14.2525C102.444 14.2525 101.326 13.1472 101.307 11.4102H109.091V10.7588C109.091 7.67965 107.189 5.39001 104.052 5.39001C101.287 5.39001 98.9148 7.58096 98.9148 10.8378C98.9148 13.9959 101.013 16.2461 104.15 16.2461ZM101.326 9.71269C101.464 8.46918 102.581 7.42305 104.052 7.42305C105.464 7.42305 106.62 8.31128 106.738 9.71269H101.326Z" fill="#2D2D31" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M90.0123 16.2296H87.6987V7.93956H85.8948V5.88678H90.0123V16.2296Z" fill="#2D2D31" />
|
||||
<path d="M88.6835 4.45145C89.5266 4.45145 90.154 3.81983 90.154 2.99082C90.154 2.18155 89.5266 1.54993 88.6835 1.54993C87.8404 1.54993 87.213 2.18155 87.213 2.99082C87.213 3.81983 87.8404 4.45145 88.6835 4.45145Z" fill="#2D2D31" />
|
||||
<path d="M20.2007 13.6935V18.258H8.88588C5.5894 18.258 2.71111 16.4222 1.17116 13.6935C0.947288 13.2968 0.751353 12.8806 0.586995 12.4486C0.26435 11.6021 0.0615332 10.6938 0 9.74603V8.51195C0.0133592 8.30074 0.03441 8.09119 0.0619381 7.88413C0.118209 7.45921 0.203222 7.04343 0.314953 6.63926C1.37195 2.80758 4.8089 0 8.88588 0C12.9629 0 16.3994 2.80758 17.4564 6.63926H12.6184C11.8241 5.39025 10.4493 4.5645 8.88588 4.5645C7.32245 4.5645 5.94767 5.39025 5.15341 6.63926C4.91132 7.01895 4.72349 7.43764 4.60042 7.88413C4.49112 8.27999 4.43282 8.69744 4.43282 9.12899C4.43282 10.4373 4.96962 11.6166 5.83027 12.4486C6.62778 13.2209 7.70299 13.6935 8.88588 13.6935H20.2007Z" fill="#FD366E" />
|
||||
<path d="M20.2007 7.88412V12.4486H11.9415C12.8022 11.6166 13.339 10.4373 13.339 9.12899C13.339 8.69744 13.2807 8.27999 13.1714 7.88412H20.2007Z" fill="#FD366E" />
|
||||
</svg>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
@ -1,22 +1,112 @@
|
|||
<?php
|
||||
use Utopia\System\System;
|
||||
|
||||
$development = $this->getParam('development', false);
|
||||
$type = $this->getParam('type', 'general_server_error');
|
||||
$code = $this->getParam('code', 500);
|
||||
$errorID = $this->getParam('errorID', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
|
||||
$message = $this->getParam('message', '');
|
||||
$trace = $this->getParam('trace', []);
|
||||
$projectName = $this->getParam('projectName', '');
|
||||
$projectURL = $this->getParam('projectURL', '');
|
||||
$title = $this->getParam('title', '')
|
||||
$title = $this->getParam('title', 'Error');
|
||||
$exception = $this->getParam('exception', null);
|
||||
|
||||
$isSimpleMessage = true;
|
||||
$label = '';
|
||||
$labelClass = '';
|
||||
$buttons = [];
|
||||
|
||||
$protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https';
|
||||
$hostname = System::getEnv('_APP_DOMAIN');
|
||||
// TODO: remove this later
|
||||
if (System::getEnv('_APP_ENV') === 'development') {
|
||||
$hostname = 'localhost';
|
||||
}
|
||||
|
||||
$url = $protocol . '://' . $hostname;
|
||||
|
||||
if($exception !== null && method_exists($exception, 'getCTAs')) {
|
||||
foreach ($exception->getCTAs() as $index => $cta) {
|
||||
$class = ($index === 0) ? 'bordered-button' : 'button';
|
||||
|
||||
$buttons[] = [
|
||||
'text' => $cta['label'],
|
||||
'url' => $cta['url'],
|
||||
'class' => $class
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
switch ($type) {
|
||||
case 'proxy_error_override':
|
||||
$type = '';
|
||||
$label = 'Error ' . $code;
|
||||
|
||||
$message = $code >= 500 ? 'An unexpected server error occured.' : 'An unexpected client error occured.';
|
||||
switch($code) {
|
||||
case 401:
|
||||
$message = 'You must sign in to access this page.';
|
||||
break;
|
||||
case 403:
|
||||
$message = 'You are not authorized to access this page.';
|
||||
break;
|
||||
case 404:
|
||||
$message = 'The page you are looking for does not exist.';
|
||||
break;
|
||||
case 504:
|
||||
$message = 'The server did not respond in time.';
|
||||
break;
|
||||
case 501:
|
||||
$message = 'This page is not implemented yet.';
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case 'function_execute_permission_missing':
|
||||
$label = 'Execution not permitted';
|
||||
$labelClass = 'warning';
|
||||
break;
|
||||
case 'build_not_ready':
|
||||
$label = 'Deployment is still building';
|
||||
$message = 'The page will update after the build completes.';
|
||||
$labelClass = 'warning';
|
||||
break;
|
||||
case 'build_failed':
|
||||
$label = 'Deployment build failed';
|
||||
$message = 'An error occurred during the build process.';
|
||||
$labelClass = 'error';
|
||||
break;
|
||||
case 'rule_not_found':
|
||||
$label = 'Nothing is here yet';
|
||||
$message = 'This page is empty, but you can make it yours.';
|
||||
break;
|
||||
case 'deployment_not_found':
|
||||
$label = 'No active deployments';
|
||||
$message = 'This page is empty, activate a deployment to make it live.';
|
||||
break;
|
||||
case 'build_canceled':
|
||||
$label = 'Deployment build canceled';
|
||||
$message = 'This build was canceled and won\'t be deployed.';
|
||||
break;
|
||||
case 'general_route_not_found':
|
||||
$label = 'Page not found';
|
||||
$message = 'The page you\'re looking for doesn\'t exist.';
|
||||
break;
|
||||
default:
|
||||
$label = 'Error ' . $code;
|
||||
$message = $message;
|
||||
$isSimpleMessage = false;
|
||||
break;
|
||||
}
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="description" content="" />
|
||||
<link rel="icon" href="/favicon.png" />
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js" defer></script>
|
||||
<link rel="icon" type="image/svg+xml" href="<?php echo $url; ?>/images/logos/appwrite-icon.svg" />
|
||||
<link rel="mask-icon" type="image/png" href="<?php echo $url; ?>/images/logos/appwrite-icon.png" />
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/inter/inter-v8-latin-600.woff2"
|
||||
|
|
@ -29,102 +119,427 @@ $title = $this->getParam('title', '')
|
|||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin />
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/poppins/poppins-v19-latin-500.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin />
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/poppins/poppins-v19-latin-600.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin />
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/poppins/poppins-v19-latin-700.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin />
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/source-code-pro/source-code-pro-v20-latin-regular.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin />
|
||||
|
||||
<link rel="stylesheet" href="https://unpkg.com/@appwrite.io/pink" />
|
||||
<link rel="preload" as="style" type="text/css" href="/fonts/main.css" />
|
||||
<link rel="stylesheet" href="/fonts/main.css" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta http-equiv="content-security-policy" content="">
|
||||
<title><?php echo $this->print($title); ?></title>
|
||||
|
||||
<style>
|
||||
@media(min-width:768px) {
|
||||
article.card {
|
||||
padding: 2rem !important;
|
||||
@import url(https://fonts.bunny.net/css?family=fira-code:400|inter:400);
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.main {
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
width: 100vw;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
span {
|
||||
padding: var(--space-1, 2px) var(--space-3, 6px);
|
||||
border-radius: var(--border-radius-XS, 6px);
|
||||
background: var(--color-overlay-on-neutral, rgba(0, 0, 0, 0.06));
|
||||
color: var(--color-fgColor-neutral-secondary, #56565C);
|
||||
text-align: center;
|
||||
font-family: var(--font-family-sansSerif, Inter), sans-serif;
|
||||
font-size: var(--font-size-S, 14px);
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 140%;
|
||||
letter-spacing: -0.063px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: var(--color-fgColor-neutral-primary, #2D2D31);
|
||||
text-align: center;
|
||||
font-family: var(--font-family-sansSerif, Inter), sans-serif;
|
||||
font-size: var(--font-size-XXXL, 32px);
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 140%;
|
||||
letter-spacing: -0.144px;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.content h1 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.content.small-error h1 {
|
||||
font-size: var(--font-size-M, 20px);
|
||||
}
|
||||
|
||||
.content.large-error h1 {
|
||||
font-size: var(--font-size-XXXL, 32px);
|
||||
}
|
||||
|
||||
.bordered-button {
|
||||
border-radius: var(--border-radius-S, 8px);
|
||||
font-family: var(--font-family-sansSerif, Inter), sans-serif;
|
||||
font-size: var(--font-size-S, 14px);
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 140%;
|
||||
letter-spacing: -0.063px;
|
||||
padding: var(--space-3, 6px) var(--space-5, 10px);
|
||||
cursor: pointer;
|
||||
border: var(--border-width-S, 1px) solid var(--color-border-neutral-strong, #D8D8DB);
|
||||
background: var(--color-bgColor-neutral-primary, #FFF);
|
||||
color: var(--color-fgColor-neutral-secondary, #56565C);
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: var(--border-radius-S, 8px);
|
||||
font-family: var(--font-family-sansSerif, Inter), sans-serif;
|
||||
font-size: var(--font-size-S, 14px);
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 140%;
|
||||
letter-spacing: -0.063px;
|
||||
padding: var(--space-3, 6px) var(--space-5, 10px);
|
||||
cursor: pointer;
|
||||
border: var(--border-width-S, 1px) solid transparent;
|
||||
background: var(--color-bgColor-neutral-primary, #FFF);
|
||||
color: var(--color-fgColor-neutral-secondary, #56565C);
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.brand {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
bottom: 32px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.brand p {
|
||||
font-family: var(--font-family-monospace, "Fira Code"), monospace;
|
||||
font-size: var(--font-size-XS, 12px);
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 130%;
|
||||
letter-spacing: 0.96px;
|
||||
text-transform: uppercase;
|
||||
color: var(--color-fgColor-neutral-secondary, #56565C);
|
||||
}
|
||||
|
||||
.brand svg {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.warning {
|
||||
background: var(--color-overlay-on-neutral, rgba(254, 124, 67, 0.16));
|
||||
color: var(--color-fgColor-neutral-secondary, #61250A);
|
||||
}
|
||||
|
||||
.error {
|
||||
background: var(--color-overlay-on-neutral, rgba(255, 69, 58, 0.16));
|
||||
color: var(--color-fgColor-neutral-secondary, #B31212);
|
||||
}
|
||||
|
||||
.logo-dark {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.logo-light {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.type {
|
||||
padding: var(--space-1, 2px) var(--space-3, 6px);
|
||||
border-radius: var(--border-radius-XS, 6px);
|
||||
border: var(--border-width-S, 1px) solid var(--color-border-neutral-strong, #EDEDF0);
|
||||
background: var(--color-overlay-on-neutral, rgba(250, 250, 251, 1));
|
||||
color: var(--color-fgColor-neutral-secondary, #56565C);
|
||||
text-align: center;
|
||||
font-family: var(--font-family-monospace, "Fira Code"), monospace;
|
||||
font-size: var(--font-size-XS, 12px);
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 140%;
|
||||
letter-spacing: 0px;
|
||||
}
|
||||
|
||||
.error-trace {
|
||||
max-width: 900px;
|
||||
padding: 20px;
|
||||
font-family: var(--font-family-sansSerif, Inter), sans-serif;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
color: var(--color-fgColor-neutral-secondary, #56565C);
|
||||
font-family: var(--font-family-sansSerif, Inter), sans-serif;
|
||||
font-size: var(--font-size-S, 14px);
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 140%;
|
||||
letter-spacing: -0.45px;
|
||||
}
|
||||
|
||||
.back-button:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.trace-grid {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: 16px;
|
||||
background: var(--color-bgColor-neutral-secondary, #FFFFFF);
|
||||
padding: 10px 12px;
|
||||
border: var(--border-width-S, 1px) solid var(--color-border-neutral-strong, #EDEDF0);
|
||||
}
|
||||
|
||||
.trace-grid-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 12px;
|
||||
background: var(--color-bgColor-neutral-secondary, #FAFAFB);
|
||||
border-radius: 8px 8px 0 0;
|
||||
border: var(--border-width-S, 1px) solid var(--color-border-neutral-strong, #EDEDF0);
|
||||
font-family: var(--font-family-sansSerif, Inter), sans-serif;
|
||||
font-size: var(--font-size-S, 14px);
|
||||
font-weight: 400;
|
||||
line-height: 140%;
|
||||
letter-spacing: -0.45px;
|
||||
color: var(--color-fgColor-neutral-secondary, #56565C);
|
||||
}
|
||||
|
||||
.trace-label {
|
||||
font-family: var(--font-family-sansSerif, Inter), sans-serif;
|
||||
font-size: var(--font-size-S, 14px);
|
||||
font-weight: 400;
|
||||
line-height: 140%;
|
||||
letter-spacing: -0.45px;
|
||||
color: var(--color-fgColor-neutral-secondary, #56565C);
|
||||
}
|
||||
|
||||
.trace-value {
|
||||
color: var(--color-fgColor-neutral-secondary, #56565C);
|
||||
font-family: var(--font-family-monospace, "Fira Code"), monospace;
|
||||
font-size: var(--font-size-S, 14px);
|
||||
font-weight: 400;
|
||||
line-height: 140%;
|
||||
letter-spacing: 0px;
|
||||
}
|
||||
|
||||
.trace-args {
|
||||
/* grid-column: 1 / -1; */
|
||||
padding: 10px 12px;
|
||||
/* white-space: pre-wrap; */
|
||||
overflow-x: auto;
|
||||
font-family: var(--font-family-monospace, "Fira Code"), monospace;
|
||||
font-size: var(--font-size-S, 14px);
|
||||
font-weight: 400;
|
||||
line-height: 140%;
|
||||
color: var(--color-fgColor-neutral-secondary, #56565C);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.content {
|
||||
margin-left: 16px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #1D1D21;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: var(--color-fgColor-neutral-primary, #EDEDF0);
|
||||
}
|
||||
|
||||
span {
|
||||
background: var(--color-overlay-on-neutral, rgba(255, 255, 255, 0.2));
|
||||
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
|
||||
}
|
||||
|
||||
.bordered-button {
|
||||
border: var(--border-width-S, 1px) solid var(--color-border-neutral-strong, #414146);
|
||||
background: var(--color-bgColor-neutral-primary, #1D1D21);
|
||||
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
|
||||
}
|
||||
|
||||
button {
|
||||
background: var(--color-bgColor-neutral-primary, #1D1D21);
|
||||
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
|
||||
}
|
||||
|
||||
.brand p {
|
||||
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
|
||||
}
|
||||
|
||||
.warning {
|
||||
background: var(--color-overlay-on-neutral, rgba(254, 124, 67, 0.24));
|
||||
color: var(--color-fgColor-neutral-secondary, #FFD5C2);
|
||||
}
|
||||
|
||||
.error {
|
||||
background: var(--color-overlay-on-neutral, rgba(255, 69, 58, 0.28));
|
||||
color: var(--color-fgColor-neutral-secondary, #FFD5D4);
|
||||
}
|
||||
|
||||
.logo-light {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.logo-dark {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.type {
|
||||
background: var(--color-overlay-on-neutral, rgba(25, 25, 28, 1));
|
||||
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
|
||||
border: var(--border-width-S, 1px) solid var(--color-border-neutral-strong, #414146);
|
||||
}
|
||||
|
||||
.back-button {
|
||||
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
|
||||
}
|
||||
|
||||
.trace-grid {
|
||||
background: var(--color-bgColor-neutral-secondary, #1D1D21);
|
||||
border: var(--border-width-S, 1px) solid var(--color-border-neutral-strong, #2D2D31);
|
||||
}
|
||||
|
||||
.trace-grid-header {
|
||||
background: var(--color-bgColor-neutral-secondary, #19191C);
|
||||
border: var(--border-width-S, 1px) solid var(--color-border-neutral-strong, #2D2D31);
|
||||
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
|
||||
}
|
||||
|
||||
.trace-label {
|
||||
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
|
||||
}
|
||||
|
||||
.trace-value {
|
||||
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
|
||||
}
|
||||
|
||||
.trace-args {
|
||||
color: var(--color-fgColor-neutral-secondary, #C3C3C6);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container u-margin-block-start-24">
|
||||
<article class="card u-padding-16">
|
||||
<div class="u-flex u-flex-vertical u-gap-16">
|
||||
<h1 class="heading-level-4 u-trim-1">Error <?php echo $this->print($code); ?></h1>
|
||||
<p class="text"><?php echo $this->print($message); ?></p>
|
||||
<div class="u-flex u-flex-vertical u-gap-8">
|
||||
<p class="text">Type</p>
|
||||
<p><code class="inline-code"><?php echo $this->print($type); ?></code></p>
|
||||
<body x-data="{ page: 'error' }">
|
||||
<div class="main">
|
||||
<div x-show="page === 'error'" class="content <?php echo $isSimpleMessage ? 'large-error' : 'small-error' ?>">
|
||||
<div class="center"><span class="<?php echo $this->print($labelClass); ?>"><?php echo $this->print($label); ?></span></div>
|
||||
<h1><?php echo $this->print($message); ?></h1>
|
||||
<?php if (!empty($type)): ?>
|
||||
<div class="center">
|
||||
<span class='type'><?php echo $this->print($type); ?></span>
|
||||
</div>
|
||||
<?php if ($development) : ?>
|
||||
<h2 class="heading-level-5 u-trim-1">Error Trace</h2>
|
||||
<?php foreach ($trace as $log) : ?>
|
||||
<div class="table-with-scroll">
|
||||
<div class="table-wrapper">
|
||||
<table class="table is-remove-outer-styles">
|
||||
<tbody class="table-tbody">
|
||||
<?php foreach ($log as $key => $value) : ?>
|
||||
<tr>
|
||||
<td class="table-col" style="width: 120px"><?php echo $this->print($key, self::FILTER_ESCAPE); ?></td>
|
||||
<td class="table-col"><code class="grid-code u-max-height-200 u-overflow-x-auto u-overflow-y-auto">
|
||||
<?php if (is_array($value)) : ?>
|
||||
|
||||
<pre><?php echo $this->print(var_export($value, true), self::FILTER_ESCAPE); ?></pre>
|
||||
<?php else : ?>
|
||||
<pre><?php echo $this->print($value, self::FILTER_ESCAPE); ?></pre>
|
||||
<?php endif; ?>
|
||||
</code>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="center" style="margin-top: 20px;">
|
||||
<?php if (!empty($buttons)): ?>
|
||||
<?php foreach ($buttons as $button): ?>
|
||||
<a href="<?php echo htmlspecialchars($button['url']); ?>">
|
||||
<button class="<?php echo htmlspecialchars($button['class']); ?>">
|
||||
<?php echo htmlspecialchars($button['text']); ?>
|
||||
</button>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($development) : ?>
|
||||
<button class="<?php echo count($buttons) === 0 ? 'bordered-button' : 'button' ?>" x-on:click="page = 'trace'">View error trace</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div x-show="page === 'trace'" class="error-trace">
|
||||
<button class="back-button" x-on:click="page = 'error'">
|
||||
Back
|
||||
</button>
|
||||
<div class="trace-grid-header">Error trace</div>
|
||||
<?php foreach ($trace as $index => $traceItem): ?>
|
||||
<div class="trace-grid">
|
||||
<?php if (isset($traceItem['file'])): ?>
|
||||
<div class="trace-label">file</div>
|
||||
<div class="trace-value"><?php echo $this->print($traceItem['file']); ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($traceItem['line'])): ?>
|
||||
<div class="trace-label">line</div>
|
||||
<div class="trace-value"><?php echo $this->print($traceItem['line']); ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($traceItem['function'])): ?>
|
||||
<div class="trace-label">function</div>
|
||||
<div class="trace-value"><?php echo $this->print($traceItem['function']); ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($traceItem['args'])): ?>
|
||||
<div class="trace-label">args</div>
|
||||
<div class="trace-args"><pre><?php echo $this->print(\var_export($traceItem['args'], true)); ?></pre></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div x-show="page === 'error'" class="brand">
|
||||
<p>Powered by</p>
|
||||
<svg class="logo-dark" width="110" height="20" viewBox="0 0 110 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M31.8649 16.2461C33.6492 16.2461 34.5511 15.3184 34.9433 14.6867H35.1197C35.1981 15.3578 35.6687 15.9895 36.5903 15.9895H38.3353V14.0156H37.8843C37.5706 14.0156 37.4138 13.838 37.4138 13.5617V5.64661H35.1001V6.90986H34.9236C34.4727 6.27823 33.5315 5.39001 31.8061 5.39001C29.0611 5.39001 27.022 7.67965 27.022 10.818C27.022 13.9564 29.1003 16.2461 31.8649 16.2461ZM32.2767 13.9959C30.6493 13.9959 29.3748 12.7919 29.3748 10.8378C29.3748 8.92316 30.6101 7.62044 32.2571 7.62044C33.8256 7.62044 35.1393 8.86395 35.1393 10.8378C35.1393 12.5945 34.0217 13.9959 32.2767 13.9959Z" fill="#EDEDF0" />
|
||||
<path d="M39.7013 20H42.0149V14.6867H42.1914C42.6227 15.3184 43.5443 16.2461 45.3677 16.2461C48.1127 16.2461 50.1127 13.9169 50.1127 10.818C50.1127 7.69939 47.9755 5.39001 45.2109 5.39001C43.4462 5.39001 42.5835 6.35719 42.1718 6.89012H41.9953V5.63019H39.7013V20ZM44.8776 14.0551C43.2894 14.0551 41.9757 12.8708 41.9757 10.818C41.9757 9.06133 43.0933 7.58096 44.8383 7.58096C46.4657 7.58096 47.7402 8.86395 47.7402 10.818C47.7402 12.7326 46.5049 14.0551 44.8776 14.0551Z" fill="#EDEDF0" />
|
||||
<path d="M51.3065 20H53.6202V14.6867H53.7966C54.228 15.3184 55.1495 16.2461 56.973 16.2461C59.718 16.2461 61.5273 13.9169 61.5273 10.818C61.5273 7.69939 59.5807 5.39001 56.8161 5.39001C55.0515 5.39001 54.1888 6.35719 53.777 6.89012H53.6005V5.64661H51.3065V20ZM56.4828 14.0551C54.8946 14.0551 53.5809 12.8708 53.5809 10.818C53.5809 9.06133 54.6985 7.58096 56.4436 7.58096C58.071 7.58096 59.3454 8.86395 59.3454 10.818C59.3454 12.7326 58.1102 14.0551 56.4828 14.0551Z" fill="#EDEDF0" />
|
||||
<path d="M64.5857 16.2296H67.8601L69.7227 8.11721H69.8404L71.7031 16.2296H74.9579L77.5642 5.88678H75.2323L73.3697 14.0189H73.1932L71.3305 5.88678H68.2522L66.3699 14.0189H66.1935L64.3504 5.88678H61.8799L64.5857 16.2296Z" fill="#EDEDF0" />
|
||||
<path d="M78.7363 16.2296H81.0499V11.1174C81.0499 9.16334 81.9519 7.9593 83.6381 7.9593H84.6576V5.63019H83.893C82.5793 5.63019 81.5793 6.53815 81.1872 7.40663H81.0303V5.88678H78.7363V16.2296Z" fill="#EDEDF0" />
|
||||
<path d="M96.1391 16.2296H97.943V14.1571H96.1587C95.4529 14.1571 95.1588 13.8413 95.1588 13.111V7.93956H98.0606V5.88678H95.1588V2.98526H92.9628V5.88678H91.0413V7.93956H92.8255V13.1307C92.8255 15.3217 94.1392 16.2296 96.1391 16.2296Z" fill="#EDEDF0" />
|
||||
<path d="M104.15 16.2461C106.287 16.2461 108.17 15.1802 108.836 13.0287L106.719 12.5155C106.346 13.6603 105.268 14.2525 104.13 14.2525C102.444 14.2525 101.327 13.1472 101.307 11.4102H109.091V10.7588C109.091 7.67965 107.189 5.39001 104.052 5.39001C101.287 5.39001 98.915 7.58096 98.915 10.8378C98.915 13.9959 101.013 16.2461 104.15 16.2461ZM101.327 9.71269C101.464 8.46918 102.581 7.42305 104.052 7.42305C105.464 7.42305 106.621 8.31128 106.738 9.71269H101.327Z" fill="#EDEDF0" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M90.0125 16.2296H87.6989V7.93956H85.895V5.88678H90.0125V16.2296Z" fill="#EDEDF0" />
|
||||
<path d="M88.6834 4.45145C89.5265 4.45145 90.154 3.81983 90.154 2.99082C90.154 2.18155 89.5265 1.54993 88.6834 1.54993C87.8403 1.54993 87.2129 2.18155 87.2129 2.99082C87.2129 3.81983 87.8403 4.45145 88.6834 4.45145Z" fill="#EDEDF0" />
|
||||
<path d="M20.2007 13.6935V18.258H8.88588C5.5894 18.258 2.71111 16.4222 1.17116 13.6935C0.947288 13.2968 0.751353 12.8806 0.586995 12.4486C0.26435 11.6021 0.0615332 10.6938 0 9.74603V8.51195C0.0133592 8.30074 0.03441 8.09119 0.0619381 7.88413C0.118209 7.45921 0.203222 7.04343 0.314953 6.63926C1.37195 2.80758 4.8089 0 8.88588 0C12.9629 0 16.3994 2.80758 17.4564 6.63926H12.6184C11.8241 5.39025 10.4493 4.5645 8.88588 4.5645C7.32245 4.5645 5.94767 5.39025 5.15341 6.63926C4.91132 7.01895 4.72349 7.43764 4.60042 7.88413C4.49112 8.27999 4.43282 8.69744 4.43282 9.12899C4.43282 10.4373 4.96962 11.6166 5.83027 12.4486C6.62778 13.2209 7.70299 13.6935 8.88588 13.6935H20.2007Z" fill="#FD366E" />
|
||||
<path d="M20.2006 7.88412V12.4486H11.9414C12.8021 11.6166 13.3389 10.4373 13.3389 9.12899C13.3389 8.69744 13.2806 8.27999 13.1713 7.88412H20.2006Z" fill="#FD366E" />
|
||||
</svg>
|
||||
<svg class="logo-light" width="110" height="20" viewBox="0 0 110 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M31.8648 16.2461C33.649 16.2461 34.5509 15.3184 34.9431 14.6867H35.1195C35.198 15.3578 35.6685 15.9895 36.5901 15.9895H38.3351V14.0156H37.8841C37.5704 14.0156 37.4136 13.838 37.4136 13.5617V5.64661H35.0999V6.90986H34.9235C34.4725 6.27823 33.5314 5.39001 31.8059 5.39001C29.0609 5.39001 27.0218 7.67965 27.0218 10.818C27.0218 13.9564 29.1001 16.2461 31.8648 16.2461ZM32.2765 13.9959C30.6491 13.9959 29.3746 12.7919 29.3746 10.8378C29.3746 8.92316 30.6099 7.62044 32.2569 7.62044C33.8255 7.62044 35.1391 8.78499 35.1391 10.8378C35.1391 12.5945 34.0215 13.9959 32.2765 13.9959Z" fill="#2D2D31" />
|
||||
<path d="M39.7011 20H42.0147V14.6867H42.1912C42.6226 15.3184 43.5441 16.2461 45.3676 16.2461C48.1126 16.2461 50.1125 13.9169 50.1125 10.818C50.1125 7.69939 47.9753 5.39001 45.2107 5.39001C43.4461 5.39001 42.5833 6.35719 42.1716 6.89012H41.9951V5.64661H39.7011V20ZM44.8774 14.0551C43.2892 14.0551 41.9755 12.8708 41.9755 10.818C41.9755 9.06133 43.0931 7.58096 44.8382 7.58096C46.4656 7.58096 47.74 8.86395 47.74 10.818C47.74 12.7326 46.5048 14.0551 44.8774 14.0551Z" fill="#2D2D31" />
|
||||
<path d="M51.3063 20H53.62V14.6867H53.7964C54.2278 15.3184 55.1493 16.2461 56.9728 16.2461C59.7178 16.2461 61.5271 13.9169 61.5271 10.818C61.5271 7.69939 59.5805 5.39001 56.8159 5.39001C55.0513 5.39001 54.1886 6.35719 53.7768 6.89012H53.6004V5.64661H51.3063V20ZM56.4826 14.0551C54.8944 14.0551 53.5808 12.8708 53.5808 10.818C53.5808 9.06133 54.6984 7.58096 56.4434 7.58096C58.0708 7.58096 59.3453 8.86395 59.3453 10.818C59.3453 12.7326 58.11 14.0551 56.4826 14.0551Z" fill="#2D2D31" />
|
||||
<path d="M64.5855 16.2296H67.8599L69.7226 8.11721H69.8402L71.7029 16.2296H74.9577L77.564 5.88678H75.2322L73.3695 14.0189H73.193L71.3303 5.88678H68.252L66.3697 14.0189H66.1933L64.3502 5.88678H61.8797L64.5855 16.2296Z" fill="#2D2D31" />
|
||||
<path d="M78.7361 16.2296H81.0498V11.1174C81.0498 9.16334 81.9517 7.9593 83.6379 7.9593H84.6575V5.63019H83.8928C82.5791 5.63019 81.5791 6.53815 81.187 7.40663H81.0301V5.88678H78.7361V16.2296Z" fill="#2D2D31" />
|
||||
<path d="M96.1389 16.2296H97.9428V14.1571H96.1585C95.4527 14.1571 95.1586 13.8413 95.1586 13.111V7.93956H98.0604V5.88678H95.1586V2.98526H92.9626V5.88678H91.0411V7.93956H92.8253V13.1307C92.8253 15.3217 94.139 16.2296 96.1389 16.2296Z" fill="#2D2D31" />
|
||||
<path d="M104.15 16.2461C106.287 16.2461 108.169 15.1802 108.836 13.0287L106.718 12.5155C106.346 13.6603 105.268 14.2525 104.13 14.2525C102.444 14.2525 101.326 13.1472 101.307 11.4102H109.091V10.7588C109.091 7.67965 107.189 5.39001 104.052 5.39001C101.287 5.39001 98.9148 7.58096 98.9148 10.8378C98.9148 13.9959 101.013 16.2461 104.15 16.2461ZM101.326 9.71269C101.464 8.46918 102.581 7.42305 104.052 7.42305C105.464 7.42305 106.62 8.31128 106.738 9.71269H101.326Z" fill="#2D2D31" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M90.0123 16.2296H87.6987V7.93956H85.8948V5.88678H90.0123V16.2296Z" fill="#2D2D31" />
|
||||
<path d="M88.6835 4.45145C89.5266 4.45145 90.154 3.81983 90.154 2.99082C90.154 2.18155 89.5266 1.54993 88.6835 1.54993C87.8404 1.54993 87.213 2.18155 87.213 2.99082C87.213 3.81983 87.8404 4.45145 88.6835 4.45145Z" fill="#2D2D31" />
|
||||
<path d="M20.2007 13.6935V18.258H8.88588C5.5894 18.258 2.71111 16.4222 1.17116 13.6935C0.947288 13.2968 0.751353 12.8806 0.586995 12.4486C0.26435 11.6021 0.0615332 10.6938 0 9.74603V8.51195C0.0133592 8.30074 0.03441 8.09119 0.0619381 7.88413C0.118209 7.45921 0.203222 7.04343 0.314953 6.63926C1.37195 2.80758 4.8089 0 8.88588 0C12.9629 0 16.3994 2.80758 17.4564 6.63926H12.6184C11.8241 5.39025 10.4493 4.5645 8.88588 4.5645C7.32245 4.5645 5.94767 5.39025 5.15341 6.63926C4.91132 7.01895 4.72349 7.43764 4.60042 7.88413C4.49112 8.27999 4.43282 8.69744 4.43282 9.12899C4.43282 10.4373 4.96962 11.6166 5.83027 12.4486C6.62778 13.2209 7.70299 13.6935 8.88588 13.6935H20.2007Z" fill="#FD366E" />
|
||||
<path d="M20.2007 7.88412V12.4486H11.9415C12.8022 11.6166 13.339 10.4373 13.339 9.12899C13.339 8.69744 13.2807 8.27999 13.1714 7.88412H20.2007Z" fill="#FD366E" />
|
||||
</svg>
|
||||
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
const app = (JSON.parse(localStorage.getItem('appwrite')) ?? {});
|
||||
const theme = app.theme ?? 'auto';
|
||||
if (theme === 'auto') {
|
||||
const darkThemeMq = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
if (darkThemeMq.matches) {
|
||||
document.body.setAttribute('class', `theme-dark`);
|
||||
} else {
|
||||
document.body.setAttribute('class', `theme-light`);
|
||||
}
|
||||
} else {
|
||||
document.body.setAttribute('class', `theme-${theme}`);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
@ -61,10 +61,13 @@ $image = $this->getParam('image', '');
|
|||
- traefik.http.routers.appwrite_api_https.tls=true
|
||||
volumes:
|
||||
- appwrite-uploads:/storage/uploads:rw
|
||||
- appwrite-imports:/storage/imports:rw
|
||||
- appwrite-cache:/storage/cache:rw
|
||||
- appwrite-config:/storage/config:rw
|
||||
- appwrite-certificates:/storage/certificates:rw
|
||||
- appwrite-functions:/storage/functions:rw
|
||||
- appwrite-sites:/storage/sites:rw
|
||||
- appwrite-builds:/storage/builds:rw
|
||||
depends_on:
|
||||
- mariadb
|
||||
- redis
|
||||
|
|
@ -86,10 +89,12 @@ $image = $this->getParam('image', '');
|
|||
- _APP_OPTIONS_ABUSE
|
||||
- _APP_OPTIONS_ROUTER_PROTECTION
|
||||
- _APP_OPTIONS_FORCE_HTTPS
|
||||
- _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS
|
||||
- _APP_OPTIONS_ROUTER_FORCE_HTTPS
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET
|
||||
- _APP_DOMAIN_TARGET_CNAME
|
||||
- _APP_DOMAIN_TARGET_AAAA
|
||||
- _APP_DOMAIN_TARGET_A
|
||||
- _APP_DOMAIN_FUNCTIONS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
|
|
@ -133,12 +138,15 @@ $image = $this->getParam('image', '');
|
|||
- _APP_STORAGE_WASABI_SECRET
|
||||
- _APP_STORAGE_WASABI_REGION
|
||||
- _APP_STORAGE_WASABI_BUCKET
|
||||
- _APP_FUNCTIONS_SIZE_LIMIT
|
||||
- _APP_COMPUTE_SIZE_LIMIT
|
||||
- _APP_FUNCTIONS_TIMEOUT
|
||||
- _APP_FUNCTIONS_BUILD_TIMEOUT
|
||||
- _APP_FUNCTIONS_CPUS
|
||||
- _APP_FUNCTIONS_MEMORY
|
||||
- _APP_SITES_TIMEOUT
|
||||
- _APP_COMPUTE_BUILD_TIMEOUT
|
||||
- _APP_COMPUTE_CPUS
|
||||
- _APP_COMPUTE_MEMORY
|
||||
- _APP_FUNCTIONS_RUNTIMES
|
||||
- _APP_SITES_RUNTIMES
|
||||
- _APP_DOMAIN_SITES
|
||||
- _APP_EXECUTOR_SECRET
|
||||
- _APP_EXECUTOR_HOST
|
||||
- _APP_LOGGING_CONFIG
|
||||
|
|
@ -169,7 +177,7 @@ $image = $this->getParam('image', '');
|
|||
appwrite-console:
|
||||
<<: *x-logging
|
||||
container_name: appwrite-console
|
||||
image: <?php echo $organization; ?>/console:5.2.58
|
||||
image: <?php echo $organization; ?>/console:6.0.1
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
|
|
@ -300,6 +308,7 @@ $image = $this->getParam('image', '');
|
|||
- appwrite-uploads:/storage/uploads:rw
|
||||
- appwrite-cache:/storage/cache:rw
|
||||
- appwrite-functions:/storage/functions:rw
|
||||
- appwrite-sites:/storage/sites:rw
|
||||
- appwrite-builds:/storage/builds:rw
|
||||
- appwrite-certificates:/storage/certificates:rw
|
||||
environment:
|
||||
|
|
@ -386,7 +395,9 @@ $image = $this->getParam('image', '');
|
|||
- mariadb
|
||||
volumes:
|
||||
- appwrite-functions:/storage/functions:rw
|
||||
- appwrite-sites:/storage/sites:rw
|
||||
- appwrite-builds:/storage/builds:rw
|
||||
- appwrite-uploads:/storage/uploads:rw
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
|
|
@ -407,12 +418,13 @@ $image = $this->getParam('image', '');
|
|||
- _APP_VCS_GITHUB_PRIVATE_KEY
|
||||
- _APP_VCS_GITHUB_APP_ID
|
||||
- _APP_FUNCTIONS_TIMEOUT
|
||||
- _APP_FUNCTIONS_BUILD_TIMEOUT
|
||||
- _APP_FUNCTIONS_CPUS
|
||||
- _APP_FUNCTIONS_MEMORY
|
||||
- _APP_FUNCTIONS_SIZE_LIMIT
|
||||
- _APP_SITES_TIMEOUT
|
||||
- _APP_COMPUTE_BUILD_TIMEOUT
|
||||
- _APP_COMPUTE_CPUS
|
||||
- _APP_COMPUTE_MEMORY
|
||||
- _APP_COMPUTE_SIZE_LIMIT
|
||||
- _APP_OPTIONS_FORCE_HTTPS
|
||||
- _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS
|
||||
- _APP_OPTIONS_ROUTER_FORCE_HTTPS
|
||||
- _APP_DOMAIN
|
||||
- _APP_STORAGE_DEVICE
|
||||
- _APP_STORAGE_S3_ACCESS_KEY
|
||||
|
|
@ -436,6 +448,7 @@ $image = $this->getParam('image', '');
|
|||
- _APP_STORAGE_WASABI_SECRET
|
||||
- _APP_STORAGE_WASABI_REGION
|
||||
- _APP_STORAGE_WASABI_BUCKET
|
||||
- _APP_DOMAIN_SITES
|
||||
|
||||
appwrite-worker-certificates:
|
||||
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
|
||||
|
|
@ -456,7 +469,9 @@ $image = $this->getParam('image', '');
|
|||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET
|
||||
- _APP_DOMAIN_TARGET_CNAME
|
||||
- _APP_DOMAIN_TARGET_AAAA
|
||||
- _APP_DOMAIN_TARGET_A
|
||||
- _APP_DOMAIN_FUNCTIONS
|
||||
- _APP_EMAIL_CERTIFICATES
|
||||
- _APP_REDIS_HOST
|
||||
|
|
@ -498,9 +513,10 @@ $image = $this->getParam('image', '');
|
|||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_FUNCTIONS_TIMEOUT
|
||||
- _APP_FUNCTIONS_BUILD_TIMEOUT
|
||||
- _APP_FUNCTIONS_CPUS
|
||||
- _APP_FUNCTIONS_MEMORY
|
||||
- _APP_SITES_TIMEOUT
|
||||
- _APP_COMPUTE_BUILD_TIMEOUT
|
||||
- _APP_COMPUTE_CPUS
|
||||
- _APP_COMPUTE_MEMORY
|
||||
- _APP_EXECUTOR_SECRET
|
||||
- _APP_EXECUTOR_HOST
|
||||
- _APP_USAGE_STATS
|
||||
|
|
@ -601,6 +617,8 @@ $image = $this->getParam('image', '');
|
|||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- appwrite-imports:/storage/imports:rw
|
||||
depends_on:
|
||||
- mariadb
|
||||
environment:
|
||||
|
|
@ -608,7 +626,9 @@ $image = $this->getParam('image', '');
|
|||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET
|
||||
- _APP_DOMAIN_TARGET_CNAME
|
||||
- _APP_DOMAIN_TARGET_AAAA
|
||||
- _APP_DOMAIN_TARGET_A
|
||||
- _APP_EMAIL_SECURITY
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
|
|
@ -637,7 +657,9 @@ $image = $this->getParam('image', '');
|
|||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET
|
||||
- _APP_DOMAIN_TARGET_CNAME
|
||||
- _APP_DOMAIN_TARGET_AAAA
|
||||
- _APP_DOMAIN_TARGET_A
|
||||
- _APP_DOMAIN_FUNCTIONS
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
|
|
@ -663,11 +685,9 @@ $image = $this->getParam('image', '');
|
|||
container_name: appwrite-task-stats-resources
|
||||
entrypoint: stats-resources
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- ./app:/usr/src/code/app
|
||||
- ./src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
|
|
@ -829,6 +849,14 @@ $image = $this->getParam('image', '');
|
|||
- appwrite
|
||||
environment:
|
||||
- _APP_ASSISTANT_OPENAI_API_KEY
|
||||
|
||||
appwrite-browser:
|
||||
image: appwrite/browser:0.2.4
|
||||
container_name: appwrite-browser
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
|
||||
openruntimes-executor:
|
||||
container_name: openruntimes-executor
|
||||
|
|
@ -836,7 +864,7 @@ $image = $this->getParam('image', '');
|
|||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
stop_signal: SIGINT
|
||||
image: openruntimes/executor:0.6.11
|
||||
image: openruntimes/executor:0.7.14
|
||||
networks:
|
||||
- appwrite
|
||||
- runtimes
|
||||
|
|
@ -844,18 +872,20 @@ $image = $this->getParam('image', '');
|
|||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- appwrite-builds:/storage/builds:rw
|
||||
- appwrite-functions:/storage/functions:rw
|
||||
- appwrite-sites:/storage/sites:rw
|
||||
# Host mount nessessary to share files between executor and runtimes.
|
||||
# It's not possible to share mount file between 2 containers without host mount (copying is too slow)
|
||||
- /tmp:/tmp:rw
|
||||
environment:
|
||||
- OPR_EXECUTOR_INACTIVE_TRESHOLD=$_APP_FUNCTIONS_INACTIVE_THRESHOLD
|
||||
- OPR_EXECUTOR_MAINTENANCE_INTERVAL=$_APP_FUNCTIONS_MAINTENANCE_INTERVAL
|
||||
- OPR_EXECUTOR_NETWORK=$_APP_FUNCTIONS_RUNTIMES_NETWORK
|
||||
- OPR_EXECUTOR_INACTIVE_TRESHOLD=$_APP_COMPUTE_INACTIVE_THRESHOLD
|
||||
- OPR_EXECUTOR_MAINTENANCE_INTERVAL=$_APP_COMPUTE_MAINTENANCE_INTERVAL
|
||||
- OPR_EXECUTOR_NETWORK=$_APP_COMPUTE_RUNTIMES_NETWORK
|
||||
- OPR_EXECUTOR_DOCKER_HUB_USERNAME=$_APP_DOCKER_HUB_USERNAME
|
||||
- OPR_EXECUTOR_DOCKER_HUB_PASSWORD=$_APP_DOCKER_HUB_PASSWORD
|
||||
- OPR_EXECUTOR_ENV=$_APP_ENV
|
||||
- OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES
|
||||
- OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES,$_APP_SITES_RUNTIMES
|
||||
- OPR_EXECUTOR_SECRET=$_APP_EXECUTOR_SECRET
|
||||
- OPR_EXECUTOR_RUNTIME_VERSIONS=v5
|
||||
- OPR_EXECUTOR_LOGGING_CONFIG=$_APP_LOGGING_CONFIG
|
||||
- OPR_EXECUTOR_STORAGE_DEVICE=$_APP_STORAGE_DEVICE
|
||||
- OPR_EXECUTOR_STORAGE_S3_ACCESS_KEY=$_APP_STORAGE_S3_ACCESS_KEY
|
||||
|
|
@ -934,7 +964,9 @@ volumes:
|
|||
appwrite-redis:
|
||||
appwrite-cache:
|
||||
appwrite-uploads:
|
||||
appwrite-imports:
|
||||
appwrite-certificates:
|
||||
appwrite-functions:
|
||||
appwrite-sites:
|
||||
appwrite-builds:
|
||||
appwrite-config:
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ use Utopia\Queue\Publisher;
|
|||
use Utopia\Queue\Server;
|
||||
use Utopia\Registry\Registry;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Telemetry\Adapter\None as NoTelemetry;
|
||||
|
||||
Authorization::disable();
|
||||
Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
|
||||
|
|
@ -334,6 +335,16 @@ Server::setResource('pools', function (Registry $register) {
|
|||
return $register->get('pools');
|
||||
}, ['register']);
|
||||
|
||||
Server::setResource('telemetry', fn () => new NoTelemetry());
|
||||
|
||||
Server::setResource('deviceForSites', function (Document $project) {
|
||||
return getDevice(APP_STORAGE_SITES . '/app-' . $project->getId());
|
||||
}, ['project']);
|
||||
|
||||
Server::setResource('deviceForImports', function (Document $project) {
|
||||
return getDevice(APP_STORAGE_IMPORTS . '/app-' . $project->getId());
|
||||
}, ['project']);
|
||||
|
||||
Server::setResource('deviceForFunctions', function (Document $project) {
|
||||
return getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId());
|
||||
}, ['project']);
|
||||
|
|
@ -355,6 +366,10 @@ Server::setResource(
|
|||
fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false
|
||||
);
|
||||
|
||||
Server::setResource('plan', function (array $plan = []) {
|
||||
return [];
|
||||
});
|
||||
|
||||
Server::setResource('certificates', function () {
|
||||
$email = System::getEnv('_APP_EMAIL_CERTIFICATES', System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS'));
|
||||
if (empty($email)) {
|
||||
|
|
@ -365,7 +380,7 @@ Server::setResource('certificates', function () {
|
|||
});
|
||||
|
||||
Server::setResource('logError', function (Registry $register, Document $project) {
|
||||
return function (Throwable $error, string $namespace, string $action, ?array $extras) use ($register, $project) {
|
||||
return function (Throwable $error, string $namespace, string $action, ?array $extras = null) use ($register, $project) {
|
||||
$logger = $register->get('logger');
|
||||
|
||||
if ($logger) {
|
||||
|
|
@ -387,7 +402,7 @@ Server::setResource('logError', function (Registry $register, Document $project)
|
|||
$log->addExtra('trace', $error->getTraceAsString());
|
||||
|
||||
|
||||
foreach ($extras as $key => $value) {
|
||||
foreach (($extras ?? []) as $key => $value) {
|
||||
$log->addExtra($key, $value);
|
||||
}
|
||||
|
||||
|
|
|
|||
3
bin/screenshot
Executable file
3
bin/screenshot
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
php /usr/src/code/app/cli.php screenshot $@
|
||||
|
|
@ -14,7 +14,8 @@
|
|||
"test": "vendor/bin/phpunit",
|
||||
"lint": "vendor/bin/pint --test",
|
||||
"format": "vendor/bin/pint",
|
||||
"bench": "vendor/bin/phpbench run --report=benchmark"
|
||||
"bench": "vendor/bin/phpbench run --report=benchmark",
|
||||
"check": "./vendor/bin/phpstan analyse -c phpstan.neon"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
@ -43,7 +44,7 @@
|
|||
"ext-openssl": "*",
|
||||
"ext-zlib": "*",
|
||||
"ext-sockets": "*",
|
||||
"appwrite/php-runtimes": "0.16.*",
|
||||
"appwrite/php-runtimes": "0.19.*",
|
||||
"appwrite/php-clamav": "2.0.*",
|
||||
"utopia-php/abuse": "0.52.*",
|
||||
"utopia-php/analytics": "0.10.*",
|
||||
|
|
@ -51,6 +52,7 @@
|
|||
"utopia-php/cache": "0.13.*",
|
||||
"utopia-php/cli": "0.15.*",
|
||||
"utopia-php/config": "0.2.*",
|
||||
"utopia-php/detector": "0.1.*",
|
||||
"utopia-php/database": "0.69.*",
|
||||
"utopia-php/domains": "0.5.*",
|
||||
"utopia-php/dsn": "0.2.1",
|
||||
|
|
@ -71,7 +73,7 @@
|
|||
"utopia-php/swoole": "0.8.*",
|
||||
"utopia-php/system": "0.9.*",
|
||||
"utopia-php/telemetry": "0.1.*",
|
||||
"utopia-php/vcs": "0.9.*",
|
||||
"utopia-php/vcs": "0.10.*",
|
||||
"utopia-php/websocket": "0.3.*",
|
||||
"matomo/device-detector": "6.1.*",
|
||||
"dragonmantank/cron-expression": "3.3.2",
|
||||
|
|
@ -87,6 +89,7 @@
|
|||
"appwrite/sdk-generator": "0.40.*",
|
||||
"phpunit/phpunit": "9.*",
|
||||
"swoole/ide-helper": "5.1.2",
|
||||
"phpstan/phpstan": "1.8.*",
|
||||
"textalk/websocket": "1.5.*",
|
||||
"laravel/pint": "1.*",
|
||||
"phpbench/phpbench": "1.*"
|
||||
|
|
|
|||
157
composer.lock
generated
157
composer.lock
generated
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "2c14e20244a06f508dd67cda717aefeb",
|
||||
"content-hash": "735023e2b70ce47fe65985f195b257bd",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/jwt",
|
||||
|
|
@ -157,16 +157,16 @@
|
|||
},
|
||||
{
|
||||
"name": "appwrite/php-runtimes",
|
||||
"version": "0.16.5",
|
||||
"version": "0.19.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/appwrite/runtimes.git",
|
||||
"reference": "1e430646fdf847a7caf3c611dcf3d6d5a28c3fd9"
|
||||
"reference": "8d21483efc19b9d977e323188989ee67a188464b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/appwrite/runtimes/zipball/1e430646fdf847a7caf3c611dcf3d6d5a28c3fd9",
|
||||
"reference": "1e430646fdf847a7caf3c611dcf3d6d5a28c3fd9",
|
||||
"url": "https://api.github.com/repos/appwrite/runtimes/zipball/8d21483efc19b9d977e323188989ee67a188464b",
|
||||
"reference": "8d21483efc19b9d977e323188989ee67a188464b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -206,9 +206,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/appwrite/runtimes/issues",
|
||||
"source": "https://github.com/appwrite/runtimes/tree/0.16.5"
|
||||
"source": "https://github.com/appwrite/runtimes/tree/0.19.0"
|
||||
},
|
||||
"time": "2024-11-25T15:17:06+00:00"
|
||||
"time": "2025-03-25T22:37:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "beberlei/assert",
|
||||
|
|
@ -3499,16 +3499,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/database",
|
||||
"version": "0.69.2",
|
||||
"version": "0.69.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/database.git",
|
||||
"reference": "60591ab073bb80bb9843338754b679bb8169e4ed"
|
||||
"reference": "4abe53609dfc23b2ea82884d12b149df6a8af2f5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/60591ab073bb80bb9843338754b679bb8169e4ed",
|
||||
"reference": "60591ab073bb80bb9843338754b679bb8169e4ed",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/4abe53609dfc23b2ea82884d12b149df6a8af2f5",
|
||||
"reference": "4abe53609dfc23b2ea82884d12b149df6a8af2f5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -3549,9 +3549,54 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/database/issues",
|
||||
"source": "https://github.com/utopia-php/database/tree/0.69.2"
|
||||
"source": "https://github.com/utopia-php/database/tree/0.69.5"
|
||||
},
|
||||
"time": "2025-05-14T07:51:44+00:00"
|
||||
"time": "2025-05-17T08:01:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/detector",
|
||||
"version": "0.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/detector.git",
|
||||
"reference": "895a4147463965b5f9cbc083b764b6476f547879"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/detector/zipball/895a4147463965b5f9cbc083b764b6476f547879",
|
||||
"reference": "895a4147463965b5f9cbc083b764b6476f547879",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "1.2.*",
|
||||
"phpstan/phpstan": "1.8.*",
|
||||
"phpunit/phpunit": "^9.4"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Utopia\\Detector\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "A simple library for fast and reliable environment identification.",
|
||||
"keywords": [
|
||||
"detector",
|
||||
"framework",
|
||||
"php",
|
||||
"utopia"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/detector/issues",
|
||||
"source": "https://github.com/utopia-php/detector/tree/0.1.4"
|
||||
},
|
||||
"time": "2025-04-09T11:50:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/domains",
|
||||
|
|
@ -4546,16 +4591,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/vcs",
|
||||
"version": "0.9.5",
|
||||
"version": "0.10.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/vcs.git",
|
||||
"reference": "055956545ca7ab4e8688df5de1df3e2833859793"
|
||||
"reference": "1f9823ebcb8fd098607de0074f18f48e28985012"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/vcs/zipball/055956545ca7ab4e8688df5de1df3e2833859793",
|
||||
"reference": "055956545ca7ab4e8688df5de1df3e2833859793",
|
||||
"url": "https://api.github.com/repos/utopia-php/vcs/zipball/1f9823ebcb8fd098607de0074f18f48e28985012",
|
||||
"reference": "1f9823ebcb8fd098607de0074f18f48e28985012",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -4573,8 +4618,7 @@
|
|||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Utopia\\VCS\\": "src/VCS",
|
||||
"Utopia\\Detector\\": "src/Detector"
|
||||
"Utopia\\VCS\\": "src/VCS"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
|
|
@ -4590,9 +4634,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/vcs/issues",
|
||||
"source": "https://github.com/utopia-php/vcs/tree/0.9.5"
|
||||
"source": "https://github.com/utopia-php/vcs/tree/0.10.2"
|
||||
},
|
||||
"time": "2025-04-17T04:38:49+00:00"
|
||||
"time": "2025-04-17T04:35:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/websocket",
|
||||
|
|
@ -4770,16 +4814,16 @@
|
|||
"packages-dev": [
|
||||
{
|
||||
"name": "appwrite/sdk-generator",
|
||||
"version": "0.40.16",
|
||||
"version": "0.40.17",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/appwrite/sdk-generator.git",
|
||||
"reference": "f1f506da74033f0cb5a11e3dffcfd1ee8daf237d"
|
||||
"reference": "7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/f1f506da74033f0cb5a11e3dffcfd1ee8daf237d",
|
||||
"reference": "f1f506da74033f0cb5a11e3dffcfd1ee8daf237d",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de",
|
||||
"reference": "7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -4815,9 +4859,9 @@
|
|||
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
|
||||
"support": {
|
||||
"issues": "https://github.com/appwrite/sdk-generator/issues",
|
||||
"source": "https://github.com/appwrite/sdk-generator/tree/0.40.16"
|
||||
"source": "https://github.com/appwrite/sdk-generator/tree/0.40.17"
|
||||
},
|
||||
"time": "2025-05-09T12:06:09+00:00"
|
||||
"time": "2025-05-16T15:10:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/annotations",
|
||||
|
|
@ -5617,6 +5661,65 @@
|
|||
],
|
||||
"time": "2025-03-12T08:01:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "1.8.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "46e223dd68a620da18855c23046ddb00940b4014"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/46e223dd68a620da18855c23046ddb00940b4014",
|
||||
"reference": "46e223dd68a620da18855c23046ddb00940b4014",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2|^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"phpstan/phpstan-shim": "*"
|
||||
},
|
||||
"bin": [
|
||||
"phpstan",
|
||||
"phpstan.phar"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "PHPStan - PHP Static Analysis Tool",
|
||||
"keywords": [
|
||||
"dev",
|
||||
"static analysis"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan/issues",
|
||||
"source": "https://github.com/phpstan/phpstan/tree/1.8.11"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/ondrejmirtes",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/phpstan",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-10-24T15:45:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "9.2.32",
|
||||
|
|
|
|||
|
|
@ -72,10 +72,13 @@ services:
|
|||
- traefik.http.routers.appwrite_api_https.tls=true
|
||||
volumes:
|
||||
- appwrite-uploads:/storage/uploads:rw
|
||||
- appwrite-imports:/storage/imports:rw
|
||||
- appwrite-cache:/storage/cache:rw
|
||||
- appwrite-config:/storage/config:rw
|
||||
- appwrite-certificates:/storage/certificates:rw
|
||||
- appwrite-functions:/storage/functions:rw
|
||||
- appwrite-sites:/storage/sites:rw
|
||||
- appwrite-builds:/storage/builds:rw
|
||||
- ./phpunit.xml:/usr/src/code/phpunit.xml
|
||||
- ./tests:/usr/src/code/tests
|
||||
- ./app:/usr/src/code/app
|
||||
|
|
@ -110,10 +113,12 @@ services:
|
|||
- _APP_OPTIONS_ABUSE
|
||||
- _APP_OPTIONS_ROUTER_PROTECTION
|
||||
- _APP_OPTIONS_FORCE_HTTPS
|
||||
- _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS
|
||||
- _APP_OPTIONS_ROUTER_FORCE_HTTPS
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET
|
||||
- _APP_DOMAIN_TARGET_CNAME
|
||||
- _APP_DOMAIN_TARGET_AAAA
|
||||
- _APP_DOMAIN_TARGET_A
|
||||
- _APP_DOMAIN_FUNCTIONS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
|
|
@ -157,12 +162,15 @@ services:
|
|||
- _APP_STORAGE_WASABI_SECRET
|
||||
- _APP_STORAGE_WASABI_REGION
|
||||
- _APP_STORAGE_WASABI_BUCKET
|
||||
- _APP_FUNCTIONS_SIZE_LIMIT
|
||||
- _APP_COMPUTE_SIZE_LIMIT
|
||||
- _APP_FUNCTIONS_TIMEOUT
|
||||
- _APP_FUNCTIONS_BUILD_TIMEOUT
|
||||
- _APP_FUNCTIONS_CPUS
|
||||
- _APP_FUNCTIONS_MEMORY
|
||||
- _APP_SITES_TIMEOUT
|
||||
- _APP_COMPUTE_BUILD_TIMEOUT
|
||||
- _APP_COMPUTE_CPUS
|
||||
- _APP_COMPUTE_MEMORY
|
||||
- _APP_FUNCTIONS_RUNTIMES
|
||||
- _APP_SITES_RUNTIMES
|
||||
- _APP_DOMAIN_SITES
|
||||
- _APP_EXECUTOR_SECRET
|
||||
- _APP_EXECUTOR_HOST
|
||||
- _APP_LOGGING_CONFIG
|
||||
|
|
@ -205,7 +213,7 @@ services:
|
|||
appwrite-console:
|
||||
<<: *x-logging
|
||||
container_name: appwrite-console
|
||||
image: appwrite/console:5.2.58
|
||||
image: appwrite/console:6.0.1
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
|
|
@ -348,6 +356,7 @@ services:
|
|||
- appwrite-uploads:/storage/uploads:rw
|
||||
- appwrite-cache:/storage/cache:rw
|
||||
- appwrite-functions:/storage/functions:rw
|
||||
- appwrite-sites:/storage/sites:rw
|
||||
- appwrite-builds:/storage/builds:rw
|
||||
- appwrite-certificates:/storage/certificates:rw
|
||||
- ./app:/usr/src/code/app
|
||||
|
|
@ -436,7 +445,9 @@ services:
|
|||
- appwrite
|
||||
volumes:
|
||||
- appwrite-functions:/storage/functions:rw
|
||||
- appwrite-sites:/storage/sites:rw
|
||||
- appwrite-builds:/storage/builds:rw
|
||||
- appwrite-uploads:/storage/uploads:rw
|
||||
- ./app:/usr/src/code/app
|
||||
- ./src:/usr/src/code/src
|
||||
depends_on:
|
||||
|
|
@ -462,12 +473,13 @@ services:
|
|||
- _APP_VCS_GITHUB_PRIVATE_KEY
|
||||
- _APP_VCS_GITHUB_APP_ID
|
||||
- _APP_FUNCTIONS_TIMEOUT
|
||||
- _APP_FUNCTIONS_BUILD_TIMEOUT
|
||||
- _APP_FUNCTIONS_CPUS
|
||||
- _APP_FUNCTIONS_MEMORY
|
||||
- _APP_FUNCTIONS_SIZE_LIMIT
|
||||
- _APP_SITES_TIMEOUT
|
||||
- _APP_COMPUTE_BUILD_TIMEOUT
|
||||
- _APP_COMPUTE_CPUS
|
||||
- _APP_COMPUTE_MEMORY
|
||||
- _APP_COMPUTE_SIZE_LIMIT
|
||||
- _APP_OPTIONS_FORCE_HTTPS
|
||||
- _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS
|
||||
- _APP_OPTIONS_ROUTER_FORCE_HTTPS
|
||||
- _APP_DOMAIN
|
||||
- _APP_STORAGE_DEVICE
|
||||
- _APP_STORAGE_S3_ACCESS_KEY
|
||||
|
|
@ -492,6 +504,7 @@ services:
|
|||
- _APP_STORAGE_WASABI_REGION
|
||||
- _APP_STORAGE_WASABI_BUCKET
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
- _APP_DOMAIN_SITES
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
|
||||
|
|
@ -515,7 +528,9 @@ services:
|
|||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET
|
||||
- _APP_DOMAIN_TARGET_CNAME
|
||||
- _APP_DOMAIN_TARGET_AAAA
|
||||
- _APP_DOMAIN_TARGET_A
|
||||
- _APP_DOMAIN_FUNCTIONS
|
||||
- _APP_EMAIL_CERTIFICATES
|
||||
- _APP_REDIS_HOST
|
||||
|
|
@ -560,9 +575,10 @@ services:
|
|||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_FUNCTIONS_TIMEOUT
|
||||
- _APP_FUNCTIONS_BUILD_TIMEOUT
|
||||
- _APP_FUNCTIONS_CPUS
|
||||
- _APP_FUNCTIONS_MEMORY
|
||||
- _APP_SITES_TIMEOUT
|
||||
- _APP_COMPUTE_BUILD_TIMEOUT
|
||||
- _APP_COMPUTE_CPUS
|
||||
- _APP_COMPUTE_MEMORY
|
||||
- _APP_EXECUTOR_SECRET
|
||||
- _APP_EXECUTOR_HOST
|
||||
- _APP_USAGE_STATS
|
||||
|
|
@ -670,6 +686,7 @@ services:
|
|||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- appwrite-imports:/storage/imports:rw
|
||||
- ./app:/usr/src/code/app
|
||||
- ./src:/usr/src/code/src
|
||||
- ./tests:/usr/src/code/tests
|
||||
|
|
@ -680,7 +697,9 @@ services:
|
|||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET
|
||||
- _APP_DOMAIN_TARGET_CNAME
|
||||
- _APP_DOMAIN_TARGET_AAAA
|
||||
- _APP_DOMAIN_TARGET_A
|
||||
- _APP_EMAIL_SECURITY
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
|
|
@ -712,7 +731,9 @@ services:
|
|||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET
|
||||
- _APP_DOMAIN_TARGET_CNAME
|
||||
- _APP_DOMAIN_TARGET_AAAA
|
||||
- _APP_DOMAIN_TARGET_A
|
||||
- _APP_DOMAIN_FUNCTIONS
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
|
|
@ -919,12 +940,18 @@ services:
|
|||
environment:
|
||||
- _APP_ASSISTANT_OPENAI_API_KEY
|
||||
|
||||
appwrite-browser:
|
||||
container_name: appwrite-browser
|
||||
image: appwrite/browser:0.2.4
|
||||
networks:
|
||||
- appwrite
|
||||
|
||||
openruntimes-executor:
|
||||
container_name: openruntimes-executor
|
||||
hostname: exc1
|
||||
<<: *x-logging
|
||||
stop_signal: SIGINT
|
||||
image: openruntimes/executor:0.6.11
|
||||
image: openruntimes/executor:0.7.14
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
|
|
@ -933,19 +960,21 @@ services:
|
|||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- appwrite-builds:/storage/builds:rw
|
||||
- appwrite-functions:/storage/functions:rw
|
||||
- appwrite-sites:/storage/sites:rw
|
||||
# Host mount nessessary to share files between executor and runtimes.
|
||||
# It's not possible to share mount file between 2 containers without host mount (copying is too slow)
|
||||
- /tmp:/tmp:rw
|
||||
environment:
|
||||
- OPR_EXECUTOR_INACTIVE_TRESHOLD=$_APP_FUNCTIONS_INACTIVE_THRESHOLD
|
||||
- OPR_EXECUTOR_MAINTENANCE_INTERVAL=$_APP_FUNCTIONS_MAINTENANCE_INTERVAL
|
||||
- OPR_EXECUTOR_NETWORK=$_APP_FUNCTIONS_RUNTIMES_NETWORK
|
||||
- OPR_EXECUTOR_IMAGE_PULL=enabled
|
||||
- OPR_EXECUTOR_INACTIVE_TRESHOLD=$_APP_COMPUTE_INACTIVE_THRESHOLD
|
||||
- OPR_EXECUTOR_MAINTENANCE_INTERVAL=$_APP_COMPUTE_MAINTENANCE_INTERVAL
|
||||
- OPR_EXECUTOR_NETWORK=$_APP_COMPUTE_RUNTIMES_NETWORK
|
||||
- OPR_EXECUTOR_DOCKER_HUB_USERNAME=$_APP_DOCKER_HUB_USERNAME
|
||||
- OPR_EXECUTOR_DOCKER_HUB_PASSWORD=$_APP_DOCKER_HUB_PASSWORD
|
||||
- OPR_EXECUTOR_ENV=$_APP_ENV
|
||||
- OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES
|
||||
- OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES,$_APP_SITES_RUNTIMES
|
||||
- OPR_EXECUTOR_SECRET=$_APP_EXECUTOR_SECRET
|
||||
- OPR_EXECUTOR_RUNTIME_VERSIONS=v2,v4
|
||||
- OPR_EXECUTOR_RUNTIME_VERSIONS=v2,v5
|
||||
- OPR_EXECUTOR_LOGGING_CONFIG=$_APP_LOGGING_CONFIG
|
||||
- OPR_EXECUTOR_STORAGE_DEVICE=$_APP_STORAGE_DEVICE
|
||||
- OPR_EXECUTOR_STORAGE_S3_ACCESS_KEY=$_APP_STORAGE_S3_ACCESS_KEY
|
||||
|
|
@ -1101,7 +1130,9 @@ volumes:
|
|||
appwrite-redis:
|
||||
appwrite-cache:
|
||||
appwrite-uploads:
|
||||
appwrite-imports:
|
||||
appwrite-certificates:
|
||||
appwrite-functions:
|
||||
appwrite-sites:
|
||||
appwrite-builds:
|
||||
appwrite-config:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.createAnonymousSession(new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
}));
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.createEmailPasswordSession(
|
||||
"email@example.com", // email
|
||||
"password", // password
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.createEmailToken(
|
||||
"<USER_ID>", // userId
|
||||
"email@example.com", // email
|
||||
false, // phrase (optional)
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.createJWT(new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
}));
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.createMagicURLToken(
|
||||
"<USER_ID>", // userId
|
||||
"email@example.com", // email
|
||||
"https://example.com", // url (optional)
|
||||
false, // phrase (optional)
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
import io.appwrite.enums.AuthenticatorType;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.createMfaAuthenticator(
|
||||
AuthenticatorType.TOTP, // type
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
import io.appwrite.enums.AuthenticationFactor;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.createMfaChallenge(
|
||||
AuthenticationFactor.EMAIL, // factor
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.createMfaRecoveryCodes(new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
}));
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
import io.appwrite.enums.OAuthProvider;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.createOAuth2Session(
|
||||
OAuthProvider.AMAZON, // provider
|
||||
"https://example.com", // success (optional)
|
||||
"https://example.com", // failure (optional)
|
||||
listOf(), // scopes (optional)
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
import io.appwrite.enums.OAuthProvider;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.createOAuth2Token(
|
||||
OAuthProvider.AMAZON, // provider
|
||||
"https://example.com", // success (optional)
|
||||
"https://example.com", // failure (optional)
|
||||
listOf(), // scopes (optional)
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.createPhoneToken(
|
||||
"<USER_ID>", // userId
|
||||
"+12065550100", // phone
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.createPhoneVerification(new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
}));
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.createPushTarget(
|
||||
"<TARGET_ID>", // targetId
|
||||
"<IDENTIFIER>", // identifier
|
||||
"<PROVIDER_ID>", // providerId (optional)
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.createRecovery(
|
||||
"email@example.com", // email
|
||||
"https://example.com", // url
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.createSession(
|
||||
"<USER_ID>", // userId
|
||||
"<SECRET>", // secret
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.createVerification(
|
||||
"https://example.com", // url
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
})
|
||||
);
|
||||
|
||||
25
docs/examples/1.7.x/client-android/java/account/create.md
Normal file
25
docs/examples/1.7.x/client-android/java/account/create.md
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.create(
|
||||
"<USER_ID>", // userId
|
||||
"email@example.com", // email
|
||||
"", // password
|
||||
"<NAME>", // name (optional)
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.deleteIdentity(
|
||||
"<IDENTITY_ID>", // identityId
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
import io.appwrite.enums.AuthenticatorType;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.deleteMfaAuthenticator(
|
||||
AuthenticatorType.TOTP, // type
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.deletePushTarget(
|
||||
"<TARGET_ID>", // targetId
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.deleteSession(
|
||||
"<SESSION_ID>", // sessionId
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.deleteSessions(new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
}));
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.getMfaRecoveryCodes(new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
}));
|
||||
18
docs/examples/1.7.x/client-android/java/account/get-prefs.md
Normal file
18
docs/examples/1.7.x/client-android/java/account/get-prefs.md
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.getPrefs(new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
}));
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import io.appwrite.Client;
|
||||
import io.appwrite.coroutines.CoroutineCallback;
|
||||
import io.appwrite.services.Account;
|
||||
|
||||
Client client = new Client(context)
|
||||
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
|
||||
.setProject("<YOUR_PROJECT_ID>"); // Your project ID
|
||||
|
||||
Account account = new Account(client);
|
||||
|
||||
account.getSession(
|
||||
"<SESSION_ID>", // sessionId
|
||||
new CoroutineCallback<>((result, error) -> {
|
||||
if (error != null) {
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("Appwrite", result.toString());
|
||||
})
|
||||
);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue