Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2b0eeaadc | ||
|
|
1db94afdd9 | ||
|
|
12733f5c0e | ||
|
|
24aa8b33f8 | ||
|
|
3f039cdb40 | ||
|
|
9c8ca51d7b |
@@ -1,11 +1,7 @@
|
||||
reviews:
|
||||
path_filters:
|
||||
- "!app/config/specs/**"
|
||||
- "!docs/examples/**"
|
||||
- "!docs/references/**"
|
||||
- "!docs/sdks/**"
|
||||
auto_review:
|
||||
base_branches:
|
||||
- main
|
||||
- 1.6.x
|
||||
- 1.7.x
|
||||
- 1.7.x
|
||||
- feat-sites # temporary until merged to 1.7.x
|
||||
@@ -18,14 +18,12 @@ _APP_SYSTEM_RESPONSE_FORMAT=
|
||||
_APP_OPTIONS_ABUSE=disabled
|
||||
_APP_OPTIONS_ROUTER_PROTECTION=disabled
|
||||
_APP_OPTIONS_FORCE_HTTPS=disabled
|
||||
_APP_OPTIONS_ROUTER_FORCE_HTTPS=disabled
|
||||
_APP_OPTIONS_COMPUTE_FORCE_HTTPS=disabled
|
||||
_APP_OPENSSL_KEY_V1=your-secret-key
|
||||
_APP_DOMAIN=traefik
|
||||
_APP_DOMAIN_FUNCTIONS=functions.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_DOMAIN_TARGET=test.appwrite.io
|
||||
_APP_RULES_FORMAT=md5
|
||||
_APP_REDIS_HOST=redis
|
||||
_APP_REDIS_PORT=6379
|
||||
@@ -73,8 +71,7 @@ _APP_SMS_PROJECTS_DENY_LIST=
|
||||
_APP_STORAGE_LIMIT=30000000
|
||||
_APP_STORAGE_PREVIEW_LIMIT=20000000
|
||||
_APP_COMPUTE_SIZE_LIMIT=30000000
|
||||
_APP_FUNCTIONS_TIMEOUT=900
|
||||
_APP_SITES_TIMEOUT=30
|
||||
_APP_COMPUTE_TIMEOUT=900
|
||||
_APP_COMPUTE_BUILD_TIMEOUT=900
|
||||
_APP_COMPUTE_CPUS=8
|
||||
_APP_COMPUTE_MEMORY=8192
|
||||
@@ -91,9 +88,8 @@ _APP_MAINTENANCE_RETENTION_CACHE=2592000
|
||||
_APP_MAINTENANCE_RETENTION_EXECUTION=1209600
|
||||
_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=30
|
||||
_APP_STATS_RESOURCES_INTERVAL=3600
|
||||
_APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000
|
||||
_APP_MAINTENANCE_RETENTION_SCHEDULES=86400
|
||||
_APP_USAGE_STATS=enabled
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
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
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Cleanup
|
||||
run: |
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 2
|
||||
submodules: recursive
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
|
||||
@@ -8,7 +8,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Run CodeQL
|
||||
run: |
|
||||
|
||||
@@ -197,7 +197,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 --exclude=devKeys
|
||||
appwrite test /usr/src/code/tests/e2e/Services/${{ matrix.service }} --debug
|
||||
|
||||
e2e_shared_mode_test:
|
||||
name: E2E Shared Mode Service Test
|
||||
@@ -228,8 +228,7 @@ jobs:
|
||||
Webhooks,
|
||||
VCS,
|
||||
Messaging,
|
||||
Migrations,
|
||||
Tokens
|
||||
Migrations
|
||||
]
|
||||
tables-mode: [
|
||||
'Shared V1',
|
||||
@@ -276,86 +275,86 @@ 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 --exclude=devKeys
|
||||
appwrite test /usr/src/code/tests/e2e/Services/${{ matrix.service }} --debug
|
||||
|
||||
e2e_dev_keys:
|
||||
name: E2E Service Test (Dev Keys)
|
||||
benchmarking:
|
||||
name: Benchmark
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
strategy:
|
||||
fail-fast: false
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: checkout
|
||||
- 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: |
|
||||
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||
sed -i 's/_APP_OPTIONS_ABUSE=disabled/_APP_OPTIONS_ABUSE=enabled/' .env
|
||||
sed -i 's/traefik/localhost/g' .env
|
||||
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||
docker compose up -d
|
||||
sleep 30
|
||||
|
||||
- name: Run Projects tests with dev keys in ${{ matrix.tables-mode }} table mode
|
||||
sleep 10
|
||||
- name: Install Oha
|
||||
run: |
|
||||
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
|
||||
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 compose.yml
|
||||
rm .env
|
||||
curl https://appwrite.io/install/compose -o 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:
|
||||
key: ${{ env.CACHE_KEY }}
|
||||
path: /tmp/${{ env.IMAGE }}.tar
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: Load and Start Appwrite
|
||||
run: |
|
||||
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||
sed -i 's/_APP_OPTIONS_ABUSE=disabled/_APP_OPTIONS_ABUSE=enabled/' .env
|
||||
docker compose up -d
|
||||
sleep 30
|
||||
|
||||
- name: Run Projects tests with dev keys in ${{ matrix.tables-mode }} table mode
|
||||
run: |
|
||||
if [ "${{ matrix.tables-mode }}" == "Shared V1" ]; then
|
||||
echo "Using shared tables V1"
|
||||
export _APP_DATABASE_SHARED_TABLES=database_db_main
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=database_db_main
|
||||
elif [ "${{ matrix.tables-mode }}" == "Shared V2" ]; then
|
||||
echo "Using shared tables V2"
|
||||
export _APP_DATABASE_SHARED_TABLES=database_db_main
|
||||
export _APP_DATABASE_SHARED_TABLES_V1=
|
||||
fi
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
@@ -7,7 +7,6 @@ tasks:
|
||||
docker pull composer
|
||||
command: |
|
||||
docker run --rm --interactive --tty \
|
||||
--user "$(id -u):$(id -g)" \
|
||||
--volume $PWD:/app \
|
||||
composer install \
|
||||
--ignore-platform-reqs \
|
||||
@@ -24,3 +23,11 @@ vscode:
|
||||
extensions:
|
||||
- ms-azuretools.vscode-docker
|
||||
- zobo.php-intellisense
|
||||
|
||||
github:
|
||||
# https://www.gitpod.io/docs/prebuilds#github-specific-configuration
|
||||
prebuilds:
|
||||
# enable for pull requests coming from forks (defaults to false)
|
||||
pullRequestsFromForks: true
|
||||
# add a check to pull requests (defaults to true)
|
||||
addCheck: false
|
||||
|
||||
@@ -44,14 +44,12 @@ 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 && \
|
||||
|
||||
@@ -9,7 +9,6 @@ use Appwrite\Event\StatsResources;
|
||||
use Appwrite\Event\StatsUsage;
|
||||
use Appwrite\Platform\Appwrite;
|
||||
use Appwrite\Runtimes\Runtimes;
|
||||
use Executor\Executor;
|
||||
use Utopia\Cache\Adapter\Sharding;
|
||||
use Utopia\Cache\Cache;
|
||||
use Utopia\CLI\CLI;
|
||||
@@ -256,8 +255,6 @@ CLI::setResource('logError', function (Registry $register) {
|
||||
};
|
||||
}, ['register']);
|
||||
|
||||
CLI::setResource('executor', fn () => new Executor(fn (string $projectId, string $deploymentId) => System::getEnv('_APP_EXECUTOR_HOST')));
|
||||
|
||||
$platform = new Appwrite();
|
||||
$platform->init(Service::TYPE_TASK);
|
||||
|
||||
|
||||
@@ -1038,7 +1038,7 @@ return [
|
||||
'$id' => ID::custom('providerUid'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 2048, // Decrease to 128 as in index length?
|
||||
'size' => 2048,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
@@ -1107,14 +1107,14 @@ return [
|
||||
'$id' => ID::custom('_key_userInternalId_provider_providerUid'),
|
||||
'type' => Database::INDEX_UNIQUE,
|
||||
'attributes' => ['userInternalId', 'provider', 'providerUid'],
|
||||
'lengths' => [11, 128, 128], // providerUid is length 2000!
|
||||
'lengths' => [11, 128, 128],
|
||||
'orders' => [Database::ORDER_ASC, Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('_key_provider_providerUid'),
|
||||
'type' => Database::INDEX_UNIQUE,
|
||||
'attributes' => ['provider', 'providerUid'],
|
||||
'lengths' => [128, 128], // providerUid is length 2000!
|
||||
'lengths' => [128, 128],
|
||||
'orders' => [Database::ORDER_ASC, Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
|
||||
@@ -287,17 +287,6 @@ 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,
|
||||
@@ -700,125 +689,6 @@ 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' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('search'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 16384,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'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' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('_key_search'),
|
||||
'type' => Database::INDEX_FULLTEXT,
|
||||
'attributes' => ['search'],
|
||||
'lengths' => [],
|
||||
'orders' => [],
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
'webhooks' => [
|
||||
'$collection' => ID::custom(Database::METADATA),
|
||||
'$id' => ID::custom('webhooks'),
|
||||
|
||||
@@ -1202,7 +1202,7 @@ return [
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('adapter'), // ssr or static; named this way as it's a term in SSR frameworks
|
||||
'$id' => ID::custom('adapter'), // ssr or static
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 128,
|
||||
@@ -1727,7 +1727,7 @@ return [
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('adapter'), // ssr or static; named this way as it's a term in SSR frameworks
|
||||
'$id' => ID::custom('adapter'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 128,
|
||||
@@ -2275,17 +2275,6 @@ return [
|
||||
'array' => false,
|
||||
'filters' => ['json', 'encrypt'],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('options'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 65536,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => [],
|
||||
'array' => false,
|
||||
'filters' => ['json'],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('resources'),
|
||||
'type' => Database::VAR_STRING,
|
||||
@@ -2340,29 +2329,7 @@ return [
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('resourceId'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('resourceType'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
]
|
||||
],
|
||||
'indexes' => [
|
||||
[
|
||||
@@ -2386,13 +2353,6 @@ return [
|
||||
'lengths' => [Database::LENGTH_KEY],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => '_key_resource_id',
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['resourceId'],
|
||||
'lengths' => [Database::LENGTH_KEY],
|
||||
'orders' => [Database::ORDER_DESC],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('_fulltext_search'),
|
||||
'type' => Database::INDEX_FULLTEXT,
|
||||
@@ -2402,77 +2362,4 @@ return [
|
||||
]
|
||||
],
|
||||
],
|
||||
|
||||
'resourceTokens' => [
|
||||
'$collection' => ID::custom(Database::METADATA),
|
||||
'$id' => ID::custom('resourceTokens'),
|
||||
'name' => 'Resource Tokens',
|
||||
'attributes' => [
|
||||
[
|
||||
'$id' => ID::custom('resourceId'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('resourceInternalId'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
'signed' => true,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('resourceType'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 100,
|
||||
'signed' => true,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('secret'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 512,
|
||||
'signed' => true,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => ['encrypt'],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('expire'),
|
||||
'type' => Database::VAR_DATETIME,
|
||||
'format' => '',
|
||||
'size' => 255,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
]
|
||||
],
|
||||
'indexes' => [
|
||||
[
|
||||
'$id' => '_key_expiry_date',
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['expire'],
|
||||
'lengths' => [],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
@@ -488,18 +488,6 @@ 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,
|
||||
],
|
||||
|
||||
/** VCS */
|
||||
Exception::INSTALLATION_NOT_FOUND => [
|
||||
'name' => Exception::INSTALLATION_NOT_FOUND,
|
||||
@@ -558,11 +546,6 @@ return [
|
||||
'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 => [
|
||||
@@ -597,11 +580,6 @@ 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.',
|
||||
|
||||
@@ -81,8 +81,6 @@ $admins = [
|
||||
'topics.read',
|
||||
'subscribers.write',
|
||||
'subscribers.read',
|
||||
'tokens.read',
|
||||
'tokens.write',
|
||||
];
|
||||
|
||||
return [
|
||||
|
||||
@@ -142,10 +142,4 @@ 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',
|
||||
],
|
||||
];
|
||||
|
||||
@@ -184,7 +184,7 @@ return [
|
||||
'docsUrl' => 'https://appwrite.io/docs/sites',
|
||||
'tests' => false,
|
||||
'optional' => true,
|
||||
'icon' => '/images/services/sites.png',
|
||||
'icon' => '', // TODO: Update icon later
|
||||
],
|
||||
'functions' => [
|
||||
'key' => 'functions',
|
||||
|
||||
@@ -4748,7 +4748,7 @@
|
||||
"tags": [
|
||||
"functions"
|
||||
],
|
||||
"description": "Get a list of all the current user function execution logs. You can use the query params to filter your results.",
|
||||
"description": "",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Executions List",
|
||||
@@ -4763,7 +4763,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "listExecutions",
|
||||
"weight": 384,
|
||||
"weight": 383,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -4822,7 +4822,7 @@
|
||||
"tags": [
|
||||
"functions"
|
||||
],
|
||||
"description": "Trigger 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.",
|
||||
"description": "",
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Execution",
|
||||
@@ -4837,7 +4837,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "createExecution",
|
||||
"weight": 382,
|
||||
"weight": 381,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -4936,7 +4936,7 @@
|
||||
"tags": [
|
||||
"functions"
|
||||
],
|
||||
"description": "Get a function execution log by its unique ID.",
|
||||
"description": "",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Execution",
|
||||
@@ -4951,7 +4951,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "getExecution",
|
||||
"weight": 383,
|
||||
"weight": 382,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -5534,7 +5534,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "createSubscriber",
|
||||
"weight": 349,
|
||||
"weight": 348,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -5616,7 +5616,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "deleteSubscriber",
|
||||
"weight": 353,
|
||||
"weight": 352,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -7448,451 +7448,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"\/tokens\/buckets\/{bucketId}\/files\/{fileId}": {
|
||||
"get": {
|
||||
"summary": "List tokens",
|
||||
"operationId": "tokensList",
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "List all the tokens created for a specific file or bucket. You can use the query params to filter your results.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Resource Tokens List",
|
||||
"content": {
|
||||
"application\/json": {
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/resourceTokenList"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "list",
|
||||
"weight": 432,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/list.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList all the tokens created for a specific file or bucket. You can use the query params to filter your results.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
"scope": "tokens.read",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "bucketId",
|
||||
"description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<BUCKET_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"name": "fileId",
|
||||
"description": "File unique ID.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<FILE_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"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: expire",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"default": []
|
||||
},
|
||||
"in": "query"
|
||||
}
|
||||
]
|
||||
},
|
||||
"post": {
|
||||
"summary": "Create file token",
|
||||
"operationId": "tokensCreateFileToken",
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Create a new token. A token is linked to a file or a bucket and manages permissions for those file(s). Token can be passed as a header or request get parameter.",
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "ResourceToken",
|
||||
"content": {
|
||||
"application\/json": {
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/resourceToken"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "createFileToken",
|
||||
"weight": 429,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/create-file-token.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file or a bucket and manages permissions for those file(s). Token can be passed as a header or request get parameter.",
|
||||
"rate-limit": 60,
|
||||
"rate-time": 60,
|
||||
"rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}",
|
||||
"scope": "tokens.write",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "bucketId",
|
||||
"description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<BUCKET_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"name": "fileId",
|
||||
"description": "File unique ID.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<FILE_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application\/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"expire": {
|
||||
"type": "string",
|
||||
"description": "Token expiry date",
|
||||
"x-example": null,
|
||||
"x-nullable": true
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"description": "An array of permission strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
|
||||
"x-example": "[\"read(\"any\")\"]",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"\/tokens\/{tokenId}": {
|
||||
"get": {
|
||||
"summary": "Get token",
|
||||
"operationId": "tokensGet",
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Get a token by its unique ID.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "ResourceToken",
|
||||
"content": {
|
||||
"application\/json": {
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/resourceToken"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"weight": 430,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/get.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a token by its unique ID.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
"scope": "tokens.read",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tokenId",
|
||||
"description": "Token ID.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
}
|
||||
]
|
||||
},
|
||||
"patch": {
|
||||
"summary": "Update token",
|
||||
"operationId": "tokensUpdate",
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Update a token by its unique ID. Use this endpoint to update a token's expiry date or permissions.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "ResourceToken",
|
||||
"content": {
|
||||
"application\/json": {
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/resourceToken"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "update",
|
||||
"weight": 433,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/update.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate a token by its unique ID. Use this endpoint to update a token's expiry date or permissions.",
|
||||
"rate-limit": 60,
|
||||
"rate-time": 60,
|
||||
"rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}",
|
||||
"scope": "tokens.write",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tokenId",
|
||||
"description": "Token unique ID.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application\/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"expire": {
|
||||
"type": "string",
|
||||
"description": "File token expiry date",
|
||||
"x-example": null,
|
||||
"x-nullable": true
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"description": "An array of permission string. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
|
||||
"x-example": "[\"read(\"any\")\"]",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"summary": "Delete token",
|
||||
"operationId": "tokensDelete",
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Delete a token by its unique ID.",
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No content"
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "delete",
|
||||
"weight": 434,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/delete.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a token by its unique ID.",
|
||||
"rate-limit": 60,
|
||||
"rate-time": 60,
|
||||
"rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}",
|
||||
"scope": "tokens.write",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tokenId",
|
||||
"description": "Token ID.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"\/tokens\/{tokenId}\/jwt": {
|
||||
"get": {
|
||||
"summary": "Get token as JWT",
|
||||
"operationId": "tokensGetJWT",
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Get a JWT based token by its unique ID. You can use the JWT to authenticate on behalf of the user.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "JWT",
|
||||
"content": {
|
||||
"application\/json": {
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/jwt"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "getJWT",
|
||||
"weight": 431,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/get-j-w-t.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a JWT based token by its unique ID. You can use the JWT to authenticate on behalf of the user.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
"scope": "tokens.read",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tokenId",
|
||||
"description": "File token ID.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
@@ -8143,30 +7698,6 @@
|
||||
"files"
|
||||
]
|
||||
},
|
||||
"resourceTokenList": {
|
||||
"description": "Resource Tokens List",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"total": {
|
||||
"type": "integer",
|
||||
"description": "Total number of tokens documents that matched your query.",
|
||||
"x-example": 5,
|
||||
"format": "int32"
|
||||
},
|
||||
"tokens": {
|
||||
"type": "array",
|
||||
"description": "List of tokens.",
|
||||
"items": {
|
||||
"$ref": "#\/components\/schemas\/resourceToken"
|
||||
},
|
||||
"x-example": ""
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"total",
|
||||
"tokens"
|
||||
]
|
||||
},
|
||||
"teamList": {
|
||||
"description": "Teams List",
|
||||
"type": "object",
|
||||
@@ -9363,50 +8894,6 @@
|
||||
"chunksUploaded"
|
||||
]
|
||||
},
|
||||
"resourceToken": {
|
||||
"description": "ResourceToken",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"$id": {
|
||||
"type": "string",
|
||||
"description": "Token ID.",
|
||||
"x-example": "bb8ea5c16897e"
|
||||
},
|
||||
"$createdAt": {
|
||||
"type": "string",
|
||||
"description": "Token creation date in ISO 8601 format.",
|
||||
"x-example": "2020-10-15T06:38:00.000+00:00"
|
||||
},
|
||||
"resourceId": {
|
||||
"type": "string",
|
||||
"description": "Resource ID.",
|
||||
"x-example": "5e5ea5c168bb8:5e5ea5c168bb8"
|
||||
},
|
||||
"resourceInternalId": {
|
||||
"type": "string",
|
||||
"description": "File ID.",
|
||||
"x-example": "1:1"
|
||||
},
|
||||
"resourceType": {
|
||||
"type": "string",
|
||||
"description": "Resource type.",
|
||||
"x-example": "file"
|
||||
},
|
||||
"expire": {
|
||||
"type": "string",
|
||||
"description": "Token expiration date in ISO 8601 format.",
|
||||
"x-example": "2020-10-15T06:38:00.000+00:00"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"$id",
|
||||
"$createdAt",
|
||||
"resourceId",
|
||||
"resourceInternalId",
|
||||
"resourceType",
|
||||
"expire"
|
||||
]
|
||||
},
|
||||
"team": {
|
||||
"description": "Team",
|
||||
"type": "object",
|
||||
|
||||
@@ -4748,7 +4748,7 @@
|
||||
"tags": [
|
||||
"functions"
|
||||
],
|
||||
"description": "Get a list of all the current user function execution logs. You can use the query params to filter your results.",
|
||||
"description": "",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Executions List",
|
||||
@@ -4763,7 +4763,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "listExecutions",
|
||||
"weight": 389,
|
||||
"weight": 383,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -4822,7 +4822,7 @@
|
||||
"tags": [
|
||||
"functions"
|
||||
],
|
||||
"description": "Trigger 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.",
|
||||
"description": "",
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Execution",
|
||||
@@ -4837,7 +4837,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "createExecution",
|
||||
"weight": 387,
|
||||
"weight": 381,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -4936,7 +4936,7 @@
|
||||
"tags": [
|
||||
"functions"
|
||||
],
|
||||
"description": "Get a function execution log by its unique ID.",
|
||||
"description": "",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Execution",
|
||||
@@ -4951,7 +4951,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "getExecution",
|
||||
"weight": 388,
|
||||
"weight": 382,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -5534,7 +5534,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "createSubscriber",
|
||||
"weight": 349,
|
||||
"weight": 348,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -5616,7 +5616,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "deleteSubscriber",
|
||||
"weight": 353,
|
||||
"weight": 352,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -7448,451 +7448,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"\/tokens\/buckets\/{bucketId}\/files\/{fileId}": {
|
||||
"get": {
|
||||
"summary": "List tokens",
|
||||
"operationId": "tokensList",
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "List all the tokens created for a specific file or bucket. You can use the query params to filter your results.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Resource Tokens List",
|
||||
"content": {
|
||||
"application\/json": {
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/resourceTokenList"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "list",
|
||||
"weight": 432,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/list.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList all the tokens created for a specific file or bucket. You can use the query params to filter your results.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
"scope": "tokens.read",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "bucketId",
|
||||
"description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<BUCKET_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"name": "fileId",
|
||||
"description": "File unique ID.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<FILE_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"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: expire",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"default": []
|
||||
},
|
||||
"in": "query"
|
||||
}
|
||||
]
|
||||
},
|
||||
"post": {
|
||||
"summary": "Create file token",
|
||||
"operationId": "tokensCreateFileToken",
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Create a new token. A token is linked to a file or a bucket and manages permissions for those file(s). Token can be passed as a header or request get parameter.",
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "ResourceToken",
|
||||
"content": {
|
||||
"application\/json": {
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/resourceToken"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "createFileToken",
|
||||
"weight": 429,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/create-file-token.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file or a bucket and manages permissions for those file(s). Token can be passed as a header or request get parameter.",
|
||||
"rate-limit": 60,
|
||||
"rate-time": 60,
|
||||
"rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}",
|
||||
"scope": "tokens.write",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "bucketId",
|
||||
"description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<BUCKET_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"name": "fileId",
|
||||
"description": "File unique ID.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<FILE_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application\/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"expire": {
|
||||
"type": "string",
|
||||
"description": "Token expiry date",
|
||||
"x-example": null,
|
||||
"x-nullable": true
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"description": "An array of permission strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
|
||||
"x-example": "[\"read(\"any\")\"]",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"\/tokens\/{tokenId}": {
|
||||
"get": {
|
||||
"summary": "Get token",
|
||||
"operationId": "tokensGet",
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Get a token by its unique ID.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "ResourceToken",
|
||||
"content": {
|
||||
"application\/json": {
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/resourceToken"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"weight": 430,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/get.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a token by its unique ID.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
"scope": "tokens.read",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tokenId",
|
||||
"description": "Token ID.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
}
|
||||
]
|
||||
},
|
||||
"patch": {
|
||||
"summary": "Update token",
|
||||
"operationId": "tokensUpdate",
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Update a token by its unique ID. Use this endpoint to update a token's expiry date or permissions.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "ResourceToken",
|
||||
"content": {
|
||||
"application\/json": {
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/resourceToken"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "update",
|
||||
"weight": 433,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/update.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate a token by its unique ID. Use this endpoint to update a token's expiry date or permissions.",
|
||||
"rate-limit": 60,
|
||||
"rate-time": 60,
|
||||
"rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}",
|
||||
"scope": "tokens.write",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tokenId",
|
||||
"description": "Token unique ID.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application\/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"expire": {
|
||||
"type": "string",
|
||||
"description": "File token expiry date",
|
||||
"x-example": null,
|
||||
"x-nullable": true
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"description": "An array of permission string. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
|
||||
"x-example": "[\"read(\"any\")\"]",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"summary": "Delete token",
|
||||
"operationId": "tokensDelete",
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Delete a token by its unique ID.",
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No content"
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "delete",
|
||||
"weight": 434,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/delete.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a token by its unique ID.",
|
||||
"rate-limit": 60,
|
||||
"rate-time": 60,
|
||||
"rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}",
|
||||
"scope": "tokens.write",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tokenId",
|
||||
"description": "Token ID.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"\/tokens\/{tokenId}\/jwt": {
|
||||
"get": {
|
||||
"summary": "Get token as JWT",
|
||||
"operationId": "tokensGetJWT",
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Get a JWT based token by its unique ID. You can use the JWT to authenticate on behalf of the user.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "JWT",
|
||||
"content": {
|
||||
"application\/json": {
|
||||
"schema": {
|
||||
"$ref": "#\/components\/schemas\/jwt"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "getJWT",
|
||||
"weight": 431,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/get-j-w-t.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a JWT based token by its unique ID. You can use the JWT to authenticate on behalf of the user.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
"scope": "tokens.read",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tokenId",
|
||||
"description": "File token ID.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN_ID>"
|
||||
},
|
||||
"in": "path"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
@@ -8143,30 +7698,6 @@
|
||||
"files"
|
||||
]
|
||||
},
|
||||
"resourceTokenList": {
|
||||
"description": "Resource Tokens List",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"total": {
|
||||
"type": "integer",
|
||||
"description": "Total number of tokens documents that matched your query.",
|
||||
"x-example": 5,
|
||||
"format": "int32"
|
||||
},
|
||||
"tokens": {
|
||||
"type": "array",
|
||||
"description": "List of tokens.",
|
||||
"items": {
|
||||
"$ref": "#\/components\/schemas\/resourceToken"
|
||||
},
|
||||
"x-example": ""
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"total",
|
||||
"tokens"
|
||||
]
|
||||
},
|
||||
"teamList": {
|
||||
"description": "Teams List",
|
||||
"type": "object",
|
||||
@@ -9363,50 +8894,6 @@
|
||||
"chunksUploaded"
|
||||
]
|
||||
},
|
||||
"resourceToken": {
|
||||
"description": "ResourceToken",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"$id": {
|
||||
"type": "string",
|
||||
"description": "Token ID.",
|
||||
"x-example": "bb8ea5c16897e"
|
||||
},
|
||||
"$createdAt": {
|
||||
"type": "string",
|
||||
"description": "Token creation date in ISO 8601 format.",
|
||||
"x-example": "2020-10-15T06:38:00.000+00:00"
|
||||
},
|
||||
"resourceId": {
|
||||
"type": "string",
|
||||
"description": "Resource ID.",
|
||||
"x-example": "5e5ea5c168bb8:5e5ea5c168bb8"
|
||||
},
|
||||
"resourceInternalId": {
|
||||
"type": "string",
|
||||
"description": "File ID.",
|
||||
"x-example": "1:1"
|
||||
},
|
||||
"resourceType": {
|
||||
"type": "string",
|
||||
"description": "Resource type.",
|
||||
"x-example": "file"
|
||||
},
|
||||
"expire": {
|
||||
"type": "string",
|
||||
"description": "Token expiration date in ISO 8601 format.",
|
||||
"x-example": "2020-10-15T06:38:00.000+00:00"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"$id",
|
||||
"$createdAt",
|
||||
"resourceId",
|
||||
"resourceInternalId",
|
||||
"resourceType",
|
||||
"expire"
|
||||
]
|
||||
},
|
||||
"team": {
|
||||
"description": "Team",
|
||||
"type": "object",
|
||||
|
||||
@@ -4918,7 +4918,7 @@
|
||||
"tags": [
|
||||
"functions"
|
||||
],
|
||||
"description": "Get a list of all the current user function execution logs. You can use the query params to filter your results.",
|
||||
"description": "",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Executions List",
|
||||
@@ -4929,7 +4929,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "listExecutions",
|
||||
"weight": 384,
|
||||
"weight": 383,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -4991,7 +4991,7 @@
|
||||
"tags": [
|
||||
"functions"
|
||||
],
|
||||
"description": "Trigger 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.",
|
||||
"description": "",
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Execution",
|
||||
@@ -5002,7 +5002,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "createExecution",
|
||||
"weight": 382,
|
||||
"weight": 381,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -5109,7 +5109,7 @@
|
||||
"tags": [
|
||||
"functions"
|
||||
],
|
||||
"description": "Get a function execution log by its unique ID.",
|
||||
"description": "",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Execution",
|
||||
@@ -5120,7 +5120,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "getExecution",
|
||||
"weight": 383,
|
||||
"weight": 382,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -5761,7 +5761,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "createSubscriber",
|
||||
"weight": 349,
|
||||
"weight": 348,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -5845,7 +5845,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "deleteSubscriber",
|
||||
"weight": 353,
|
||||
"weight": 352,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -7653,451 +7653,6 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"\/tokens\/buckets\/{bucketId}\/files\/{fileId}": {
|
||||
"get": {
|
||||
"summary": "List tokens",
|
||||
"operationId": "tokensList",
|
||||
"consumes": [
|
||||
"application\/json"
|
||||
],
|
||||
"produces": [
|
||||
"application\/json"
|
||||
],
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "List all the tokens created for a specific file or bucket. You can use the query params to filter your results.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Resource Tokens List",
|
||||
"schema": {
|
||||
"$ref": "#\/definitions\/resourceTokenList"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "list",
|
||||
"weight": 432,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/list.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList all the tokens created for a specific file or bucket. You can use the query params to filter your results.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
"scope": "tokens.read",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "bucketId",
|
||||
"description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "<BUCKET_ID>",
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"name": "fileId",
|
||||
"description": "File unique ID.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "<FILE_ID>",
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"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: expire",
|
||||
"required": false,
|
||||
"type": "array",
|
||||
"collectionFormat": "multi",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"default": [],
|
||||
"in": "query"
|
||||
}
|
||||
]
|
||||
},
|
||||
"post": {
|
||||
"summary": "Create file token",
|
||||
"operationId": "tokensCreateFileToken",
|
||||
"consumes": [
|
||||
"application\/json"
|
||||
],
|
||||
"produces": [
|
||||
"application\/json"
|
||||
],
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Create a new token. A token is linked to a file or a bucket and manages permissions for those file(s). Token can be passed as a header or request get parameter.",
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "ResourceToken",
|
||||
"schema": {
|
||||
"$ref": "#\/definitions\/resourceToken"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "createFileToken",
|
||||
"weight": 429,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/create-file-token.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file or a bucket and manages permissions for those file(s). Token can be passed as a header or request get parameter.",
|
||||
"rate-limit": 60,
|
||||
"rate-time": 60,
|
||||
"rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}",
|
||||
"scope": "tokens.write",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "bucketId",
|
||||
"description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "<BUCKET_ID>",
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"name": "fileId",
|
||||
"description": "File unique ID.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "<FILE_ID>",
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"name": "payload",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"expire": {
|
||||
"type": "string",
|
||||
"description": "Token expiry date",
|
||||
"default": null,
|
||||
"x-example": null,
|
||||
"x-nullable": true
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"description": "An array of permission strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
|
||||
"default": [],
|
||||
"x-example": "[\"read(\"any\")\"]",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"\/tokens\/{tokenId}": {
|
||||
"get": {
|
||||
"summary": "Get token",
|
||||
"operationId": "tokensGet",
|
||||
"consumes": [
|
||||
"application\/json"
|
||||
],
|
||||
"produces": [
|
||||
"application\/json"
|
||||
],
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Get a token by its unique ID.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "ResourceToken",
|
||||
"schema": {
|
||||
"$ref": "#\/definitions\/resourceToken"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"weight": 430,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/get.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a token by its unique ID.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
"scope": "tokens.read",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tokenId",
|
||||
"description": "Token ID.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN_ID>",
|
||||
"in": "path"
|
||||
}
|
||||
]
|
||||
},
|
||||
"patch": {
|
||||
"summary": "Update token",
|
||||
"operationId": "tokensUpdate",
|
||||
"consumes": [
|
||||
"application\/json"
|
||||
],
|
||||
"produces": [
|
||||
"application\/json"
|
||||
],
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Update a token by its unique ID. Use this endpoint to update a token's expiry date or permissions.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "ResourceToken",
|
||||
"schema": {
|
||||
"$ref": "#\/definitions\/resourceToken"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "update",
|
||||
"weight": 433,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/update.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate a token by its unique ID. Use this endpoint to update a token's expiry date or permissions.",
|
||||
"rate-limit": 60,
|
||||
"rate-time": 60,
|
||||
"rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}",
|
||||
"scope": "tokens.write",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tokenId",
|
||||
"description": "Token unique ID.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN_ID>",
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"name": "payload",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"expire": {
|
||||
"type": "string",
|
||||
"description": "File token expiry date",
|
||||
"default": null,
|
||||
"x-example": null,
|
||||
"x-nullable": true
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"description": "An array of permission string. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
|
||||
"default": null,
|
||||
"x-example": "[\"read(\"any\")\"]",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"delete": {
|
||||
"summary": "Delete token",
|
||||
"operationId": "tokensDelete",
|
||||
"consumes": [
|
||||
"application\/json"
|
||||
],
|
||||
"produces": [],
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Delete a token by its unique ID.",
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No content"
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "delete",
|
||||
"weight": 434,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/delete.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a token by its unique ID.",
|
||||
"rate-limit": 60,
|
||||
"rate-time": 60,
|
||||
"rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}",
|
||||
"scope": "tokens.write",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tokenId",
|
||||
"description": "Token ID.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN_ID>",
|
||||
"in": "path"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"\/tokens\/{tokenId}\/jwt": {
|
||||
"get": {
|
||||
"summary": "Get token as JWT",
|
||||
"operationId": "tokensGetJWT",
|
||||
"consumes": [
|
||||
"application\/json"
|
||||
],
|
||||
"produces": [
|
||||
"application\/json"
|
||||
],
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Get a JWT based token by its unique ID. You can use the JWT to authenticate on behalf of the user.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "JWT",
|
||||
"schema": {
|
||||
"$ref": "#\/definitions\/jwt"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "getJWT",
|
||||
"weight": 431,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/get-j-w-t.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a JWT based token by its unique ID. You can use the JWT to authenticate on behalf of the user.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
"scope": "tokens.read",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tokenId",
|
||||
"description": "File token ID.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN_ID>",
|
||||
"in": "path"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
@@ -8320,31 +7875,6 @@
|
||||
"files"
|
||||
]
|
||||
},
|
||||
"resourceTokenList": {
|
||||
"description": "Resource Tokens List",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"total": {
|
||||
"type": "integer",
|
||||
"description": "Total number of tokens documents that matched your query.",
|
||||
"x-example": 5,
|
||||
"format": "int32"
|
||||
},
|
||||
"tokens": {
|
||||
"type": "array",
|
||||
"description": "List of tokens.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#\/definitions\/resourceToken"
|
||||
},
|
||||
"x-example": ""
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"total",
|
||||
"tokens"
|
||||
]
|
||||
},
|
||||
"teamList": {
|
||||
"description": "Teams List",
|
||||
"type": "object",
|
||||
@@ -9552,50 +9082,6 @@
|
||||
"chunksUploaded"
|
||||
]
|
||||
},
|
||||
"resourceToken": {
|
||||
"description": "ResourceToken",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"$id": {
|
||||
"type": "string",
|
||||
"description": "Token ID.",
|
||||
"x-example": "bb8ea5c16897e"
|
||||
},
|
||||
"$createdAt": {
|
||||
"type": "string",
|
||||
"description": "Token creation date in ISO 8601 format.",
|
||||
"x-example": "2020-10-15T06:38:00.000+00:00"
|
||||
},
|
||||
"resourceId": {
|
||||
"type": "string",
|
||||
"description": "Resource ID.",
|
||||
"x-example": "5e5ea5c168bb8:5e5ea5c168bb8"
|
||||
},
|
||||
"resourceInternalId": {
|
||||
"type": "string",
|
||||
"description": "File ID.",
|
||||
"x-example": "1:1"
|
||||
},
|
||||
"resourceType": {
|
||||
"type": "string",
|
||||
"description": "Resource type.",
|
||||
"x-example": "file"
|
||||
},
|
||||
"expire": {
|
||||
"type": "string",
|
||||
"description": "Token expiration date in ISO 8601 format.",
|
||||
"x-example": "2020-10-15T06:38:00.000+00:00"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"$id",
|
||||
"$createdAt",
|
||||
"resourceId",
|
||||
"resourceInternalId",
|
||||
"resourceType",
|
||||
"expire"
|
||||
]
|
||||
},
|
||||
"team": {
|
||||
"description": "Team",
|
||||
"type": "object",
|
||||
|
||||
@@ -4918,7 +4918,7 @@
|
||||
"tags": [
|
||||
"functions"
|
||||
],
|
||||
"description": "Get a list of all the current user function execution logs. You can use the query params to filter your results.",
|
||||
"description": "",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Executions List",
|
||||
@@ -4929,7 +4929,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "listExecutions",
|
||||
"weight": 389,
|
||||
"weight": 383,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -4991,7 +4991,7 @@
|
||||
"tags": [
|
||||
"functions"
|
||||
],
|
||||
"description": "Trigger 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.",
|
||||
"description": "",
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Execution",
|
||||
@@ -5002,7 +5002,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "createExecution",
|
||||
"weight": 387,
|
||||
"weight": 381,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -5109,7 +5109,7 @@
|
||||
"tags": [
|
||||
"functions"
|
||||
],
|
||||
"description": "Get a function execution log by its unique ID.",
|
||||
"description": "",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Execution",
|
||||
@@ -5120,7 +5120,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "getExecution",
|
||||
"weight": 388,
|
||||
"weight": 382,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -5761,7 +5761,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "createSubscriber",
|
||||
"weight": 349,
|
||||
"weight": 348,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -5845,7 +5845,7 @@
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "deleteSubscriber",
|
||||
"weight": 353,
|
||||
"weight": 352,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
@@ -7653,451 +7653,6 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"\/tokens\/buckets\/{bucketId}\/files\/{fileId}": {
|
||||
"get": {
|
||||
"summary": "List tokens",
|
||||
"operationId": "tokensList",
|
||||
"consumes": [
|
||||
"application\/json"
|
||||
],
|
||||
"produces": [
|
||||
"application\/json"
|
||||
],
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "List all the tokens created for a specific file or bucket. You can use the query params to filter your results.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Resource Tokens List",
|
||||
"schema": {
|
||||
"$ref": "#\/definitions\/resourceTokenList"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "list",
|
||||
"weight": 432,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/list.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList all the tokens created for a specific file or bucket. You can use the query params to filter your results.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
"scope": "tokens.read",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "bucketId",
|
||||
"description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "<BUCKET_ID>",
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"name": "fileId",
|
||||
"description": "File unique ID.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "<FILE_ID>",
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"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: expire",
|
||||
"required": false,
|
||||
"type": "array",
|
||||
"collectionFormat": "multi",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"default": [],
|
||||
"in": "query"
|
||||
}
|
||||
]
|
||||
},
|
||||
"post": {
|
||||
"summary": "Create file token",
|
||||
"operationId": "tokensCreateFileToken",
|
||||
"consumes": [
|
||||
"application\/json"
|
||||
],
|
||||
"produces": [
|
||||
"application\/json"
|
||||
],
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Create a new token. A token is linked to a file or a bucket and manages permissions for those file(s). Token can be passed as a header or request get parameter.",
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "ResourceToken",
|
||||
"schema": {
|
||||
"$ref": "#\/definitions\/resourceToken"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "createFileToken",
|
||||
"weight": 429,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/create-file-token.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file or a bucket and manages permissions for those file(s). Token can be passed as a header or request get parameter.",
|
||||
"rate-limit": 60,
|
||||
"rate-time": 60,
|
||||
"rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}",
|
||||
"scope": "tokens.write",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "bucketId",
|
||||
"description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "<BUCKET_ID>",
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"name": "fileId",
|
||||
"description": "File unique ID.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "<FILE_ID>",
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"name": "payload",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"expire": {
|
||||
"type": "string",
|
||||
"description": "Token expiry date",
|
||||
"default": null,
|
||||
"x-example": null,
|
||||
"x-nullable": true
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"description": "An array of permission strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
|
||||
"default": [],
|
||||
"x-example": "[\"read(\"any\")\"]",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"\/tokens\/{tokenId}": {
|
||||
"get": {
|
||||
"summary": "Get token",
|
||||
"operationId": "tokensGet",
|
||||
"consumes": [
|
||||
"application\/json"
|
||||
],
|
||||
"produces": [
|
||||
"application\/json"
|
||||
],
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Get a token by its unique ID.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "ResourceToken",
|
||||
"schema": {
|
||||
"$ref": "#\/definitions\/resourceToken"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "get",
|
||||
"weight": 430,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/get.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a token by its unique ID.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
"scope": "tokens.read",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tokenId",
|
||||
"description": "Token ID.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN_ID>",
|
||||
"in": "path"
|
||||
}
|
||||
]
|
||||
},
|
||||
"patch": {
|
||||
"summary": "Update token",
|
||||
"operationId": "tokensUpdate",
|
||||
"consumes": [
|
||||
"application\/json"
|
||||
],
|
||||
"produces": [
|
||||
"application\/json"
|
||||
],
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Update a token by its unique ID. Use this endpoint to update a token's expiry date or permissions.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "ResourceToken",
|
||||
"schema": {
|
||||
"$ref": "#\/definitions\/resourceToken"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "update",
|
||||
"weight": 433,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/update.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate a token by its unique ID. Use this endpoint to update a token's expiry date or permissions.",
|
||||
"rate-limit": 60,
|
||||
"rate-time": 60,
|
||||
"rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}",
|
||||
"scope": "tokens.write",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tokenId",
|
||||
"description": "Token unique ID.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN_ID>",
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"name": "payload",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"expire": {
|
||||
"type": "string",
|
||||
"description": "File token expiry date",
|
||||
"default": null,
|
||||
"x-example": null,
|
||||
"x-nullable": true
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"description": "An array of permission string. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
|
||||
"default": null,
|
||||
"x-example": "[\"read(\"any\")\"]",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"delete": {
|
||||
"summary": "Delete token",
|
||||
"operationId": "tokensDelete",
|
||||
"consumes": [
|
||||
"application\/json"
|
||||
],
|
||||
"produces": [],
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Delete a token by its unique ID.",
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No content"
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "delete",
|
||||
"weight": 434,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/delete.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a token by its unique ID.",
|
||||
"rate-limit": 60,
|
||||
"rate-time": 60,
|
||||
"rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}",
|
||||
"scope": "tokens.write",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tokenId",
|
||||
"description": "Token ID.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN_ID>",
|
||||
"in": "path"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"\/tokens\/{tokenId}\/jwt": {
|
||||
"get": {
|
||||
"summary": "Get token as JWT",
|
||||
"operationId": "tokensGetJWT",
|
||||
"consumes": [
|
||||
"application\/json"
|
||||
],
|
||||
"produces": [
|
||||
"application\/json"
|
||||
],
|
||||
"tags": [
|
||||
"tokens"
|
||||
],
|
||||
"description": "Get a JWT based token by its unique ID. You can use the JWT to authenticate on behalf of the user.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "JWT",
|
||||
"schema": {
|
||||
"$ref": "#\/definitions\/jwt"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-appwrite": {
|
||||
"method": "getJWT",
|
||||
"weight": 431,
|
||||
"cookies": false,
|
||||
"type": "",
|
||||
"deprecated": false,
|
||||
"demo": "tokens\/get-j-w-t.md",
|
||||
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a JWT based token by its unique ID. You can use the JWT to authenticate on behalf of the user.",
|
||||
"rate-limit": 0,
|
||||
"rate-time": 3600,
|
||||
"rate-key": "url:{url},ip:{ip}",
|
||||
"scope": "tokens.read",
|
||||
"platforms": [
|
||||
"client",
|
||||
"server",
|
||||
"server"
|
||||
],
|
||||
"packaging": false,
|
||||
"auth": {
|
||||
"Project": []
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Project": [],
|
||||
"Session": [],
|
||||
"JWT": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tokenId",
|
||||
"description": "File token ID.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"x-example": "<TOKEN_ID>",
|
||||
"in": "path"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
@@ -8320,31 +7875,6 @@
|
||||
"files"
|
||||
]
|
||||
},
|
||||
"resourceTokenList": {
|
||||
"description": "Resource Tokens List",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"total": {
|
||||
"type": "integer",
|
||||
"description": "Total number of tokens documents that matched your query.",
|
||||
"x-example": 5,
|
||||
"format": "int32"
|
||||
},
|
||||
"tokens": {
|
||||
"type": "array",
|
||||
"description": "List of tokens.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#\/definitions\/resourceToken"
|
||||
},
|
||||
"x-example": ""
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"total",
|
||||
"tokens"
|
||||
]
|
||||
},
|
||||
"teamList": {
|
||||
"description": "Teams List",
|
||||
"type": "object",
|
||||
@@ -9552,50 +9082,6 @@
|
||||
"chunksUploaded"
|
||||
]
|
||||
},
|
||||
"resourceToken": {
|
||||
"description": "ResourceToken",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"$id": {
|
||||
"type": "string",
|
||||
"description": "Token ID.",
|
||||
"x-example": "bb8ea5c16897e"
|
||||
},
|
||||
"$createdAt": {
|
||||
"type": "string",
|
||||
"description": "Token creation date in ISO 8601 format.",
|
||||
"x-example": "2020-10-15T06:38:00.000+00:00"
|
||||
},
|
||||
"resourceId": {
|
||||
"type": "string",
|
||||
"description": "Resource ID.",
|
||||
"x-example": "5e5ea5c168bb8:5e5ea5c168bb8"
|
||||
},
|
||||
"resourceInternalId": {
|
||||
"type": "string",
|
||||
"description": "File ID.",
|
||||
"x-example": "1:1"
|
||||
},
|
||||
"resourceType": {
|
||||
"type": "string",
|
||||
"description": "Resource type.",
|
||||
"x-example": "file"
|
||||
},
|
||||
"expire": {
|
||||
"type": "string",
|
||||
"description": "Token expiration date in ISO 8601 format.",
|
||||
"x-example": "2020-10-15T06:38:00.000+00:00"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"$id",
|
||||
"$createdAt",
|
||||
"resourceId",
|
||||
"resourceInternalId",
|
||||
"resourceType",
|
||||
"expire"
|
||||
]
|
||||
},
|
||||
"team": {
|
||||
"description": "Team",
|
||||
"type": "object",
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
<?php
|
||||
|
||||
// TODO: Remove, replace with runtimes.php directly
|
||||
// Used in function templates and site frameworks
|
||||
|
||||
return [
|
||||
'NODE' => [
|
||||
'name' => 'node',
|
||||
|
||||
@@ -116,15 +116,6 @@ const TEMPLATE_FRAMEWORKS = [
|
||||
'outputDirectory' => './dist/angular/browser',
|
||||
'fallbackFile' => 'index.html',
|
||||
],
|
||||
'ANALOG' => [
|
||||
'key' => 'analog',
|
||||
'name' => 'Analog',
|
||||
'installCommand' => 'npm install',
|
||||
'buildCommand' => 'npm run build',
|
||||
'buildRuntime' => 'node-22',
|
||||
'adapter' => 'ssr',
|
||||
'outputDirectory' => './dist/analog',
|
||||
],
|
||||
'VUE' => [
|
||||
'key' => 'vue',
|
||||
'name' => 'Vue.js',
|
||||
@@ -590,139 +581,6 @@ return [
|
||||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
'key' => 'starter-for-astro',
|
||||
'name' => 'Astro starter',
|
||||
'useCases' => [UseCases::STARTER],
|
||||
'tagline' => 'Simple Astro application integrated with Appwrite SDK.',
|
||||
'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
|
||||
'screenshotDark' => $url . '/images/sites/templates/starter-for-astro-dark.png',
|
||||
'screenshotLight' => $url . '/images/sites/templates/starter-for-astro-light.png',
|
||||
'frameworks' => [
|
||||
getFramework('ASTRO', [
|
||||
'providerRootDirectory' => './',
|
||||
'adapter' => 'static',
|
||||
]),
|
||||
],
|
||||
'vcsProvider' => 'github',
|
||||
'providerRepositoryId' => 'starter-for-astro',
|
||||
'providerOwner' => 'appwrite',
|
||||
'providerVersion' => '0.1.*',
|
||||
'variables' => [
|
||||
[
|
||||
'name' => 'PUBLIC_APPWRITE_ENDPOINT',
|
||||
'description' => 'Endpoint of Appwrite server',
|
||||
'value' => '{apiEndpoint}',
|
||||
'placeholder' => '{apiEndpoint}',
|
||||
'required' => true,
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'name' => 'PUBLIC_APPWRITE_PROJECT_ID',
|
||||
'description' => 'Your Appwrite project ID',
|
||||
'value' => '{projectId}',
|
||||
'placeholder' => '{projectId}',
|
||||
'required' => true,
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'name' => 'PUBLIC_APPWRITE_PROJECT_NAME',
|
||||
'description' => 'Your Appwrite project name',
|
||||
'value' => '{projectName}',
|
||||
'placeholder' => '{projectName}',
|
||||
'required' => true,
|
||||
'type' => 'text'
|
||||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
'key' => 'starter-for-analog',
|
||||
'name' => 'Analog starter',
|
||||
'useCases' => [UseCases::STARTER],
|
||||
'tagline' => 'Simple Analog application integrated with Appwrite SDK.',
|
||||
'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
|
||||
'screenshotDark' => $url . '/images/sites/templates/starter-for-analog-dark.png',
|
||||
'screenshotLight' => $url . '/images/sites/templates/starter-for-analog-light.png',
|
||||
'frameworks' => [
|
||||
getFramework('ANALOG', [
|
||||
'providerRootDirectory' => './',
|
||||
]),
|
||||
],
|
||||
'vcsProvider' => 'github',
|
||||
'providerRepositoryId' => 'starter-for-analog',
|
||||
'providerOwner' => 'appwrite',
|
||||
'providerVersion' => '0.1.*',
|
||||
'variables' => [
|
||||
[
|
||||
'name' => 'VITE_APPWRITE_ENDPOINT',
|
||||
'description' => 'Endpoint of Appwrite server',
|
||||
'value' => '{apiEndpoint}',
|
||||
'placeholder' => '{apiEndpoint}',
|
||||
'required' => true,
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'name' => 'VITE_APPWRITE_PROJECT_ID',
|
||||
'description' => 'Your Appwrite project ID',
|
||||
'value' => '{projectId}',
|
||||
'placeholder' => '{projectId}',
|
||||
'required' => true,
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'name' => 'VITE_APPWRITE_PROJECT_NAME',
|
||||
'description' => 'Your Appwrite project name',
|
||||
'value' => '{projectName}',
|
||||
'placeholder' => '{projectName}',
|
||||
'required' => true,
|
||||
'type' => 'text'
|
||||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
'key' => 'starter-for-remix',
|
||||
'name' => 'Remix starter',
|
||||
'useCases' => [UseCases::STARTER],
|
||||
'tagline' => 'Simple Remix application integrated with Appwrite SDK.',
|
||||
'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
|
||||
'screenshotDark' => $url . '/images/sites/templates/starter-for-remix-dark.png',
|
||||
'screenshotLight' => $url . '/images/sites/templates/starter-for-remix-light.png',
|
||||
'frameworks' => [
|
||||
getFramework('REMIX', [
|
||||
'providerRootDirectory' => './',
|
||||
]),
|
||||
],
|
||||
'vcsProvider' => 'github',
|
||||
'providerRepositoryId' => 'starter-for-remix',
|
||||
'providerOwner' => 'appwrite',
|
||||
'providerVersion' => '0.1.*',
|
||||
'variables' => [
|
||||
[
|
||||
'name' => 'VITE_APPWRITE_ENDPOINT',
|
||||
'description' => 'Endpoint of Appwrite server',
|
||||
'value' => '{apiEndpoint}',
|
||||
'placeholder' => '{apiEndpoint}',
|
||||
'required' => true,
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'name' => 'VITE_APPWRITE_PROJECT_ID',
|
||||
'description' => 'Your Appwrite project ID',
|
||||
'value' => '{projectId}',
|
||||
'placeholder' => '{projectId}',
|
||||
'required' => true,
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'name' => 'VITE_APPWRITE_PROJECT_NAME',
|
||||
'description' => 'Your Appwrite project name',
|
||||
'value' => '{projectName}',
|
||||
'placeholder' => '{projectName}',
|
||||
'required' => true,
|
||||
'type' => 'text'
|
||||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
'key' => 'starter-for-svelte',
|
||||
'name' => 'Svelte starter',
|
||||
@@ -1108,7 +966,6 @@ return [
|
||||
'providerVersion' => '0.1.*',
|
||||
'variables' => []
|
||||
],
|
||||
// TODO: Remove astro starter eventually, or add all frameworks's starters
|
||||
[
|
||||
'key' => 'astro-starter',
|
||||
'name' => 'Astro starter',
|
||||
|
||||
@@ -45,16 +45,7 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => '_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS',
|
||||
'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.',
|
||||
'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.',
|
||||
'introduction' => '',
|
||||
'default' => 'disabled',
|
||||
'required' => false,
|
||||
@@ -99,40 +90,13 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => '_APP_DOMAIN_TARGET',
|
||||
'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\'.',
|
||||
'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\'.',
|
||||
'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.',
|
||||
@@ -782,22 +746,13 @@ return [
|
||||
'variables' => [
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_SIZE_LIMIT',
|
||||
'description' => 'Deprecated since 1.7.0. The maximum size of a function in bytes. The default value is 30MB.',
|
||||
'description' => '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).',
|
||||
@@ -818,22 +773,13 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_BUILD_TIMEOUT',
|
||||
'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.',
|
||||
'description' => '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\'.',
|
||||
@@ -845,40 +791,22 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_CPUS',
|
||||
'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, CPU limit will be disabled.',
|
||||
'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, 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' => '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, memory limit will be disabled.',
|
||||
'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, 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.',
|
||||
@@ -936,22 +864,13 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_INACTIVE_THRESHOLD',
|
||||
'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.',
|
||||
'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.',
|
||||
'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.',
|
||||
@@ -990,22 +909,13 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_RUNTIMES_NETWORK',
|
||||
'description' => 'Deprecated since 1.7.0. The docker network used for communication between the executor and runtimes.',
|
||||
'description' => '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.',
|
||||
@@ -1026,7 +936,7 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => '_APP_FUNCTIONS_MAINTENANCE_INTERVAL',
|
||||
'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).',
|
||||
'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).',
|
||||
'introduction' => '1.4.0',
|
||||
'default' => '3600',
|
||||
'required' => false,
|
||||
@@ -1034,42 +944,8 @@ 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' => '',
|
||||
@@ -1172,22 +1048,13 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => '_APP_MAINTENANCE_RETENTION_AUDIT',
|
||||
'description' => 'The maximum duration (in seconds) upto which to retain audit logs. The default value is 1209600 seconds (14 days).',
|
||||
'description' => 'IThe maximum duration (in seconds) upto which to retain audit logs. The default value is 1209600 seconds (14 days).',
|
||||
'introduction' => '0.7.0',
|
||||
'default' => '1209600',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE',
|
||||
'description' => 'The maximum duration (in seconds) upto which to retain console audit logs. The default value is 15778800 seconds (6 months).',
|
||||
'introduction' => '1.6.2',
|
||||
'default' => '15778800',
|
||||
'required' => false,
|
||||
'question' => '',
|
||||
'filter' => ''
|
||||
],
|
||||
[
|
||||
'name' => '_APP_MAINTENANCE_RETENTION_ABUSE',
|
||||
'description' => 'The maximum duration (in seconds) upto which to retain abuse logs. The default value is 86400 seconds (1 day).',
|
||||
|
||||
@@ -1188,8 +1188,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, $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('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('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')
|
||||
@@ -1784,8 +1784,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, $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('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('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')
|
||||
@@ -1864,7 +1864,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, $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('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('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')
|
||||
@@ -3159,7 +3159,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, $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'])
|
||||
->param('url', '', fn ($clients) => new Host($clients), 'URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients'])
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
@@ -3434,7 +3434,7 @@ App::post('/v1/account/verification')
|
||||
))
|
||||
->label('abuse-limit', 10)
|
||||
->label('abuse-key', 'url:{url},userId:{userId}')
|
||||
->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
|
||||
->param('url', '', fn ($clients) => new Host($clients), 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add built-in confirm page
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
|
||||
@@ -8,9 +8,7 @@ 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()
|
||||
@@ -42,21 +40,10 @@ App::get('/v1/console/variables')
|
||||
))
|
||||
->inject('response')
|
||||
->action(function (Response $response) {
|
||||
$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
|
||||
);
|
||||
$isDomainEnabled = !empty(System::getEnv('_APP_DOMAIN', ''))
|
||||
&& !empty(System::getEnv('_APP_DOMAIN_TARGET', ''))
|
||||
&& System::getEnv('_APP_DOMAIN', '') !== 'localhost'
|
||||
&& System::getEnv('_APP_DOMAIN_TARGET', '') !== 'localhost';
|
||||
|
||||
$isVcsEnabled = !empty(System::getEnv('_APP_VCS_GITHUB_APP_NAME', ''))
|
||||
&& !empty(System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY', ''))
|
||||
@@ -67,9 +54,7 @@ App::get('/v1/console/variables')
|
||||
$isAssistantEnabled = !empty(System::getEnv('_APP_ASSISTANT_OPENAI_API_KEY', ''));
|
||||
|
||||
$variables = new Document([
|
||||
'_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_DOMAIN_TARGET' => System::getEnv('_APP_DOMAIN_TARGET'),
|
||||
'_APP_STORAGE_LIMIT' => +System::getEnv('_APP_STORAGE_LIMIT'),
|
||||
'_APP_COMPUTE_SIZE_LIMIT' => +System::getEnv('_APP_COMPUTE_SIZE_LIMIT'),
|
||||
'_APP_USAGE_STATS' => System::getEnv('_APP_USAGE_STATS'),
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
<?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;
|
||||
@@ -18,21 +15,12 @@ use Utopia\Database\Document;
|
||||
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;
|
||||
@@ -101,6 +89,7 @@ App::post('/v1/migrations/appwrite')
|
||||
->dynamic($migration, Response::MODEL_MIGRATION);
|
||||
});
|
||||
|
||||
|
||||
App::post('/v1/migrations/firebase')
|
||||
->groups(['api', 'migrations'])
|
||||
->desc('Migrate Firebase data')
|
||||
@@ -301,130 +290,6 @@ 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',
|
||||
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')
|
||||
|
||||
@@ -149,7 +149,7 @@ App::get('/v1/project/usage')
|
||||
$executionsBreakdown = array_map(function ($function) use ($dbForProject) {
|
||||
$id = $function->getId();
|
||||
$name = $function->getAttribute('name');
|
||||
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS);
|
||||
$metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS);
|
||||
$value = $dbForProject->findOne('stats', [
|
||||
Query::equal('metric', [$metric]),
|
||||
Query::equal('period', ['inf'])
|
||||
@@ -165,7 +165,7 @@ App::get('/v1/project/usage')
|
||||
$executionsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) {
|
||||
$id = $function->getId();
|
||||
$name = $function->getAttribute('name');
|
||||
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS);
|
||||
$metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS);
|
||||
$value = $dbForProject->findOne('stats', [
|
||||
Query::equal('metric', [$metric]),
|
||||
Query::equal('period', ['inf'])
|
||||
@@ -181,7 +181,7 @@ App::get('/v1/project/usage')
|
||||
$buildsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) {
|
||||
$id = $function->getId();
|
||||
$name = $function->getAttribute('name');
|
||||
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS);
|
||||
$metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS);
|
||||
$value = $dbForProject->findOne('stats', [
|
||||
Query::equal('metric', [$metric]),
|
||||
Query::equal('period', ['inf'])
|
||||
@@ -230,13 +230,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}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE);
|
||||
$deploymentMetric = str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $function->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE);
|
||||
$deploymentValue = $dbForProject->findOne('stats', [
|
||||
Query::equal('metric', [$deploymentMetric]),
|
||||
Query::equal('period', ['inf'])
|
||||
]);
|
||||
|
||||
$buildMetric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE);
|
||||
$buildMetric = str_replace(['{functionInternalId}'], [$function->getInternalId()], METRIC_FUNCTION_ID_BUILDS_STORAGE);
|
||||
$buildValue = $dbForProject->findOne('stats', [
|
||||
Query::equal('metric', [$buildMetric]),
|
||||
Query::equal('period', ['inf'])
|
||||
@@ -254,7 +254,7 @@ App::get('/v1/project/usage')
|
||||
$executionsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) {
|
||||
$id = $function->getId();
|
||||
$name = $function->getAttribute('name');
|
||||
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS);
|
||||
$metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS);
|
||||
$value = $dbForProject->findOne('stats', [
|
||||
Query::equal('metric', [$metric]),
|
||||
Query::equal('period', ['inf'])
|
||||
@@ -270,7 +270,7 @@ App::get('/v1/project/usage')
|
||||
$buildsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) {
|
||||
$id = $function->getId();
|
||||
$name = $function->getAttribute('name');
|
||||
$metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS);
|
||||
$metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS);
|
||||
$value = $dbForProject->findOne('stats', [
|
||||
Query::equal('metric', [$metric]),
|
||||
Query::equal('period', ['inf'])
|
||||
|
||||
@@ -4,7 +4,7 @@ use Appwrite\Event\Certificate;
|
||||
use Appwrite\Event\Delete;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Network\Validator\DNS;
|
||||
use Appwrite\Network\Validator\CNAME;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
@@ -21,8 +21,6 @@ use Utopia\Database\Validator\UID;
|
||||
use Utopia\Domains\Domain;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\AnyOf;
|
||||
use Utopia\Validator\IP;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
App::get('/v1/proxy/rules')
|
||||
@@ -210,27 +208,17 @@ App::patch('/v1/proxy/rules/:ruleId/verification')
|
||||
throw new Exception(Exception::RULE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$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);
|
||||
}
|
||||
$target = new Domain(System::getEnv('_APP_DOMAIN_TARGET', ''));
|
||||
|
||||
if (empty($validators)) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'At least one of domain targets environment variable must be configured.');
|
||||
if (!$target->isKnown() || $target->isTest()) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Domain target must be configured as environment variable.');
|
||||
}
|
||||
|
||||
if ($rule->getAttribute('verification') === true) {
|
||||
return $response->dynamic($rule, Response::MODEL_PROXY_RULE);
|
||||
}
|
||||
|
||||
$validator = new AnyOf($validators, AnyOf::TYPE_STRING);
|
||||
$validator = new CNAME($target->get()); // Verify Domain with DNS records
|
||||
$domain = new Domain($rule->getAttribute('domain', ''));
|
||||
|
||||
$validationStart = \microtime(true);
|
||||
@@ -238,14 +226,7 @@ App::patch('/v1/proxy/rules/:ruleId/verification')
|
||||
$log->addExtra('dnsTiming', \strval(\microtime(true) - $validationStart));
|
||||
$log->addTag('dnsDomain', $domain->get());
|
||||
|
||||
$errors = [];
|
||||
foreach ($validators as $validator) {
|
||||
if (!empty($validator->getLogs())) {
|
||||
$errors[] = $validator->getLogs();
|
||||
}
|
||||
}
|
||||
|
||||
$error = \implode("\n", $errors);
|
||||
$error = $validator->getLogs();
|
||||
$log->addExtra('dnsResponse', \is_array($error) ? \json_encode($error) : \strval($error));
|
||||
|
||||
throw new Exception(Exception::RULE_VERIFICATION_FAILED);
|
||||
|
||||
@@ -936,10 +936,9 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
|
||||
->param('output', '', new WhiteList(\array_keys(Config::getParam('storage-outputs')), true), 'Output format type (jpeg, jpg, png, gif and webp).', 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, Document $resourceToken, 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, Response $response, Database $dbForProject, Device $deviceForFiles, Device $deviceForLocal) {
|
||||
|
||||
if (!\extension_loaded('imagick')) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing');
|
||||
@@ -954,24 +953,19 @@ 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 && !$isToken) {
|
||||
if (!$fileSecurity && !$valid) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
if ($fileSecurity && !$valid && !$isToken) {
|
||||
if ($fileSecurity && !$valid) {
|
||||
$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);
|
||||
}
|
||||
@@ -1771,7 +1765,6 @@ 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'])
|
||||
|
||||
@@ -51,7 +51,6 @@ 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')
|
||||
@@ -456,7 +455,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, $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('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('name', '', new Text(128), 'Name of the new team member. Max length: 128 chars.', true)
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
@@ -616,10 +615,7 @@ App::post('/v1/teams/:teamId/memberships')
|
||||
$membership = ($isPrivilegedUser || $isAppUser) ?
|
||||
Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)) :
|
||||
$dbForProject->createDocument('memberships', $membership);
|
||||
|
||||
if ($isPrivilegedUser || $isAppUser) {
|
||||
Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1));
|
||||
}
|
||||
Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1));
|
||||
|
||||
} elseif ($membership->getAttribute('confirm') === false) {
|
||||
$membership->setAttribute('secret', Auth::hash($secret));
|
||||
@@ -1035,6 +1031,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
|
||||
->param('membershipId', '', new UID(), 'Membership ID.')
|
||||
->param('roles', [], function (Document $project) {
|
||||
if ($project->getId() === 'console') {
|
||||
;
|
||||
$roles = array_keys(Config::getParam('roles', []));
|
||||
array_filter($roles, function ($role) {
|
||||
return !in_array($role, [Auth::USER_ROLE_APPS, Auth::USER_ROLE_GUESTS, Auth::USER_ROLE_USERS]);
|
||||
@@ -1046,10 +1043,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
->inject('project')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents) {
|
||||
->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) {
|
||||
|
||||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
if ($team->isEmpty()) {
|
||||
@@ -1070,21 +1066,6 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
|
||||
$isAppUser = Auth::isAppUser(Authorization::getRoles());
|
||||
$isOwner = Authorization::isRole('team:' . $team->getId() . '/owner');
|
||||
|
||||
if ($project->getId() === 'console') {
|
||||
// Quick check: fetch up to 2 owners to determine if only one exists
|
||||
$ownersCount = $dbForProject->count(
|
||||
collection: 'memberships',
|
||||
queries: [Query::contains('roles', ['owner'])],
|
||||
max: 2
|
||||
);
|
||||
|
||||
// Prevent role change if there's only one owner left,
|
||||
// the requester is that owner, and the new `$roles` no longer include 'owner'!
|
||||
if ($ownersCount === 1 && $isOwner && !\in_array('owner', $roles)) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'There must be at least one owner in the organization.');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isOwner && !$isPrivilegedUser && !$isAppUser) { // Not owner, not admin, not app (server)
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, 'User is not allowed to modify roles');
|
||||
}
|
||||
|
||||
@@ -56,8 +56,10 @@ Config::setParam('domainVerification', false);
|
||||
Config::setParam('cookieDomain', 'localhost');
|
||||
Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE);
|
||||
|
||||
function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey)
|
||||
function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey)
|
||||
{
|
||||
$utopia->getRoute()?->label('error', __DIR__ . '/../views/general/error.phtml');
|
||||
|
||||
$host = $request->getHostname() ?? '';
|
||||
if (!empty($previewHostname)) {
|
||||
$host = $previewHostname;
|
||||
@@ -75,28 +77,24 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
)[0] ?? new Document();
|
||||
}
|
||||
|
||||
$errorView = __DIR__ . '/../views/general/error.phtml';
|
||||
$url = (System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https') . '://' . System::getEnv('_APP_DOMAIN', '');
|
||||
|
||||
if ($rule->isEmpty()) {
|
||||
if ($host === System::getEnv('_APP_DOMAIN_FUNCTIONS', '') || $host === System::getEnv('_APP_DOMAIN_SITES', '')) {
|
||||
throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'This domain cannot be used for security reasons. Please use any subdomain instead.', view: $errorView);
|
||||
throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'This domain cannot be used for security reasons. Please use any subdomain instead.');
|
||||
}
|
||||
|
||||
if (\str_ends_with($host, System::getEnv('_APP_DOMAIN_FUNCTIONS', '')) || \str_ends_with($host, System::getEnv('_APP_DOMAIN_SITES', ''))) {
|
||||
$exception = new AppwriteException(AppwriteException::RULE_NOT_FOUND, 'This domain is not connected to any Appwrite resources. Visit domains tab under function/site settings to configure it.', view: $errorView);
|
||||
|
||||
$exception->addCTA('Start with this domain', $url . '/console');
|
||||
throw $exception;
|
||||
throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'This domain is not connected to any Appwrite resource yet. Please configure custom domain or function domain to allow this request.');
|
||||
}
|
||||
|
||||
if (System::getEnv('_APP_OPTIONS_ROUTER_PROTECTION', 'disabled') === 'enabled') {
|
||||
if ($host !== 'localhost' && $host !== APP_HOSTNAME_INTERNAL && $host !== System::getEnv('_APP_CONSOLE_DOMAIN', '')) {
|
||||
throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'Router protection does not allow accessing Appwrite over this domain. Please add it as custom domain to your project or disable _APP_OPTIONS_ROUTER_PROTECTION environment variable.', view: $errorView);
|
||||
throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'Router protection does not allow accessing Appwrite over this domain. Please add it as custom domain to your project or disable _APP_OPTIONS_ROUTER_PROTECTION environment variable.');
|
||||
}
|
||||
}
|
||||
|
||||
// Act as API - no Proxy logic
|
||||
$utopia->getRoute()?->label('error', '');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -106,7 +104,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
);
|
||||
|
||||
if (!$project->isEmpty() && $project->getId() !== 'console') {
|
||||
$accessedAt = $project->getAttribute('accessedAt', 0);
|
||||
$accessedAt = $project->getAttribute('accessedAt', '');
|
||||
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));
|
||||
@@ -116,7 +114,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
if (array_key_exists('proxy', $project->getAttribute('services', []))) {
|
||||
$status = $project->getAttribute('services', [])['proxy'];
|
||||
if (!$status) {
|
||||
throw new AppwriteException(AppwriteException::GENERAL_SERVICE_DISABLED, view: $errorView);
|
||||
throw new AppwriteException(AppwriteException::GENERAL_SERVICE_DISABLED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,10 +127,10 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
$type = $rule->getAttribute('type', '');
|
||||
|
||||
if ($type === 'deployment') {
|
||||
if (System::getEnv('_APP_OPTIONS_ROUTER_FORCE_HTTPS', 'disabled') === 'enabled') { // Force HTTPS
|
||||
if (System::getEnv('_APP_OPTIONS_COMPUTE_FORCE_HTTPS', 'disabled') === 'enabled') { // Force HTTPS
|
||||
if ($request->getProtocol() !== 'https' && $request->getHostname() !== APP_HOSTNAME_INTERNAL) {
|
||||
if ($request->getMethod() !== Request::METHOD_GET) {
|
||||
throw new AppwriteException(AppwriteException::GENERAL_PROTOCOL_UNSUPPORTED, 'Method unsupported over HTTP. Please use HTTPS instead.', view: $errorView);
|
||||
throw new AppwriteException(AppwriteException::GENERAL_PROTOCOL_UNSUPPORTED, 'Method unsupported over HTTP. Please use HTTPS instead.');
|
||||
}
|
||||
return $response->redirect('https://' . $request->getHostname() . $request->getURI());
|
||||
}
|
||||
@@ -141,7 +139,6 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
/** @var Database $dbForProject */
|
||||
$dbForProject = $getProjectDB($project);
|
||||
|
||||
/** @var Document $deployment */
|
||||
$deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $rule->getAttribute('deploymentId')));
|
||||
|
||||
if ($deployment->getAttribute('resourceType', '') === 'functions') {
|
||||
@@ -150,15 +147,6 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
$type = 'site';
|
||||
}
|
||||
|
||||
if ($deployment->isEmpty()) {
|
||||
$resourceType = $rule->getAttribute('deploymentResourceType', '');
|
||||
$resourceId = $rule->getAttribute('deploymentResourceId', '');
|
||||
$type = ($resourceType === 'site') ? 'sites' : 'functions';
|
||||
$exception = new AppwriteException(AppwriteException::DEPLOYMENT_NOT_FOUND, view: $errorView);
|
||||
$exception->addCTA('View deployments', $url . '/console/project-' . $projectId . '/' . $type . '/' . $resourceType . '-' . $resourceId);
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$resource = $type === 'function' ?
|
||||
Authorization::skip(fn () => $dbForProject->getDocument('functions', $deployment->getAttribute('resourceId', ''))) :
|
||||
Authorization::skip(fn () => $dbForProject->getDocument('sites', $deployment->getAttribute('resourceId', '')));
|
||||
@@ -251,15 +239,11 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
$requestHeaders = $request->getHeaders();
|
||||
|
||||
if ($resource->isEmpty() || !$resource->getAttribute('enabled')) {
|
||||
if ($type === 'functions') {
|
||||
throw new AppwriteException(AppwriteException::FUNCTION_NOT_FOUND, view: $errorView);
|
||||
} else {
|
||||
throw new AppwriteException(AppwriteException::SITE_NOT_FOUND, view: $errorView);
|
||||
}
|
||||
throw new AppwriteException(AppwriteException::FUNCTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($isResourceBlocked($project, $type === 'function' ? RESOURCE_TYPE_FUNCTIONS : RESOURCE_TYPE_SITES, $resource->getId())) {
|
||||
throw new AppwriteException(AppwriteException::GENERAL_RESOURCE_BLOCKED, view: $errorView);
|
||||
throw new AppwriteException(AppwriteException::GENERAL_RESOURCE_BLOCKED);
|
||||
}
|
||||
|
||||
$version = match ($type) {
|
||||
@@ -282,40 +266,22 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
}
|
||||
|
||||
if (\is_null($runtime)) {
|
||||
throw new AppwriteException(AppwriteException::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $resource->getAttribute('runtime', '') . '" is not supported', view: $errorView);
|
||||
throw new AppwriteException(AppwriteException::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $resource->getAttribute('runtime', '') . '" is not supported');
|
||||
}
|
||||
|
||||
$allowAnyStatus = !\is_null($apiKey) && $apiKey->isDeploymentStatusIgnored();
|
||||
if (!$allowAnyStatus && $deployment->getAttribute('status') !== 'ready') {
|
||||
$status = $deployment->getAttribute('status');
|
||||
|
||||
switch ($status) {
|
||||
case 'failed':
|
||||
$exception = new AppwriteException(AppwriteException::BUILD_FAILED, view: $errorView);
|
||||
$ctaUrl = '/console/project-' . $project->getId() . '/sites/site-' . $resource->getId() . '/deployments/deployment-' . $deployment->getId();
|
||||
$exception->addCTA('View logs', $url . $ctaUrl);
|
||||
break;
|
||||
case 'canceled':
|
||||
$exception = new AppwriteException(AppwriteException::BUILD_CANCELED, view: $errorView);
|
||||
$ctaUrl = '/console/project-' . $project->getId() . '/sites/site-' . $resource->getId() . '/deployments';
|
||||
$exception->addCTA('View deployments', $url . $ctaUrl);
|
||||
break;
|
||||
default:
|
||||
$exception = new AppwriteException(AppwriteException::BUILD_NOT_READY, view: $errorView);
|
||||
$ctaUrl = '/console/project-' . $project->getId() . '/sites/site-' . $resource->getId() . '/deployments/deployment-' . $deployment->getId();
|
||||
$exception->addCTA('Reload', '/');
|
||||
$exception->addCTA('View logs', $url . $ctaUrl);
|
||||
break;
|
||||
if ($deployment->getAttribute('status') === 'failed') {
|
||||
throw new AppwriteException(AppwriteException::BUILD_FAILED);
|
||||
} else {
|
||||
throw new AppwriteException(AppwriteException::BUILD_NOT_READY);
|
||||
}
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
if ($type === 'function') {
|
||||
$permissions = $resource->getAttribute('execute');
|
||||
if (!(\in_array('any', $permissions)) && !(\in_array('guests', $permissions))) {
|
||||
$exception = new AppwriteException(AppwriteException::FUNCTION_EXECUTE_PERMISSION_MISSING, view: $errorView);
|
||||
$exception->addCTA('View settings', $url . '/console/project-' . $project->getId() . '/functions/function-' . $resource->getId() . '/settings');
|
||||
throw $exception;
|
||||
throw new AppwriteException(AppwriteException::USER_UNAUTHORIZED, 'To execute function using domain, execute permissions must include "any" or "guests"');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,6 +420,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
}
|
||||
|
||||
/** Execute function */
|
||||
$executor = new Executor(System::getEnv('_APP_EXECUTOR_HOST'));
|
||||
try {
|
||||
$version = match ($type) {
|
||||
'function' => $resource->getAttribute('version', 'v2'),
|
||||
@@ -538,24 +505,6 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
}
|
||||
}
|
||||
|
||||
// Branded error pages (when developer left body empty)
|
||||
if ($executionResponse['statusCode'] >= 400 && empty($executionResponse['body'])) {
|
||||
$layout = new View($errorView);
|
||||
$layout
|
||||
->setParam('title', $project->getAttribute('name') . ' - Error')
|
||||
->setParam('type', 'proxy_error_override')
|
||||
->setParam('code', $executionResponse['statusCode']);
|
||||
|
||||
$executionResponse['body'] = $layout->render();
|
||||
foreach ($executionResponse['headers'] as $key => $value) {
|
||||
if (\strtolower($key) === 'content-length') {
|
||||
$executionResponse['headers'][$key] = \strlen($executionResponse['body']);
|
||||
} elseif (\strtolower($key) === 'content-type') {
|
||||
$executionResponse['headers'][$key] = 'text/html';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$headersFiltered = [];
|
||||
foreach ($executionResponse['headers'] as $key => $value) {
|
||||
if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_RESPONSE)) {
|
||||
@@ -637,67 +586,22 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
$fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size'];
|
||||
}
|
||||
|
||||
if (!empty($apiKey) && !empty($apiKey->getDisabledMetrics())) {
|
||||
foreach ($apiKey->getDisabledMetrics() as $key) {
|
||||
$queueForStatsUsage->disableMetric($key);
|
||||
}
|
||||
}
|
||||
|
||||
$metricTypeExecutions = str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_EXECUTIONS);
|
||||
$metricTypeIdExecutions = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS);
|
||||
$metricTypeExecutionsCompute = str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE);
|
||||
$metricTypeIdExecutionsCompute = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE);
|
||||
$metricTypeExecutionsMbSeconds = str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS);
|
||||
$metricTypeIdExecutionsMBSeconds = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS);
|
||||
if ($deployment->getAttribute('resourceType') === 'sites') {
|
||||
$queueForStatsUsage
|
||||
->disableMetric(METRIC_NETWORK_REQUESTS)
|
||||
->disableMetric(METRIC_NETWORK_INBOUND)
|
||||
->disableMetric(METRIC_NETWORK_OUTBOUND);
|
||||
if ($resource->getAttribute('adapter') !== 'ssr') {
|
||||
$queueForStatsUsage
|
||||
->disableMetric(METRIC_EXECUTIONS)
|
||||
->disableMetric(METRIC_EXECUTIONS_COMPUTE)
|
||||
->disableMetric(METRIC_EXECUTIONS_MB_SECONDS)
|
||||
->disableMetric($metricTypeExecutions)
|
||||
->disableMetric($metricTypeIdExecutions)
|
||||
->disableMetric($metricTypeExecutionsCompute)
|
||||
->disableMetric($metricTypeIdExecutionsCompute)
|
||||
->disableMetric($metricTypeExecutionsMbSeconds)
|
||||
->disableMetric($metricTypeIdExecutionsMBSeconds);
|
||||
}
|
||||
|
||||
$queueForStatsUsage
|
||||
->addMetric(METRIC_SITES_REQUESTS, 1)
|
||||
->addMetric(METRIC_SITES_INBOUND, $request->getSize() + $fileSize)
|
||||
->addMetric(METRIC_SITES_OUTBOUND, $response->getSize())
|
||||
->addMetric(str_replace('{siteInternalId}', $resource->getInternalId(), METRIC_SITES_ID_REQUESTS), 1)
|
||||
->addMetric(str_replace('{siteInternalId}', $resource->getInternalId(), METRIC_SITES_ID_INBOUND), $request->getSize() + $fileSize)
|
||||
->addMetric(str_replace('{siteInternalId}', $resource->getInternalId(), METRIC_SITES_ID_OUTBOUND), $response->getSize())
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
$compute = (int)($execution->getAttribute('duration') * 1000);
|
||||
$mbSeconds = (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT));
|
||||
$queueForStatsUsage
|
||||
->addMetric(METRIC_NETWORK_REQUESTS, 1)
|
||||
->addMetric(METRIC_NETWORK_INBOUND, $request->getSize() + $fileSize)
|
||||
->addMetric(METRIC_NETWORK_OUTBOUND, $response->getSize())
|
||||
->addMetric(METRIC_EXECUTIONS, 1)
|
||||
->addMetric($metricTypeExecutions, 1)
|
||||
->addMetric($metricTypeIdExecutions, 1)
|
||||
->addMetric(METRIC_EXECUTIONS_COMPUTE, $compute) // per project
|
||||
->addMetric($metricTypeExecutionsCompute, $compute) // per function
|
||||
->addMetric($metricTypeIdExecutionsCompute, $compute) // per function
|
||||
->addMetric(METRIC_EXECUTIONS_MB_SECONDS, $mbSeconds)
|
||||
->addMetric($metricTypeExecutionsMbSeconds, $mbSeconds)
|
||||
->addMetric($metricTypeIdExecutionsMBSeconds, $mbSeconds)
|
||||
->addMetric(str_replace('{functionInternalId}', $resource->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), 1)
|
||||
->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000)) // per project
|
||||
->addMetric(str_replace('{functionInternalId}', $resource->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function
|
||||
->addMetric(METRIC_EXECUTIONS_MB_SECONDS, (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT)))
|
||||
->addMetric(str_replace('{functionInternalId}', $resource->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT)))
|
||||
->setProject($project)
|
||||
->trigger();
|
||||
|
||||
return true;
|
||||
} elseif ($type === 'api') {
|
||||
$utopia->getRoute()?->label('error', '');
|
||||
return false;
|
||||
} elseif ($type === 'redirect') {
|
||||
$url = $rule->getAttribute('redirectUrl', '');
|
||||
@@ -710,9 +614,10 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
$response->redirect($url, \intval($rule->getAttribute('redirectStatusCode', 301)));
|
||||
return true;
|
||||
} else {
|
||||
throw new AppwriteException(AppwriteException::GENERAL_SERVER_ERROR, 'Unknown resource type ' . $type, view: $errorView);
|
||||
throw new AppwriteException(AppwriteException::GENERAL_SERVER_ERROR, 'Unknown resource type ' . $type);
|
||||
}
|
||||
|
||||
$utopia->getRoute()?->label('error', '');
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -757,12 +662,10 @@ App::init()
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForCertificates')
|
||||
->inject('queueForFunctions')
|
||||
->inject('executor')
|
||||
->inject('isResourceBlocked')
|
||||
->inject('previewHostname')
|
||||
->inject('devKey')
|
||||
->inject('apiKey')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, Executor $executor, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey) {
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) {
|
||||
/*
|
||||
* Appwrite Router
|
||||
*/
|
||||
@@ -770,7 +673,7 @@ App::init()
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
// Only run Router when external domain
|
||||
if ($host !== $mainDomain || !empty($previewHostname)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) {
|
||||
$utopia->getRoute()?->label('router', true);
|
||||
}
|
||||
}
|
||||
@@ -995,10 +898,6 @@ App::init()
|
||||
->addHeader('Access-Control-Allow-Origin', $refDomain)
|
||||
->addHeader('Access-Control-Allow-Credentials', 'true');
|
||||
|
||||
if (!$devKey->isEmpty()) {
|
||||
$response->addHeader('Access-Control-Allow-Origin', '*');
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate Client Domain - Check to avoid CSRF attack
|
||||
* Adding Appwrite API domains to allow XDOMAIN communication
|
||||
@@ -1009,7 +908,6 @@ App::init()
|
||||
|
||||
if (
|
||||
!$originValidator->isValid($origin)
|
||||
&& $devKey->isEmpty()
|
||||
&& \in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_PATCH, Request::METHOD_DELETE])
|
||||
&& $route->getLabel('origin', false) !== '*'
|
||||
&& empty($request->getHeader('x-appwrite-key', ''))
|
||||
@@ -1028,14 +926,12 @@ App::options()
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('queueForFunctions')
|
||||
->inject('executor')
|
||||
->inject('geodb')
|
||||
->inject('isResourceBlocked')
|
||||
->inject('previewHostname')
|
||||
->inject('project')
|
||||
->inject('devKey')
|
||||
->inject('apiKey')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey) {
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname, Document $project, ?Key $apiKey) {
|
||||
/*
|
||||
* Appwrite Router
|
||||
*/
|
||||
@@ -1043,7 +939,7 @@ App::options()
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
// Only run Router when external domain
|
||||
if ($host !== $mainDomain || !empty($previewHostname)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) {
|
||||
$utopia->getRoute()?->label('router', true);
|
||||
}
|
||||
}
|
||||
@@ -1059,10 +955,6 @@ App::options()
|
||||
->addHeader('Access-Control-Allow-Credentials', 'true')
|
||||
->noContent();
|
||||
|
||||
if (!$devKey->isEmpty()) {
|
||||
$response->addHeader('Access-Control-Allow-Origin', '*');
|
||||
}
|
||||
|
||||
/** OPTIONS requests in utopia do not execute shutdown handlers, as a result we need to track the OPTIONS requests explicitly
|
||||
* @see https://github.com/utopia-php/http/blob/0.33.16/src/App.php#L825-L855
|
||||
*/
|
||||
@@ -1083,7 +975,6 @@ App::error()
|
||||
->inject('logger')
|
||||
->inject('log')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('devKey')
|
||||
->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, StatsUsage $queueForStatsUsage) {
|
||||
$version = System::getEnv('_APP_VERSION', 'UNKNOWN');
|
||||
$route = $utopia->getRoute();
|
||||
@@ -1165,18 +1056,17 @@ App::error()
|
||||
if (!empty($providerConfig) && $error->getCode() >= 400 && $error->getCode() < 500) {
|
||||
// Register error logger
|
||||
try {
|
||||
$loggingProvider = new DSN($providerConfig);
|
||||
$loggingProvider = new DSN($providerConfig ?? '');
|
||||
$providerName = $loggingProvider->getScheme();
|
||||
|
||||
if (!empty($providerName) && $providerName === 'sentry') {
|
||||
$key = $loggingProvider->getPassword();
|
||||
$projectId = $loggingProvider->getUser() ?? '';
|
||||
$host = 'https://' . $loggingProvider->getHost();
|
||||
$sampleRate = $loggingProvider->getParam('sample', 0.01);
|
||||
|
||||
$adapter = new Sentry($projectId, $key, $host);
|
||||
$logger = new Logger($adapter);
|
||||
$logger->setSample($sampleRate);
|
||||
$logger->setSample(0.01);
|
||||
$publish = true;
|
||||
} else {
|
||||
throw new \Exception('Invalid experimental logging provider');
|
||||
@@ -1298,7 +1188,7 @@ App::error()
|
||||
|
||||
$type = $error->getType();
|
||||
|
||||
$output = App::isDevelopment() ? [
|
||||
$output = ((App::isDevelopment())) ? [
|
||||
'message' => $message,
|
||||
'code' => $code,
|
||||
'file' => $file,
|
||||
@@ -1319,14 +1209,9 @@ App::error()
|
||||
->addHeader('Pragma', 'no-cache')
|
||||
->setStatusCode($code);
|
||||
|
||||
$template = $error->getView() ?? (($route) ? $route->getLabel('error', null) : null);
|
||||
$template = ($route) ? $route->getLabel('error', null) : null;
|
||||
|
||||
// TODO: Ideally use group 'api' here, but all wildcard routes seem to have 'api' at the moment
|
||||
if (!\str_starts_with($route->getPath(), '/v1')) {
|
||||
$template = __DIR__ . '/../views/general/error.phtml';
|
||||
}
|
||||
|
||||
if (!empty($template)) {
|
||||
if ($template) {
|
||||
$layout = new View($template);
|
||||
|
||||
$layout
|
||||
@@ -1337,8 +1222,7 @@ App::error()
|
||||
->setParam('message', $output['message'] ?? '')
|
||||
->setParam('type', $output['type'] ?? '')
|
||||
->setParam('code', $output['code'] ?? '')
|
||||
->setParam('trace', $output['trace'] ?? [])
|
||||
->setParam('exception', $error);
|
||||
->setParam('trace', $output['trace'] ?? []);
|
||||
|
||||
$response->html($layout->render());
|
||||
return;
|
||||
@@ -1363,12 +1247,11 @@ App::get('/robots.txt')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('queueForFunctions')
|
||||
->inject('executor')
|
||||
->inject('geodb')
|
||||
->inject('isResourceBlocked')
|
||||
->inject('previewHostname')
|
||||
->inject('apiKey')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) {
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) {
|
||||
$host = $request->getHostname() ?? '';
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
|
||||
@@ -1376,7 +1259,7 @@ App::get('/robots.txt')
|
||||
$template = new View(__DIR__ . '/../views/general/robots.phtml');
|
||||
$response->text($template->render(false));
|
||||
} else {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) {
|
||||
$utopia->getRoute()?->label('router', true);
|
||||
}
|
||||
}
|
||||
@@ -1395,12 +1278,11 @@ App::get('/humans.txt')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('queueForFunctions')
|
||||
->inject('executor')
|
||||
->inject('geodb')
|
||||
->inject('isResourceBlocked')
|
||||
->inject('previewHostname')
|
||||
->inject('apiKey')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) {
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) {
|
||||
$host = $request->getHostname() ?? '';
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
|
||||
@@ -1408,7 +1290,7 @@ App::get('/humans.txt')
|
||||
$template = new View(__DIR__ . '/../views/general/humans.phtml');
|
||||
$response->text($template->render(false));
|
||||
} else {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) {
|
||||
$utopia->getRoute()?->label('router', true);
|
||||
}
|
||||
}
|
||||
@@ -1555,12 +1437,11 @@ foreach (Config::getParam('services', []) as $service) {
|
||||
}
|
||||
}
|
||||
|
||||
// Modules
|
||||
$platform = new Appwrite();
|
||||
$platform->init(Service::TYPE_HTTP);
|
||||
|
||||
// Check for any errors found while we were initialising the SDK Methods.
|
||||
if (!empty(Method::getErrors())) {
|
||||
throw new \Exception('Errors found during SDK initialization:' . PHP_EOL . implode(PHP_EOL, Method::getErrors()));
|
||||
}
|
||||
|
||||
// Modules
|
||||
|
||||
$platform = new Appwrite();
|
||||
$platform->init(Service::TYPE_HTTP);
|
||||
|
||||
@@ -175,10 +175,8 @@ $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}'], [$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);
|
||||
->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);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -250,7 +248,7 @@ App::init()
|
||||
);
|
||||
|
||||
if ($dbKey) {
|
||||
$accessedAt = $dbKey->getAttribute('accessedAt', 0);
|
||||
$accessedAt = $dbKey->getAttribute('accessedAt', '');
|
||||
|
||||
if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_KEY_ACCESS)) > $accessedAt) {
|
||||
$dbKey->setAttribute('accessedAt', DateTime::now());
|
||||
@@ -261,7 +259,7 @@ App::init()
|
||||
$sdkValidator = new WhiteList($servers, true);
|
||||
$sdk = $request->getHeader('x-sdk-name', 'UNKNOWN');
|
||||
|
||||
if ($sdk !== 'UNKNOWN' && $sdkValidator->isValid($sdk)) {
|
||||
if ($sdkValidator->isValid($sdk)) {
|
||||
$sdks = $dbKey->getAttribute('sdks', []);
|
||||
|
||||
if (!in_array($sdk, $sdks)) {
|
||||
@@ -311,7 +309,7 @@ App::init()
|
||||
|
||||
// Update project last activity
|
||||
if (!$project->isEmpty() && $project->getId() !== 'console') {
|
||||
$accessedAt = $project->getAttribute('accessedAt', 0);
|
||||
$accessedAt = $project->getAttribute('accessedAt', '');
|
||||
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));
|
||||
@@ -320,7 +318,7 @@ App::init()
|
||||
|
||||
// Update user last activity
|
||||
if (!empty($user->getId())) {
|
||||
$accessedAt = $user->getAttribute('accessedAt', 0);
|
||||
$accessedAt = $user->getAttribute('accessedAt', '');
|
||||
if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_USER_ACCESS)) > $accessedAt) {
|
||||
$user->setAttribute('accessedAt', DateTime::now());
|
||||
|
||||
@@ -399,12 +397,9 @@ App::init()
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('dbForProject')
|
||||
->inject('timelimit')
|
||||
->inject('resourceToken')
|
||||
->inject('mode')
|
||||
->inject('apiKey')
|
||||
->inject('plan')
|
||||
->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) {
|
||||
->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) use ($usageDatabaseListener, $eventDatabaseListener) {
|
||||
|
||||
$route = $utopia->getRoute();
|
||||
|
||||
@@ -471,7 +466,6 @@ 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);
|
||||
@@ -535,10 +529,6 @@ App::init()
|
||||
|
||||
$useCache = $route->getLabel('cache', false);
|
||||
if ($useCache) {
|
||||
$route = $utopia->match($request);
|
||||
$isImageTransformation = $route->getPath() === '/v1/storage/buckets/:bucketId/files/:fileId/preview';
|
||||
$isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !Auth::isPrivilegedUser(Authorization::getRoles());
|
||||
|
||||
$key = md5($request->getURI() . '*' . implode('*', $request->getParams()) . '*' . APP_CACHE_BUSTER);
|
||||
$cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key));
|
||||
$cache = new Cache(
|
||||
@@ -551,14 +541,10 @@ App::init()
|
||||
$parts = explode('/', $cacheLog->getAttribute('resourceType'));
|
||||
$type = $parts[0] ?? null;
|
||||
|
||||
if ($type === 'bucket' && (!$isImageTransformation || !$isDisabled)) {
|
||||
if ($type === 'bucket') {
|
||||
$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);
|
||||
}
|
||||
@@ -566,23 +552,20 @@ App::init()
|
||||
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
|
||||
$validator = new Authorization(Database::PERMISSION_READ);
|
||||
$valid = $validator->isValid($bucket->getRead());
|
||||
if (!$fileSecurity && !$valid && !$isToken) {
|
||||
|
||||
if (!$fileSecurity && !$valid) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$parts = explode('/', $cacheLog->getAttribute('resource'));
|
||||
$fileId = $parts[1] ?? null;
|
||||
|
||||
if ($fileSecurity && !$valid && !$isToken) {
|
||||
if ($fileSecurity && !$valid) {
|
||||
$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);
|
||||
}
|
||||
@@ -599,10 +582,8 @@ App::init()
|
||||
$response
|
||||
->addHeader('Cache-Control', sprintf('private, max-age=%d', $timestamp))
|
||||
->addHeader('X-Appwrite-Cache', 'hit')
|
||||
->setContentType($cacheLog->getAttribute('mimeType'));
|
||||
if (!$isImageTransformation || !$isDisabled) {
|
||||
$response->send($data);
|
||||
}
|
||||
->setContentType($cacheLog->getAttribute('mimeType'))
|
||||
->send($data);
|
||||
} else {
|
||||
$response
|
||||
->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate')
|
||||
@@ -808,7 +789,7 @@ App::shutdown()
|
||||
$key = md5($request->getURI() . '*' . implode('*', $request->getParams()) . '*' . APP_CACHE_BUSTER);
|
||||
$signature = md5($data['payload']);
|
||||
$cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key));
|
||||
$accessedAt = $cacheLog->getAttribute('accessedAt', 0);
|
||||
$accessedAt = $cacheLog->getAttribute('accessedAt', '');
|
||||
$now = DateTime::now();
|
||||
if ($cacheLog->isEmpty()) {
|
||||
Authorization::skip(fn () => $dbForProject->createDocument('cache', new Document([
|
||||
|
||||
@@ -50,7 +50,6 @@ 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`
|
||||
@@ -196,35 +195,36 @@ 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_BUILDS_MB_SECONDS = '{functionInternalId}.builds.mbSeconds';
|
||||
const METRIC_SITES_ID_BUILDS = 'sites.{siteInternalId}.builds';
|
||||
const METRIC_SITES_ID_BUILDS_SUCCESS = 'sites.{siteInternalId}.builds.success';
|
||||
const METRIC_SITES_ID_BUILDS_FAILED = 'sites.{siteInternalId}.builds.failed';
|
||||
const METRIC_SITES_ID_BUILDS_STORAGE = 'sites.{siteInternalId}.builds.storage';
|
||||
const METRIC_SITES_ID_BUILDS_COMPUTE = 'sites.{siteInternalId}.builds.compute';
|
||||
const METRIC_SITES_ID_BUILDS_COMPUTE_SUCCESS = 'sites.{siteInternalId}.builds.compute.success';
|
||||
const METRIC_SITES_ID_BUILDS_COMPUTE_FAILED = 'sites.{siteInternalId}.builds.compute.failed';
|
||||
const METRIC_SITES_ID_BUILDS_MB_SECONDS = 'sites.{siteInternalId}.builds.mbSeconds';
|
||||
const METRIC_FUNCTION_ID_DEPLOYMENTS = '{resourceType}.{resourceInternalId}.deployments';
|
||||
const METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE = '{resourceType}.{resourceInternalId}.deployments.storage';
|
||||
const METRIC_EXECUTIONS = 'executions';
|
||||
const METRIC_EXECUTIONS_COMPUTE = 'executions.compute';
|
||||
const METRIC_EXECUTIONS_MB_SECONDS = '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_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_SITE_ID_DEPLOYMENTS = '{resourceType}.{resourceInternalId}.deployments';
|
||||
const METRIC_SITE_ID_DEPLOYMENTS_STORAGE = '{resourceType}.{resourceInternalId}.deployments.storage';
|
||||
const METRIC_SITE_ID_BUILDS = '{siteInternalId}.builds';
|
||||
const METRIC_SITE_ID_BUILDS_STORAGE = '{siteInternalId}.builds.storage';
|
||||
const METRIC_SITE_ID_BUILDS_COMPUTE = '{siteInternalId}.builds.compute';
|
||||
const METRIC_SITE_ID_BUILDS_MB_SECONDS = '{siteInternalId}.builds.mbSeconds';
|
||||
const METRIC_NETWORK_REQUESTS = 'network.requests';
|
||||
const METRIC_NETWORK_INBOUND = 'network.inbound';
|
||||
const METRIC_NETWORK_OUTBOUND = 'network.outbound';
|
||||
@@ -239,12 +239,10 @@ const METRIC_TARGETS = 'targets';
|
||||
const METRIC_PROVIDER_TYPE_TARGETS = '{providerType}.targets';
|
||||
const METRIC_KEYS = 'keys';
|
||||
const METRIC_DOMAINS = 'domains';
|
||||
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';
|
||||
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';
|
||||
|
||||
// Resource types
|
||||
|
||||
|
||||
@@ -133,20 +133,6 @@ 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) {
|
||||
|
||||
@@ -21,7 +21,6 @@ use Appwrite\Extend\Exception;
|
||||
use Appwrite\GraphQL\Schema;
|
||||
use Appwrite\Network\Validator\Origin;
|
||||
use Appwrite\Utopia\Request;
|
||||
use Executor\Executor;
|
||||
use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis;
|
||||
use Utopia\App;
|
||||
use Utopia\Cache\Adapter\Sharding;
|
||||
@@ -29,7 +28,6 @@ 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;
|
||||
@@ -40,7 +38,6 @@ use Utopia\Logger\Log;
|
||||
use Utopia\Pools\Group;
|
||||
use Utopia\Queue\Publisher;
|
||||
use Utopia\Storage\Device;
|
||||
use Utopia\Storage\Device\AWS;
|
||||
use Utopia\Storage\Device\Backblaze;
|
||||
use Utopia\Storage\Device\DOSpaces;
|
||||
use Utopia\Storage\Device\Linode;
|
||||
@@ -50,7 +47,6 @@ use Utopia\Storage\Device\Wasabi;
|
||||
use Utopia\Storage\Storage;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\Hostname;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\VCS\Adapter\Git\GitHub as VcsGitHub;
|
||||
|
||||
// Runtime Execution
|
||||
@@ -514,10 +510,6 @@ App::setResource('deviceForSites', function ($project) {
|
||||
return getDevice(APP_STORAGE_SITES . '/app-' . $project->getId());
|
||||
}, ['project']);
|
||||
|
||||
App::setResource('deviceForImports', function (Document $project) {
|
||||
return getDevice(APP_STORAGE_IMPORTS . '/app-' . $project->getId());
|
||||
}, ['project']);
|
||||
|
||||
App::setResource('deviceForFunctions', function ($project) {
|
||||
return getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId());
|
||||
}, ['project']);
|
||||
@@ -552,12 +544,7 @@ function getDevice(string $root, string $connection = ''): Device
|
||||
|
||||
switch ($device) {
|
||||
case Storage::DEVICE_S3:
|
||||
if (!empty($url)) {
|
||||
return new S3($root, $accessKey, $accessSecret, $url, $region, $acl);
|
||||
} else {
|
||||
return new AWS($root, $accessKey, $accessSecret, $bucket, $region, $acl);
|
||||
}
|
||||
// no break
|
||||
return new S3($root, $accessKey, $accessSecret, $bucket, $region, $acl, $url);
|
||||
case STORAGE::DEVICE_DO_SPACES:
|
||||
$device = new DOSpaces($root, $accessKey, $accessSecret, $bucket, $region, $acl);
|
||||
$device->setHttpVersion(S3::HTTP_VERSION_1_1);
|
||||
@@ -584,12 +571,7 @@ function getDevice(string $root, string $connection = ''): Device
|
||||
$s3Bucket = System::getEnv('_APP_STORAGE_S3_BUCKET', '');
|
||||
$s3Acl = 'private';
|
||||
$s3EndpointUrl = System::getEnv('_APP_STORAGE_S3_ENDPOINT', '');
|
||||
if (!empty($s3EndpointUrl)) {
|
||||
return new S3($root, $s3AccessKey, $s3SecretKey, $s3EndpointUrl, $s3Region, $s3Acl);
|
||||
} else {
|
||||
return new AWS($root, $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl);
|
||||
}
|
||||
// no break
|
||||
return new S3($root, $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl, $s3EndpointUrl);
|
||||
case Storage::DEVICE_DO_SPACES:
|
||||
$doSpacesAccessKey = System::getEnv('_APP_STORAGE_DO_SPACES_ACCESS_KEY', '');
|
||||
$doSpacesSecretKey = System::getEnv('_APP_STORAGE_DO_SPACES_SECRET', '');
|
||||
@@ -791,49 +773,6 @@ 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 = $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') {
|
||||
@@ -895,48 +834,3 @@ App::setResource('apiKey', function (Request $request, Document $project): ?Key
|
||||
|
||||
return Key::decode($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(App::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'] ?? '';
|
||||
$secret = $payload['secret'] ?? '';
|
||||
if (empty($tokenId) || empty($secret)) {
|
||||
return new Document([]);
|
||||
}
|
||||
|
||||
$token = Authorization::skip(fn () => $dbForProject->getDocument('resourceTokens', $tokenId));
|
||||
|
||||
if ($token->isEmpty() || $token->getAttribute('secret') !== $secret) {
|
||||
return new Document([]);
|
||||
}
|
||||
|
||||
if ($token->getAttribute('resourceType') === 'file') {
|
||||
$internalIds = explode(':', $token->getAttribute('resourceInternalId'));
|
||||
$ids = explode(':', $token->getAttribute('resourceId'));
|
||||
|
||||
if (count($internalIds) !== 2 || count($ids) !== 2) {
|
||||
return new Document([]);
|
||||
}
|
||||
|
||||
return new Document([
|
||||
'bucketId' => $ids[0],
|
||||
'fileId' => $ids[1],
|
||||
'bucketInternalId' => $internalIds[0],
|
||||
'fileInternalId' => $internalIds[1],
|
||||
]);
|
||||
}
|
||||
}
|
||||
return new Document([]);
|
||||
}, ['project', 'dbForProject', 'request']);
|
||||
|
||||
@@ -1,112 +1,22 @@
|
||||
<?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', []);
|
||||
$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;
|
||||
}
|
||||
$projectName = $this->getParam('projectName', '');
|
||||
$projectURL = $this->getParam('projectURL', '');
|
||||
$title = $this->getParam('title', '')
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<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" />
|
||||
<meta charset="utf-8" />
|
||||
<meta name="description" content="" />
|
||||
<link rel="icon" href="/favicon.png" />
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/inter/inter-v8-latin-600.woff2"
|
||||
@@ -119,427 +29,102 @@ switch ($type) {
|
||||
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>
|
||||
@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);
|
||||
@media(min-width:768px) {
|
||||
article.card {
|
||||
padding: 2rem !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<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>
|
||||
<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>
|
||||
</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 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 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>
|
||||
</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>
|
||||
|
||||
</article>
|
||||
</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>
|
||||
@@ -65,8 +65,6 @@ $image = $this->getParam('image', '');
|
||||
- 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
|
||||
@@ -88,12 +86,10 @@ $image = $this->getParam('image', '');
|
||||
- _APP_OPTIONS_ABUSE
|
||||
- _APP_OPTIONS_ROUTER_PROTECTION
|
||||
- _APP_OPTIONS_FORCE_HTTPS
|
||||
- _APP_OPTIONS_ROUTER_FORCE_HTTPS
|
||||
- _APP_OPTIONS_COMPUTE_FORCE_HTTPS
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET_CNAME
|
||||
- _APP_DOMAIN_TARGET_AAAA
|
||||
- _APP_DOMAIN_TARGET_A
|
||||
- _APP_DOMAIN_TARGET
|
||||
- _APP_DOMAIN_FUNCTIONS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
@@ -138,14 +134,12 @@ $image = $this->getParam('image', '');
|
||||
- _APP_STORAGE_WASABI_REGION
|
||||
- _APP_STORAGE_WASABI_BUCKET
|
||||
- _APP_COMPUTE_SIZE_LIMIT
|
||||
- _APP_FUNCTIONS_TIMEOUT
|
||||
- _APP_SITES_TIMEOUT
|
||||
- _APP_COMPUTE_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
|
||||
@@ -155,7 +149,6 @@ $image = $this->getParam('image', '');
|
||||
- _APP_MAINTENANCE_RETENTION_CACHE
|
||||
- _APP_MAINTENANCE_RETENTION_ABUSE
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
|
||||
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
|
||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES
|
||||
- _APP_SMS_PROVIDER
|
||||
@@ -306,7 +299,6 @@ $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:
|
||||
@@ -349,7 +341,6 @@ $image = $this->getParam('image', '');
|
||||
- _APP_EXECUTOR_HOST
|
||||
- _APP_MAINTENANCE_RETENTION_ABUSE
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
|
||||
- _APP_MAINTENANCE_RETENTION_EXECUTION
|
||||
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
||||
- _APP_EMAIL_CERTIFICATES
|
||||
@@ -393,9 +384,7 @@ $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
|
||||
@@ -415,14 +404,13 @@ $image = $this->getParam('image', '');
|
||||
- _APP_VCS_GITHUB_APP_NAME
|
||||
- _APP_VCS_GITHUB_PRIVATE_KEY
|
||||
- _APP_VCS_GITHUB_APP_ID
|
||||
- _APP_FUNCTIONS_TIMEOUT
|
||||
- _APP_SITES_TIMEOUT
|
||||
- _APP_COMPUTE_TIMEOUT
|
||||
- _APP_COMPUTE_BUILD_TIMEOUT
|
||||
- _APP_COMPUTE_CPUS
|
||||
- _APP_COMPUTE_MEMORY
|
||||
- _APP_COMPUTE_SIZE_LIMIT
|
||||
- _APP_OPTIONS_FORCE_HTTPS
|
||||
- _APP_OPTIONS_ROUTER_FORCE_HTTPS
|
||||
- _APP_OPTIONS_COMPUTE_FORCE_HTTPS
|
||||
- _APP_DOMAIN
|
||||
- _APP_STORAGE_DEVICE
|
||||
- _APP_STORAGE_S3_ACCESS_KEY
|
||||
@@ -446,7 +434,6 @@ $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"; ?>
|
||||
@@ -467,9 +454,7 @@ $image = $this->getParam('image', '');
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET_CNAME
|
||||
- _APP_DOMAIN_TARGET_AAAA
|
||||
- _APP_DOMAIN_TARGET_A
|
||||
- _APP_DOMAIN_TARGET
|
||||
- _APP_DOMAIN_FUNCTIONS
|
||||
- _APP_EMAIL_CERTIFICATES
|
||||
- _APP_REDIS_HOST
|
||||
@@ -510,8 +495,7 @@ $image = $this->getParam('image', '');
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_FUNCTIONS_TIMEOUT
|
||||
- _APP_SITES_TIMEOUT
|
||||
- _APP_COMPUTE_TIMEOUT
|
||||
- _APP_COMPUTE_BUILD_TIMEOUT
|
||||
- _APP_COMPUTE_CPUS
|
||||
- _APP_COMPUTE_MEMORY
|
||||
@@ -622,9 +606,7 @@ $image = $this->getParam('image', '');
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET_CNAME
|
||||
- _APP_DOMAIN_TARGET_AAAA
|
||||
- _APP_DOMAIN_TARGET_A
|
||||
- _APP_DOMAIN_TARGET
|
||||
- _APP_EMAIL_SECURITY
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
@@ -653,9 +635,7 @@ $image = $this->getParam('image', '');
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET_CNAME
|
||||
- _APP_DOMAIN_TARGET_AAAA
|
||||
- _APP_DOMAIN_TARGET_A
|
||||
- _APP_DOMAIN_TARGET
|
||||
- _APP_DOMAIN_FUNCTIONS
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
@@ -672,7 +652,6 @@ $image = $this->getParam('image', '');
|
||||
- _APP_MAINTENANCE_RETENTION_CACHE
|
||||
- _APP_MAINTENANCE_RETENTION_ABUSE
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
|
||||
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
|
||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES
|
||||
|
||||
@@ -875,14 +854,6 @@ $image = $this->getParam('image', '');
|
||||
- appwrite
|
||||
environment:
|
||||
- _APP_ASSISTANT_OPENAI_API_KEY
|
||||
|
||||
appwrite-browser:
|
||||
image: appwrite/browser:0.2.2
|
||||
container_name: appwrite-browser
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
|
||||
openruntimes-executor:
|
||||
container_name: openruntimes-executor
|
||||
@@ -890,7 +861,7 @@ $image = $this->getParam('image', '');
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
stop_signal: SIGINT
|
||||
image: openruntimes/executor:0.7.13
|
||||
image: openruntimes/executor:0.7.0
|
||||
networks:
|
||||
- appwrite
|
||||
- runtimes
|
||||
@@ -898,7 +869,6 @@ $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
|
||||
@@ -909,9 +879,8 @@ $image = $this->getParam('image', '');
|
||||
- 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,$_APP_SITES_RUNTIMES
|
||||
- OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_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
|
||||
@@ -992,6 +961,5 @@ volumes:
|
||||
appwrite-uploads:
|
||||
appwrite-certificates:
|
||||
appwrite-functions:
|
||||
appwrite-sites:
|
||||
appwrite-builds:
|
||||
appwrite-config:
|
||||
|
||||
@@ -16,9 +16,10 @@ use Appwrite\Event\Migration;
|
||||
use Appwrite\Event\Realtime;
|
||||
use Appwrite\Event\StatsUsage;
|
||||
use Appwrite\Event\StatsUsageDump;
|
||||
/** remove */
|
||||
/** /remove */
|
||||
use Appwrite\Event\Webhook;
|
||||
use Appwrite\Platform\Appwrite;
|
||||
use Executor\Executor;
|
||||
use Swoole\Runtime;
|
||||
use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis;
|
||||
use Utopia\Cache\Adapter\Sharding;
|
||||
@@ -214,18 +215,15 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) {
|
||||
}, ['pools', 'cache']);
|
||||
|
||||
Server::setResource('abuseRetention', function () {
|
||||
return time() - (int) System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400); // 1 day
|
||||
return time() - (int) System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400);
|
||||
});
|
||||
|
||||
Server::setResource('auditRetention', function (Document $project) {
|
||||
if ($project->getId() === 'console') {
|
||||
return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE', 15778800)); // 6 months
|
||||
}
|
||||
return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_AUDIT', 1209600)); // 14 days
|
||||
}, ['project']);
|
||||
Server::setResource('auditRetention', function () {
|
||||
return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_AUDIT', 1209600));
|
||||
});
|
||||
|
||||
Server::setResource('executionRetention', function () {
|
||||
return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_EXECUTION', 1209600)); // 14 days
|
||||
return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_EXECUTION', 1209600));
|
||||
});
|
||||
|
||||
Server::setResource('cache', function (Registry $register) {
|
||||
@@ -343,10 +341,6 @@ 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']);
|
||||
@@ -378,7 +372,7 @@ Server::setResource('certificates', function () {
|
||||
});
|
||||
|
||||
Server::setResource('logError', function (Registry $register, Document $project) {
|
||||
return function (Throwable $error, string $namespace, string $action, ?array $extras = null) use ($register, $project) {
|
||||
return function (Throwable $error, string $namespace, string $action, ?array $extras) use ($register, $project) {
|
||||
$logger = $register->get('logger');
|
||||
|
||||
if ($logger) {
|
||||
@@ -400,7 +394,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);
|
||||
}
|
||||
|
||||
@@ -422,8 +416,6 @@ Server::setResource('logError', function (Registry $register, Document $project)
|
||||
};
|
||||
}, ['register', 'project']);
|
||||
|
||||
Server::setResource('executor', fn () => new Executor(fn (string $projectId, string $deploymentId) => System::getEnv('_APP_EXECUTOR_HOST')));
|
||||
|
||||
$pools = $register->get('pools');
|
||||
$platform = new Appwrite();
|
||||
$args = $platform->getEnv('argv');
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
services:
|
||||
traefik:
|
||||
ports:
|
||||
- 9500:8080
|
||||
appwrite:
|
||||
ports:
|
||||
- 9501:80
|
||||
appwrite-realtime:
|
||||
ports:
|
||||
- 9505:80
|
||||
mariadb:
|
||||
ports:
|
||||
- 3306:3306
|
||||
redis:
|
||||
ports:
|
||||
- 6379:6379
|
||||
# Dev Tools Start ------------------------------------------------------------------------------------------
|
||||
#
|
||||
# The Appwrite Team uses the following tools to help debug, monitor and diagnose the Appwrite stack
|
||||
#
|
||||
# Here is a description of the different tools and why are we using them:
|
||||
#
|
||||
# MailCatcher - An SMTP server. Catches all system emails and displays them in a nice UI.
|
||||
# RequestCatcher - An HTTP server. Catches all system https calls and displays them using a simple HTTP API. Used to debug & tests webhooks and HTTP tasks
|
||||
# Redis Insight - A nice UI for exploring Redis data
|
||||
# Adminer - A nice UI for exploring MariaDB data
|
||||
# GraphQl Explorer - A nice UI for exploring GraphQL API
|
||||
maildev: # used mainly for dev tests
|
||||
image: appwrite/mailcatcher:1.0.0
|
||||
container_name: appwrite-mailcatcher
|
||||
ports:
|
||||
- "9503:1080"
|
||||
networks:
|
||||
- appwrite
|
||||
|
||||
request-catcher: # used mainly for dev tests
|
||||
image: appwrite/requestcatcher:1.0.0
|
||||
container_name: appwrite-requestcatcher
|
||||
ports:
|
||||
- "9504:5000"
|
||||
networks:
|
||||
- appwrite
|
||||
|
||||
adminer:
|
||||
image: adminer
|
||||
container_name: appwrite-adminer
|
||||
restart: always
|
||||
ports:
|
||||
- 9506:8080
|
||||
networks:
|
||||
- appwrite
|
||||
|
||||
redis-insight:
|
||||
image: redis/redisinsight:latest
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
environment:
|
||||
- REDIS_HOSTS=redis
|
||||
ports:
|
||||
- "8081:5540"
|
||||
|
||||
graphql-explorer:
|
||||
container_name: appwrite-graphql-explorer
|
||||
image: appwrite/altair:0.3.0
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
ports:
|
||||
- "9509:3000"
|
||||
environment:
|
||||
- SERVER_URL=http://localhost/v1/graphql
|
||||
@@ -0,0 +1,55 @@
|
||||
# WARNING!
|
||||
# This is a development version of THE Appwrite docker-compose.yml file.
|
||||
# Avoid using this file in your production environment.
|
||||
# We're exposing here sensitive ports and mounting code volumes for rapid development and debugging of the server stack.
|
||||
|
||||
include:
|
||||
- ./compose/appwrite.yml
|
||||
- ./compose/assistant.yml
|
||||
- ./compose/browser.yml
|
||||
- ./compose/console.yml
|
||||
- ./compose/mariadb.yml
|
||||
- ./compose/realtime.yml
|
||||
- ./compose/redis.yml
|
||||
- ./compose/traefik.yml
|
||||
|
||||
- ./compose/openruntimes-proxy.yml
|
||||
- ./compose/openruntimes-executor.yml
|
||||
|
||||
- ./compose/task-scheduler-executions.yml
|
||||
- ./compose/task-scheduler-functions.yml
|
||||
- ./compose/task-scheduler-messages.yml
|
||||
|
||||
- ./compose/worker-audits.yml
|
||||
- ./compose/worker-builds.yml
|
||||
- ./compose/worker-certificates.yml
|
||||
- ./compose/worker-databases.yml
|
||||
- ./compose/worker-deletes.yml
|
||||
- ./compose/worker-functions.yml
|
||||
- ./compose/worker-mails.yml
|
||||
- ./compose/worker-maintenance.yml
|
||||
- ./compose/worker-messaging.yml
|
||||
- ./compose/worker-migrations.yml
|
||||
- ./compose/worker-stats-resources.yml
|
||||
- ./compose/worker-stats-usage.yml
|
||||
- ./compose/worker-stats-usage-dump.yml
|
||||
- ./compose/worker-webhooks.yml
|
||||
|
||||
networks:
|
||||
gateway:
|
||||
name: gateway
|
||||
appwrite:
|
||||
name: appwrite
|
||||
runtimes:
|
||||
name: runtimes
|
||||
|
||||
volumes:
|
||||
appwrite-mariadb:
|
||||
appwrite-redis:
|
||||
appwrite-cache:
|
||||
appwrite-uploads:
|
||||
appwrite-certificates:
|
||||
appwrite-functions:
|
||||
appwrite-sites:
|
||||
appwrite-builds:
|
||||
appwrite-config:
|
||||
@@ -0,0 +1,156 @@
|
||||
services:
|
||||
appwrite:
|
||||
container_name: appwrite
|
||||
image: appwrite-dev
|
||||
build:
|
||||
context: ..
|
||||
args:
|
||||
DEBUG: false
|
||||
TESTING: false
|
||||
VERSION: dev
|
||||
networks:
|
||||
- appwrite
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.constraint-label-stack=appwrite"
|
||||
- "traefik.docker.network=appwrite"
|
||||
- "traefik.http.services.appwrite_api.loadbalancer.server.port=80"
|
||||
#http
|
||||
- traefik.http.routers.appwrite_api_http.entrypoints=appwrite_web
|
||||
- traefik.http.routers.appwrite_api_http.rule=PathPrefix(`/`)
|
||||
- traefik.http.routers.appwrite_api_http.service=appwrite_api
|
||||
# https
|
||||
- traefik.http.routers.appwrite_api_https.entrypoints=appwrite_websecure
|
||||
- traefik.http.routers.appwrite_api_https.rule=PathPrefix(`/`)
|
||||
- traefik.http.routers.appwrite_api_https.service=appwrite_api
|
||||
- traefik.http.routers.appwrite_api_https.tls=true
|
||||
volumes:
|
||||
- appwrite-uploads:/storage/uploads: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
|
||||
- ../docs:/usr/src/code/docs
|
||||
- ../public:/usr/src/code/public
|
||||
- ../src:/usr/src/code/src
|
||||
- ../dev:/usr/src/code/dev
|
||||
depends_on:
|
||||
- mariadb
|
||||
- redis
|
||||
entrypoint:
|
||||
- php
|
||||
- -e
|
||||
- app/http.php
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_EDITION
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_LOCALE
|
||||
- _APP_COMPRESSION_MIN_SIZE_BYTES
|
||||
- _APP_CONSOLE_WHITELIST_ROOT
|
||||
- _APP_CONSOLE_WHITELIST_EMAILS
|
||||
- _APP_CONSOLE_SESSION_ALERTS
|
||||
- _APP_CONSOLE_WHITELIST_IPS
|
||||
- _APP_CONSOLE_HOSTNAMES
|
||||
- _APP_SYSTEM_EMAIL_NAME
|
||||
- _APP_SYSTEM_EMAIL_ADDRESS
|
||||
- _APP_SYSTEM_TEAM_EMAIL
|
||||
- _APP_EMAIL_SECURITY
|
||||
- _APP_SYSTEM_RESPONSE_FORMAT
|
||||
- _APP_OPTIONS_ABUSE
|
||||
- _APP_OPTIONS_ROUTER_PROTECTION
|
||||
- _APP_OPTIONS_FORCE_HTTPS
|
||||
- _APP_OPTIONS_COMPUTE_FORCE_HTTPS
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET
|
||||
- _APP_DOMAIN_FUNCTIONS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_SMTP_HOST
|
||||
- _APP_SMTP_PORT
|
||||
- _APP_SMTP_SECURE
|
||||
- _APP_SMTP_USERNAME
|
||||
- _APP_SMTP_PASSWORD
|
||||
- _APP_USAGE_STATS
|
||||
- _APP_STORAGE_LIMIT
|
||||
- _APP_STORAGE_PREVIEW_LIMIT
|
||||
- _APP_STORAGE_ANTIVIRUS
|
||||
- _APP_STORAGE_ANTIVIRUS_HOST
|
||||
- _APP_STORAGE_ANTIVIRUS_PORT
|
||||
- _APP_STORAGE_DEVICE
|
||||
- _APP_STORAGE_S3_ACCESS_KEY
|
||||
- _APP_STORAGE_S3_SECRET
|
||||
- _APP_STORAGE_S3_REGION
|
||||
- _APP_STORAGE_S3_BUCKET
|
||||
- _APP_STORAGE_S3_ENDPOINT
|
||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
|
||||
- _APP_STORAGE_DO_SPACES_SECRET
|
||||
- _APP_STORAGE_DO_SPACES_REGION
|
||||
- _APP_STORAGE_DO_SPACES_BUCKET
|
||||
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY
|
||||
- _APP_STORAGE_BACKBLAZE_SECRET
|
||||
- _APP_STORAGE_BACKBLAZE_REGION
|
||||
- _APP_STORAGE_BACKBLAZE_BUCKET
|
||||
- _APP_STORAGE_LINODE_ACCESS_KEY
|
||||
- _APP_STORAGE_LINODE_SECRET
|
||||
- _APP_STORAGE_LINODE_REGION
|
||||
- _APP_STORAGE_LINODE_BUCKET
|
||||
- _APP_STORAGE_WASABI_ACCESS_KEY
|
||||
- _APP_STORAGE_WASABI_SECRET
|
||||
- _APP_STORAGE_WASABI_REGION
|
||||
- _APP_STORAGE_WASABI_BUCKET
|
||||
- _APP_COMPUTE_SIZE_LIMIT
|
||||
- _APP_COMPUTE_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
|
||||
- _APP_MAINTENANCE_INTERVAL
|
||||
- _APP_MAINTENANCE_RETENTION_EXECUTION
|
||||
- _APP_MAINTENANCE_RETENTION_CACHE
|
||||
- _APP_MAINTENANCE_RETENTION_ABUSE
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
|
||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES
|
||||
- _APP_SMS_PROVIDER
|
||||
- _APP_SMS_FROM
|
||||
- _APP_GRAPHQL_MAX_BATCH_SIZE
|
||||
- _APP_GRAPHQL_MAX_COMPLEXITY
|
||||
- _APP_GRAPHQL_MAX_DEPTH
|
||||
- _APP_VCS_GITHUB_APP_NAME
|
||||
- _APP_VCS_GITHUB_PRIVATE_KEY
|
||||
- _APP_VCS_GITHUB_APP_ID
|
||||
- _APP_VCS_GITHUB_WEBHOOK_SECRET
|
||||
- _APP_VCS_GITHUB_CLIENT_SECRET
|
||||
- _APP_VCS_GITHUB_CLIENT_ID
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
|
||||
- _APP_ASSISTANT_OPENAI_API_KEY
|
||||
- _APP_MESSAGE_SMS_TEST_DSN
|
||||
- _APP_MESSAGE_EMAIL_TEST_DSN
|
||||
- _APP_MESSAGE_PUSH_TEST_DSN
|
||||
- _APP_CONSOLE_COUNTRIES_DENYLIST
|
||||
- _APP_EXPERIMENT_LOGGING_PROVIDER
|
||||
- _APP_EXPERIMENT_LOGGING_CONFIG
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
- _APP_DATABASE_SHARED_TABLES_V1
|
||||
- _APP_DATABASE_SHARED_NAMESPACE
|
||||
- _APP_FUNCTIONS_CREATION_ABUSE_LIMIT
|
||||
@@ -0,0 +1,8 @@
|
||||
services:
|
||||
appwrite-assistant:
|
||||
container_name: appwrite-assistant
|
||||
image: appwrite/assistant:0.7.0
|
||||
networks:
|
||||
- appwrite
|
||||
environment:
|
||||
- _APP_ASSISTANT_OPENAI_API_KEY
|
||||
@@ -0,0 +1,6 @@
|
||||
services:
|
||||
appwrite-browser:
|
||||
container_name: appwrite-browser
|
||||
image: appwrite/browser:0.2.2
|
||||
networks:
|
||||
- appwrite
|
||||
@@ -0,0 +1,21 @@
|
||||
services:
|
||||
appwrite-console:
|
||||
container_name: appwrite-console
|
||||
image: appwrite/console:5.3.0-sites-rc.36
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.constraint-label-stack=appwrite"
|
||||
- "traefik.docker.network=appwrite"
|
||||
- "traefik.http.services.appwrite_console.loadbalancer.server.port=80"
|
||||
#ws
|
||||
- traefik.http.routers.appwrite_console_http.entrypoints=appwrite_web
|
||||
- traefik.http.routers.appwrite_console_http.rule=PathPrefix(`/console`)
|
||||
- traefik.http.routers.appwrite_console_http.service=appwrite_console
|
||||
# wss
|
||||
- traefik.http.routers.appwrite_console_https.entrypoints=appwrite_websecure
|
||||
- traefik.http.routers.appwrite_console_https.rule=PathPrefix(`/console`)
|
||||
- traefik.http.routers.appwrite_console_https.service=appwrite_console
|
||||
- traefik.http.routers.appwrite_console_https.tls=true
|
||||
@@ -0,0 +1,15 @@
|
||||
services:
|
||||
mariadb:
|
||||
image: mariadb:10.11 # fix issues when upgrading using: mysql_upgrade -u root -p
|
||||
container_name: appwrite-mariadb
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- appwrite-mariadb:/var/lib/mysql:rw
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=${_APP_DB_ROOT_PASS}
|
||||
- MYSQL_DATABASE=${_APP_DB_SCHEMA}
|
||||
- MYSQL_USER=${_APP_DB_USER}
|
||||
- MYSQL_PASSWORD=${_APP_DB_PASS}
|
||||
- MARIADB_AUTO_UPGRADE=1
|
||||
command: "mysqld --innodb-flush-method=fsync"
|
||||
@@ -0,0 +1,52 @@
|
||||
services:
|
||||
openruntimes-executor:
|
||||
container_name: openruntimes-executor
|
||||
hostname: exc1
|
||||
stop_signal: SIGINT
|
||||
image: openruntimes/executor:0.7.13
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- appwrite
|
||||
- runtimes
|
||||
volumes:
|
||||
- /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_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,$_APP_SITES_RUNTIMES
|
||||
- OPR_EXECUTOR_SECRET=$_APP_EXECUTOR_SECRET
|
||||
- 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
|
||||
- OPR_EXECUTOR_STORAGE_S3_SECRET=$_APP_STORAGE_S3_SECRET
|
||||
- OPR_EXECUTOR_STORAGE_S3_REGION=$_APP_STORAGE_S3_REGION
|
||||
- OPR_EXECUTOR_STORAGE_S3_BUCKET=$_APP_STORAGE_S3_BUCKET
|
||||
- OPR_EXECUTOR_STORAGE_S3_ENDPOINT=$_APP_STORAGE_S3_ENDPOINT
|
||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_ACCESS_KEY=$_APP_STORAGE_DO_SPACES_ACCESS_KEY
|
||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_SECRET=$_APP_STORAGE_DO_SPACES_SECRET
|
||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_REGION=$_APP_STORAGE_DO_SPACES_REGION
|
||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_BUCKET=$_APP_STORAGE_DO_SPACES_BUCKET
|
||||
- OPR_EXECUTOR_STORAGE_BACKBLAZE_ACCESS_KEY=$_APP_STORAGE_BACKBLAZE_ACCESS_KEY
|
||||
- OPR_EXECUTOR_STORAGE_BACKBLAZE_SECRET=$_APP_STORAGE_BACKBLAZE_SECRET
|
||||
- OPR_EXECUTOR_STORAGE_BACKBLAZE_REGION=$_APP_STORAGE_BACKBLAZE_REGION
|
||||
- OPR_EXECUTOR_STORAGE_BACKBLAZE_BUCKET=$_APP_STORAGE_BACKBLAZE_BUCKET
|
||||
- OPR_EXECUTOR_STORAGE_LINODE_ACCESS_KEY=$_APP_STORAGE_LINODE_ACCESS_KEY
|
||||
- OPR_EXECUTOR_STORAGE_LINODE_SECRET=$_APP_STORAGE_LINODE_SECRET
|
||||
- OPR_EXECUTOR_STORAGE_LINODE_REGION=$_APP_STORAGE_LINODE_REGION
|
||||
- OPR_EXECUTOR_STORAGE_LINODE_BUCKET=$_APP_STORAGE_LINODE_BUCKET
|
||||
- OPR_EXECUTOR_STORAGE_WASABI_ACCESS_KEY=$_APP_STORAGE_WASABI_ACCESS_KEY
|
||||
- OPR_EXECUTOR_STORAGE_WASABI_SECRET=$_APP_STORAGE_WASABI_SECRET
|
||||
- OPR_EXECUTOR_STORAGE_WASABI_REGION=$_APP_STORAGE_WASABI_REGION
|
||||
- OPR_EXECUTOR_STORAGE_WASABI_BUCKET=$_APP_STORAGE_WASABI_BUCKET
|
||||
@@ -0,0 +1,20 @@
|
||||
services:
|
||||
openruntimes-proxy:
|
||||
container_name: openruntimes-proxy
|
||||
hostname: proxy
|
||||
stop_signal: SIGINT
|
||||
image: openruntimes/proxy:0.5.5
|
||||
networks:
|
||||
- appwrite
|
||||
- runtimes
|
||||
environment:
|
||||
- OPR_PROXY_WORKER_PER_CORE=$_APP_WORKER_PER_CORE
|
||||
- OPR_PROXY_ENV=$_APP_ENV
|
||||
- OPR_PROXY_EXECUTOR_SECRET=$_APP_EXECUTOR_SECRET
|
||||
- OPR_PROXY_SECRET=$_APP_EXECUTOR_SECRET
|
||||
- OPR_PROXY_LOGGING_CONFIG=$_APP_LOGGING_CONFIG
|
||||
- OPR_PROXY_ALGORITHM=random
|
||||
- OPR_PROXY_EXECUTORS=exc1
|
||||
- OPR_PROXY_HEALTHCHECK_INTERVAL=10000
|
||||
- OPR_PROXY_MAX_TIMEOUT=600
|
||||
- OPR_PROXY_HEALTHCHECK=enabled
|
||||
@@ -0,0 +1,46 @@
|
||||
services:
|
||||
appwrite-realtime:
|
||||
entrypoint: realtime
|
||||
container_name: appwrite-realtime
|
||||
image: appwrite-dev
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.constraint-label-stack=appwrite"
|
||||
- "traefik.docker.network=appwrite"
|
||||
- "traefik.http.services.appwrite_realtime.loadbalancer.server.port=80"
|
||||
#ws
|
||||
- traefik.http.routers.appwrite_realtime_ws.entrypoints=appwrite_web
|
||||
- traefik.http.routers.appwrite_realtime_ws.rule=PathPrefix(`/v1/realtime`)
|
||||
- traefik.http.routers.appwrite_realtime_ws.service=appwrite_realtime
|
||||
# wss
|
||||
- traefik.http.routers.appwrite_realtime_wss.entrypoints=appwrite_websecure
|
||||
- traefik.http.routers.appwrite_realtime_wss.rule=PathPrefix(`/v1/realtime`)
|
||||
- traefik.http.routers.appwrite_realtime_wss.service=appwrite_realtime
|
||||
- traefik.http.routers.appwrite_realtime_wss.tls=true
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- ../app:/usr/src/code/app
|
||||
- ../src:/usr/src/code/src
|
||||
depends_on:
|
||||
- mariadb
|
||||
- redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPTIONS_ABUSE
|
||||
- _APP_OPTIONS_ROUTER_PROTECTION
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_USAGE_STATS
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
@@ -0,0 +1,13 @@
|
||||
services:
|
||||
redis:
|
||||
image: redis:7.2.4-alpine
|
||||
container_name: appwrite-redis
|
||||
command: >
|
||||
redis-server
|
||||
--maxmemory 512mb
|
||||
--maxmemory-policy allkeys-lru
|
||||
--maxmemory-samples 5
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- appwrite-redis:/data:rw
|
||||
@@ -0,0 +1,26 @@
|
||||
services:
|
||||
appwrite-task-scheduler-executions:
|
||||
entrypoint: schedule-executions
|
||||
container_name: appwrite-task-scheduler-executions
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- ../app:/usr/src/code/app
|
||||
- ../src:/usr/src/code/src
|
||||
depends_on:
|
||||
- mariadb
|
||||
- redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
@@ -0,0 +1,27 @@
|
||||
services:
|
||||
appwrite-task-scheduler-functions:
|
||||
entrypoint: schedule-functions
|
||||
container_name: appwrite-task-scheduler-functions
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- ../app:/usr/src/code/app
|
||||
- ../src:/usr/src/code/src
|
||||
depends_on:
|
||||
- mariadb
|
||||
- redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
@@ -0,0 +1,27 @@
|
||||
services:
|
||||
appwrite-task-scheduler-messages:
|
||||
entrypoint: schedule-messages
|
||||
container_name: appwrite-task-scheduler-messages
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- ../app:/usr/src/code/app
|
||||
- ../src:/usr/src/code/src
|
||||
depends_on:
|
||||
- mariadb
|
||||
- redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
@@ -0,0 +1,30 @@
|
||||
services:
|
||||
appwrite-task-stats-resources:
|
||||
container_name: appwrite-task-stats-resources
|
||||
entrypoint: stats-resources
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- ../app:/usr/src/code/app
|
||||
- ../src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_USAGE_STATS
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
- _APP_STATS_RESOURCES_INTERVAL
|
||||
@@ -0,0 +1,29 @@
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:2.11
|
||||
container_name: appwrite-traefik
|
||||
command:
|
||||
- --log.level=DEBUG
|
||||
- --api.insecure=true
|
||||
- --providers.file.directory=/storage/config
|
||||
- --providers.file.watch=true
|
||||
- --providers.docker=true
|
||||
- --providers.docker.exposedByDefault=false
|
||||
- --providers.docker.constraints=Label(`traefik.constraint-label-stack`,`appwrite`)
|
||||
- --entrypoints.appwrite_web.address=:80
|
||||
- --entrypoints.appwrite_websecure.address=:443
|
||||
- --accesslog=true
|
||||
ports:
|
||||
- 80:80
|
||||
- 8080:80
|
||||
- 443:443
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- appwrite-config:/storage/config:ro
|
||||
- appwrite-certificates:/storage/certificates:ro
|
||||
depends_on:
|
||||
- appwrite
|
||||
networks:
|
||||
- gateway
|
||||
- appwrite
|
||||
- runtimes
|
||||
@@ -0,0 +1,28 @@
|
||||
services:
|
||||
appwrite-worker-audits:
|
||||
entrypoint: worker-audits
|
||||
container_name: appwrite-worker-audits
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- ../app:/usr/src/code/app
|
||||
- ../src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
@@ -0,0 +1,68 @@
|
||||
services:
|
||||
appwrite-worker-builds:
|
||||
entrypoint: worker-builds
|
||||
container_name: appwrite-worker-builds
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- 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:
|
||||
- redis
|
||||
- mariadb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_EXECUTOR_SECRET
|
||||
- _APP_EXECUTOR_HOST
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_VCS_GITHUB_APP_NAME
|
||||
- _APP_VCS_GITHUB_PRIVATE_KEY
|
||||
- _APP_VCS_GITHUB_APP_ID
|
||||
- _APP_COMPUTE_TIMEOUT
|
||||
- _APP_COMPUTE_BUILD_TIMEOUT
|
||||
- _APP_COMPUTE_CPUS
|
||||
- _APP_COMPUTE_MEMORY
|
||||
- _APP_COMPUTE_SIZE_LIMIT
|
||||
- _APP_OPTIONS_FORCE_HTTPS
|
||||
- _APP_OPTIONS_COMPUTE_FORCE_HTTPS
|
||||
- _APP_DOMAIN
|
||||
- _APP_STORAGE_DEVICE
|
||||
- _APP_STORAGE_S3_ACCESS_KEY
|
||||
- _APP_STORAGE_S3_SECRET
|
||||
- _APP_STORAGE_S3_REGION
|
||||
- _APP_STORAGE_S3_BUCKET
|
||||
- _APP_STORAGE_S3_ENDPOINT
|
||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
|
||||
- _APP_STORAGE_DO_SPACES_SECRET
|
||||
- _APP_STORAGE_DO_SPACES_REGION
|
||||
- _APP_STORAGE_DO_SPACES_BUCKET
|
||||
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY
|
||||
- _APP_STORAGE_BACKBLAZE_SECRET
|
||||
- _APP_STORAGE_BACKBLAZE_REGION
|
||||
- _APP_STORAGE_BACKBLAZE_BUCKET
|
||||
- _APP_STORAGE_LINODE_ACCESS_KEY
|
||||
- _APP_STORAGE_LINODE_SECRET
|
||||
- _APP_STORAGE_LINODE_REGION
|
||||
- _APP_STORAGE_LINODE_BUCKET
|
||||
- _APP_STORAGE_WASABI_ACCESS_KEY
|
||||
- _APP_STORAGE_WASABI_SECRET
|
||||
- _APP_STORAGE_WASABI_REGION
|
||||
- _APP_STORAGE_WASABI_BUCKET
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
- _APP_DOMAIN_SITES
|
||||
@@ -0,0 +1,34 @@
|
||||
services:
|
||||
appwrite-worker-certificates:
|
||||
entrypoint: worker-certificates
|
||||
container_name: appwrite-worker-certificates
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
volumes:
|
||||
- appwrite-config:/storage/config:rw
|
||||
- appwrite-certificates:/storage/certificates:rw
|
||||
- ../app:/usr/src/code/app
|
||||
- ../src:/usr/src/code/src
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET
|
||||
- _APP_DOMAIN_FUNCTIONS
|
||||
- _APP_EMAIL_CERTIFICATES
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
@@ -0,0 +1,30 @@
|
||||
services:
|
||||
appwrite-worker-databases:
|
||||
entrypoint: worker-databases
|
||||
container_name: appwrite-worker-databases
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- ../app:/usr/src/code/app
|
||||
- ../src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_WORKERS_NUM
|
||||
- _APP_QUEUE_NAME
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
@@ -0,0 +1,60 @@
|
||||
services:
|
||||
appwrite-worker-deletes:
|
||||
entrypoint: worker-deletes
|
||||
container_name: appwrite-worker-deletes
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
volumes:
|
||||
- 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
|
||||
- ../src:/usr/src/code/src
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_STORAGE_DEVICE
|
||||
- _APP_STORAGE_S3_ACCESS_KEY
|
||||
- _APP_STORAGE_S3_SECRET
|
||||
- _APP_STORAGE_S3_REGION
|
||||
- _APP_STORAGE_S3_BUCKET
|
||||
- _APP_STORAGE_S3_ENDPOINT
|
||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
|
||||
- _APP_STORAGE_DO_SPACES_SECRET
|
||||
- _APP_STORAGE_DO_SPACES_REGION
|
||||
- _APP_STORAGE_DO_SPACES_BUCKET
|
||||
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY
|
||||
- _APP_STORAGE_BACKBLAZE_SECRET
|
||||
- _APP_STORAGE_BACKBLAZE_REGION
|
||||
- _APP_STORAGE_BACKBLAZE_BUCKET
|
||||
- _APP_STORAGE_LINODE_ACCESS_KEY
|
||||
- _APP_STORAGE_LINODE_SECRET
|
||||
- _APP_STORAGE_LINODE_REGION
|
||||
- _APP_STORAGE_LINODE_BUCKET
|
||||
- _APP_STORAGE_WASABI_ACCESS_KEY
|
||||
- _APP_STORAGE_WASABI_SECRET
|
||||
- _APP_STORAGE_WASABI_REGION
|
||||
- _APP_STORAGE_WASABI_BUCKET
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_EXECUTOR_SECRET
|
||||
- _APP_EXECUTOR_HOST
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
- _APP_DATABASE_SHARED_TABLES_V1
|
||||
- _APP_EMAIL_CERTIFICATES
|
||||
@@ -0,0 +1,41 @@
|
||||
services:
|
||||
appwrite-worker-functions:
|
||||
entrypoint: worker-functions
|
||||
container_name: appwrite-worker-functions
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- ../app:/usr/src/code/app
|
||||
- ../src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
- openruntimes-executor
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_OPTIONS_FORCE_HTTPS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_COMPUTE_TIMEOUT
|
||||
- _APP_COMPUTE_BUILD_TIMEOUT
|
||||
- _APP_COMPUTE_CPUS
|
||||
- _APP_COMPUTE_MEMORY
|
||||
- _APP_EXECUTOR_SECRET
|
||||
- _APP_EXECUTOR_HOST
|
||||
- _APP_USAGE_STATS
|
||||
- _APP_DOCKER_HUB_USERNAME
|
||||
- _APP_DOCKER_HUB_PASSWORD
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_LOGGING_PROVIDER
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
@@ -0,0 +1,31 @@
|
||||
services:
|
||||
appwrite-worker-mails:
|
||||
entrypoint: worker-mails
|
||||
container_name: appwrite-worker-mails
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- ../app:/usr/src/code/app
|
||||
- ../src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_SYSTEM_EMAIL_NAME
|
||||
- _APP_SYSTEM_EMAIL_ADDRESS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_SMTP_HOST
|
||||
- _APP_SMTP_PORT
|
||||
- _APP_SMTP_SECURE
|
||||
- _APP_SMTP_USERNAME
|
||||
- _APP_SMTP_PASSWORD
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_DOMAIN
|
||||
- _APP_OPTIONS_FORCE_HTTPS
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
@@ -0,0 +1,37 @@
|
||||
services:
|
||||
appwrite-task-maintenance:
|
||||
entrypoint: maintenance
|
||||
container_name: appwrite-task-maintenance
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- ../app:/usr/src/code/app
|
||||
- ../src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET
|
||||
- _APP_DOMAIN_FUNCTIONS
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_MAINTENANCE_INTERVAL
|
||||
- _APP_MAINTENANCE_RETENTION_EXECUTION
|
||||
- _APP_MAINTENANCE_RETENTION_CACHE
|
||||
- _APP_MAINTENANCE_RETENTION_ABUSE
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
|
||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES
|
||||
- _APP_MAINTENANCE_DELAY
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
@@ -0,0 +1,54 @@
|
||||
services:
|
||||
appwrite-worker-messaging:
|
||||
entrypoint: worker-messaging
|
||||
container_name: appwrite-worker-messaging
|
||||
restart: unless-stopped
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- appwrite-uploads:/storage/uploads:rw
|
||||
- ../app:/usr/src/code/app
|
||||
- ../src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_SMS_FROM
|
||||
- _APP_SMS_PROVIDER
|
||||
- _APP_SMS_PROJECTS_DENY_LIST
|
||||
- _APP_STORAGE_DEVICE
|
||||
- _APP_STORAGE_S3_ACCESS_KEY
|
||||
- _APP_STORAGE_S3_SECRET
|
||||
- _APP_STORAGE_S3_REGION
|
||||
- _APP_STORAGE_S3_BUCKET
|
||||
- _APP_STORAGE_S3_ENDPOINT
|
||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
|
||||
- _APP_STORAGE_DO_SPACES_SECRET
|
||||
- _APP_STORAGE_DO_SPACES_REGION
|
||||
- _APP_STORAGE_DO_SPACES_BUCKET
|
||||
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY
|
||||
- _APP_STORAGE_BACKBLAZE_SECRET
|
||||
- _APP_STORAGE_BACKBLAZE_REGION
|
||||
- _APP_STORAGE_BACKBLAZE_BUCKET
|
||||
- _APP_STORAGE_LINODE_ACCESS_KEY
|
||||
- _APP_STORAGE_LINODE_SECRET
|
||||
- _APP_STORAGE_LINODE_REGION
|
||||
- _APP_STORAGE_LINODE_BUCKET
|
||||
- _APP_STORAGE_WASABI_ACCESS_KEY
|
||||
- _APP_STORAGE_WASABI_SECRET
|
||||
- _APP_STORAGE_WASABI_REGION
|
||||
- _APP_STORAGE_WASABI_BUCKET
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
@@ -0,0 +1,33 @@
|
||||
services:
|
||||
appwrite-worker-migrations:
|
||||
entrypoint: worker-migrations
|
||||
container_name: appwrite-worker-migrations
|
||||
restart: unless-stopped
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- ../app:/usr/src/code/app
|
||||
- ../src:/usr/src/code/src
|
||||
depends_on:
|
||||
- mariadb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET
|
||||
- _APP_EMAIL_SECURITY
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
@@ -0,0 +1,30 @@
|
||||
services:
|
||||
appwrite-worker-stats-resources:
|
||||
entrypoint: worker-stats-resources
|
||||
container_name: appwrite-worker-stats-resources
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- ../app:/usr/src/code/app
|
||||
- ../src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_USAGE_STATS
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_USAGE_AGGREGATION_INTERVAL
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
@@ -0,0 +1,31 @@
|
||||
services:
|
||||
appwrite-worker-stats-usage-dump:
|
||||
entrypoint: worker-stats-usage-dump
|
||||
container_name: appwrite-worker-stats-usage-dump
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- ../app:/usr/src/code/app
|
||||
- ../src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_USAGE_STATS
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_USAGE_AGGREGATION_INTERVAL
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
- _APP_STATS_USAGE_DUAL_WRITING_DBS
|
||||
@@ -0,0 +1,30 @@
|
||||
services:
|
||||
appwrite-worker-stats-usage:
|
||||
entrypoint: worker-stats-usage
|
||||
container_name: appwrite-worker-stats-usage
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- ../app:/usr/src/code/app
|
||||
- ../src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_USAGE_STATS
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_USAGE_AGGREGATION_INTERVAL
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
@@ -0,0 +1,30 @@
|
||||
services:
|
||||
appwrite-worker-webhooks:
|
||||
entrypoint: worker-webhooks
|
||||
container_name: appwrite-worker-webhooks
|
||||
image: appwrite-dev
|
||||
networks:
|
||||
- appwrite
|
||||
volumes:
|
||||
- ../app:/usr/src/code/app
|
||||
- ../src:/usr/src/code/src
|
||||
depends_on:
|
||||
- redis
|
||||
- mariadb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_EMAIL_SECURITY
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_WEBHOOK_MAX_FAILED_ATTEMPTS
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
@@ -53,19 +53,19 @@
|
||||
"utopia-php/cli": "0.15.*",
|
||||
"utopia-php/config": "0.2.*",
|
||||
"utopia-php/detector": "0.1.*",
|
||||
"utopia-php/database": "0.66.*",
|
||||
"utopia-php/database": "0.61.*",
|
||||
"utopia-php/domains": "0.5.*",
|
||||
"utopia-php/dsn": "0.2.1",
|
||||
"utopia-php/framework": "0.33.*",
|
||||
"utopia-php/fetch": "0.4.*",
|
||||
"utopia-php/fetch": "0.3.*",
|
||||
"utopia-php/image": "0.8.*",
|
||||
"utopia-php/locale": "0.4.*",
|
||||
"utopia-php/logger": "0.6.*",
|
||||
"utopia-php/messaging": "0.16.*",
|
||||
"utopia-php/migration": "0.9.1",
|
||||
"utopia-php/migration": "0.8.*",
|
||||
"utopia-php/orchestration": "0.9.*",
|
||||
"utopia-php/platform": "0.7.*",
|
||||
"utopia-php/pools": "0.8.*",
|
||||
"utopia-php/pools": "0.7.*",
|
||||
"utopia-php/preloader": "0.2.*",
|
||||
"utopia-php/queue": "0.9.*",
|
||||
"utopia-php/registry": "0.5.*",
|
||||
@@ -74,7 +74,7 @@
|
||||
"utopia-php/system": "0.9.*",
|
||||
"utopia-php/telemetry": "0.1.*",
|
||||
"utopia-php/vcs": "0.10.*",
|
||||
"utopia-php/websocket": "0.3.*",
|
||||
"utopia-php/websocket": "0.1.*",
|
||||
"matomo/device-detector": "6.1.*",
|
||||
"dragonmantank/cron-expression": "3.3.2",
|
||||
"phpmailer/phpmailer": "6.9.1",
|
||||
|
||||
@@ -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": "51959289a3f882160f5a9eeb605d41d7",
|
||||
"content-hash": "e4281c45c1b60dade2ec8df58e6926d5",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/jwt",
|
||||
@@ -751,6 +751,66 @@
|
||||
},
|
||||
"time": "2025-03-26T18:01:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "jean85/pretty-package-versions",
|
||||
"version": "2.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Jean85/pretty-package-versions.git",
|
||||
"reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/4d7aa5dab42e2a76d99559706022885de0e18e1a",
|
||||
"reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"composer-runtime-api": "^2.1.0",
|
||||
"php": "^7.4|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.2",
|
||||
"jean85/composer-provided-replaced-stub-package": "^1.0",
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"phpunit/phpunit": "^7.5|^8.5|^9.6",
|
||||
"rector/rector": "^2.0",
|
||||
"vimeo/psalm": "^4.3 || ^5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Jean85\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Alessandro Lai",
|
||||
"email": "alessandro.lai85@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A library to get pretty versions strings of installed dependencies",
|
||||
"keywords": [
|
||||
"composer",
|
||||
"package",
|
||||
"release",
|
||||
"versions"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Jean85/pretty-package-versions/issues",
|
||||
"source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.1"
|
||||
},
|
||||
"time": "2025-03-19T14:43:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/csv",
|
||||
"version": "9.14.0",
|
||||
@@ -909,6 +969,75 @@
|
||||
},
|
||||
"time": "2023-10-02T10:01:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mongodb/mongodb",
|
||||
"version": "1.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mongodb/mongo-php-library.git",
|
||||
"reference": "b0bbd657f84219212487d01a8ffe93a789e1e488"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/mongodb/mongo-php-library/zipball/b0bbd657f84219212487d01a8ffe93a789e1e488",
|
||||
"reference": "b0bbd657f84219212487d01a8ffe93a789e1e488",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-hash": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mongodb": "^1.11.0",
|
||||
"jean85/pretty-package-versions": "^1.2 || ^2.0.1",
|
||||
"php": "^7.1 || ^8.0",
|
||||
"symfony/polyfill-php80": "^1.19"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^9.0",
|
||||
"squizlabs/php_codesniffer": "^3.6",
|
||||
"symfony/phpunit-bridge": "^5.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.10.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"MongoDB\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Andreas Braun",
|
||||
"email": "andreas.braun@mongodb.com"
|
||||
},
|
||||
{
|
||||
"name": "Jeremy Mikola",
|
||||
"email": "jmikola@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "MongoDB driver library",
|
||||
"homepage": "https://jira.mongodb.org/browse/PHPLIB",
|
||||
"keywords": [
|
||||
"database",
|
||||
"driver",
|
||||
"mongodb",
|
||||
"persistence"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/mongodb/mongo-php-library/issues",
|
||||
"source": "https://github.com/mongodb/mongo-php-library/tree/1.10.0"
|
||||
},
|
||||
"time": "2021-10-20T22:22:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mustangostang/spyc",
|
||||
"version": "0.6.3",
|
||||
@@ -1365,16 +1494,16 @@
|
||||
},
|
||||
{
|
||||
"name": "open-telemetry/sdk",
|
||||
"version": "1.2.4",
|
||||
"version": "1.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/opentelemetry-php/sdk.git",
|
||||
"reference": "47fcb66ae5328c5a799195247b1dce551d85873e"
|
||||
"reference": "37eec0fe47ddd627911f318f29b6cd48196be0c0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/47fcb66ae5328c5a799195247b1dce551d85873e",
|
||||
"reference": "47fcb66ae5328c5a799195247b1dce551d85873e",
|
||||
"url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/37eec0fe47ddd627911f318f29b6cd48196be0c0",
|
||||
"reference": "37eec0fe47ddd627911f318f29b6cd48196be0c0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1451,7 +1580,7 @@
|
||||
"issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
|
||||
"source": "https://github.com/open-telemetry/opentelemetry-php"
|
||||
},
|
||||
"time": "2025-04-15T07:02:07+00:00"
|
||||
"time": "2025-01-29T21:40:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "open-telemetry/sem-conv",
|
||||
@@ -2804,6 +2933,86 @@
|
||||
],
|
||||
"time": "2024-09-09T11:45:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.31.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
|
||||
"reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Php80\\": ""
|
||||
},
|
||||
"classmap": [
|
||||
"Resources/stubs"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ion Bazan",
|
||||
"email": "ion.bazan@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-09T11:45:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php82",
|
||||
"version": "v1.31.0",
|
||||
@@ -2965,16 +3174,16 @@
|
||||
},
|
||||
{
|
||||
"name": "tbachert/spi",
|
||||
"version": "v1.0.3",
|
||||
"version": "v1.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Nevay/spi.git",
|
||||
"reference": "506a79c98e1a51522e76ee921ccb6c62d52faf3a"
|
||||
"reference": "2ddfaf815dafb45791a61b08170de8d583c16062"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Nevay/spi/zipball/506a79c98e1a51522e76ee921ccb6c62d52faf3a",
|
||||
"reference": "506a79c98e1a51522e76ee921ccb6c62d52faf3a",
|
||||
"url": "https://api.github.com/repos/Nevay/spi/zipball/2ddfaf815dafb45791a61b08170de8d583c16062",
|
||||
"reference": "2ddfaf815dafb45791a61b08170de8d583c16062",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3011,9 +3220,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Nevay/spi/issues",
|
||||
"source": "https://github.com/Nevay/spi/tree/v1.0.3"
|
||||
"source": "https://github.com/Nevay/spi/tree/v1.0.2"
|
||||
},
|
||||
"time": "2025-04-02T19:38:14+00:00"
|
||||
"time": "2024-10-04T16:36:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "thecodingmachine/safe",
|
||||
@@ -3351,16 +3560,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/cli",
|
||||
"version": "0.15.2",
|
||||
"version": "0.15.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/cli.git",
|
||||
"reference": "da00ff6b8b29a826a1794002ae43442cdf3a0f5f"
|
||||
"reference": "d69bbe51a6a94dc4e5bcdd542b5938038b985a65"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/cli/zipball/da00ff6b8b29a826a1794002ae43442cdf3a0f5f",
|
||||
"reference": "da00ff6b8b29a826a1794002ae43442cdf3a0f5f",
|
||||
"url": "https://api.github.com/repos/utopia-php/cli/zipball/d69bbe51a6a94dc4e5bcdd542b5938038b985a65",
|
||||
"reference": "d69bbe51a6a94dc4e5bcdd542b5938038b985a65",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3394,9 +3603,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/cli/issues",
|
||||
"source": "https://github.com/utopia-php/cli/tree/0.15.2"
|
||||
"source": "https://github.com/utopia-php/cli/tree/0.15.1"
|
||||
},
|
||||
"time": "2025-04-15T10:08:48+00:00"
|
||||
"time": "2024-10-04T13:55:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/compression",
|
||||
@@ -3497,16 +3706,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/database",
|
||||
"version": "0.66.0",
|
||||
"version": "0.61.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/database.git",
|
||||
"reference": "67d2ab418efba31dc76b3564cf043e2b3f98d027"
|
||||
"reference": "349fbdf4bc088f7775c7dfb8b80239a617a88436"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/67d2ab418efba31dc76b3564cf043e2b3f98d027",
|
||||
"reference": "67d2ab418efba31dc76b3564cf043e2b3f98d027",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/349fbdf4bc088f7775c7dfb8b80239a617a88436",
|
||||
"reference": "349fbdf4bc088f7775c7dfb8b80239a617a88436",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3515,7 +3724,7 @@
|
||||
"php": ">=8.1",
|
||||
"utopia-php/cache": "0.12.*",
|
||||
"utopia-php/framework": "0.33.*",
|
||||
"utopia-php/pools": "0.8.*"
|
||||
"utopia-php/mongo": "0.3.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "1.23.*",
|
||||
@@ -3547,22 +3756,22 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/database/issues",
|
||||
"source": "https://github.com/utopia-php/database/tree/0.66.0"
|
||||
"source": "https://github.com/utopia-php/database/tree/0.61.2"
|
||||
},
|
||||
"time": "2025-04-16T07:10:27+00:00"
|
||||
"time": "2025-03-15T11:47:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/detector",
|
||||
"version": "0.1.4",
|
||||
"version": "0.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/detector.git",
|
||||
"reference": "895a4147463965b5f9cbc083b764b6476f547879"
|
||||
"reference": "8617ea205738743ef3363ad95791139e82ae44d5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/detector/zipball/895a4147463965b5f9cbc083b764b6476f547879",
|
||||
"reference": "895a4147463965b5f9cbc083b764b6476f547879",
|
||||
"url": "https://api.github.com/repos/utopia-php/detector/zipball/8617ea205738743ef3363ad95791139e82ae44d5",
|
||||
"reference": "8617ea205738743ef3363ad95791139e82ae44d5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3592,9 +3801,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/detector/issues",
|
||||
"source": "https://github.com/utopia-php/detector/tree/0.1.4"
|
||||
"source": "https://github.com/utopia-php/detector/tree/0.1.2"
|
||||
},
|
||||
"time": "2025-04-09T11:50:45+00:00"
|
||||
"time": "2025-03-11T13:01:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/domains",
|
||||
@@ -3705,16 +3914,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/fetch",
|
||||
"version": "0.4.1",
|
||||
"version": "0.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/fetch.git",
|
||||
"reference": "65095dac14037db0c822fb5e209e5bd3187a0303"
|
||||
"reference": "524dd50afa8c64670c4fb18f1df4db9b5bb4b3d0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/fetch/zipball/65095dac14037db0c822fb5e209e5bd3187a0303",
|
||||
"reference": "65095dac14037db0c822fb5e209e5bd3187a0303",
|
||||
"url": "https://api.github.com/repos/utopia-php/fetch/zipball/524dd50afa8c64670c4fb18f1df4db9b5bb4b3d0",
|
||||
"reference": "524dd50afa8c64670c4fb18f1df4db9b5bb4b3d0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3738,9 +3947,9 @@
|
||||
"description": "A simple library that provides an interface for making HTTP Requests.",
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/fetch/issues",
|
||||
"source": "https://github.com/utopia-php/fetch/tree/0.4.1"
|
||||
"source": "https://github.com/utopia-php/fetch/tree/0.3.1"
|
||||
},
|
||||
"time": "2025-04-14T07:34:27+00:00"
|
||||
"time": "2025-03-05T18:08:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/framework",
|
||||
@@ -3791,16 +4000,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/image",
|
||||
"version": "0.8.2",
|
||||
"version": "0.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/image.git",
|
||||
"reference": "6c736965177f9a9e71311e22b80cfa88511768e9"
|
||||
"reference": "dcae5b1c6deb3ff6865f4e68f012b3709c289bca"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/image/zipball/6c736965177f9a9e71311e22b80cfa88511768e9",
|
||||
"reference": "6c736965177f9a9e71311e22b80cfa88511768e9",
|
||||
"url": "https://api.github.com/repos/utopia-php/image/zipball/dcae5b1c6deb3ff6865f4e68f012b3709c289bca",
|
||||
"reference": "dcae5b1c6deb3ff6865f4e68f012b3709c289bca",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3834,9 +4043,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/image/issues",
|
||||
"source": "https://github.com/utopia-php/image/tree/0.8.2"
|
||||
"source": "https://github.com/utopia-php/image/tree/0.8.0"
|
||||
},
|
||||
"time": "2025-04-08T11:31:45+00:00"
|
||||
"time": "2025-02-20T11:49:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/locale",
|
||||
@@ -3996,16 +4205,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/migration",
|
||||
"version": "0.9.1",
|
||||
"version": "0.8.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/migration.git",
|
||||
"reference": "f8b54727c7b0abe416a74a2a4c9fa4350c7a59a3"
|
||||
"reference": "845fd04ccf5e0edb03c184b864e0596080a432b8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/migration/zipball/f8b54727c7b0abe416a74a2a4c9fa4350c7a59a3",
|
||||
"reference": "f8b54727c7b0abe416a74a2a4c9fa4350c7a59a3",
|
||||
"url": "https://api.github.com/repos/utopia-php/migration/zipball/845fd04ccf5e0edb03c184b864e0596080a432b8",
|
||||
"reference": "845fd04ccf5e0edb03c184b864e0596080a432b8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4046,9 +4255,69 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/migration/issues",
|
||||
"source": "https://github.com/utopia-php/migration/tree/0.9.1"
|
||||
"source": "https://github.com/utopia-php/migration/tree/0.8.4"
|
||||
},
|
||||
"time": "2025-04-17T05:18:58+00:00"
|
||||
"time": "2025-03-28T02:08:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/mongo",
|
||||
"version": "0.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/mongo.git",
|
||||
"reference": "52326a9a43e2d27ff0c15c48ba746dacbe9a7aee"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/mongo/zipball/52326a9a43e2d27ff0c15c48ba746dacbe9a7aee",
|
||||
"reference": "52326a9a43e2d27ff0c15c48ba746dacbe9a7aee",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mongodb": "*",
|
||||
"mongodb/mongodb": "1.10.0",
|
||||
"php": ">=8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.14",
|
||||
"laravel/pint": "1.2.*",
|
||||
"phpstan/phpstan": "1.8.*",
|
||||
"phpunit/phpunit": "^9.4",
|
||||
"swoole/ide-helper": "4.8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Utopia\\Mongo\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Eldad Fux",
|
||||
"email": "eldad@appwrite.io"
|
||||
},
|
||||
{
|
||||
"name": "Wess",
|
||||
"email": "wess@appwrite.io"
|
||||
}
|
||||
],
|
||||
"description": "A simple library to manage Mongo database",
|
||||
"keywords": [
|
||||
"database",
|
||||
"mongo",
|
||||
"php",
|
||||
"upf",
|
||||
"utopia"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/mongo/issues",
|
||||
"source": "https://github.com/utopia-php/mongo/tree/0.3.1"
|
||||
},
|
||||
"time": "2023-09-01T17:25:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/orchestration",
|
||||
@@ -4152,16 +4421,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/pools",
|
||||
"version": "0.8.2",
|
||||
"version": "0.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/pools.git",
|
||||
"reference": "05c67aba42eb68ac65489cc1e7fc5db83db2dd4d"
|
||||
"reference": "ad64d45afda08ec8b29e2642a8d18075964d40bf"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/pools/zipball/05c67aba42eb68ac65489cc1e7fc5db83db2dd4d",
|
||||
"reference": "05c67aba42eb68ac65489cc1e7fc5db83db2dd4d",
|
||||
"url": "https://api.github.com/repos/utopia-php/pools/zipball/ad64d45afda08ec8b29e2642a8d18075964d40bf",
|
||||
"reference": "ad64d45afda08ec8b29e2642a8d18075964d40bf",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4198,9 +4467,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/pools/issues",
|
||||
"source": "https://github.com/utopia-php/pools/tree/0.8.2"
|
||||
"source": "https://github.com/utopia-php/pools/tree/0.7.0"
|
||||
},
|
||||
"time": "2025-04-17T02:04:54+00:00"
|
||||
"time": "2025-03-18T03:55:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/preloader",
|
||||
@@ -4257,23 +4526,23 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/queue",
|
||||
"version": "0.9.1",
|
||||
"version": "0.9.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/queue.git",
|
||||
"reference": "32b6f84c55aae761db5a5ae76cc91ca8dbc8bc32"
|
||||
"reference": "077075f1d57afa430f76c35ed3bf4616e0eee8e7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/queue/zipball/32b6f84c55aae761db5a5ae76cc91ca8dbc8bc32",
|
||||
"reference": "32b6f84c55aae761db5a5ae76cc91ca8dbc8bc32",
|
||||
"url": "https://api.github.com/repos/utopia-php/queue/zipball/077075f1d57afa430f76c35ed3bf4616e0eee8e7",
|
||||
"reference": "077075f1d57afa430f76c35ed3bf4616e0eee8e7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.3",
|
||||
"php-amqplib/php-amqplib": "^3.7",
|
||||
"utopia-php/cli": "0.15.*",
|
||||
"utopia-php/fetch": "0.4.*",
|
||||
"utopia-php/fetch": "^0.3.0",
|
||||
"utopia-php/framework": "0.33.*",
|
||||
"utopia-php/telemetry": "0.1.*"
|
||||
},
|
||||
@@ -4316,9 +4585,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/queue/issues",
|
||||
"source": "https://github.com/utopia-php/queue/tree/0.9.1"
|
||||
"source": "https://github.com/utopia-php/queue/tree/0.9.0"
|
||||
},
|
||||
"time": "2025-03-28T19:49:36+00:00"
|
||||
"time": "2025-03-13T12:22:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/registry",
|
||||
@@ -4637,28 +4906,27 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/websocket",
|
||||
"version": "0.3.0",
|
||||
"version": "0.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/websocket.git",
|
||||
"reference": "629e53640b108eab43c7cc9ab375efade8622d43"
|
||||
"reference": "51fcb86171400d8aa40d76c54593481fd273dab5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/websocket/zipball/629e53640b108eab43c7cc9ab375efade8622d43",
|
||||
"reference": "629e53640b108eab43c7cc9ab375efade8622d43",
|
||||
"url": "https://api.github.com/repos/utopia-php/websocket/zipball/51fcb86171400d8aa40d76c54593481fd273dab5",
|
||||
"reference": "51fcb86171400d8aa40d76c54593481fd273dab5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "^1.15",
|
||||
"phpstan/phpstan": "^1.12",
|
||||
"phpunit/phpunit": "^9.5.5",
|
||||
"swoole/ide-helper": "5.1.2",
|
||||
"swoole/ide-helper": "4.6.6",
|
||||
"textalk/websocket": "1.5.2",
|
||||
"workerman/workerman": "4.1.*"
|
||||
"vimeo/psalm": "^4.8.1",
|
||||
"workerman/workerman": "^4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@@ -4670,6 +4938,16 @@
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Eldad Fux",
|
||||
"email": "eldad@appwrite.io"
|
||||
},
|
||||
{
|
||||
"name": "Torsten Dittmann",
|
||||
"email": "torsten@appwrite.io"
|
||||
}
|
||||
],
|
||||
"description": "A simple abstraction for WebSocket servers.",
|
||||
"keywords": [
|
||||
"framework",
|
||||
@@ -4680,9 +4958,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/websocket/issues",
|
||||
"source": "https://github.com/utopia-php/websocket/tree/0.3.0"
|
||||
"source": "https://github.com/utopia-php/websocket/tree/0.1.0"
|
||||
},
|
||||
"time": "2025-03-28T01:11:13+00:00"
|
||||
"time": "2021-12-20T10:50:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "webmozart/assert",
|
||||
@@ -4811,16 +5089,16 @@
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "appwrite/sdk-generator",
|
||||
"version": "0.40.13",
|
||||
"version": "0.40.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/appwrite/sdk-generator.git",
|
||||
"reference": "c4bc0ff4589969252b99354368743a99997f0428"
|
||||
"reference": "0ec5f4a60c15e33e208bc3444ba6148b1d0f0027"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/c4bc0ff4589969252b99354368743a99997f0428",
|
||||
"reference": "c4bc0ff4589969252b99354368743a99997f0428",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/0ec5f4a60c15e33e208bc3444ba6148b1d0f0027",
|
||||
"reference": "0ec5f4a60c15e33e208bc3444ba6148b1d0f0027",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4856,9 +5134,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.13"
|
||||
"source": "https://github.com/appwrite/sdk-generator/tree/0.40.11"
|
||||
},
|
||||
"time": "2025-04-23T11:59:44+00:00"
|
||||
"time": "2025-03-26T10:53:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/annotations",
|
||||
@@ -5085,16 +5363,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/pint",
|
||||
"version": "v1.22.0",
|
||||
"version": "v1.21.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/pint.git",
|
||||
"reference": "7ddfaa6523a675fae5c4123ee38fc6bfb8ee4f36"
|
||||
"reference": "370772e7d9e9da087678a0edf2b11b6960e40558"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/pint/zipball/7ddfaa6523a675fae5c4123ee38fc6bfb8ee4f36",
|
||||
"reference": "7ddfaa6523a675fae5c4123ee38fc6bfb8ee4f36",
|
||||
"url": "https://api.github.com/repos/laravel/pint/zipball/370772e7d9e9da087678a0edf2b11b6960e40558",
|
||||
"reference": "370772e7d9e9da087678a0edf2b11b6960e40558",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5105,9 +5383,9 @@
|
||||
"php": "^8.2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.75.0",
|
||||
"friendsofphp/php-cs-fixer": "^3.72.0",
|
||||
"illuminate/view": "^11.44.2",
|
||||
"larastan/larastan": "^3.3.1",
|
||||
"larastan/larastan": "^3.2.0",
|
||||
"laravel-zero/framework": "^11.36.1",
|
||||
"mockery/mockery": "^1.6.12",
|
||||
"nunomaduro/termwind": "^2.3",
|
||||
@@ -5147,7 +5425,7 @@
|
||||
"issues": "https://github.com/laravel/pint/issues",
|
||||
"source": "https://github.com/laravel/pint"
|
||||
},
|
||||
"time": "2025-04-08T22:11:45+00:00"
|
||||
"time": "2025-03-14T22:31:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "matthiasmullie/minify",
|
||||
@@ -8229,7 +8507,7 @@
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {},
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
@@ -8253,5 +8531,5 @@
|
||||
"platform-overrides": {
|
||||
"php": "8.3"
|
||||
},
|
||||
"plugin-api-version": "2.6.0"
|
||||
"plugin-api-version": "2.3.0"
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Import documents from a CSV file into your Appwrite database. This endpoint allows you to import documents from a CSV file uploaded to Appwrite Storage bucket.
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
@@ -1,11 +0,0 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_28_719)">
|
||||
<path d="M24.4429 17.4322V22.9096H10.7519C6.76318 22.9096 3.28044 20.7067 1.4171 17.4322C1.14622 16.9561 0.909137 16.4567 0.710264 15.9383C0.319864 14.9225 0.0744552 13.8325 0 12.6952V11.2143C0.0161646 10.9609 0.0416361 10.7094 0.0749451 10.4609C0.143032 9.95105 0.245898 9.45211 0.381093 8.96711C1.66006 4.36909 5.81877 1 10.7519 1C15.6851 1 19.8433 4.36909 21.1223 8.96711H15.2682C14.3072 7.4683 12.6437 6.4774 10.7519 6.4774C8.86017 6.4774 7.19668 7.4683 6.23562 8.96711C5.9427 9.42274 5.71542 9.92516 5.56651 10.4609C5.43425 10.936 5.36371 11.4369 5.36371 11.9548C5.36371 13.5248 6.01324 14.94 7.05463 15.9383C8.01961 16.865 9.32061 17.4322 10.7519 17.4322H24.4429Z" fill="#FD366E" />
|
||||
<path d="M24.4429 10.4609V15.9383H14.4492C15.4906 14.94 16.1401 13.5248 16.1401 11.9548C16.1401 11.4369 16.0696 10.936 15.9373 10.4609H24.4429Z" fill="#FD366E" />
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_28_719">
|
||||
<rect width="24" height="24" fill="white" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 53 KiB |
@@ -24,6 +24,9 @@ class Event
|
||||
public const FUNCTIONS_QUEUE_NAME = 'v1-functions';
|
||||
public const FUNCTIONS_CLASS_NAME = 'FunctionsV1';
|
||||
|
||||
public const SITES_QUEUE_NAME = 'v1-sites';
|
||||
public const SITES_CLASS_NAME = 'SitesV1';
|
||||
|
||||
/** remove */
|
||||
public const USAGE_QUEUE_NAME = 'v1-usage';
|
||||
public const USAGE_CLASS_NAME = 'UsageV1';
|
||||
|
||||
@@ -165,7 +165,6 @@ class Exception extends \Exception
|
||||
public const FUNCTION_SYNCHRONOUS_TIMEOUT = 'function_synchronous_timeout';
|
||||
public const FUNCTION_TEMPLATE_NOT_FOUND = 'function_template_not_found';
|
||||
public const FUNCTION_RUNTIME_NOT_DETECTED = 'function_runtime_not_detected';
|
||||
public const FUNCTION_EXECUTE_PERMISSION_MISSING = 'function_execute_permission_missing';
|
||||
|
||||
/** Deployments */
|
||||
public const DEPLOYMENT_NOT_FOUND = 'deployment_not_found';
|
||||
@@ -175,7 +174,6 @@ class Exception extends \Exception
|
||||
public const BUILD_NOT_READY = 'build_not_ready';
|
||||
public const BUILD_IN_PROGRESS = 'build_in_progress';
|
||||
public const BUILD_ALREADY_COMPLETED = 'build_already_completed';
|
||||
public const BUILD_CANCELED = 'build_canceled';
|
||||
public const BUILD_FAILED = 'build_failed';
|
||||
|
||||
/** Execution */
|
||||
@@ -318,22 +316,15 @@ class Exception extends \Exception
|
||||
/** Schedules */
|
||||
public const SCHEDULE_NOT_FOUND = 'schedule_not_found';
|
||||
|
||||
/** Tokens */
|
||||
public const TOKEN_NOT_FOUND = 'token_not_found';
|
||||
public const TOKEN_EXPIRED = 'token_expired';
|
||||
|
||||
|
||||
protected string $type = '';
|
||||
protected array $errors = [];
|
||||
protected bool $publish;
|
||||
private array $ctas = [];
|
||||
private ?string $view = null;
|
||||
|
||||
public function __construct(string $type = Exception::GENERAL_UNKNOWN, string $message = null, int|string $code = null, \Throwable $previous = null, ?string $view = null)
|
||||
public function __construct(string $type = Exception::GENERAL_UNKNOWN, string $message = null, int|string $code = null, \Throwable $previous = null)
|
||||
{
|
||||
$this->errors = Config::getParam('errors');
|
||||
$this->type = $type;
|
||||
$this->view = $view;
|
||||
$this->code = $code ?? $this->errors[$type]['code'];
|
||||
|
||||
// Mark string errors like HY001 from PDO as 500 errors
|
||||
@@ -383,23 +374,4 @@ class Exception extends \Exception
|
||||
{
|
||||
return $this->publish;
|
||||
}
|
||||
|
||||
public function addCTA(string $label, ?string $url = null): self
|
||||
{
|
||||
$this->ctas[] = [
|
||||
'label' => $label,
|
||||
'url' => $url
|
||||
];
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCTAs(): array
|
||||
{
|
||||
return $this->ctas;
|
||||
}
|
||||
|
||||
public function getView(): ?string
|
||||
{
|
||||
return $this->view;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\System\System;
|
||||
|
||||
class V19 extends Migration
|
||||
{
|
||||
@@ -730,7 +731,7 @@ class V19 extends Migration
|
||||
|
||||
if (empty($document->getAttribute('scheduleId', null))) {
|
||||
$schedule = $this->consoleDB->createDocument('schedules', new Document([
|
||||
'region' => $project->getAttribute('region'),
|
||||
'region' => System::getEnv('_APP_REGION', 'default'), // Todo replace with projects region
|
||||
'resourceType' => 'function',
|
||||
'resourceId' => $document->getId(),
|
||||
'resourceInternalId' => $document->getInternalId(),
|
||||
|
||||
@@ -4,22 +4,24 @@ namespace Appwrite\Network\Validator;
|
||||
|
||||
use Utopia\Validator;
|
||||
|
||||
class DNS extends Validator
|
||||
class CNAME extends Validator
|
||||
{
|
||||
public const RECORD_A = 'a';
|
||||
public const RECORD_AAAA = 'aaaa';
|
||||
public const RECORD_CNAME = 'cname';
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
protected mixed $logs;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $target;
|
||||
|
||||
/**
|
||||
* @param string $target
|
||||
*/
|
||||
public function __construct(protected string $target, protected string $type = self::RECORD_CNAME)
|
||||
public function __construct($target)
|
||||
{
|
||||
$this->target = $target;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -27,7 +29,7 @@ class DNS extends Validator
|
||||
*/
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Invalid DNS record';
|
||||
return 'Invalid CNAME record';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,34 +41,20 @@ class DNS extends Validator
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if DNS record value matches specific value
|
||||
* Check if CNAME record target value matches selected target
|
||||
*
|
||||
* @param mixed $domain
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isValid($value): bool
|
||||
public function isValid($domain): bool
|
||||
{
|
||||
$typeNative = match ($this->type) {
|
||||
self::RECORD_A => DNS_A,
|
||||
self::RECORD_AAAA => DNS_AAAA,
|
||||
self::RECORD_CNAME => DNS_CNAME,
|
||||
default => throw new \Exception('Record type not supported.')
|
||||
};
|
||||
|
||||
$dnsKey = match ($this->type) {
|
||||
self::RECORD_A => 'ip',
|
||||
self::RECORD_AAAA => 'ipv6',
|
||||
self::RECORD_CNAME => 'target',
|
||||
default => throw new \Exception('Record type not supported.')
|
||||
};
|
||||
|
||||
if (!is_string($value)) {
|
||||
if (!is_string($domain)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$records = \dns_get_record($value, $typeNative);
|
||||
$records = \dns_get_record($domain, DNS_CNAME);
|
||||
$this->logs = $records;
|
||||
} catch (\Throwable $th) {
|
||||
return false;
|
||||
@@ -77,7 +65,7 @@ class DNS extends Validator
|
||||
}
|
||||
|
||||
foreach ($records as $record) {
|
||||
if (isset($record[$dnsKey]) && $record[$dnsKey] === $this->target) {
|
||||
if (isset($record['target']) && $record['target'] === $this->target) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,8 @@ namespace Appwrite\Platform;
|
||||
use Appwrite\Platform\Modules\Console;
|
||||
use Appwrite\Platform\Modules\Core;
|
||||
use Appwrite\Platform\Modules\Functions;
|
||||
use Appwrite\Platform\Modules\Projects;
|
||||
use Appwrite\Platform\Modules\Proxy;
|
||||
use Appwrite\Platform\Modules\Sites;
|
||||
use Appwrite\Platform\Modules\Storage;
|
||||
use Utopia\Platform\Platform;
|
||||
|
||||
class Appwrite extends Platform
|
||||
@@ -16,11 +14,9 @@ class Appwrite extends Platform
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(new Core());
|
||||
$this->addModule(new Projects\Module());
|
||||
$this->addModule(new Functions\Module());
|
||||
$this->addModule(new Sites\Module());
|
||||
$this->addModule(new Console\Module());
|
||||
$this->addModule(new Proxy\Module());
|
||||
$this->addModule(new Storage\Module());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,11 +65,11 @@ class Get extends Action
|
||||
|
||||
$deployment = $dbForProject->getDocument('deployments', $deploymentId);
|
||||
|
||||
if ($deployment->isEmpty()) {
|
||||
if ($deployment->getAttribute('resourceId') !== $function->getId()) {
|
||||
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($deployment->getAttribute('resourceId') !== $function->getId()) {
|
||||
if ($deployment->isEmpty()) {
|
||||
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Executor\Executor;
|
||||
use Utopia\App;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
@@ -57,7 +58,6 @@ class Update extends Action
|
||||
->inject('dbForProject')
|
||||
->inject('project')
|
||||
->inject('queueForEvents')
|
||||
->inject('executor')
|
||||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
@@ -67,8 +67,7 @@ class Update extends Action
|
||||
Response $response,
|
||||
Database $dbForProject,
|
||||
Document $project,
|
||||
Event $queueForEvents,
|
||||
Executor $executor
|
||||
Event $queueForEvents
|
||||
) {
|
||||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
|
||||
@@ -86,7 +85,7 @@ class Update extends Action
|
||||
throw new Exception(Exception::BUILD_ALREADY_COMPLETED);
|
||||
}
|
||||
|
||||
$startTime = new \DateTime($deployment->getAttribute('buildStartAt', 'now'));
|
||||
$startTime = new \DateTime($deployment->getAttribute('buildStartAt'));
|
||||
$endTime = new \DateTime('now');
|
||||
$duration = $endTime->getTimestamp() - $startTime->getTimestamp();
|
||||
|
||||
@@ -102,6 +101,7 @@ class Update extends Action
|
||||
}
|
||||
|
||||
try {
|
||||
$executor = new Executor(App::getEnv('_APP_EXECUTOR_HOST'));
|
||||
$executor->deleteRuntime($project->getId(), $deploymentId . "-build");
|
||||
} catch (\Throwable $th) {
|
||||
// Don't throw if the deployment doesn't exist
|
||||
|
||||